├── .babelrc ├── .editorconfig ├── .eslintrc ├── .githooks └── pre-commit ├── .github └── workflows │ └── test.yml ├── .gitignore ├── .lintstagedrc.json ├── .prettierrc ├── demo ├── index.html └── index.js ├── index.d.ts ├── index.html ├── package-lock.json ├── package.json ├── readme.md ├── rollup.config.js ├── src ├── VueCell.vue ├── VueGrid.vue └── index.js └── test └── index.spec.js /.babelrc: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "presets": [ 4 | ["@babel/preset-env", { 5 | "modules": false 6 | }] 7 | ], 8 | "env": { 9 | "test": { 10 | "presets": [ 11 | ["@babel/preset-env", { 12 | "targets": { 13 | "node": "current" 14 | } 15 | }] 16 | ] 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "plugin:vue/recommended" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.githooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | npx lint-staged 3 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | on: 3 | - pull_request 4 | - push 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | node-version: 11 | - 16 12 | steps: 13 | - uses: actions/checkout@v2 14 | - uses: actions/setup-node@v2 15 | with: 16 | node-version: ${{ matrix.node-version }} 17 | - run: npm install 18 | - run: npm test 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "*.vue|js": [ 3 | "eslint --fix", 4 | "prettier --write", 5 | "git add" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true, 4 | "trailingComma": "none" 5 | } 6 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | vue-grd demo 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

demo

14 |
15 | <vue-grid 16 | 21 | > 26 |
27 | 28 | 29 | 30 |
31 | </vue-grid> 32 | 33 | 34 |
35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /demo/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'https://cdn.jsdelivr.net/npm/vue/dist/vue.esm.browser.js'; 2 | import VueGrd from 'https://cdn.jsdelivr.net/npm/vue-grd/dist/vue-grd.esm.js'; 3 | 4 | Vue.use(VueGrd); 5 | Vue.component('vue-cell-ex', { 6 | data() { 7 | return { 8 | selectedWidth: '3of12', 9 | widths: [ 10 | 'fill', 11 | '1of12', 12 | '2of12', 13 | '3of12', 14 | '4of12', 15 | '5of12', 16 | '6of12', 17 | '7of12', 18 | '8of12', 19 | '9of12', 20 | '10of12', 21 | '11of12', 22 | '12of12' 23 | ] 24 | }; 25 | }, 26 | mounted() { 27 | this.$refs.select.selectedIndex = 3; 28 | }, 29 | methods: { 30 | onChange(e) { 31 | this.selectedWidth = e.target.value; 32 | } 33 | }, 34 | template: ` 35 | 38 | <vue-cell 39 | > 44 |

(click to edit)

45 | </vue-cell> 46 |
47 | ` 48 | }); 49 | 50 | new Vue({ 51 | el: '#app', 52 | data() { 53 | return { 54 | selectedAlign: 'top', 55 | selectedJustify: 'start', 56 | aligns: ['top', 'middle', 'bottom', 'stretch', 'baseline'], 57 | justifies: ['start', 'center', 'end', 'between', 'around'], 58 | cells: [null, null] 59 | }; 60 | }, 61 | methods: { 62 | onChangeAlign(e) { 63 | this.selectedAlign = e.target.value; 64 | }, 65 | onChangeJustify(e) { 66 | this.selectedJustify = e.target.value; 67 | }, 68 | onClickAdd() { 69 | this.cells.push(null); 70 | }, 71 | onClickRemove() { 72 | this.cells.pop(); 73 | } 74 | } 75 | }); 76 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | import { PluginFunction } from 'vue'; 2 | 3 | type AlignValue = 4 | 'top' | 5 | 'middle' | 6 | 'bottom' | 7 | 'stretch' | 8 | 'baseline'; 9 | 10 | type JustifyValue = 11 | 'start' | 12 | 'center' | 13 | 'end' | 14 | 'between' | 15 | 'around'; 16 | 17 | type WidthValue = 18 | 'fill' | 19 | '1of12' | 20 | '2of12' | 21 | '3of12' | 22 | '4of12' | 23 | '5of12' | 24 | '6of12' | 25 | '7of12' | 26 | '8of12' | 27 | '9of12' | 28 | '10of12' | 29 | '11of12' | 30 | '12of12'; 31 | 32 | export interface VueGrdOptions {} 33 | 34 | export class VueGrid { 35 | tag: string; 36 | align: AlignValue; 37 | justify: JustifyValue; 38 | readonly computedAlign: string; 39 | readonly computedJustify: string; 40 | } 41 | 42 | export class VueCell { 43 | tag: string; 44 | width: WidthValue; 45 | readonly computedWidth: string; 46 | } 47 | 48 | declare const installer: { 49 | install: PluginFunction; 50 | }; 51 | 52 | export default installer; 53 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | vue-grd: Simple, Light-weight and Flexible Vue.js component for grid layout 6 | 7 | 8 | 9 | 10 | 11 | 12 | 26 | 27 | 28 | 29 | GitHub 30 | 31 | 32 | # vue-grd ![test](https://github.com/1000ch/vue-grd/workflows/test/badge.svg?branch=main) 33 | 34 | Simple, Light-weight and Flexible Vue.js component for grid layout. Vue.js port of [grd](https://github.com/1000ch/grd). 35 | 36 | ## Install 37 | 38 | ```sh 39 | npm install --save vue-grd 40 | ``` 41 | 42 | ## Usage 43 | 44 | You can use `` and `` components after importing and registering `VueGrid` and `VueCell`. 45 | 46 | ```html 47 | 54 | 55 | 65 | ``` 66 | 67 | You can also register them as global components. 68 | 69 | ```javascript 70 | import Vue from 'vue'; 71 | import { VueGrid, VueCell } from 'vue-grd'; 72 | 73 | Vue.component('vue-grid', VueGrid); 74 | Vue.component('vue-cell', VueCell); 75 | ``` 76 | 77 | ### `` modifiers 78 | 79 | | `tag` | description | 80 | |---|---| 81 | | [HTMLElement name](https://html.spec.whatwg.org/multipage/#toc-semantics) | Specify grid's tag name | 82 | 83 | | `align` | description | 84 | |---|---| 85 | | `top` | Pull items to top | 86 | | `middle` | Pull items to middle | 87 | | `bottom` | Pull items to bottom | 88 | | `stretch` | Stretch items | 89 | | `baseline` | Pull items to baseline | 90 | 91 | | `justify` | description | 92 | |---|---| 93 | | `start` | Layout items to start | 94 | | `center` | Layout items to center | 95 | | `end` | Layout items to end | 96 | | `between` | Add spaces between items | 97 | | `around` | Add spaces around items | 98 | 99 | ### `` modifiers 100 | 101 | | `tag` | description | 102 | |---|---| 103 | | [HTMLElement name](https://html.spec.whatwg.org/multipage/#toc-semantics) | Specify cell's tag name | 104 | 105 | | `width` | description | 106 | |---|---| 107 | | `fill` | Set item width to left | 108 | | `1of12` | Set item width to 8.3% | 109 | | `2of12` | Set item width to 16.7% | 110 | | `3of12` | Set item width to 25% | 111 | | `4of12` | Set item width to 33% | 112 | | `5of12` | Set item width to 41.7% | 113 | | `6of12` | Set item width to 50% | 114 | | `7of12` | Set item width to 58.3% | 115 | | `8of12` | Set item width to 66.7% | 116 | | `9of12` | Set item width to 75% | 117 | | `10of12` | Set item width to 83.3% | 118 | | `11of12` | Set item width to 91.7% | 119 | | `12of12` | Set item width to 100% | 120 | 121 | ## License 122 | 123 | [MIT](https://1000ch.mit-license.org) © [Shogo Sensui](https://github.com/1000ch) 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-grd", 3 | "version": "1.3.0", 4 | "description": "Simple, Light-weight and Flexible Vue.js component for grid layout.", 5 | "scripts": { 6 | "prepare": "git config --local core.hooksPath .githooks", 7 | "prepublish": "npm run build", 8 | "pretest": "eslint src --ext .js", 9 | "test": "jest", 10 | "build": "rollup -c rollup.config.js" 11 | }, 12 | "main": "dist/vue-grd.common.js", 13 | "module": "dist/vue-grd.esm.js", 14 | "browser": "dist/vue-grd.js", 15 | "jest": { 16 | "testEnvironment": "jsdom", 17 | "testRegex": "/test/.+\\.spec\\.js$", 18 | "moduleFileExtensions": [ 19 | "js", 20 | "vue" 21 | ], 22 | "transform": { 23 | ".*\\.(js)$": "babel-jest", 24 | ".*\\.(vue)$": "vue-jest" 25 | } 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "git+ssh://git@github.com/1000ch/vue-grd.git" 30 | }, 31 | "keywords": [ 32 | "vue" 33 | ], 34 | "author": "1000ch", 35 | "license": "MIT", 36 | "bugs": { 37 | "url": "https://github.com/1000ch/vue-grd/issues" 38 | }, 39 | "homepage": "https://github.com/1000ch/vue-grd#readme", 40 | "devDependencies": { 41 | "@babel/preset-env": "^7.16.4", 42 | "@rollup/plugin-babel": "^5.3.0", 43 | "@rollup/plugin-commonjs": "^21.0.1", 44 | "@rollup/plugin-node-resolve": "^13.0.6", 45 | "@vue/test-utils": "^1.3.0", 46 | "babel-core": "^7.0.0-bridge.0", 47 | "babel-jest": "^27.3.1", 48 | "babel-loader": "^8.2.3", 49 | "eslint": "^8.3.0", 50 | "eslint-plugin-vue": "^8.1.1", 51 | "jest": "^27.3.1", 52 | "prettier": "^2.5.0", 53 | "rollup": "^2.16.0", 54 | "rollup-plugin-terser": "^7.0.2", 55 | "rollup-plugin-vue": "^5.1.9", 56 | "vue": "^2.6.14", 57 | "vue-jest": "^3.0.7", 58 | "vue-template-compiler": "^2.6.14" 59 | }, 60 | "peerDependencies": { 61 | "vue": "^2.0.0" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # vue-grd ![test](https://github.com/1000ch/vue-grd/workflows/test/badge.svg?branch=main) 2 | 3 | > Simple, Light-weight and Flexible Vue.js component for grid layout. Vue.js port of [grd](https://github.com/1000ch/grd). 4 | 5 | ## Install 6 | 7 | ```sh 8 | npm install --save vue-grd 9 | ``` 10 | 11 | ## Usage 12 | 13 | You can use `` and `` components after importing and registering `VueGrid` and `VueCell`. 14 | 15 | ```html 16 | 23 | 24 | 34 | ``` 35 | 36 | You can also register them as global components. 37 | 38 | ```javascript 39 | import Vue from 'vue'; 40 | import { VueGrid, VueCell } from 'vue-grd'; 41 | 42 | Vue.component('vue-grid', VueGrid); 43 | Vue.component('vue-cell', VueCell); 44 | ``` 45 | 46 | ### `` modifiers 47 | 48 | | `tag` | description | 49 | |---|---| 50 | | [HTMLElement name](https://html.spec.whatwg.org/multipage/#toc-semantics) | Specify grid's tag name | 51 | 52 | | `align` | description | 53 | |---|---| 54 | | `top` | Pull items to top | 55 | | `middle` | Pull items to middle | 56 | | `bottom` | Pull items to bottom | 57 | | `stretch` | Stretch items | 58 | | `baseline` | Pull items to baseline | 59 | 60 | | `justify` | description | 61 | |---|---| 62 | | `start` | Layout items to start | 63 | | `center` | Layout items to center | 64 | | `end` | Layout items to end | 65 | | `between` | Add spaces between items | 66 | | `around` | Add spaces around items | 67 | 68 | ### `` modifiers 69 | 70 | | `tag` | description | 71 | |---|---| 72 | | [HTMLElement name](https://html.spec.whatwg.org/multipage/#toc-semantics) | Specify cell's tag name | 73 | 74 | | `width` | description | 75 | |---|---| 76 | | `fill` | Set item width to left | 77 | | `1of12` | Set item width to 8.3% | 78 | | `2of12` | Set item width to 16.7% | 79 | | `3of12` | Set item width to 25% | 80 | | `4of12` | Set item width to 33% | 81 | | `5of12` | Set item width to 41.7% | 82 | | `6of12` | Set item width to 50% | 83 | | `7of12` | Set item width to 58.3% | 84 | | `8of12` | Set item width to 66.7% | 85 | | `9of12` | Set item width to 75% | 86 | | `10of12` | Set item width to 83.3% | 87 | | `11of12` | Set item width to 91.7% | 88 | | `12of12` | Set item width to 100% | 89 | 90 | ## License 91 | 92 | [MIT](https://1000ch.mit-license.org) © [Shogo Sensui](https://github.com/1000ch) 93 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import pkg from './package.json'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import nodeResolve from '@rollup/plugin-node-resolve'; 4 | import babel from '@rollup/plugin-babel'; 5 | import vue from 'rollup-plugin-vue'; 6 | import { terser } from 'rollup-plugin-terser'; 7 | 8 | export default { 9 | input: 'src/index.js', 10 | output: [ 11 | { 12 | file: `dist/${pkg.name}.common.js`, 13 | format: 'cjs' 14 | }, 15 | { 16 | file: `dist/${pkg.name}.esm.js`, 17 | format: 'esm' 18 | }, 19 | { 20 | file: `dist/${pkg.name}.js`, 21 | format: 'umd', 22 | name: 'VueGrd' 23 | } 24 | ], 25 | plugins: [ 26 | nodeResolve(), 27 | commonjs(), 28 | vue({ 29 | css: true 30 | }), 31 | babel({ 32 | extensions: ['.js', '.vue'] 33 | }), 34 | terser() 35 | ] 36 | }; 37 | -------------------------------------------------------------------------------- /src/VueCell.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 44 | 45 | 105 | -------------------------------------------------------------------------------- /src/VueGrid.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 44 | 45 | 91 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import VueGrid from './VueGrid.vue'; 2 | import VueCell from './VueCell.vue'; 3 | 4 | function install(Vue, options) { 5 | Vue.component('vue-grid', VueGrid); 6 | Vue.component('vue-cell', VueCell); 7 | } 8 | 9 | export default { 10 | install, 11 | VueGrid, 12 | VueCell 13 | }; 14 | -------------------------------------------------------------------------------- /test/index.spec.js: -------------------------------------------------------------------------------- 1 | import { mount, createLocalVue } from '@vue/test-utils'; 2 | import VueGrd from '../src'; 3 | 4 | describe('VueGrd', () => { 5 | test('works with Vue.use()', () => { 6 | const localVue = createLocalVue(); 7 | localVue.use(VueGrd); 8 | 9 | const grid = mount( 10 | { 11 | template: `` 12 | }, 13 | { localVue } 14 | ); 15 | 16 | const cell = mount( 17 | { 18 | template: `` 19 | }, 20 | { localVue } 21 | ); 22 | 23 | expect(grid.html()).toEqual('
'); 24 | expect(cell.html()).toEqual('
'); 25 | }); 26 | 27 | test('works with Vue.component()', () => { 28 | const localVue = createLocalVue(); 29 | const { VueGrid, VueCell } = VueGrd; 30 | localVue.component('vue-grid', VueGrid); 31 | localVue.component('vue-cell', VueCell); 32 | 33 | const grid = mount( 34 | { 35 | template: `` 36 | }, 37 | { localVue } 38 | ); 39 | 40 | const cell = mount( 41 | { 42 | template: `` 43 | }, 44 | { localVue } 45 | ); 46 | 47 | expect(grid.html()).toEqual('
'); 48 | expect(cell.html()).toEqual('
'); 49 | }); 50 | }); 51 | 52 | describe('VueGrid', () => { 53 | test('has classes depending on provided properties', () => { 54 | const localVue = createLocalVue(); 55 | localVue.use(VueGrd); 56 | 57 | const grid1 = mount( 58 | { 59 | template: `` 60 | }, 61 | { localVue } 62 | ); 63 | 64 | const grid2 = mount( 65 | { 66 | template: `` 67 | }, 68 | { localVue } 69 | ); 70 | 71 | const grid3 = mount( 72 | { 73 | template: `` 74 | }, 75 | { localVue } 76 | ); 77 | 78 | expect(grid1.html()).toEqual('

'); 79 | expect(grid2.html()).toEqual('
'); 80 | expect(grid3.html()).toEqual( 81 | '
' 82 | ); 83 | }); 84 | }); 85 | 86 | describe('VueCell', () => { 87 | test('has classes depending on provided properties', () => { 88 | const localVue = createLocalVue(); 89 | localVue.use(VueGrd); 90 | 91 | const cell1 = mount( 92 | { 93 | template: `` 94 | }, 95 | { localVue } 96 | ); 97 | 98 | const cell2 = mount( 99 | { 100 | template: `` 101 | }, 102 | { localVue } 103 | ); 104 | 105 | expect(cell1.html()).toEqual('

'); 106 | expect(cell2.html()).toEqual('
'); 107 | }); 108 | }); 109 | --------------------------------------------------------------------------------