├── .babelrc ├── .devcontainer ├── Dockerfile └── devcontainer.json ├── .eslintrc.js ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml └── workflows │ ├── codeql-analysis.yml │ └── lint.yml ├── .gitignore ├── .storybook ├── logo.png ├── main.js ├── manager.js ├── preview.js └── theme.js ├── .stylelintrc ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── postcss.config.js ├── src ├── components │ ├── FAutocomplete │ │ ├── FAutocomplete.spec.js │ │ ├── FAutocomplete.vue │ │ └── index.js │ ├── FAvatar │ │ ├── FAvatar.spec.js │ │ ├── FAvatar.vue │ │ └── index.js │ ├── FBtn │ │ ├── FBtn.spec.js │ │ ├── FBtn.vue │ │ └── index.js │ ├── FCard │ │ ├── FCard.spec.js │ │ ├── FCard.vue │ │ ├── FCardAction.vue │ │ ├── FCardCaption.vue │ │ ├── FCardContent.vue │ │ ├── FCardImage.vue │ │ ├── FCardText.vue │ │ ├── FCardTitle.vue │ │ └── index.js │ ├── FCheckbox │ │ ├── FCheckbox.spec.js │ │ ├── FCheckbox.vue │ │ └── index.js │ ├── FContainer │ │ ├── FContainer.spec.js │ │ ├── FContainer.vue │ │ └── index.js │ ├── FGrid │ │ ├── FGrid.spec.js │ │ ├── FGrid.vue │ │ ├── FGridItem.vue │ │ └── index.js │ ├── FImg │ │ ├── FImg.spec.js │ │ ├── FImg.vue │ │ └── index.js │ ├── FInput │ │ ├── FInput.spec.js │ │ ├── FInput.vue │ │ └── index.js │ ├── FList │ │ ├── FList.spec.js │ │ ├── FList.vue │ │ ├── FListItem.spec.js │ │ ├── FListItem.vue │ │ ├── FListItemAvatar.spec.js │ │ ├── FListItemAvatar.vue │ │ ├── FListItemContent.spec.js │ │ ├── FListItemContent.vue │ │ └── index.js │ ├── FMenu │ │ ├── FMenu.spec.js │ │ ├── FMenu.vue │ │ └── index.js │ ├── FProgressLinear │ │ ├── FProgressLinear.spec.js │ │ ├── FProgressLinear.vue │ │ └── index.js │ ├── FRadio │ │ ├── FRadio.spec.js │ │ ├── FRadio.vue │ │ └── index.js │ ├── FRadioGroup │ │ ├── FRadioGroup.spec.js │ │ ├── FRadioGroup.vue │ │ └── index.js │ ├── FSelect │ │ ├── FSelect.spec.js │ │ ├── FSelect.vue │ │ └── index.js │ ├── FSlider │ │ ├── FSlider.spec.js │ │ ├── FSlider.vue │ │ └── index.js │ ├── FSwitch │ │ ├── FSwitch.spec.js │ │ ├── FSwitch.vue │ │ └── index.js │ ├── FTextarea │ │ ├── FTextarea.spec.js │ │ ├── FTextarea.vue │ │ └── index.js │ └── index.js ├── main.js ├── mixins │ ├── grid.js │ └── helper.js ├── scss │ ├── _variables.scss │ ├── components │ │ ├── _FAvatar.scss │ │ ├── _FBtn.scss │ │ ├── _FCard.scss │ │ ├── _FCheckbox.scss │ │ ├── _FContainer.scss │ │ ├── _FGrid.scss │ │ ├── _FImg.scss │ │ ├── _FInput.scss │ │ ├── _FList.scss │ │ ├── _FMenu.scss │ │ ├── _FProgressLinear.scss │ │ ├── _FRadio.scss │ │ ├── _FRadioGroup.scss │ │ ├── _FSelect.scss │ │ ├── _FSlider.scss │ │ ├── _FSwitch.scss │ │ └── _FTextarea.scss │ ├── fluentify.scss │ ├── global │ │ ├── _base.scss │ │ ├── _button.scss │ │ ├── _colors.scss │ │ ├── _grid.scss │ │ ├── _typography.scss │ │ └── _ul-ol.scss │ └── utils │ │ ├── _helpers.scss │ │ └── _mixin.scss ├── stories │ ├── FBtn.stories.js │ ├── FCard.stories.js │ ├── FCheckbox.stories.js │ ├── FInput.stories.js │ ├── FProgressLinear.stories.js │ ├── FRadio.stories.js │ ├── FRadioGroup.stories.js │ ├── FSwitch.stories.js │ └── FTextarea.stories.js └── utils │ ├── config.js │ └── helper.js ├── tests └── unit │ └── button.spec.js └── vue.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { "presets": ["@vue/cli-plugin-babel/preset"] } -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # [Choice] Node.js version: 14, 12, 10 2 | ARG VARIANT=14 3 | FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:${VARIANT} 4 | USER root 5 | RUN apt-get update 6 | 7 | ARG USER_UID=1000 8 | ARG USER_GID=$USER_UID 9 | RUN if [ "$USER_GID" != "1000" ] || [ "$USER_UID" != "1000" ]; then \ 10 | groupmod --gid $USER_GID node \ 11 | && usermod --uid $USER_UID --gid $USER_GID node \ 12 | && chmod -R $USER_UID:$USER_GID /home/node \ 13 | && chmod -R $USER_UID:root /usr/local/share/nvm /usr/local/share/npm-global; \ 14 | fi -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js", 3 | "build": { 4 | "dockerfile": "Dockerfile", 5 | // Update 'VARIANT' to pick a Node version: 10, 12, 14 6 | "args": { "VARIANT": "14" } 7 | }, 8 | 9 | // Set *default* container specific settings.json values on container create. 10 | "settings": { 11 | "terminal.integrated.shell.linux": "/bin/bash" 12 | }, 13 | 14 | // Add the IDs of extensions you want installed when the container is created. 15 | "extensions": [ 16 | "dbaeumer.vscode-eslint", 17 | "octref.vetur", 18 | "liuji-jim.vue", 19 | "eamodio.gitlens", 20 | "wix.vscode-import-cost", 21 | "mrmlnc.vscode-scss" 22 | ], 23 | 24 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 25 | "forwardPorts": [9000], 26 | 27 | // Use 'postCreateCommand' to run commands after the container is created. 28 | // "postCreateCommand": "yarn install", 29 | 30 | // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root. 31 | "remoteUser": "node" 32 | } 33 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | 'env': { 4 | 'browser': true, 5 | 'commonjs': true, 6 | 'es6': true 7 | }, 8 | extends: [ 9 | 'eslint:recommended', 10 | 'plugin:vue/recommended' 11 | ], 12 | 'parserOptions': { 13 | 'ecmaVersion': 2015, 14 | 'sourceType': 'module' 15 | }, 16 | 'rules': { 17 | 'indent': [ 18 | 'error', 19 | 2 20 | ], 21 | 'quotes': [ 22 | 'error', 23 | 'single' 24 | ], 25 | 'semi': [ 26 | 'error', 27 | 'never' 28 | ], 29 | 'vue/no-use-v-if-with-v-for': 'off' 30 | }, 31 | 'overrides': [ 32 | { 33 | 'files': [ 34 | '*.vue', 35 | '**/__tests__/*.{j,t}s?(x)', 36 | '**/tests/unit/**/*.spec.{j,t}s?(x)' 37 | ], 38 | env: { 39 | mocha: true 40 | }, 41 | 'rules': { 42 | 'indent': 'off' 43 | } 44 | } 45 | ] 46 | } -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [alexanderyw] 4 | # patreon: # Replace with a single Patreon username 5 | # open_collective: # Replace with a single Open Collective username 6 | # ko_fi: # Replace with a single Ko-fi username 7 | # tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | # custom: # Replace with a single custom sponsorship URL 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | versioning-strategy: increase 9 | ignore: 10 | - dependency-name: "@storybook/addon-links" 11 | versions: 12 | - 6.1.16 13 | - 6.1.17 14 | - 6.1.19 15 | - 6.1.21 16 | - 6.2.1 17 | - 6.2.2 18 | - 6.2.3 19 | - 6.2.4 20 | - 6.2.5 21 | - 6.2.7 22 | - 6.2.8 23 | - dependency-name: "@storybook/vue" 24 | versions: 25 | - 6.1.17 26 | - 6.1.19 27 | - 6.1.21 28 | - 6.2.1 29 | - 6.2.2 30 | - 6.2.3 31 | - 6.2.4 32 | - 6.2.5 33 | - 6.2.7 34 | - 6.2.8 35 | - dependency-name: "@storybook/addon-actions" 36 | versions: 37 | - 6.1.17 38 | - 6.1.21 39 | - 6.2.1 40 | - 6.2.2 41 | - 6.2.3 42 | - 6.2.4 43 | - 6.2.5 44 | - 6.2.7 45 | - 6.2.8 46 | - dependency-name: "@babel/core" 47 | versions: 48 | - 7.12.13 49 | - 7.12.16 50 | - 7.12.17 51 | - 7.13.10 52 | - 7.13.13 53 | - 7.13.14 54 | - 7.13.15 55 | - dependency-name: y18n 56 | versions: 57 | - 4.0.1 58 | - dependency-name: eslint-plugin-vue 59 | versions: 60 | - 7.5.0 61 | - 7.6.0 62 | - 7.7.0 63 | - 7.8.0 64 | - dependency-name: chai 65 | versions: 66 | - 4.3.1 67 | - 4.3.3 68 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | # The branches below must be a subset of the branches above 8 | branches: [master] 9 | schedule: 10 | - cron: '0 6 * * 1' 11 | 12 | jobs: 13 | analyze: 14 | name: Analyze 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | # Override automatic language detection by changing the below list 21 | # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] 22 | language: ['javascript'] 23 | # Learn more... 24 | # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection 25 | 26 | steps: 27 | - name: Checkout repository 28 | uses: actions/checkout@v2 29 | with: 30 | # We must fetch at least the immediate parents so that if this is 31 | # a pull request then we can checkout the head. 32 | fetch-depth: 2 33 | 34 | # If this run was triggered by a pull request event, then checkout 35 | # the head of the pull request instead of the merge commit. 36 | - run: git checkout HEAD^2 37 | if: ${{ github.event_name == 'pull_request' }} 38 | 39 | # Initializes the CodeQL tools for scanning. 40 | - name: Initialize CodeQL 41 | uses: github/codeql-action/init@v1 42 | with: 43 | languages: ${{ matrix.language }} 44 | 45 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 46 | # If this step fails, then you should remove it and run the build manually (see below) 47 | - name: Autobuild 48 | uses: github/codeql-action/autobuild@v1 49 | 50 | # ℹ️ Command-line programs to run using the OS shell. 51 | # 📚 https://git.io/JvXDl 52 | 53 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 54 | # and modify them (or add more) to build your code if your project 55 | # uses a compiled language 56 | 57 | #- run: | 58 | # make bootstrap 59 | # make release 60 | 61 | - name: Perform CodeQL Analysis 62 | uses: github/codeql-action/analyze@v1 63 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Javascript and css linting 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v2 20 | 21 | - name: Use Node.js ${{ matrix.node-version }} 22 | uses: actions/setup-node@v1 23 | 24 | - run: npm ci 25 | 26 | - run: npm run build 27 | 28 | lint: 29 | 30 | runs-on: ubuntu-latest 31 | 32 | steps: 33 | - name: Checkout repository 34 | uses: actions/checkout@v2 35 | 36 | - name: Use Node.js ${{ matrix.node-version }} 37 | uses: actions/setup-node@v1 38 | 39 | - run: npm ci 40 | 41 | - run: npm run lint:js 42 | 43 | - run: npm run lint:css 44 | -------------------------------------------------------------------------------- /.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 | /reports 65 | /test/dist 66 | 67 | # storybook 68 | /storybook-static -------------------------------------------------------------------------------- /.storybook/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluentifyJs/fluentify/c5c24b5f7111b771dc2cc9c2ef915ca5b8e9dc89/.storybook/logo.png -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = { 4 | addons: [ 5 | '@storybook/preset-scss', 6 | '@storybook/addon-actions', 7 | '@storybook/addon-links' 8 | ], 9 | webpackFinal: async (config, { configType }) => { 10 | // `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION' 11 | // You can change the configuration based on that. 12 | // 'PRODUCTION' is used when building the static version of storybook. 13 | config.watch = true 14 | 15 | // Make whatever fine-grained changes you need 16 | config.module.rules.push({ 17 | test: /\.scss$/, 18 | use: ['style-loader', 'css-loader', 'sass-loader'], 19 | include: path.resolve(__dirname, '../'), 20 | }, 21 | { 22 | test: /\.(png|svg|jpg|gif)$/, 23 | use: [ 24 | 'file-loader', 25 | ], 26 | include: path.resolve(__dirname, "../") 27 | }); 28 | 29 | // Return the altered config 30 | return config; 31 | }, 32 | }; 33 | -------------------------------------------------------------------------------- /.storybook/manager.js: -------------------------------------------------------------------------------- 1 | import { addons } from '@storybook/addons'; 2 | import yourTheme from './theme'; 3 | 4 | addons.setConfig({ 5 | theme: yourTheme, 6 | }); -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-extraneous-dependencies */ 2 | import { configure, addDecorator } from '@storybook/vue' 3 | 4 | import '!style-loader!css-loader!sass-loader!../src/scss/fluentify.scss' 5 | 6 | const req = require.context('../src/stories', true, /.stories.js$/) 7 | 8 | addDecorator(() => ({ 9 | template: '
', 10 | })) 11 | 12 | function loadStories() { 13 | req.keys().forEach(filename => req(filename)) 14 | } 15 | 16 | configure(loadStories, module) 17 | -------------------------------------------------------------------------------- /.storybook/theme.js: -------------------------------------------------------------------------------- 1 | import { create } from '@storybook/theming'; 2 | import logo from './logo.png'; 3 | 4 | export default create({ 5 | base: 'light', 6 | 7 | colorPrimary: '#41B883', 8 | colorSecondary: '#34495E', 9 | 10 | // UI 11 | appBg: 'white', 12 | appContentBg: 'white', 13 | appBorderColor: '#41B883', 14 | appBorderRadius: 4, 15 | 16 | // Typography 17 | fontBase: '"Open Sans", sans-serif', 18 | fontCode: 'monospace', 19 | 20 | // Text colors 21 | textColor: '#34495E', 22 | textInverseColor: 'rgba(255,255,255,0.9)', 23 | 24 | // Toolbar default and active colors 25 | barTextColor: 'silver', 26 | barSelectedColor: '#34495E', 27 | barBg: '#41B883', 28 | 29 | // Form colors 30 | inputBg: 'white', 31 | inputBorder: '#41B883', 32 | inputTextColor: '#34495E', 33 | inputBorderRadius: 4, 34 | 35 | brandTitle: 'Fluentify', 36 | brandUrl: 'https://github.com/FluentifyJs/fluentify', 37 | brandImage: logo, 38 | }); -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "block-no-empty": null, 4 | "color-no-invalid-hex": true, 5 | "comment-empty-line-before": [ "always", { 6 | "ignore": ["stylelint-commands", "after-comment"] 7 | } ], 8 | "declaration-colon-space-after": "always", 9 | "indentation": [4], 10 | "max-empty-lines": 2, 11 | "rule-empty-line-before": [ "always", { 12 | "except": ["first-nested"], 13 | "ignore": ["after-comment"] 14 | } ], 15 | "unit-whitelist": ["em", "rem", "%", "px", "s", "ms", "deg", "fr"] 16 | } 17 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are **welcome** and will be fully **credited**. 4 | 5 | We accept contributions via Pull Requests on [Github](https://github.com/AlexanderYW/fluentify). 6 | 7 | 8 | ## Pull Requests 9 | 10 | - **Keep the same style** - eslint will automatically be ran before committing 11 | 12 | - **Tip** to pass lint tests easier use the `npm run lint:fix` command 13 | 14 | - **Add tests!** - Your patch won't be accepted if it doesn't have tests. 15 | 16 | - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. 17 | 18 | - **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. 19 | 20 | - **Create feature branches** - Don't ask us to pull from your master branch. 21 | 22 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. 23 | 24 | - **Send coherent history** - Make sure your commits message means something 25 | 26 | 27 | ## Running Tests 28 | 29 | Launch visual tests and watch the components at the same time 30 | 31 | ``` bash 32 | $ npm run dev 33 | ``` 34 | 35 | 36 | **Happy coding**! 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Alexander Wennerstrøm 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 | ![fluentify-opengraph](https://user-images.githubusercontent.com/4184558/67981054-169c3600-fc20-11e9-83e1-52f695776774.png) 2 | 3 | [![codebeat badge](https://codebeat.co/badges/d2cb26e8-55e3-40a7-b4be-bc9811f0cd98)](https://codebeat.co/projects/github-com-fluentifyjs-fluentify-master) 4 | ![image](https://img.shields.io/npm/dm/@fluentify/fluentify.svg) 5 | ![image](https://img.shields.io/npm/v/@fluentify/fluentify.svg) 6 | ![image](https://img.shields.io/npm/l/@fluentify/fluentify.svg) 7 | ![Javascript and css linting](https://github.com/FluentifyJs/fluentify/workflows/Javascript%20and%20css%20linting/badge.svg) 8 | ![CodeQL](https://github.com/FluentifyJs/fluentify/workflows/CodeQL/badge.svg) 9 | 10 | ### [View demo](https://fluent.ayw.io/) 11 | 12 | ## This Components framework is *Work in progress*, please keep that in mind that it's not ready for production yet, feel free to contribute and get it ready faster 13 | 14 | # Todo: 15 | ## Components 16 | - [x] Container 17 | - [x] Grid - Rows and Columns using css grid (Room for improvements) 18 | - [x] Button 19 | - [x] List 20 | - [x] List item 21 | - [x] List item avatar 22 | - [x] List item content (with support of single line, double line and triple line) 23 | - [ ] Card 24 | - [ ] Video player 25 | - [x] Menu component 26 | - [ ] Modal / Dialog 27 | - [ ] Date picker 28 | - [ ] Date calendar picker 29 | - [ ] Time picker 30 | - [ ] Color picker 31 | - [ ] Flyout / Snackbar 32 | - [x] Progressbar linear 33 | - [ ] Progressbar circular 34 | - [x] Input field 35 | - [x] Checkbox input 36 | - [x] Radio input 37 | - [x] Radio Group 38 | - [ ] Select (Missing arrow icon) 39 | - [ ] File picker 40 | - [ ] Textarea 41 | - [ ] Datalist 42 | - [ ] Divider 43 | - [ ] Data table 44 | - [ ] Image component 45 | - [ ] Switch 46 | - [x] Slider (horizontal/vertical) 47 | - [ ] Rating 48 | - [ ] Autocomplete / Auto-suggest input 49 | - [ ] Context menu 50 | - [ ] Navigation view (Content of view will be the list component) 51 | - [ ] Command bar 52 | - [ ] Tree view 53 | - [ ] Pivot 54 | - [ ] Icon component 55 | 56 | # Classes 57 | 58 | - [ ] Typography 59 | - [ ] Colors 60 | - [ ] Padding helper 61 | - [ ] Margin helper 62 | - [ ] Display helper (block, inline, inline-block etc) 63 | - [ ] MDL2 icon font 64 | 65 | # Theme 66 | - [ ] Custom colors support 67 | - [ ] Dark theme for all components 68 | 69 | # Website 70 | - [ ] Main page 71 | - [ ] Documentation 72 | - [ ] Theme generator 73 | - [ ] Codepen template 74 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@fluentify/fluentify", 3 | "version": "0.2.0", 4 | "description": "Fluent design system components based framework for Vue.js", 5 | "author": "Alexander Wennerstrøm ", 6 | "scripts": { 7 | "build": "vue-cli-service build", 8 | "test": "npm run coverage", 9 | "clean": "rimraf dist", 10 | "coverage": "vue-cli-service test:unit", 11 | "lint": "npm run lint:css && npm run lint:js && vue-cli-service lint", 12 | "lint:css": "stylelint src/**/*.{vue,css,scss}", 13 | "lint:js": "npx eslint --ext js --ext jsx --ext vue src src/**/*.spec.js", 14 | "lint:js:fix": "npm run lint:js -- --fix", 15 | "lint:staged": "lint-staged", 16 | "prepublish": "npm run build", 17 | "pretest": "npm run lint", 18 | "storybook:build": "build-storybook", 19 | "storybook:serve": "start-storybook -p 9000" 20 | }, 21 | "dependencies": { 22 | "vue": "^2.6.12" 23 | }, 24 | "devDependencies": { 25 | "@babel/core": "^7.14.0", 26 | "@storybook/preset-scss": "^1.0.3", 27 | "@storybook/addon-actions": "^6.2.9", 28 | "@storybook/addon-links": "^6.1.20", 29 | "@storybook/vue": "^6.2.9", 30 | "@vue/cli-plugin-babel": "^4.5.11", 31 | "@vue/cli-plugin-eslint": "^4.5.11", 32 | "@vue/cli-plugin-unit-mocha": "~4.5.11", 33 | "@vue/cli-service": "^4.5.11", 34 | "@vue/eslint-config-standard": "^4.0.0", 35 | "@vue/test-utils": "^1.1.3", 36 | "babel-eslint": "^10.1.0", 37 | "babel-loader": "^8.2.2", 38 | "babel-preset-vue": "^2.0.2", 39 | "chai": "^4.3.4", 40 | "eslint": "^6.8.0", 41 | "eslint-plugin-vue": "^6.2.2", 42 | "file-loader": "^6.2.0", 43 | "lint-staged": "^10.5.4", 44 | "node-sass": "^5.0.0", 45 | "pre-commit": "^1.2.2", 46 | "rimraf": "^3.0.2", 47 | "sass": "^1.32.8", 48 | "sass-loader": "^10.1.1", 49 | "stylelint": "^13.12.0", 50 | "vue-template-compiler": "^2.6.12" 51 | }, 52 | "browserslist": [ 53 | "last 2 versions" 54 | ], 55 | "browser": "dist/fluentify.js", 56 | "bugs": { 57 | "url": "https://github.com/FluentifyJs/fluentify/issues" 58 | }, 59 | "homepage": "https://github.com/FluentifyJs/fluentify#readme", 60 | "keywords": [ 61 | "vue", 62 | "vuejs", 63 | "fluent", 64 | "design", 65 | "framework", 66 | "components" 67 | ], 68 | "license": "MIT", 69 | "lint-staged": { 70 | "*.{vue,jsx,js}": [ 71 | "npm run lint:js" 72 | ], 73 | "*.{vue,css}": [ 74 | "npx stylefmt", 75 | "npm run lint:css" 76 | ] 77 | }, 78 | "main": "dist/fluentify.common.js", 79 | "module": "dist/fluentify.esm.js", 80 | "pre-commit": "lint:staged", 81 | "repository": { 82 | "type": "git", 83 | "url": "git+https://github.com/FluentifyJs/fluentify.git" 84 | }, 85 | "style": "dist/fluentify.css", 86 | "unpkg": "dist/fluentify.js" 87 | } 88 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('autoprefixer')({ 4 | 'overrideBrowserslist': [ 5 | '> 1%', 6 | 'last 2 versions' 7 | ] 8 | }) 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /src/components/FAutocomplete/FAutocomplete.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FAutocomplete from './FAutocomplete.vue' 3 | import { createVM } from 'src/../test/helpers/utils.js' 4 | import { expect } from 'chai' 5 | 6 | describe('FAutocomplete.vue', function () { 7 | it('should render correct contents', function () { 8 | const vm = createVM(this, '', 9 | { 10 | components: { 11 | FAutocomplete 12 | }, 13 | data () { 14 | return { 15 | value: 'Yes it have', 16 | items: [ 17 | { id: 1, title: 'This is a title', text: 'This is a small text paragraph', avatar: 'https://via.placeholder.com/150', disabled: false }, 18 | { id: 2, title: 'This is a title', text: 'This is a small text paragraph', avatar: 'https://via.placeholder.com/150', disabled: false }, 19 | { id: 3, title: 'This is a title', text: 'This is a small text paragraph', avatar: 'https://via.placeholder.com/150', disabled: false } 20 | ] 21 | } 22 | } 23 | } 24 | ) 25 | expect(vm.$el.querySelectorAll('.f-input input')[0].value.length).to.be.equal(0) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /src/components/FAutocomplete/FAutocomplete.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 102 | -------------------------------------------------------------------------------- /src/components/FAutocomplete/index.js: -------------------------------------------------------------------------------- 1 | import FAutocomplete from './FAutocomplete' 2 | 3 | import { use, registerComponent } from '../../utils/helper' 4 | 5 | const Plugin = { 6 | install (Vue) { 7 | registerComponent(Vue, FAutocomplete) 8 | } 9 | } 10 | 11 | use(Plugin) 12 | 13 | export default Plugin 14 | 15 | export { 16 | FAutocomplete 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FAvatar/FAvatar.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FAvatar from './FAvatar.vue' 3 | import { createVM } from 'src/../test/helpers/utils.js' 4 | import { expect } from 'chai' 5 | 6 | describe('FAvatar.vue', function () { 7 | it('should render avatar with default settings and image', function () { 8 | const vm = createVM(this, ` 9 | 10 | `, 11 | { 12 | components: { 13 | FAvatar 14 | }, 15 | data () { 16 | return { 17 | src: 'https://via.placeholder.com/48' 18 | } 19 | } 20 | } 21 | ) 22 | expect(vm.$el.querySelectorAll('.f-avatar img').length).to.be.equal(1) 23 | }) 24 | it('should render avatar with size 150', function () { 25 | const vm = createVM(this, ` 26 | 27 | `, 28 | { 29 | components: { 30 | FAvatar 31 | }, 32 | data () { 33 | return { 34 | size: 150, 35 | src: 'https://via.placeholder.com/150' 36 | } 37 | } 38 | } 39 | ) 40 | expect(vm.$el.querySelectorAll('.f-avatar img').length).to.be.equal(1) 41 | }) 42 | it('should render avatar with with slot content', function () { 43 | const vm = createVM(this, ` 44 | 45 | AW 46 | 47 | `, 48 | { 49 | components: { 50 | FAvatar 51 | } 52 | } 53 | ) 54 | expect(vm.$el.querySelectorAll('.f-avatar span').length).to.be.equal(1) 55 | }) 56 | }) 57 | -------------------------------------------------------------------------------- /src/components/FAvatar/FAvatar.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 56 | -------------------------------------------------------------------------------- /src/components/FAvatar/index.js: -------------------------------------------------------------------------------- 1 | import FAvatar from './FAvatar' 2 | 3 | import { use, registerComponent } from '../../utils/helper' 4 | 5 | const Plugin = { 6 | install (Vue) { 7 | registerComponent(Vue, FAvatar) 8 | } 9 | } 10 | 11 | use(Plugin) 12 | 13 | export default Plugin 14 | 15 | export { 16 | FAvatar 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FBtn/FBtn.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FBtn from './FBtn.vue' 3 | import { createVM } from 'src/../test/helpers/utils.js' 4 | 5 | describe('FBtn.vue', function () { 6 | it('should render correct contents', function () { 7 | const vm = createVM(this, ` 8 | Nice Button 9 | Nice Button 10 | Nice Button 11 | `, { components: { FBtn }}) 12 | vm.$el.querySelector('.f-btn span').textContent.should.eql('Nice Button') 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /src/components/FBtn/FBtn.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 42 | -------------------------------------------------------------------------------- /src/components/FBtn/index.js: -------------------------------------------------------------------------------- 1 | import FBtn from './FBtn' 2 | 3 | import { use, registerComponent } from '../../utils/helper' 4 | 5 | const Plugin = { 6 | install (Vue) { 7 | registerComponent(Vue, FBtn) 8 | } 9 | } 10 | 11 | use(Plugin) 12 | 13 | export default Plugin 14 | 15 | export { 16 | FBtn 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FCard/FCard.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FCard from './FCard.vue' 3 | import { 4 | createVM 5 | } from 'src/../test/helpers/utils.js' 6 | import { 7 | expect 8 | } from 'chai' 9 | 10 | describe('FCard.vue', function () { 11 | it('should render correct contents', function () { 12 | const vm = createVM(this, ` 13 | 14 |

PROFILE

15 |
16 | `, { 17 | components: { 18 | FCard 19 | }, 20 | data() { 21 | return { 22 | value: 'Yes it have' 23 | } 24 | } 25 | }) 26 | expect(vm.$el.querySelectorAll('.f-card').length).to.be.equal(1) 27 | }) 28 | }) -------------------------------------------------------------------------------- /src/components/FCard/FCard.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 83 | -------------------------------------------------------------------------------- /src/components/FCard/FCardAction.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /src/components/FCard/FCardCaption.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /src/components/FCard/FCardContent.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /src/components/FCard/FCardImage.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 29 | 30 | -------------------------------------------------------------------------------- /src/components/FCard/FCardText.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /src/components/FCard/FCardTitle.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /src/components/FCard/index.js: -------------------------------------------------------------------------------- 1 | import FCard from './FCard' 2 | import FCardAction from './FCardAction' 3 | import FCardCaption from './FCardCaption' 4 | import FCardImage from './FCardImage' 5 | import FCardText from './FCardText' 6 | import FCardTitle from './FCardTitle' 7 | import FCardContent from './FCardContent' 8 | 9 | import { use, registerComponent } from '../../utils/helper' 10 | 11 | const Plugin = { 12 | install (Vue) { 13 | registerComponent(Vue, FCard) 14 | } 15 | } 16 | 17 | use(Plugin) 18 | 19 | export default Plugin 20 | 21 | export { 22 | FCard, 23 | FCardAction, 24 | FCardCaption, 25 | FCardImage, 26 | FCardText, 27 | FCardTitle, 28 | FCardContent 29 | } 30 | -------------------------------------------------------------------------------- /src/components/FCheckbox/FCheckbox.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FCheckbox from './FCheckbox.vue' 3 | import { 4 | createVM 5 | } from 'src/../test/helpers/utils.js' 6 | import { 7 | expect 8 | } from 'chai' 9 | 10 | describe('FCheckbox.vue', function () { 11 | it('should render normal unchecked', function () { 12 | const vm = createVM(this, ` 13 | 14 | `, { 15 | components: { 16 | FCheckbox 17 | }, 18 | data() { 19 | return { 20 | value: true 21 | } 22 | } 23 | }) 24 | expect(vm.$el.querySelectorAll('.f-checkbox input')[0].checked).to.be.equal(false) 25 | }) 26 | it('should render normal checked', function () { 27 | const vm = createVM(this, ` 28 | 29 | `, { 30 | components: { 31 | FCheckbox 32 | }, 33 | data() { 34 | return { 35 | value: true 36 | } 37 | } 38 | }) 39 | expect(vm.$el.querySelectorAll('.f-checkbox input')[0].checked).to.be.equal(true) 40 | }) 41 | it('should render normal indeterminate', function () { 42 | const vm = createVM(this, ` 43 | 44 | `, { 45 | components: { 46 | FCheckbox 47 | }, 48 | data() { 49 | return { 50 | value: true 51 | } 52 | } 53 | }) 54 | expect(vm.$el.querySelectorAll('.f-checkbox input')[0].indeterminate).to.be.equal(true) 55 | }) 56 | }) -------------------------------------------------------------------------------- /src/components/FCheckbox/FCheckbox.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 58 | -------------------------------------------------------------------------------- /src/components/FCheckbox/index.js: -------------------------------------------------------------------------------- 1 | import FCheckbox from './FCheckbox' 2 | 3 | import { use, registerComponent } from '../../utils/helper' 4 | 5 | const Plugin = { 6 | install (Vue) { 7 | registerComponent(Vue, FCheckbox) 8 | } 9 | } 10 | 11 | use(Plugin) 12 | 13 | export default Plugin 14 | 15 | export { 16 | FCheckbox 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FContainer/FContainer.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FContainer from './FContainer' 3 | 4 | import { 5 | createVM 6 | } from 'src/../test/helpers/utils.js' 7 | import { 8 | expect 9 | } from 'chai' 10 | 11 | describe('FContainer.vue', function () { 12 | it('should render container', function () { 13 | const vm = createVM(this, ` 14 | 15 |

Fluentify Container

16 |
17 | `, { 18 | components: { 19 | FContainer 20 | }, 21 | data() { 22 | return { 23 | } 24 | } 25 | }) 26 | expect(vm.$el.querySelectorAll('.f-container').length).to.be.equal(1) 27 | }) 28 | }) -------------------------------------------------------------------------------- /src/components/FContainer/FContainer.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 30 | -------------------------------------------------------------------------------- /src/components/FContainer/index.js: -------------------------------------------------------------------------------- 1 | import FContainer from './FContainer' 2 | 3 | import { use, registerComponent } from '../../utils/helper' 4 | 5 | const Plugin = { 6 | install (Vue) { 7 | registerComponent(Vue, FContainer) 8 | } 9 | } 10 | 11 | use(Plugin) 12 | 13 | export default Plugin 14 | 15 | export { 16 | FContainer 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FGrid/FGrid.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FGrid from './FGrid' 3 | import FGridItem from './FGridItem' 4 | 5 | import { 6 | createVM 7 | } from 'src/../test/helpers/utils.js' 8 | import { 9 | expect 10 | } from 'chai' 11 | 12 | describe('FGrid.vue', function () { 13 | it('should render single line list', function () { 14 | const vm = createVM(this, ` 15 | 16 | 17 | Hello 18 | 19 | 20 | `, { 21 | components: { 22 | FGrid, 23 | FGridItem 24 | }, 25 | data() { 26 | return { 27 | src: 'https://via.placeholder.com/48', 28 | size: 32 29 | } 30 | } 31 | }) 32 | expect(vm.$el.querySelectorAll('.f-grid').length).to.be.equal(1) 33 | }) 34 | }) -------------------------------------------------------------------------------- /src/components/FGrid/FGrid.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 35 | -------------------------------------------------------------------------------- /src/components/FGrid/FGridItem.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 35 | -------------------------------------------------------------------------------- /src/components/FGrid/index.js: -------------------------------------------------------------------------------- 1 | import FGrid from './FGrid' 2 | import FGridItem from './FGridItem' 3 | 4 | import { use, registerComponent } from '../../utils/helper' 5 | 6 | const Plugin = { 7 | install (Vue) { 8 | registerComponent(Vue, FGrid), 9 | registerComponent(Vue, FGridItem) 10 | } 11 | } 12 | 13 | use(Plugin) 14 | 15 | export default Plugin 16 | 17 | export { 18 | FGrid, 19 | FGridItem 20 | } 21 | -------------------------------------------------------------------------------- /src/components/FImg/FImg.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FImg from './FImg' 3 | 4 | import { 5 | createVM 6 | } from 'src/../test/helpers/utils.js' 7 | import { 8 | expect 9 | } from 'chai' 10 | 11 | describe('FImg.vue', function () { 12 | it('should render default use case of component', function () { 13 | const vm = createVM(this, ` 14 | 15 | `, { 16 | components: { 17 | FImg 18 | }, 19 | data() { 20 | return { 21 | src: 'https://via.placeholder.com/148' 22 | } 23 | } 24 | }) 25 | expect(vm.$el.querySelectorAll('.f-img').length).to.be.equal(1) 26 | }) 27 | it('should render component with aspect ratio 3/4', function () { 28 | const vm = createVM(this, ` 29 | 30 | `, { 31 | components: { 32 | FImg 33 | }, 34 | data() { 35 | return { 36 | src: 'https://via.placeholder.com/148' 37 | } 38 | } 39 | }) 40 | expect(vm.$el.querySelectorAll('.f-img').length).to.be.equal(1) 41 | }) 42 | it('should render component with aspect ratio 3/4 and full width', function () { 43 | const vm = createVM(this, ` 44 | 45 | `, { 46 | components: { 47 | FImg 48 | }, 49 | data() { 50 | return { 51 | src: 'https://via.placeholder.com/148' 52 | } 53 | } 54 | }) 55 | expect(vm.$el.querySelectorAll('.f-img').length).to.be.equal(1) 56 | }) 57 | }) -------------------------------------------------------------------------------- /src/components/FImg/FImg.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 59 | -------------------------------------------------------------------------------- /src/components/FImg/index.js: -------------------------------------------------------------------------------- 1 | import FImg from './FImg' 2 | 3 | import { 4 | use, 5 | registerComponent 6 | } from '../../utils/helper' 7 | 8 | const Plugin = { 9 | install(Vue) { 10 | registerComponent(Vue, FImg) 11 | } 12 | } 13 | 14 | use(Plugin) 15 | 16 | export default Plugin 17 | 18 | export { 19 | FImg 20 | } -------------------------------------------------------------------------------- /src/components/FInput/FInput.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FInput from './FInput.vue' 3 | import { 4 | createVM 5 | } from 'src/../test/helpers/utils.js' 6 | import { 7 | expect 8 | } from 'chai' 9 | 10 | describe('FInput.vue', function () { 11 | it('should render correct contents', function () { 12 | const vm = createVM(this, ` 13 | Empty 14 | 15 |
16 |
17 | Has value 18 | 19 |
20 |
21 | Has label 22 | 23 | `, { 24 | components: { 25 | FInput 26 | }, 27 | data() { 28 | return { 29 | value: 'Yes it have' 30 | } 31 | } 32 | }) 33 | expect(vm.$el.querySelectorAll('.f-input input')[0].value.length).to.be.equal(0) 34 | expect(vm.$el.querySelectorAll('.f-input input')[1].value.length).to.be.equal(11) 35 | }) 36 | }) -------------------------------------------------------------------------------- /src/components/FInput/FInput.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 80 | -------------------------------------------------------------------------------- /src/components/FInput/index.js: -------------------------------------------------------------------------------- 1 | import FInput from './FInput' 2 | 3 | import { use, registerComponent } from '../../utils/helper' 4 | 5 | const Plugin = { 6 | install (Vue) { 7 | registerComponent(Vue, FInput) 8 | } 9 | } 10 | 11 | use(Plugin) 12 | 13 | export default Plugin 14 | 15 | export { 16 | FInput 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FList/FList.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FList from './FList.vue' 3 | import FListItem from './FListItem.vue' 4 | import FListItemAvatar from './FListItemAvatar.vue' 5 | import FListItemContent from './FListItemContent.vue' 6 | import FAvatar from '../FAvatar/FAvatar.vue' 7 | import { 8 | createVM 9 | } from 'src/../test/helpers/utils.js' 10 | import { 11 | expect 12 | } from 'chai' 13 | 14 | describe('FList.vue', function () { 15 | it('should render single line list', function () { 16 | const vm = createVM(this, ` 17 | 18 | 19 | 20 | Single line list item 21 | 22 | 23 | 24 | `, { 25 | components: { 26 | FList, 27 | FListItem, 28 | FListItemContent, 29 | }, 30 | data() { 31 | return { 32 | src: 'https://via.placeholder.com/48', 33 | size: 32 34 | } 35 | } 36 | }) 37 | expect(vm.$el.querySelectorAll('.f-list').length).to.be.equal(1) 38 | }) 39 | it('should render single line with avatar', function () { 40 | const vm = createVM(this, ` 41 | 42 | 43 | 44 | 45 | 46 | 47 | List item 48 | 49 | 50 | 51 | `, { 52 | components: { 53 | FList, 54 | FListItem, 55 | FListItemAvatar, 56 | FListItemContent, 57 | FAvatar 58 | }, 59 | data() { 60 | return { 61 | src: 'https://via.placeholder.com/48', 62 | size: 32 63 | } 64 | } 65 | }) 66 | expect(vm.$el.querySelectorAll('.f-list').length).to.be.equal(1) 67 | }) 68 | it('should render two lines list item', function () { 69 | const vm = createVM(this, ` 70 | 71 | 72 | 73 | Line one
74 | Line two 75 |
76 |
77 |
78 | `, { 79 | components: { 80 | FList, 81 | FListItem, 82 | FListItemAvatar, 83 | FListItemContent, 84 | FAvatar 85 | }, 86 | data() { 87 | return { 88 | src: 'https://via.placeholder.com/48', 89 | size: 32 90 | } 91 | } 92 | }) 93 | expect(vm.$el.querySelectorAll('.f-list').length).to.be.equal(1) 94 | }) 95 | it('should render two lines list item with avatar', function () { 96 | const vm = createVM(this, ` 97 | 98 | 99 | 100 | 101 | 102 | 103 | Line one
104 | Line two 105 |
106 |
107 |
108 | `, { 109 | components: { 110 | FList, 111 | FListItem, 112 | FListItemAvatar, 113 | FListItemContent, 114 | FAvatar 115 | }, 116 | data() { 117 | return { 118 | src: 'https://via.placeholder.com/48', 119 | size: 32 120 | } 121 | } 122 | }) 123 | expect(vm.$el.querySelectorAll('.f-list').length).to.be.equal(1) 124 | }) 125 | it('should render three lines list item', function () { 126 | const vm = createVM(this, ` 127 | 128 | 129 | 130 | Line one
131 | Line two
132 | Line three 133 |
134 |
135 |
136 | `, { 137 | components: { 138 | FList, 139 | FListItem, 140 | FListItemAvatar, 141 | FListItemContent, 142 | FAvatar 143 | }, 144 | data() { 145 | return { 146 | src: 'https://via.placeholder.com/48', 147 | size: 32 148 | } 149 | } 150 | }) 151 | expect(vm.$el.querySelectorAll('.f-list').length).to.be.equal(1) 152 | }) 153 | it('should render three lines list item with avatar', function () { 154 | const vm = createVM(this, ` 155 | 156 | 157 | 158 | 159 | 160 | 161 | Line one
162 | Line two
163 | Line three 164 |
165 |
166 |
167 | `, { 168 | components: { 169 | FList, 170 | FListItem, 171 | FListItemAvatar, 172 | FListItemContent, 173 | FAvatar 174 | }, 175 | data() { 176 | return { 177 | src: 'https://via.placeholder.com/48', 178 | size: 32 179 | } 180 | } 181 | }) 182 | expect(vm.$el.querySelectorAll('.f-list').length).to.be.equal(1) 183 | }) 184 | }) -------------------------------------------------------------------------------- /src/components/FList/FList.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 27 | -------------------------------------------------------------------------------- /src/components/FList/FListItem.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FListItem from './FListItem.vue' 3 | import FListItemContent from './FListItemContent.vue' 4 | import FListItemAvatar from './FListItemAvatar.vue' 5 | import { createVM } from 'src/../test/helpers/utils.js' 6 | import { expect } from 'chai' 7 | 8 | describe('FListItem.vue', function () { 9 | it('should render correct contents', function () { 10 | const vm = createVM(this, ` 11 | 12 | 13 | H 14 | 15 | 16 | Hello 17 | 18 | 19 | `, { components: { FListItem, FListItemContent, FListItemAvatar }}) 20 | expect(vm.$el.querySelectorAll('.f-list-item').length).to.be.equal(1) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /src/components/FList/FListItem.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 59 | -------------------------------------------------------------------------------- /src/components/FList/FListItemAvatar.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FListItemAvatar from './FListItemAvatar.vue' 3 | import { FAvatar } from '../FAvatar' 4 | import { createVM } from 'src/../test/helpers/utils.js' 5 | import { expect } from 'chai' 6 | 7 | describe('FListItemAvatar.vue', function () { 8 | it('should render correct contents', function () { 9 | const vm = createVM(this, ` 10 | 11 | 12 | 13 | `, { components: { FListItemAvatar, FAvatar }}) 14 | expect(vm.$el.querySelectorAll('.f-list-item-avatar').length).to.be.equal(1) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /src/components/FList/FListItemAvatar.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 27 | -------------------------------------------------------------------------------- /src/components/FList/FListItemContent.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FListItemContent from './FListItemContent.vue' 3 | import { createVM } from 'src/../test/helpers/utils.js' 4 | import { expect } from 'chai' 5 | 6 | describe('FListItemContent.vue', function () { 7 | it('should render correct contents', function () { 8 | const vm = createVM(this, ` 9 | 10 | Hello 11 | 12 | `, { components: { FListItemContent }}) 13 | expect(vm.$el.querySelectorAll('.f-list-item-content').length).to.be.equal(1) 14 | }) 15 | }) 16 | -------------------------------------------------------------------------------- /src/components/FList/FListItemContent.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 23 | -------------------------------------------------------------------------------- /src/components/FList/index.js: -------------------------------------------------------------------------------- 1 | import FList from './FList' 2 | import FListItem from './FListItem' 3 | import FListItemAvatar from './FListItemAvatar' 4 | import FListItemContent from './FListItemContent' 5 | 6 | import { use, registerComponent } from '../../utils/helper' 7 | 8 | const Plugin = { 9 | install (Vue) { 10 | registerComponent(Vue, FList), 11 | registerComponent(Vue, FListItem), 12 | registerComponent(Vue, FListItemAvatar), 13 | registerComponent(Vue, FListItemContent) 14 | } 15 | } 16 | 17 | use(Plugin) 18 | 19 | export default Plugin 20 | 21 | export { 22 | FList, 23 | FListItem, 24 | FListItemAvatar, 25 | FListItemContent 26 | } 27 | -------------------------------------------------------------------------------- /src/components/FMenu/FMenu.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FMenu from './FMenu.vue' 3 | import FBtn from '../FBtn/FBtn.vue' 4 | import FList from '../FList/FList.vue' 5 | import FListItem from '../FList/FListItem.vue' 6 | import FListItemContent from '../FList/FListItemContent.vue' 7 | import { 8 | createVM 9 | } from 'src/../test/helpers/utils.js' 10 | 11 | describe('FMenu.vue', function () { 12 | it('should render correct contents', function () { 13 | const vm = createVM(this, ` 14 | 15 | Dropdown 16 | 17 | 22 | 23 | {{ item }} 24 | 25 | 26 | 27 | 28 | `, { 29 | components: { 30 | FMenu, 31 | FBtn, 32 | FList, 33 | FListItem, 34 | FListItemContent 35 | }, 36 | methods: { 37 | testMethod (index) { 38 | alert(`item: ${index}`) 39 | } 40 | } 41 | }) 42 | vm.$el.querySelector('.f-menu .f-btn span').textContent.should.eql('Dropdown') 43 | }) 44 | }) 45 | -------------------------------------------------------------------------------- /src/components/FMenu/FMenu.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 100 | -------------------------------------------------------------------------------- /src/components/FMenu/index.js: -------------------------------------------------------------------------------- 1 | import FMenu from './FMenu' 2 | 3 | import { use, registerComponent } from '../../utils/helper' 4 | 5 | const Plugin = { 6 | install (Vue) { 7 | registerComponent(Vue, FMenu) 8 | } 9 | } 10 | 11 | use(Plugin) 12 | 13 | export default Plugin 14 | 15 | export { 16 | FMenu 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FProgressLinear/FProgressLinear.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FProgressLinear from './FProgressLinear.vue' 3 | import { createVM } from 'src/../test/helpers/utils.js' 4 | import { expect } from 'chai' 5 | 6 | describe('FProgressLinear.vue', function () { 7 | it('should render correct contents', function () { 8 | const vm = createVM(this, ` 9 | 10 | `, 11 | { 12 | components: { 13 | FProgressLinear 14 | }, 15 | data () { 16 | return { 17 | value: 20 18 | } 19 | } 20 | } 21 | ) 22 | expect(vm.$el.querySelectorAll('.f-progress-linear').length).to.be.equal(1) 23 | }) 24 | it('should render progress linear with buffered at 50%', function () { 25 | const vm = createVM(this, ` 26 | 27 | `, 28 | { 29 | components: { 30 | FProgressLinear 31 | }, 32 | data () { 33 | return { 34 | value: 20, 35 | buffered: 50 36 | } 37 | } 38 | } 39 | ) 40 | expect(vm.$el.querySelectorAll('.f-progress-linear').length).to.be.equal(1) 41 | }) 42 | it('should render progress linear as indeterminated with altered height', function () { 43 | const vm = createVM(this, ` 44 | 45 | `, 46 | { 47 | components: { 48 | FProgressLinear 49 | }, 50 | data () { 51 | return { 52 | value: 0 53 | } 54 | } 55 | } 56 | ) 57 | expect(vm.$el.querySelectorAll('.f-progress-linear').length).to.be.equal(1) 58 | }) 59 | }) 60 | -------------------------------------------------------------------------------- /src/components/FProgressLinear/FProgressLinear.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 109 | -------------------------------------------------------------------------------- /src/components/FProgressLinear/index.js: -------------------------------------------------------------------------------- 1 | import FProgressLinear from './FProgressLinear' 2 | 3 | import { use, registerComponent } from '../../utils/helper' 4 | 5 | const Plugin = { 6 | install (Vue) { 7 | registerComponent(Vue, FProgressLinear) 8 | } 9 | } 10 | 11 | use(Plugin) 12 | 13 | export default Plugin 14 | 15 | export { 16 | FProgressLinear 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FRadio/FRadio.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FRadio from './FRadio.vue' 3 | import { 4 | createVM 5 | } from 'src/../test/helpers/utils.js' 6 | import { 7 | expect 8 | } from 'chai' 9 | 10 | describe('FRadio.vue', function () { 11 | it('should render normal unchecked', function () { 12 | const vm = createVM(this, ` 13 | 14 | 15 | 16 | `, { 17 | components: { 18 | FRadio 19 | }, 20 | data() { 21 | return { 22 | value: 1 23 | } 24 | } 25 | }) 26 | expect(vm.$el.querySelectorAll('.f-radio input')[0].checked).to.be.equal(true) 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /src/components/FRadio/FRadio.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 109 | -------------------------------------------------------------------------------- /src/components/FRadio/index.js: -------------------------------------------------------------------------------- 1 | import FRadio from './FRadio' 2 | 3 | import { use, registerComponent } from '../../utils/helper' 4 | 5 | const Plugin = { 6 | install (Vue) { 7 | registerComponent(Vue, FRadio) 8 | } 9 | } 10 | 11 | use(Plugin) 12 | 13 | export default Plugin 14 | 15 | export { 16 | FRadio 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FRadioGroup/FRadioGroup.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FRadioGroup from './FRadioGroup.vue' 3 | import FRadio from '../FRadio/FRadio.vue' 4 | import { 5 | createVM 6 | } from 'src/../test/helpers/utils.js' 7 | import { 8 | expect 9 | } from 'chai' 10 | 11 | describe('FRadioGroup.vue', function () { 12 | it('should render second as selected', function () { 13 | const vm = createVM(this, ` 14 |
15 | 16 | 22 | 26 | 27 |
28 | `, { 29 | components: { 30 | FRadioGroup, 31 | FRadio 32 | }, 33 | data() { 34 | return { 35 | value: 2 36 | } 37 | } 38 | }) 39 | expect(vm.$el.querySelectorAll('.f-radio input')[1].checked).to.be.equal(true) 40 | }) 41 | }) -------------------------------------------------------------------------------- /src/components/FRadioGroup/FRadioGroup.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 65 | -------------------------------------------------------------------------------- /src/components/FRadioGroup/index.js: -------------------------------------------------------------------------------- 1 | import FRadioGroup from './FRadioGroup' 2 | 3 | import { use, registerComponent } from '../../utils/helper' 4 | 5 | const Plugin = { 6 | install (Vue) { 7 | registerComponent(Vue, FRadioGroup) 8 | } 9 | } 10 | 11 | use(Plugin) 12 | 13 | export default Plugin 14 | 15 | export { 16 | FRadioGroup 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FSelect/FSelect.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FSelect from './FSelect.vue' 3 | import { createVM } from 'src/../test/helpers/utils.js' 4 | import { expect } from 'chai' 5 | 6 | describe('FSelect.vue', function () { 7 | it('should render correct contents', function () { 8 | const vm = createVM( 9 | this, 10 | '', 11 | { 12 | components: { 13 | FSelect 14 | }, 15 | data () { 16 | return { 17 | itemsArrayOfString: ['Hello', 'Nice', 'To', 'Meet', 'You'] 18 | } 19 | } 20 | } 21 | ) 22 | 23 | expect(vm.$el.querySelectorAll('.f-select select').length).to.be.equal(1) 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /src/components/FSelect/FSelect.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 46 | -------------------------------------------------------------------------------- /src/components/FSelect/index.js: -------------------------------------------------------------------------------- 1 | import FSelect from './FSelect' 2 | 3 | import { use, registerComponent } from '../../utils/helper' 4 | 5 | const Plugin = { 6 | install (Vue) { 7 | registerComponent(Vue, FSelect) 8 | } 9 | } 10 | 11 | use(Plugin) 12 | 13 | export default Plugin 14 | 15 | export { 16 | FSelect 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FSlider/FSlider.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FSlider from './FSlider.vue' 3 | import { 4 | createVM 5 | } from 'src/../test/helpers/utils.js' 6 | import { 7 | expect 8 | } from 'chai' 9 | 10 | describe('FSlider.vue', function () { 11 | it('should render correct contents', function () { 12 | const vm = createVM(this, ` 13 | 14 | `, { 15 | components: { 16 | FSlider 17 | }, 18 | data() { 19 | return { 20 | value: 300 21 | } 22 | } 23 | }) 24 | expect(vm.$el.querySelectorAll('.f-slider').length).to.be.equal(1) 25 | }) 26 | it('should render slider as vertical', function () { 27 | const vm = createVM(this, ` 28 | 29 | `, { 30 | components: { 31 | FSlider 32 | }, 33 | data() { 34 | return { 35 | value: 300 36 | } 37 | } 38 | }) 39 | expect(vm.$el.querySelectorAll('.f-slider').length).to.be.equal(1) 40 | }) 41 | }) -------------------------------------------------------------------------------- /src/components/FSlider/FSlider.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 162 | -------------------------------------------------------------------------------- /src/components/FSlider/index.js: -------------------------------------------------------------------------------- 1 | import FSlider from './FSlider' 2 | 3 | import { use, registerComponent } from '../../utils/helper' 4 | 5 | const Plugin = { 6 | install (Vue) { 7 | registerComponent(Vue, FSlider) 8 | } 9 | } 10 | 11 | use(Plugin) 12 | 13 | export default Plugin 14 | 15 | export { 16 | FSlider 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FSwitch/FSwitch.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FSwitch from './FSwitch.vue' 3 | import { 4 | createVM 5 | } from 'src/../test/helpers/utils.js' 6 | import { 7 | expect 8 | } from 'chai' 9 | 10 | describe('FSwitch.vue', function () { 11 | it('should render normal unchecked', function () { 12 | const vm = createVM(this, ` 13 | 14 | `, { 15 | components: { 16 | FSwitch 17 | }, 18 | data() { 19 | return { 20 | value: true 21 | } 22 | } 23 | }) 24 | expect(vm.$el.querySelectorAll('.f-switch input')[0].checked).to.be.equal(false) 25 | }) 26 | it('should render normal checked', function () { 27 | const vm = createVM(this, ` 28 | 29 | `, { 30 | components: { 31 | FSwitch 32 | }, 33 | data() { 34 | return { 35 | value: true 36 | } 37 | } 38 | }) 39 | expect(vm.$el.querySelectorAll('.f-switch input')[0].checked).to.be.equal(true) 40 | }) 41 | it('should render normal indeterminate', function () { 42 | const vm = createVM(this, ` 43 | 44 | `, { 45 | components: { 46 | FSwitch 47 | }, 48 | data() { 49 | return { 50 | value: true 51 | } 52 | } 53 | }) 54 | expect(vm.$el.querySelectorAll('.f-switch input')[0].indeterminate).to.be.equal(true) 55 | }) 56 | }) -------------------------------------------------------------------------------- /src/components/FSwitch/FSwitch.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 93 | -------------------------------------------------------------------------------- /src/components/FSwitch/index.js: -------------------------------------------------------------------------------- 1 | import FSwitch from './FSwitch' 2 | 3 | import { use, registerComponent } from '../../utils/helper' 4 | 5 | const Plugin = { 6 | install (Vue) { 7 | registerComponent(Vue, FSwitch) 8 | } 9 | } 10 | 11 | use(Plugin) 12 | 13 | export default Plugin 14 | 15 | export { 16 | FSwitch 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FTextarea/FTextarea.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import FTextarea from './FTextarea.vue' 3 | import { 4 | createVM 5 | } from 'src/../test/helpers/utils.js' 6 | import { 7 | expect 8 | } from 'chai' 9 | 10 | describe('FTextarea.vue', function () { 11 | it('should render correct contents', function () { 12 | const vm = createVM(this, ` 13 | Empty 14 | 15 |
16 |
17 | Has value 18 | 19 |
20 |
21 | Has label 22 | 23 | `, { 24 | components: { 25 | FTextarea 26 | }, 27 | data() { 28 | return { 29 | value: 'Yes it have' 30 | } 31 | } 32 | }) 33 | expect(vm.$el.querySelectorAll('.f-textarea textarea')[0].value.length).to.be.equal(0) 34 | expect(vm.$el.querySelectorAll('.f-textarea textarea')[1].value.length).to.be.equal(11) 35 | }) 36 | }) -------------------------------------------------------------------------------- /src/components/FTextarea/FTextarea.vue: -------------------------------------------------------------------------------- 1 |