├── .editorconfig ├── .env.lib ├── .eslintignore ├── .eslintrc.js ├── .github └── FUNDING.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── app ├── App.vue ├── assets │ └── img │ │ ├── codesandbox.svg │ │ ├── github.svg │ │ └── jsfiddle.svg ├── components │ ├── CodeBlock.vue │ ├── DraggableGrid.vue │ └── ShopifyDraggable.Vue ├── constant │ └── template.js ├── main.js ├── router │ └── index.js └── views │ ├── WidgetOnly.vue │ ├── WidgetWithGrid.vue │ └── index.vue ├── babel.config.js ├── docs ├── favicon.ico ├── fonts │ ├── element-icons.535877f5.woff │ └── element-icons.732389de.ttf ├── img │ ├── codesandbox.53fab8db.svg │ └── github.ea8bb7f4.svg ├── index.html └── js │ ├── chunk-vendors.b4dc3d00.js │ └── index.c253a547.js ├── lib ├── demo.html ├── vue-smart-widget.common.js ├── vue-smart-widget.umd.js └── vue-smart-widget.umd.min.js ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── components │ ├── LoadingMask.vue │ └── collapse-transition.js ├── index.js ├── packages │ ├── SmartWidget.vue │ └── SmartWidgetGrid.vue └── utils │ └── index.js ├── vetur ├── attributes.json └── tags.json └── vue.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /.env.lib: -------------------------------------------------------------------------------- 1 | NODE_ENV=production 2 | VUE_APP_BUILD_MODE=lib 3 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /config/ 3 | /dist/ 4 | /*.js 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/essential', 8 | '@vue/standard' 9 | ], 10 | rules: { 11 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 13 | }, 14 | parserOptions: { 15 | parser: 'babel-eslint' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [xiaoluoboding] 4 | 5 | custom: ['https://www.buymeacoffee.com/xlbd', 'https://paypal.me/xlbd'] 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | 23 | # lock file 24 | package-lock.json 25 | yarn.lock 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "10" 4 | - "8" 5 | - "6" -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.6.2](https://github.com/xiaoluoboding/vue-smart-widget/compare/v0.6.1...v0.6.2) (2022-09-19) 2 | 3 | 4 | ### Features 5 | 6 | * ✨ 調整尺寸時,colNum 會更新 ([0ac0c7b](https://github.com/xiaoluoboding/vue-smart-widget/commit/0ac0c7bcaafc60ec9c1f0bb10a53e6c7d5cbd0dd)) 7 | * ✨ 移除多餘的 div ([07eeeb4](https://github.com/xiaoluoboding/vue-smart-widget/commit/07eeeb415bbfc82a0dd0a584d357266c1270a1d8)) 8 | 9 | 10 | 11 | ## [0.6.1](https://github.com/xiaoluoboding/vue-smart-widget/compare/v0.6.0...v0.6.1) (2021-01-07) 12 | 13 | 14 | ### Bug Fixes 15 | 16 | * map grid item event params ([194a09a](https://github.com/xiaoluoboding/vue-smart-widget/commit/194a09aee31dbb3ce73ddca8d958392e429e8485)) 17 | 18 | 19 | ### Features 20 | 21 | * add vetur support in vscode ([9aa150b](https://github.com/xiaoluoboding/vue-smart-widget/commit/9aa150ba2ac1871aa98cfec7be0c3547214841fe)) 22 | 23 | 24 | 25 | # [0.6.0](https://github.com/xiaoluoboding/vue-smart-widget/compare/v0.5.5...v0.6.0) (2021-01-04) 26 | 27 | 28 | ### Bug Fixes 29 | 30 | * document.body.removeAttribute will remove the class attribute bug ([b72d725](https://github.com/xiaoluoboding/vue-smart-widget/commit/b72d7254208d4eefeebcaf6d5d21fd6c83c253e3)) 31 | * fix the bug of slot param contentH is wrong ([bcb00c0](https://github.com/xiaoluoboding/vue-smart-widget/commit/bcb00c0c267c80a5fdab4035964e1ae6efdb0e29)) 32 | * fullscreen widget contentH calculate wrong problem ([686c665](https://github.com/xiaoluoboding/vue-smart-widget/commit/686c6656bd453d2f269eb757ae054e06ddd57322)) 33 | 34 | 35 | ### Features 36 | 37 | * add loading.svg ([5b926e3](https://github.com/xiaoluoboding/vue-smart-widget/commit/5b926e31ed3f575b62383cf9606523340acb0f6b)) 38 | * add new properties & events on smart-widget-grid ([46a73c8](https://github.com/xiaoluoboding/vue-smart-widget/commit/46a73c8e28b610f13660eca71b16986341d29777)) 39 | * add new props for smart-widget-grid ([390b751](https://github.com/xiaoluoboding/vue-smart-widget/commit/390b75175d77d1f41f9a07359e23ee6ce9acd059)) 40 | * add static property on smart-widget-grid ([6e12f5d](https://github.com/xiaoluoboding/vue-smart-widget/commit/6e12f5d3e99091925b84c206c3a878c793b3c5ef)) 41 | * add the widget headerHeight property ([1bbe378](https://github.com/xiaoluoboding/vue-smart-widget/commit/1bbe378fe5b06ab95efe16bec76ceb38ab8e3ce7)) 42 | * improve the fullscreen action ([9c0e023](https://github.com/xiaoluoboding/vue-smart-widget/commit/9c0e023ac8176d9402a9b956c58bbdb33a0fb671)) 43 | * rewrite grid-layout events ([24edb1c](https://github.com/xiaoluoboding/vue-smart-widget/commit/24edb1c855fa9c36e98a3a60867e8da14148337e)) 44 | * use codesandbox instead jsfiddle ([914c0d6](https://github.com/xiaoluoboding/vue-smart-widget/commit/914c0d695d1df34f0d2d279df474dca5772fbeb4)) 45 | * use svg sprite instead svg assets ([0db4294](https://github.com/xiaoluoboding/vue-smart-widget/commit/0db4294d62fbd945baf68e893f5136514b22e13c)) 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Yunwei Xiao 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 | # vue-smart-widget 2 | 3 |

4 | 5 | 6 | 7 | 8 |

9 | 10 | > Smart widget is a flexible and extensible content container component. 11 | It includes header and body part, and widget body includes editboxcontentfooter. 12 | If you use with grid, it also have a draggable and resizable grid layout, 13 | base on Vue2.5.+ & [vue-grid-layout](https://github.com/jbaysolutions/vue-grid-layout). 14 | 15 | ## Both Support Vue 2/Vue 3 16 | 17 | [Vue 2](https://github.com/xiaoluoboding/vue-smart-widget) | [Vue 3](https://github.com/xiaoluoboding/vue-smart-widget/tree/next) 18 | 19 | ## Installation 20 | 21 | ### Vue 2 22 | 23 | ```bash 24 | npm i vue-smart-widget -S 25 | ``` 26 | 27 | ### Vue 3 28 | 29 | ```bash 30 | npm i vue-smart-widget@next -S 31 | ``` 32 | 33 | 34 | ## Import 35 | 36 | Install all the components: 37 | 38 | ```bash 39 | import Vue from 'vue' 40 | import VueSmartWidget from 'vue-smart-widget' 41 | 42 | Vue.use(VueSmartWidget) 43 | ``` 44 | 45 | Use widget only: 46 | 47 | ```bash 48 | import Vue from 'vue' 49 | import { SmartWidget } from 'vue-smart-widget' 50 | 51 | Vue.component('SmartWidget', SmartWidget) 52 | ``` 53 | 54 | ## Usage 55 | 56 | The SmartWidget is heavily base on [vue-grid-layout](https://github.com/jbaysolutions/vue-grid-layout), you can know about `vue-grid-layout` first, maybe you already use in your project. 57 | 58 | ### Use widget only 59 | 60 | **Html** 61 | 62 | ```html 63 | 64 |

65 | It's default widget. 66 |

67 |
68 | ``` 69 | 70 | ### Use widget with grid 71 | 72 | ```bash 73 | import Vue from 'vue' 74 | import { SmartWidgetGrid } from 'vue-smart-widget' 75 | 76 | Vue.component('SmartWidgetGrid', SmartWidgetGrid) 77 | ``` 78 | 79 | **Script** 80 | 81 | ```js 82 | new Vue({ 83 | data () { 84 | return { 85 | layout: [ 86 | { x: 0, y: 0, w: 4, h: 4, i: '0' }, 87 | { x: 4, y: 0, w: 4, h: 4, i: '1' }, 88 | { x: 8, y: 0, w: 4, h: 4, i: '2' } 89 | ] 90 | } 91 | } 92 | }) 93 | ``` 94 | 95 | **Html** 96 | 97 | ```html 98 | 99 | 100 |
101 |

Simple Widget Without Header

102 |
103 |
104 | 105 |
106 |

Default Widget With Header

107 |
108 |
109 | 110 |
111 |

Make any widget full screen

112 |
113 |
114 |
115 | ``` 116 | 117 | ## SmartWidget Props 118 | 119 | | Attribute | Description | Type | Accepted values | Default | 120 | |:--------:|--------|--------|:--------:|:--------:| 121 | | slot | Widget slot, the unique identifier of the widget. refer to `SmartWidgetGrid Props` | String | - | - | 122 | | title | Widget Header Title | String | - | - | 123 | | subTitle | Widget Header Sub Title | String | - | - | 124 | | padding | padding in Widget Body | [Number, Array] | - | `[12, 20]` | 125 | | simple | Widget without Header | Boolean | `true` or `false` | `false` | 126 | | loading | determine whether it's loading | Boolean | `true` or `false` | `false` | 127 | | fullscreen | determine whether have fullscreen button | Boolean | `true` or `false` | `false` | 128 | | collapse | determine whether have collapse button, only support `smart-widget` | Boolean | `true` or `false` | `false` | 129 | | refresh | determine whether have refresh button | Boolean | `true` or `false` | `false` | 130 | | fixedHeight | determine whether widget body's height is fixed, only support `smart-widget` | Boolean | `true` or `false` | `false` | 131 | | shadow | when to show card shadows | String | `always`、`hover`、`never` | `always` | 132 | | translateY | the length of vertically transform | Number | - | 0 | 133 | | isActived | determine whether widget is actived | Boolean | `true` or `false` | `false` | 134 | | activedColor | the actived widget `box-shadow` color, usually used with `isActived` attribute | String | hex color | #0076db | 135 | | headerHeight | Widget Header Height(px) | Number | - | 48 | 136 | 137 | ## SmartWidget Methods 138 | 139 | | Name | Description | Parameters | 140 | |:--------:|--------|:--------| 141 | | move | Every time an item is being moved and changes position | `(i, newX, newY)` | 142 | | moved | Every time an item is finished being moved and changes position | `(i, newX, newY)` | 143 | | resize | Every time an item is being resized and changes size | `(i, newH, newW, newHPx, newWPx)` | 144 | | resized | Every time an item is finished being moved and changes position | `(i, newH, newW, newHPx, newWPx)` | 145 | | container-resized | Every time the grid item/layout container changes size (browser window or other) | `(i, newH, newW, newHPx, newWPx)` | 146 | | on-refresh | Used when the widget need fetching data from ajax methods, usually used with `loading` attribute | - | 147 | | before-fullscreen | Used when the widget before fullscreen, usually used with `fullscreen` attribute | `true` or `false` | 148 | | on-fullscreen | Used when the widget is already fullscreen, usually used with `fullscreen` attribute | `true` or `false` | 149 | 150 | ## CSS Selector in SmartWidget 151 | 152 | | Name | Description | 153 | |:--------|--------| 154 | | `.smartwidget` | The main selector in SmartWidget | 155 | | `.is-actived` | The state of widget is actived | 156 | | `.vue-grid-item.vue-grid-placeholder` | The default css for the placeholder | 157 | 158 | ## SmartWidgetGrid Props 159 | 160 | > It's similar with [vue-grid-layout](https://github.com/jbaysolutions/vue-grid-layout). Care about the attribute `layout`, The value of layout must be an Array of Object items. Each item must have i, x, y, w and h proprties. especially, the i proprties, it's the unique identifier of the widget item, euqal with widget slot. 161 | 162 | | Attribute | Description | Type | Accepted values | Default | 163 | |:--------|--------|:--------:|:--------:|:--------:| 164 | | layout | This is the initial layout of the grid. | Array | - | `required` | 165 | | responsiveLayouts | This is the initial layouts of the grid per breakpoint if responsive is set to true. | Object | - | `{}` | 166 | | colNum | Says how many columns the grid has. | Number | - | `12` | 167 | | rowHeight | Says what is a height of a single row in pixels. | Number | - | `48` | 168 | | maxRows | Says what is a maximal number of rows in the grid. | Number | - | `Infinity` | 169 | | margin | Says what are the margins of elements inside the grid. | Array | - | `[10, 10]` | 170 | | draggable | Says if the grids items are draggable. | Boolean | `true` or `false` | `true` | 171 | | resizable | Says if the grids items are resizable. | Boolean | `true` or `false` | `true` | 172 | | isMirrored | Says if the RTL/LTR should be reversed. | Boolean | `true` or `false` | `false` | 173 | | autoSize | Says if the container height should swells and contracts to fit contents. | Boolean | `true` or `false` | `true` | 174 | | verticalCompact | Says if the layout should be compact vertically. | Boolean | `true` or `false` | `true` | 175 | | preventCollision | Says if grid items will move when being dragged over. | Boolean | `true` or `false` | `false` | 176 | | responsive | Says if the layout should be responsive to window width. | Boolean | `true` or `false` | `false` | 177 | | breakpoints | Breakpoints defined for responsive layout. Sets widths on wich column number changes. | Object | - | `{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }` | 178 | | cols | Defines number of columns for each breakpoint. | Object | - | `{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }` | 179 | | isStatic | Control all widgets won't be draggable, resizable or moved | Boolean | `true` or `false` | `false` | 180 | 181 | ## Slot scopes 182 | 183 | > Each widget in the grid is resizable, `slot-scope` provide the widget attribute to the children component. 184 | 185 | | Name | Description | Type | 186 | |:--------|:--------|:--------:| 187 | | contentH | Provide the widget body content(`widget-body__content`) height | Number | 188 | 189 | ## SmartWidgetGrid Methods 190 | 191 | | Name | Description | Parameters | 192 | |:--------|:--------|:--------:| 193 | | layout-created | Emited on the component created lifecycle hook | `newLayout` | 194 | | layout-before-mount | Emited on the component beforeMount lifecycle hook | `newLayout` | 195 | | layout-mounted | Emited on the component mounted lifecycle hook | `newLayout` | 196 | | layout-ready | Emited when all the operations on the mount hook finish | `newLayout` | 197 | | layout-updated | Every time the layout has finished updating and positions of all grid-items are recalculated | `newLayout` | 198 | | breakpoint-changed | Every time the breakpoint value changes due to window resize | `(newBreakpoint, newLayout)` | 199 | 200 | ## License 201 | 202 | MIT [@xiaoluoboding](https://github.com/xiaoluoboding) 203 | -------------------------------------------------------------------------------- /app/App.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 45 | 46 | 145 | -------------------------------------------------------------------------------- /app/assets/img/codesandbox.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/img/github.svg: -------------------------------------------------------------------------------- 1 | GitHub icon -------------------------------------------------------------------------------- /app/assets/img/jsfiddle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | JSFiddle icon 9 | 10 | 17 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/components/CodeBlock.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 49 | 50 | 62 | -------------------------------------------------------------------------------- /app/components/DraggableGrid.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 64 | 65 | 73 | -------------------------------------------------------------------------------- /app/components/ShopifyDraggable.Vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | 77 | 78 | 172 | -------------------------------------------------------------------------------- /app/constant/template.js: -------------------------------------------------------------------------------- 1 | const placeholder = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam deleniti fugit incidunt, iste, itaque minima neque pariatur perferendis sed suscipit velit vitae voluptatem. A consequuntur, deserunt eaque error nulla temporibus!' 2 | 3 | const defaultWidget = ` 4 |

5 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. 6 | Aperiam deleniti fugit incidunt, iste, itaque minima neque pariatur perferendis sed suscipit velit vitae voluptatem. 7 | A consequuntur, deserunt eaque error nulla temporibus! 8 |

9 |
10 | ` 11 | 12 | const advanedWidget = ` 13 | 14 |

15 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. 16 | Aperiam deleniti fugit incidunt, iste, itaque minima neque pariatur perferendis sed suscipit velit vitae voluptatem. 17 | A consequuntur, deserunt eaque error nulla temporibus! 18 |

19 |
20 | 21 | 22 | 23 | 30 |

I am content

31 | 38 |
39 | 40 | 41 | 42 | 47 |

48 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. 49 | Aperiam deleniti fugit incidunt, iste, itaque minima neque pariatur perferendis sed suscipit velit vitae voluptatem. 50 | A consequuntur, deserunt eaque error nulla temporibus! 51 |

52 |
53 | ` 54 | 55 | const widgetWithGridHTML = ` 56 | 57 | 58 |
59 |

Simple Widget

60 |
61 |
62 | 63 |
64 |

Widget with Header

65 |
66 |
67 | 68 |
69 |

Make any widget full screen

70 |
71 |
72 |
73 | ` 74 | 75 | const widgetWithGridJS = ` 76 | new Vue({ 77 | data () { 78 | return { 79 | layout: [ 80 | { x: 0, y: 0, w: 4, h: 4, i: '0' }, 81 | { x: 4, y: 0, w: 4, h: 4, i: '1' }, 82 | { x: 8, y: 0, w: 4, h: 4, i: '2' } 83 | ] 84 | } 85 | } 86 | }) 87 | ` 88 | 89 | export { 90 | placeholder, 91 | defaultWidget, 92 | advanedWidget, 93 | widgetWithGridHTML, 94 | widgetWithGridJS 95 | } 96 | -------------------------------------------------------------------------------- /app/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import ElementUI from 'element-ui' 3 | import 'element-ui/lib/theme-chalk/index.css' 4 | import router from './router' 5 | import App from './App.vue' 6 | 7 | import { SmartWidget, SmartWidgetGrid } from '../src/index' // 调试开发 8 | // import { SmartWidget, SmartWidgetGrid } from '../lib/vue-smart-widget.min.js' // 调试线上 9 | // import '../lib/vue-smart-widget.css' 10 | 11 | import VeChart from 've-charts' 12 | 13 | import VTooltip from 'v-tooltip' 14 | 15 | Vue.use(VTooltip) 16 | 17 | Vue.component('SmartWidget', SmartWidget) 18 | Vue.component('SmartWidgetGrid', SmartWidgetGrid) 19 | 20 | Vue.use(VeChart) 21 | 22 | Vue.use(ElementUI, { 23 | size: 'small' 24 | }) 25 | 26 | Vue.config.productionTip = false 27 | 28 | new Vue({ 29 | router, 30 | render: h => h(App) 31 | }).$mount('#app') 32 | -------------------------------------------------------------------------------- /app/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import HomeIndex from '@/views/index' 4 | import WidgetOnly from '@/views/WidgetOnly' 5 | import WidgetWithGrid from '@/views/WidgetWithGrid' 6 | 7 | Vue.use(Router) 8 | 9 | export default new Router({ 10 | routes: [ 11 | { 12 | path: '/', 13 | redirect: '/home' 14 | }, 15 | { 16 | path: '/home', 17 | name: 'home', 18 | component: HomeIndex 19 | }, 20 | { 21 | path: '/widget-only', 22 | name: 'widget-only', 23 | component: WidgetOnly 24 | }, 25 | { 26 | path: '/widget-with-grid', 27 | name: 'WidgetWithGrid', 28 | component: WidgetWithGrid 29 | } 30 | ] 31 | }) 32 | -------------------------------------------------------------------------------- /app/views/WidgetOnly.vue: -------------------------------------------------------------------------------- 1 | 116 | 117 | 224 | 225 | 227 | -------------------------------------------------------------------------------- /app/views/WidgetWithGrid.vue: -------------------------------------------------------------------------------- 1 | 114 | 115 | 222 | 223 | 236 | -------------------------------------------------------------------------------- /app/views/index.vue: -------------------------------------------------------------------------------- 1 | 136 | 137 | 185 | 186 | 362 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | "@vue/cli-plugin-babel/preset" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoluoboding/vue-smart-widget/a34ab05922c539cf0710693d4496ca6c73f4b4d2/docs/favicon.ico -------------------------------------------------------------------------------- /docs/fonts/element-icons.535877f5.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoluoboding/vue-smart-widget/a34ab05922c539cf0710693d4496ca6c73f4b4d2/docs/fonts/element-icons.535877f5.woff -------------------------------------------------------------------------------- /docs/fonts/element-icons.732389de.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoluoboding/vue-smart-widget/a34ab05922c539cf0710693d4496ca6c73f4b4d2/docs/fonts/element-icons.732389de.ttf -------------------------------------------------------------------------------- /docs/img/codesandbox.53fab8db.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/img/github.ea8bb7f4.svg: -------------------------------------------------------------------------------- 1 | GitHub icon -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | vue-smart-widget
-------------------------------------------------------------------------------- /docs/js/index.c253a547.js: -------------------------------------------------------------------------------- 1 | (function(t){function e(e){for(var i,r,n=e[0],l=e[1],d=e[2],p=0,u=[];p-1}function s(t,e){if(!t)return;let a=t.className;const i=(e||"").split(" ");for(let s=0,r=i.length;s.el-menu-item.is-active{border-bottom-color:#40b883}.app-container .app-header{display:-webkit-box;display:-ms-flexbox;display:flex;position:fixed;top:0;overflow:hidden;width:100%;color:#333;text-align:center;line-height:60px;z-index:3;background:#fff;border-bottom:1px solid #ebeef5}.app-container .app-header h1{color:#40b883;margin:0;padding:0;text-align:left}.app-container .app-header a{text-decoration:none}.app-container .app-header .app-menu,.app-container .app-header .el-menu.el-menu--horizontal{border-bottom:none}.app-container .app-header .open-in-github{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.app-container .app-header .open-in-github a{padding:10px;color:#fff}.app-container .app-header .open-in-github a img{width:32px;height:32px}.app-container .sub-container{margin:0 auto}.app-container .sub-container.sub-header{padding:0 20px}.app-container .sub-container.sub-content{position:relative;width:100%;top:60px}.app-container .app-main{padding:5px}@media (min-width:576px){.sub-container{max-width:540px}}@media (min-width:768px){.sub-container{max-width:720px}}@media (min-width:992px){.sub-container{max-width:960px}}@media (min-width:1280px){.sub-container{max-width:1200px}}",""]),t.exports=e},f161:function(t,e,a){"use strict";a.r(e);var i=a("2b0e"),o=a("5c96"),s=a.n(o),r=(a("0fae"),a("8c4f")),n=function(){var t=this,e=t._self._c;return e("div",{staticClass:"document"},[t._m(0),e("section",{staticClass:"example-wrap"},[e("h3",[t._v("Default Widget")]),e("div",{staticClass:"example-bg"},[e("el-row",{attrs:{type:"flex",gutter:32}},[e("el-col",{attrs:{offset:8,span:8}},[e("smart-widget",{attrs:{title:"Widget Title"}},[e("p",[t._v(t._s(t.placeholder))])])],1)],1)],1),e("div",{staticClass:"example-code"},[e("div",{staticClass:"example-link"},[e("a",{attrs:{href:t.defaultUrl,target:"_blank"}},[e("img",{directives:[{name:"tooltip",rawName:"v-tooltip",value:t.tooltipOptions,expression:"tooltipOptions"}],attrs:{src:t.codesandboxIcon,alt:"View On CodeSandbox"}})])]),e("code-block",{attrs:{lang:"html",sourcecode:t.defaultWidget}})],1)]),e("section",{staticClass:"example-wrap"},[e("h3",[t._v("Advanced Widget")]),t._m(1),e("div",{staticClass:"example-bg"},[e("el-row",{attrs:{type:"flex",gutter:32}},[e("el-col",{attrs:{span:8}},[e("smart-widget",{attrs:{title:"With additional fullscreen button",fullscreen:""}},[e("p",[t._v(t._s(t.placeholder))])])],1),e("el-col",{attrs:{span:8}},[e("smart-widget",{attrs:{title:"Widget with Editbox & Footer"}},[e("template",{slot:"editbox"},[e("div",{staticClass:"widget-alert"},[e("div",{staticClass:"widget-alert__content"},[e("span",{staticClass:"el-alert__title"},[t._v("I am Editbox slot")])])])]),e("p",[t._v("I am content")]),e("template",{slot:"footer"},[e("div",{staticClass:"widget-alert"},[e("div",{staticClass:"widget-alert__content"},[e("span",{staticClass:"el-alert__title"},[t._v("I am Footer slot")])])])])],2)],1),e("el-col",{attrs:{span:8}},[e("smart-widget",{attrs:{title:"Widget with custom toolbar"}},[e("template",{slot:"toolbar"},[e("div",{staticStyle:{margin:"0 12px"}},[e("button",{staticClass:"widget-button"},[t._v("Action")])])]),e("p",[t._v(t._s(t.placeholder))])],2)],1)],1)],1),e("div",{staticClass:"example-code"},[e("div",{staticClass:"example-link"},[e("a",{attrs:{href:t.advanedUrl,target:"_blank"}},[e("img",{directives:[{name:"tooltip",rawName:"v-tooltip",value:t.tooltipOptions,expression:"tooltipOptions"}],attrs:{src:t.codesandboxIcon,alt:"View On Jsfiddle"}})])]),e("code-block",{attrs:{lang:"html",sourcecode:t.advanedWidget}})],1)]),e("section",{staticClass:"example-wrap"},[e("h3",[t._v("Widget With Grid")]),t._m(2),e("div",{staticClass:"example-bg"},[e("smart-widget-grid",{attrs:{layout:t.layout}},[e("smart-widget",{attrs:{slot:"0",simple:""},slot:"0"},[e("div",{staticClass:"layout-center"},[e("h3",[t._v("Simple Widget Without Header")])])]),e("smart-widget",{attrs:{slot:"1",title:"Default Widget","sub-title":"Drag on me"},slot:"1"},[e("div",{staticClass:"layout-center"},[e("h3",[t._v("Default Widget With Header")])])]),e("smart-widget",{attrs:{slot:"2",title:"Full Screen","sub-title":"Drag on me",fullscreen:""},slot:"2"},[e("div",{staticClass:"layout-center"},[e("h3",[t._v("Make any widget full screen")])])])],1)],1),e("div",{staticClass:"example-code"},[e("div",{staticClass:"example-link"},[e("a",{attrs:{href:t.gridUrl,target:"_blank"}},[e("img",{directives:[{name:"tooltip",rawName:"v-tooltip",value:t.tooltipOptions,expression:"tooltipOptions"}],attrs:{src:t.codesandboxIcon,alt:"View On Jsfiddle"}})])]),e("el-row",[e("el-col",{attrs:{span:12}},[e("code-block",{attrs:{lang:"js",sourcecode:t.widgetWithGridJS}})],1),e("div",{staticClass:"line"}),e("el-col",{attrs:{span:12}},[e("code-block",{attrs:{lang:"html",sourcecode:t.widgetWithGridHTML}})],1)],1)],1)]),t._m(3)])},l=[function(){var t=this,e=t._self._c;return e("div",{staticClass:"document-header"},[e("h2",{staticStyle:{padding:"0"}},[t._v("Document")]),e("blockquote",[e("p",[t._v(" Smart widget is a flexible and extensible content container component. It includes header and body part, and widget body includes "),e("em",[t._v("editbox")]),t._v("、"),e("em",[t._v("content")]),t._v("、"),e("em",[t._v("footer")]),t._v(". If you use with grid, it also have a draggable and resizable grid layout, base on "),e("strong",[t._v("Vue2.5.+")]),t._v(" & "),e("strong",[t._v("vue-grid-layout")]),t._v(". ")])])])},function(){var t=this,e=t._self._c;return e("blockquote",[e("p",[t._v(" The widget extend useful display options. ")])])},function(){var t=this,e=t._self._c;return e("blockquote",[e("p",[t._v(" The widget is draggable & resizable. work with [vue-grid-layout]. ")])])},function(){var t=this,e=t._self._c;return e("section",{staticClass:"much-more"},[t._v(" For "),e("a",{attrs:{href:"https://github.com/xiaoluoboding/vue-smart-widget#usage",target:"_black"}},[t._v("More")]),t._v(" Details. ")])}],d=function(){var t=this,e=t._self._c;return e("pre",{directives:[{name:"hljs",rawName:"v-hljs"}]},[t._v(" "),e("code",{class:t.lang,domProps:{textContent:t._s(t.sourcecode)}}),t._v("\n")])},c=[],p=a("1487"),u=a.n(p);a("2c43");i["default"].directive("hljs",{deep:!0,bind:function(t,e){const a=t.querySelectorAll("code");a.forEach(t=>{e.value&&(t.textContent=e.value),u.a.highlightBlock(t)})},componentUpdated:function(t,e){const a=t.querySelectorAll("code");a.forEach(t=>{e.value&&(t.textContent=e.value,u.a.highlightBlock(t))})}});var g={name:"CodeBlock",props:{lang:String,sourcecode:[String,Array,Object]},data(){return{}}},h=g,m=(a("5429"),a("2877")),f=Object(m["a"])(h,d,c,!1,null,null,null),w=f.exports,b=a("8cb2"),x=a.n(b);const v="Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam deleniti fugit incidunt, iste, itaque minima neque pariatur perferendis sed suscipit velit vitae voluptatem. A consequuntur, deserunt eaque error nulla temporibus!",y='\n

\n Lorem ipsum dolor sit amet, consectetur adipisicing elit.\n Aperiam deleniti fugit incidunt, iste, itaque minima neque pariatur perferendis sed suscipit velit vitae voluptatem.\n A consequuntur, deserunt eaque error nulla temporibus!\n

\n
\n',_='\x3c!-- // 1. With additional fullscreen button --\x3e\n\n

\n Lorem ipsum dolor sit amet, consectetur adipisicing elit.\n Aperiam deleniti fugit incidunt, iste, itaque minima neque pariatur perferendis sed suscipit velit vitae voluptatem.\n A consequuntur, deserunt eaque error nulla temporibus!\n

\n
\n\n\x3c!-- 2. Widget with Editbox & Footer --\x3e\n\n \n

I am content

\n \n
\n\n\x3c!-- 3. Widget with custom toolbar --\x3e\n\n \n

\n Lorem ipsum dolor sit amet, consectetur adipisicing elit.\n Aperiam deleniti fugit incidunt, iste, itaque minima neque pariatur perferendis sed suscipit velit vitae voluptatem.\n A consequuntur, deserunt eaque error nulla temporibus!\n

\n
\n',k='\n\n \n
\n

Simple Widget

\n
\n
\n \n
\n

Widget with Header

\n
\n
\n \n
\n

Make any widget full screen

\n
\n
\n
\n',C="\nnew Vue({\n data () {\n return {\n layout: [\n { x: 0, y: 0, w: 4, h: 4, i: '0' },\n { x: 4, y: 0, w: 4, h: 4, i: '1' },\n { x: 8, y: 0, w: 4, h: 4, i: '2' }\n ]\n }\n }\n})\n";var H={components:{CodeBlock:w},data(){return{layout:[{x:0,y:0,w:4,h:4,i:"0"},{x:4,y:0,w:4,h:4,i:"1"},{x:8,y:0,w:4,h:4,i:"2"}],tooltipOptions:{content:"View On CodeSandbox",placement:"left-start",classes:["stand"],offset:6,delay:{show:300,hide:300}},codesandboxIcon:x.a,defaultUrl:"https://codesandbox.io/s/vuesmartwidget-default-2ghmi?autoresize=1&fontsize=14&hidenavigation=1&theme=dark&view=preview",advanedUrl:"https://codesandbox.io/s/vuesmartwidget-advanced-8i7x0?autoresize=1&fontsize=14&hidenavigation=1&theme=dark&view=preview",gridUrl:"https://codesandbox.io/s/vuesmartwidget-grid-dgf9d?autoresize=1&fontsize=14&hidenavigation=1&theme=dark&view=preview"}},created(){this.placeholder=v,this.defaultWidget=y,this.advanedWidget=_,this.widgetWithGridHTML=k,this.widgetWithGridJS=C}},S=H,z=(a("fe55"),Object(m["a"])(S,n,l,!1,null,null,null)),W=z.exports,B=function(){var t=this,e=t._self._c;return e("div",{staticStyle:{padding:"15px"}},[e("el-row",{attrs:{type:"flex",gutter:32}},[e("el-col",{attrs:{span:8}},[e("smart-widget",{attrs:{simple:""}},[e("h3",[t._v("Simple Widget Without Header")]),e("p",[t._v(" "+t._s(t.placeholder)+" ")])])],1),e("el-col",{attrs:{span:8}},[e("smart-widget",{attrs:{title:"Default Widget",shadow:"hover","translate-y":10}},[e("p",[t._v(" "+t._s(t.placeholder)+" ")])])],1),e("el-col",{attrs:{span:8}},[e("smart-widget",{attrs:{title:"With additional fullscreen button",fullscreen:"",shadow:"never"}},[e("p",[t._v(" "+t._s(t.placeholder)+" ")])])],1)],1),e("br"),e("el-row",{attrs:{type:"flex",gutter:32}},[e("el-col",{attrs:{span:16}},[e("smart-widget",{attrs:{title:"2017 Hotest Frontend Project","sub-title":"Use ve-charts components.",fullscreen:"",collapse:"",refresh:"","is-actived":"","actived-color":"#f4a",loading:t.loading},on:{"on-refresh":t.handleRefresh,"on-fullscreen":t.handleFullscreen},scopedSlots:t._u([{key:"default",fn:function({contentH:a}){return e("ve-bar-chart",{attrs:{data:t.barData,height:a}})}}])})],1),e("el-col",{attrs:{span:8}},[e("smart-widget",{attrs:{title:"Diffrent Platforms PV",fullscreen:"",collapse:""},scopedSlots:t._u([{key:"default",fn:function({contentH:a}){return e("ve-donut-chart",{attrs:{data:t.donutData,settings:t.donutSetting,height:a}})}}])})],1)],1),e("br"),e("el-row",{attrs:{type:"flex",gutter:32}},[e("el-col",{attrs:{span:8}},[e("smart-widget",{attrs:{title:"Widget with Editbox"}},[e("template",{slot:"editbox"},[e("el-alert",{attrs:{title:"I am Editbox slot",type:"success"}})],1),e("p",[t._v(" "+t._s(t.placeholder)+" ")])],2)],1),e("el-col",{attrs:{span:8}},[e("smart-widget",{attrs:{title:"Widget with Footer"}},[e("p",[t._v(" "+t._s(t.placeholder)+" ")]),e("template",{slot:"footer"},[e("el-alert",{attrs:{title:"I am Footer slot",type:"success"}})],1)],2)],1),e("el-col",{attrs:{span:8}},[e("smart-widget",{attrs:{title:"Widget with custom toolbar","header-height":36}},[e("template",{slot:"toolbar"},[e("div",{staticStyle:{margin:"0 12px"}},[e("el-button",{attrs:{type:"primary",size:"mini"},on:{click:function(e){return t.$router.push("/widget-with-grid")}}},[t._v("Grid")])],1)]),e("p",[t._v(" "+t._s(t.placeholder)+" ")])],2)],1)],1),e("br"),e("el-row",{attrs:{type:"flex",gutter:32}},[e("el-col",[e("smart-widget",{attrs:{title:"Wiget with Table",collapse:""}},[e("el-table",{staticStyle:{width:"100%"},attrs:{data:t.tableData}},[e("el-table-column",{attrs:{fixed:"",prop:"date",label:"日期"}}),e("el-table-column",{attrs:{prop:"name",label:"姓名"}}),e("el-table-column",{attrs:{prop:"province",label:"省份"}}),e("el-table-column",{attrs:{prop:"city",label:"市区"}}),e("el-table-column",{attrs:{prop:"address",label:"地址"}}),e("el-table-column",{attrs:{prop:"zip",label:"邮编"}})],1)],1)],1)],1)],1)},M=[],O={data(){return{loading:!1,placeholder:"Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam deleniti fugit incidunt, iste, itaque minima neque pariatur perferendis sed suscipit velit vitae voluptatem. A consequuntur, deserunt eaque error nulla temporibus!",tableData:[{date:"2016-05-03",name:"王小虎",province:"上海",city:"普陀区",address:"上海市普陀区金沙江路 1518 弄",zip:200333},{date:"2016-05-02",name:"王小虎",province:"上海",city:"普陀区",address:"上海市普陀区金沙江路 1518 弄",zip:200333},{date:"2016-05-04",name:"王小虎",province:"上海",city:"普陀区",address:"上海市普陀区金沙江路 1518 弄",zip:200333},{date:"2016-05-01",name:"王小虎",province:"上海",city:"普陀区",address:"上海市普陀区金沙江路 1518 弄",zip:200333},{date:"2016-05-08",name:"王小虎",province:"上海",city:"普陀区",address:"上海市普陀区金沙江路 1518 弄",zip:200333},{date:"2016-05-06",name:"王小虎",province:"上海",city:"普陀区",address:"上海市普陀区金沙江路 1518 弄",zip:200333},{date:"2016-05-07",name:"王小虎",province:"上海",city:"普陀区",address:"上海市普陀区金沙江路 1518 弄",zip:200333}]}},methods:{handleRefresh(){this.loading=!0,setTimeout(()=>{this.loading=!1},2e3)},handleFullscreen(t){}},created(){this.barData={dimensions:{name:"Year",data:["Jan.","Feb.","Mar.","Apr.","May.","Jun.","Jul.","Aug.","Sep.","Oct.","Nov.","Dec."]},measures:[{name:"Vue",data:[3e3,3500,3900,3100,3200,3100,3600,3300,3600,3400,3100,3e3]},{name:"React",data:[2e3,2e3,2600,2300,2300,2e3,2600,2200,2500,2800,2500,2200]},{name:"Angular",data:[827,949,1400,1e3,884,911,983,989,925,1100,1200,930]}]},this.donutData={dimensions:{name:"渠道",data:["APP","PC","M端","微信","小程序"]},measures:[{name:"PV",data:[4e4,27800,22e3,20200,13600]}]},this.donutSetting={offsetY:"60%"}}},F=O,P=Object(m["a"])(F,B,M,!1,null,null,null),A=P.exports,L=function(){var t=this,e=t._self._c;return e("smart-widget-grid",{attrs:{layout:t.layout,"row-height":48,margin:[15,15],"is-static":t.isStatic},on:{"layout-updated":t.onLayoutUpdated,moved:t.onMove,resized:t.onResize}},[e("smart-widget",{attrs:{slot:"0",simple:""},slot:"0"},[e("div",{staticClass:"layout-center"},[e("h3",[t._v("Simple Widget Without Header")])])]),e("smart-widget",{attrs:{slot:"1",title:"Default Widget"},slot:"1"},[e("div",{staticClass:"layout-center"},[e("h3",[t._v("Widget with Header")])])]),e("smart-widget",{attrs:{slot:"2",title:"Full Screen",fullscreen:""},slot:"2"},[e("div",{staticClass:"layout-center"},[e("h3",[t._v("Make any widget full screen")])])]),e("smart-widget",{attrs:{slot:"3",title:"Widget with Loader",loading:!0},slot:"3"},[e("div",{staticClass:"layout-center"},[e("h3",[t._v("Widget with loading mask")])])]),e("smart-widget",{attrs:{slot:"4",title:"Editbox"},slot:"4"},[e("template",{slot:"editbox"},[e("el-alert",{attrs:{title:"I am Editbox slot",type:"success"}})],1),e("p",[t._v("Widget with Editbox")])],2),e("smart-widget",{attrs:{slot:"5",title:"Footer"},slot:"5"},[e("template",{slot:"footer"},[e("el-alert",{attrs:{title:"I am Footer slot",type:"success"}})],1),e("p",[t._v("Widget with Footer")])],2),e("smart-widget",{attrs:{slot:"6",title:"2017 Hotest Frontend Project",fullscreen:"",refresh:"","is-actived":"",loading:t.loading},on:{"before-fullscreen":e=>t.isStatic=e,"on-refresh":t.handleRefresh},slot:"6",scopedSlots:t._u([{key:"default",fn:function({contentH:a}){return[e("ve-bar-chart",{attrs:{data:t.barData,height:a}})]}}])}),e("smart-widget",{attrs:{slot:"7",title:"Diffrent Platforms PV",fullscreen:"",collapse:""},slot:"7",scopedSlots:t._u([{key:"default",fn:function({contentH:a}){return[e("ve-donut-chart",{attrs:{data:t.donutData,settings:t.donutSetting,height:a}})]}}])}),e("smart-widget",{attrs:{slot:"8",title:"Widget body content's height is fixed","fixed-height":""},slot:"8"},[e("el-table",{staticStyle:{width:"100%"},attrs:{data:t.tableData}},[e("el-table-column",{attrs:{prop:"date",label:"日期",width:"150"}}),e("el-table-column",{attrs:{prop:"name",label:"姓名",width:"180"}}),e("el-table-column",{attrs:{prop:"address",label:"地址"}})],1)],1),e("smart-widget",{attrs:{slot:"9",title:"Widget with custom toolbar"},slot:"9"},[e("template",{slot:"toolbar"},[e("div",{staticStyle:{margin:"0 12px"}},[e("el-button",{attrs:{type:"success",size:"mini"},on:{click:function(e){return t.$router.push("/widget-only")}}},[t._v("Index")])],1)]),e("el-table",{staticStyle:{width:"100%"},attrs:{data:t.tableData}},[e("el-table-column",{attrs:{prop:"date",label:"日期",width:"150"}}),e("el-table-column",{attrs:{prop:"name",label:"姓名",width:"180"}}),e("el-table-column",{attrs:{prop:"address",label:"地址"}})],1)],2)],1)},T=[],j={data(){return{loading:!1,isStatic:!1,layout:[{x:0,y:0,w:4,h:3,i:"0"},{x:4,y:0,w:4,h:3,i:"1"},{x:8,y:0,w:4,h:3,i:"2"},{x:0,y:3,w:4,h:3,i:"3"},{x:4,y:3,w:4,h:3,i:"4"},{x:8,y:3,w:4,h:3,i:"5"},{x:0,y:6,w:8,h:6,i:"6"},{x:8,y:6,w:4,h:6,i:"7"},{x:0,y:12,w:6,h:5,i:"8"},{x:6,y:12,w:6,h:5,i:"9"}]}},created(){this.barData={dimensions:{name:"Year",data:["Jan.","Feb.","Mar.","Apr.","May.","Jun.","Jul.","Aug.","Sep.","Oct.","Nov.","Dec."]},measures:[{name:"Vue",data:[3e3,3500,3900,3100,3200,3100,3600,3300,3600,3400,3100,3e3]},{name:"React",data:[2e3,2e3,2600,2300,2300,2e3,2600,2200,2500,2800,2500,2200]},{name:"Angular",data:[827,949,1400,1e3,884,911,983,989,925,1100,1200,930]}]},this.donutData={dimensions:{name:"渠道",data:["APP","PC","M端","微信","小程序"]},measures:[{name:"PV",data:[4e4,27800,22e3,20200,13600]}]},this.tableData=[{date:"2016-05-03",name:"王小虎",address:"上海市普陀区金沙江路 1518 弄"},{date:"2016-05-02",name:"王小虎",address:"上海市普陀区金沙江路 1518 弄"},{date:"2016-05-04",name:"王小虎",address:"上海市普陀区金沙江路 1518 弄"},{date:"2016-05-01",name:"王小虎",address:"上海市普陀区金沙江路 1518 弄"},{date:"2016-05-08",name:"王小虎",address:"上海市普陀区金沙江路 1518 弄"},{date:"2016-05-06",name:"王小虎",address:"上海市普陀区金沙江路 1518 弄"},{date:"2016-05-07",name:"王小虎",address:"上海市普陀区金沙江路 1518 弄"}],this.donutSetting={offsetY:"60%"}},methods:{handleRefresh(){this.loading=!0,setTimeout(()=>{this.loading=!1},2e3)},onLayoutUpdated(t){},onMove(t){},onResize(t){},onContainerResized(t){}}},E=j,D=(a("40dd"),Object(m["a"])(E,L,T,!1,null,null,null)),I=D.exports;i["default"].use(r["a"]);var $=new r["a"]({routes:[{path:"/",redirect:"/home"},{path:"/home",name:"home",component:W},{path:"/widget-only",name:"widget-only",component:A},{path:"/widget-with-grid",name:"WidgetWithGrid",component:I}]}),q=function(){var t=this,e=t._self._c;return e("div",{attrs:{id:"app"}},[e("el-container",{staticClass:"app-container"},[e("el-header",{staticClass:"app-header",attrs:{height:"61px"}},[e("el-container",{staticClass:"sub-container sub-header"},[e("h1",{on:{click:function(e){t.activeIndex="home"}}},[e("router-link",{attrs:{to:"/home"}},[e("span",{staticStyle:{color:"#40b883"}},[t._v("vue-smart-widget")])])],1),e("el-menu",{staticClass:"app-menu",attrs:{"default-active":t.activeIndex,mode:"horizontal",router:""},on:{select:e=>t.activeIndex=e}},[e("el-menu-item",{attrs:{index:"widget-only"}},[t._v(" Use Widget Only ")]),e("el-menu-item",{attrs:{index:"widget-with-grid"}},[t._v(" Use Widget with Grid ")])],1),e("div",{staticClass:"open-in-github"},[e("a",{attrs:{href:"https://github.com/xiaoluoboding/vue-smart-widget",target:"_blank"}},[e("img",{attrs:{src:a("22bf"),alt:"github"}})])])],1)],1),e("el-container",{staticClass:"sub-container sub-content"},[e("el-main",{staticClass:"app-main"},[e("keep-alive",[e("router-view")],1)],1)],1)],1)],1)},V=[],N={name:"App",data(){return{activeIndex:"home"}}},G=N,R=(a("519d"),Object(m["a"])(G,q,V,!1,null,null,null)),U=R.exports,J=function(){var t=this,e=t._self._c;return e("grid-layout",t._g(t._b({attrs:{layout:t.layout,"col-num":t.colNum},on:{"update:layout":function(e){t.layout=e}}},"grid-layout",t.layoutAttrs,!1),t.gridLayoutEvents),t._l(t.layout,(function(a){return e("grid-item",t._g(t._b({key:a.i,attrs:{"drag-ignore-from":".widget-body",static:t.isStatic}},"grid-item",a,!1),t.gridLayoutItemEvents),[t._t(a.i)],2)})),1)},Y=[],X=a("7be8");const K=(t,e)=>e.reduce((e,a)=>(a in t&&(e[a]=t[a]),e),{}),Q=(t,e)=>t.reduce((a,i,o)=>(a[i]=e(i,o,t),a),{});var Z={name:"SmartWidgetGrid",components:{GridLayout:X["GridLayout"],GridItem:X["GridItem"]},provide(){return{layout:this.layout}},props:{layout:{type:Array,required:!0},colNum:{type:Number,default:12},maxRows:{type:Number},rowHeight:{type:Number,default:48},margin:{type:Array,default:()=>[10,10]},draggable:{type:Boolean,default:!0},resizable:{type:Boolean,default:!0},isStatic:{type:Boolean,default:!1}},data(){return{layoutAttrs:{colNum:this.colNum,rowHeight:this.rowHeight,maxRows:this.maxRows,margin:this.margin,isDraggable:this.draggable,isResizable:this.resizable,useCssTransforms:!1,...this.$attrs},gridLayoutItemEvents:{}}},created(){const t=this.$listeners;this.gridLayoutItemEvents={};const e=["layout-created","layout-before-mount","layout-mounted","layout-ready","layout-updated","breakpoint-changed"],a={move:["i","newX","newY"],resize:["i","newH","newW","newHPx","newWPx"],moved:["i","newX","newY"],resized:["i","newH","newW","newHPx","newWPx"],"container-resized":["i","newH","newW","newHPx","newWPx"]};this.gridLayoutEvents=K(t,e),Object.keys(a).forEach(t=>{const e=a[t];this.gridLayoutItemEvents=Object.assign(this.gridLayoutItemEvents,{[t]:(...a)=>{const i=Q(e,(t,e)=>a[e]);this.$emit(t,i)}})})}},tt=Z,et=(a("d535"),Object(m["a"])(tt,J,Y,!1,null,null,null)),at=et.exports,it=function(){var t=this,e=t._self._c;return e("div",{staticClass:"smartwidget",class:t.smartWidgetClass,style:[t.smartWidgetStyle,t.dynamicStyle],on:{mouseover:t.handleMouseover,mouseout:t.handleMouseout}},[t.simple?t._e():e("div",{staticClass:"widget-header",style:t.widgetHeaderHeight},[t.$slots.title?t._t("title"):e("div",{staticClass:"widget-header__title ellis",style:t.widgetTitleStyle},[e("span",{domProps:{textContent:t._s(t.title)}}),""!==t.subTitle?e("span",{staticClass:"widget-header__subtitle",domProps:{textContent:t._s(t.subTitle)}}):t._e()]),e("div",{staticClass:"widget-header__toolbar"},[t.isHasGroup||!t.collapse||t.isFullScreen?t._e():e("a",{attrs:{href:"javascript:;"},on:{click:function(e){t.isCollapsed=!t.isCollapsed}}},[t.isCollapsed?[e("svg",{staticClass:"icon",attrs:{viewBox:"0 0 1024 1024",xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16"}},[e("path",{attrs:{d:"M917.333 364.8L851.2 298.667 512 637.867l-339.2-339.2-66.133 66.133L512 768z",fill:"#666"}})])]:[e("svg",{staticClass:"icon",attrs:{viewBox:"0 0 1024 1024",xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16"}},[e("path",{attrs:{d:"M106.667 659.2l66.133 66.133 339.2-339.2 339.2 339.2 66.133-66.133L512 256z",fill:"#666"}})])]],2),t.fullscreen?e("a",{attrs:{href:"javascript:;"},on:{click:t.handlefullScreen}},[t.isFullScreen?[e("svg",{attrs:{width:"16",height:"16",viewBox:"0 0 16 16",xmlns:"http://www.w3.org/2000/svg"}},[e("path",{attrs:{d:"M6 10.704V13.5a.5.5 0 1 0 1 0v-4a.5.5 0 0 0-.5-.5h-4a.5.5 0 0 0 0 1h2.79l-3.144 3.147a.5.5 0 1 0 .708.706L6 10.703zm4-5.411V2.5a.5.5 0 0 0-1 0v4a.5.5 0 0 0 .5.5h4a.5.5 0 1 0 0-1h-2.793l3.147-3.146a.5.5 0 0 0-.708-.708L10 5.293zM13 9.5a.5.5 0 1 1 1 0v4a.5.5 0 0 1-.5.5h-4a.5.5 0 1 1 0-1H13V9.5zm-10-3a.5.5 0 0 1-1 0v-4a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1H3v3.5z",fill:"#666","fill-rule":"evenodd"}})])]:[e("svg",{attrs:{width:"16",height:"16",viewBox:"0 0 16 16",xmlns:"http://www.w3.org/2000/svg"}},[e("path",{attrs:{d:"M3 12.293V9.5a.5.5 0 0 0-1 0v4a.5.5 0 0 0 .5.5h4a.5.5 0 1 0 0-1H3.707l3.147-3.146a.5.5 0 1 0-.708-.708L3 12.293zm10-8.586V6.5a.5.5 0 1 0 1 0v-4a.5.5 0 0 0-.5-.5h-4a.5.5 0 0 0 0 1h2.793L9.147 6.146a.5.5 0 1 0 .707.708L13 3.707zM13 9.5a.5.5 0 1 1 1 0v4a.5.5 0 0 1-.5.5h-4a.5.5 0 1 1 0-1H13V9.5zm-10-3a.5.5 0 0 1-1 0v-4a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1H3v3.5z",fill:"#666","fill-rule":"evenodd"}})])]],2):t._e(),t.refresh&&!t.isFullScreen?e("a",{attrs:{href:"javascript:;"}},[t.loading?[e("svg",{staticClass:"icon sw-loading",attrs:{viewBox:"0 0 1024 1024",xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16"}},[e("path",{attrs:{d:"M910.222 455.111V512H682.667v-56.889h227.555zm-625.778 0V512H56.89v-56.889h227.555zm170.667 227.556H512v227.555h-56.889V682.667zm0-625.778H512v227.555h-56.889V56.89zm341.333 699.733l-39.822 39.822-159.289-159.288 39.823-39.823 159.288 159.29zM369.778 329.956l-39.822 39.822-159.29-159.29 39.823-39.821 159.289 159.289zm-39.822 267.377l39.822 39.823-159.29 159.288-39.821-39.822 159.289-159.289zm426.666-426.666l39.822 39.822-159.288 159.289-39.823-39.822 159.29-159.29z",fill:"#666"}})])]:[e("svg",{attrs:{width:"16",height:"16",viewBox:"0 0 16 16",xmlns:"http://www.w3.org/2000/svg"},on:{click:function(e){return t.$emit("on-refresh")}}},[e("g",{attrs:{fill:"#666"}},[e("path",{attrs:{d:"M14 8A6 6 0 0 0 3.372 4.18a.5.5 0 1 0 .771.638A5 5 0 0 1 13 8a.5.5 0 1 0 1 0zM2 8a6 6 0 0 0 10.549 3.912.5.5 0 1 0-.758-.652A5 5 0 0 1 3 8a.5.5 0 0 0-1 0z"}}),e("path",{attrs:{d:"M4 1.5V4h2.5a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5v-3a.5.5 0 0 1 1 0zm8 13v-2.502H9.5a.5.5 0 0 1 0-1h3a.5.5 0 0 1 .5.5V14.5a.5.5 0 1 1-1 0z"}})])])]],2):t._e(),t.$slots.toolbar?t._t("toolbar"):t._e()],2)],2),e("collapse-transition",[e("div",{directives:[{name:"show",rawName:"v-show",value:!t.isCollapsed,expression:"!isCollapsed"}],ref:"widgetBody",class:[t.simple?"widget-body-simple":"widget-body",{"is-collapse":t.isCollapsed}],style:t.simple?{}:t.widgetBodyStyle},[e("div",{ref:"widgetBodyEditbox",staticClass:"widget-body__editbox"},[t._t("editbox")],2),e("div",{ref:"widgetBodyContent",staticClass:"widget-body__content",class:{"fixed-height":t.fixedHeight},style:t.widgetBodyContentStyle},[t._t("default",null,{contentH:t.contentH})],2),e("div",{ref:"widgetBodyFooter",staticClass:"widget-body__footer",class:{"has-group":t.isHasGroup}},[t.$slots.footer?t._t("footer"):t._e()],2),t.loading?e("loading-mask"):t._e()],1)])],1)},ot=[],st=function(){var t=this,e=t._self._c;return e("div",{staticClass:"smart-widget__loading-mask"},[e("div",{staticClass:"loading-spinner"},[e("svg",{staticClass:"circular",attrs:{viewBox:"25 25 50 50"}},[e("circle",{staticClass:"path",attrs:{cx:"50",cy:"50",r:"20",fill:"none"}})])])])},rt=[],nt=(a("172f"),{}),lt=Object(m["a"])(nt,st,rt,!1,null,null,null),dt=lt.exports,ct=a("9a90"),pt=a.n(ct),ut={name:"SmartWidget",components:{LoadingMask:dt,CollapseTransition:pt.a},props:{title:{type:String,default:""},subTitle:{type:String,default:""},padding:{type:[Number,Array],default:()=>[12,20]},simple:{type:Boolean,default:!1},loading:{type:Boolean,default:!1},fullscreen:{type:Boolean,default:!1},collapse:{type:Boolean,default:!1},refresh:{type:Boolean,default:!1},fixedHeight:{type:Boolean,default:!1},shadow:{type:String,default:"always"},translateY:{type:Number,default:0},isActived:{type:Boolean,default:!1},activedColor:{type:String,default:"#0076db"},headerHeight:{type:Number,default:48}},data(){return{isFullScreen:!1,isCollapsed:!1,isFullScreenCollapsed:!1,widgetBodyOffsetHeight:"auto",widgetBodyOldHeight:0,widgetBodyEditBoxH:0,widgetBodyFooterH:0,smartWidgetStyle:{}}},computed:{smartWidgetClass(){return{"smartwidget-fullscreen":this.isFullScreen,"smartwidget-collapsed":this.isCollapsed,"is-always-shadow":"always"===this.shadow,"is-hover-shadow":"hover"===this.shadow,"is-never-shadow":"never"===this.shadow,"is-actived":this.isActived}},bodyContentPadding(){const t="number"===typeof this.padding?Array.of(this.padding):this.padding,e=t.join("px ");return e.padEnd(e.length+2,"px")},dynamicStyle(){return this.isActived?{"box-shadow":"0 0 0 2px "+this.activedColor}:{}},widgetHeaderHeight(){return{height:this.rowHeight+"px","line-height":this.rowHeight+"px"}},widgetBodyStyle(){return{height:`calc(100% - ${this.rowHeight}px)`}},widgetBodyContentStyle(){return{padding:this.bodyContentPadding}},widgetTitleStyle(){const t="number"===typeof this.padding?Array.of(this.padding):this.padding,e=t[t.length-1];return{padding:`0 ${e}px 0 ${e}px`}},rowHeight(){return this.isHasGroup?this.$parent.rowHeight:this.headerHeight},isHasGroup:t=>Boolean(t.$parent.i),contentH:t=>t.getContentH()},mounted(){this.$nextTick(t=>{this.widgetBodyOffsetHeight=this.$refs.widgetBody.offsetHeight,this.widgetBodyEditBoxH=this.$slots.editbox?this.$refs.widgetBodyEditbox.offsetHeight:0,this.widgetBodyFooterH=this.$slots.footer?this.$refs.widgetBodyFooter.offsetHeight:0})},methods:{handlefullScreen(){this.isCollapsed&&(this.isFullScreenCollapsed=this.isCollapsed,this.isCollapsed=!this.isCollapsed),this.isFullScreen&&this.isFullScreenCollapsed&&(this.isCollapsed=this.isFullScreenCollapsed),this.isFullScreen=!this.isFullScreen,this.isHasGroup&&this.$emit("before-fullscreen",this.isFullScreen),this.isFullScreen?(this.$nextTick(t=>{this.widgetBodyOldHeight=this.widgetBodyOffsetHeight;const e=document.body.offsetHeight-this.rowHeight;this.widgetBodyOffsetHeight=e}),document.body.classList.add("no-overflow")):(this.widgetBodyOffsetHeight=this.widgetBodyOldHeight,this.isFullScreenCollapsed=this.isFullScreen,document.body.classList.remove("no-overflow")),this.$emit("on-fullscreen",this.isFullScreen)},getPaddingH(){let t=0;const e="number"===typeof this.padding?Array.of(this.padding):this.padding;switch(e.length){case 1:case 2:t=2*e[0];break;case 3:case 4:t=e[0]+e[2];break}return t},getWidgetBodyH(){let t=0;if(this.isHasGroup){const{innerH:e,margin:a,rowHeight:i}=this.$parent,[o]=a,s=(i+o)*e-o;t=s-i}else t=this.widgetBodyOffsetHeight;return t},getContentH(){const t=this.isFullScreen?this.widgetBodyOffsetHeight:this.getWidgetBodyH(),e=this.getPaddingH(),a=this.widgetBodyEditBoxH,i=this.widgetBodyFooterH,o=t-e-a-i-1;return o>0?o:this.$parent.rowHeight},handleMouseover(){const t=this.smartWidgetStyle;this.smartWidgetStyle={...t,transform:`translateY(${-this.translateY}px)`}},handleMouseout(){const t=this.smartWidgetStyle;this.smartWidgetStyle={...t,transform:"translateY(0px)"}}}},gt=ut,ht=(a("6079"),a("5522"),Object(m["a"])(gt,it,ot,!1,null,"c7f7be72",null)),mt=ht.exports;const ft=[at,mt];function wt(t,e){ft.forEach(e=>{t.component(e.name,e)})}"undefined"!==typeof window&&window.Vue&&(window.Vue.use(wt),wt.installed&&(wt.installed=!1));var bt=a("64e3"),xt=a.n(bt),vt=a("e37d");i["default"].use(vt["a"]),i["default"].component("SmartWidget",mt),i["default"].component("SmartWidgetGrid",at),i["default"].use(xt.a),i["default"].use(s.a,{size:"small"}),i["default"].config.productionTip=!1,new i["default"]({router:$,render:t=>t(U)}).$mount("#app")},fe55:function(t,e,a){"use strict";a("bad0")},fef3:function(t,e,a){var i=a("24fb");e=i(!1),e.push([t.i,"body.no-overflow[data-v-c7f7be72]{overflow:hidden;position:fixed;width:100%}.smartwidget[data-v-c7f7be72]{-webkit-box-sizing:border-box;box-sizing:border-box;background:#fff;-webkit-box-shadow:0 1px 2px 0 rgba(0,0,0,.05);box-shadow:0 1px 2px 0 rgba(0,0,0,.05);border:1px solid #ebeef5;width:100%;-webkit-transition:.3s;transition:.3s}.smartwidget.is-always-shadow[data-v-c7f7be72],.smartwidget.is-hover-shadow[data-v-c7f7be72]:hover{-webkit-box-shadow:0 0 10px 0 #e9e9e9;box-shadow:0 0 10px 0 #e9e9e9}.smartwidget.is-never-shadow[data-v-c7f7be72]{-webkit-box-shadow:0 1px 2px 0 rgba(0,0,0,.05);box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.smartwidget .widget-header[data-v-c7f7be72]{display:-webkit-box;display:-ms-flexbox;display:flex;border-bottom:1px solid #ebeef5}.smartwidget .widget-header .widget-header__title[data-v-c7f7be72]{display:inline-block;position:relative;width:auto;margin:0;font-weight:400;letter-spacing:0;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:16px}.smartwidget .widget-header .widget-header__subtitle[data-v-c7f7be72]{font-size:12px;color:#777;margin-left:10px}.smartwidget .widget-header .ellis[data-v-c7f7be72]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.smartwidget .widget-header .widget-header__prefix[data-v-c7f7be72]{background:#0076db;width:2px;height:16px;margin-left:10px}.smartwidget .widget-header .widget-header__toolbar[data-v-c7f7be72]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-flex:1;-ms-flex:1;flex:1;padding:0;margin:0}.smartwidget .widget-header .widget-header__toolbar a[data-v-c7f7be72]{display:inline-block;text-decoration:none;text-align:center;height:24px;line-height:28px;padding:0;margin:0;color:#333;min-width:35px;position:relative;font-family:Arial,Helvetica,sans-serif;border-left:1px solid rgba(0,0,0,.09)}.smartwidget .widget-body-simple[data-v-c7f7be72]{display:-webkit-box;display:-ms-flexbox;display:flex;height:inherit;width:inherit}.smartwidget .widget-body-simple .widget-body__content[data-v-c7f7be72]{width:100%}.smartwidget .widget-body[data-v-c7f7be72]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;will-change:height;position:relative;overflow:hidden}.smartwidget .widget-body .widget-body__content[data-v-c7f7be72]{-webkit-box-flex:1;-ms-flex:1;flex:1}.smartwidget .widget-body .widget-body__content.fixed-height[data-v-c7f7be72]{overflow-y:scroll}.smartwidget .widget-body .widget-body__footer[data-v-c7f7be72]{position:relative}.smartwidget .widget-body .widget-body__footer.has-group[data-v-c7f7be72]{left:0;bottom:0;width:100%}.smartwidget .widget-body.is-collapse[data-v-c7f7be72]{-webkit-transition:height .3s ease-in-out,padding-top .3s ease-in-out,padding-bottom .3s ease-in-out;transition:height .3s ease-in-out,padding-top .3s ease-in-out,padding-bottom .3s ease-in-out}.smartwidget.smartwidget-fullscreen[data-v-c7f7be72]{position:fixed;height:100%;width:100%;top:0;left:0;z-index:6666}.smartwidget.smartwidget-fullscreen .widget-header[data-v-c7f7be72]{cursor:default}.smartwidget svg.sw-loading[data-v-c7f7be72]{-webkit-animation:rotating 2s linear infinite;animation:rotating 2s linear infinite;cursor:not-allowed}",""]),t.exports=e}}); -------------------------------------------------------------------------------- /lib/demo.html: -------------------------------------------------------------------------------- 1 | 2 | vue-smart-widget demo 3 | 4 | 5 | 6 | 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-smart-widget", 3 | "version": "0.6.2", 4 | "description": "Smart widget is a flexible and extensible content container component for Vue2.5+.", 5 | "author": "xiaoluoboding ", 6 | "scripts": { 7 | "serve": "vue-cli-service serve", 8 | "build": "vue-cli-service build --dest docs", 9 | "lint": "vue-cli-service lint", 10 | "build:lib": "vue-cli-service build --mode lib --target lib --dest lib src/index.js", 11 | "bundle": "npm run build && npm run build:lib", 12 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0", 13 | "report": "vue-cli-service build --mode lib --target lib --dest lib --report src/index.js" 14 | }, 15 | "main": "lib/vue-smart-widget.common.js", 16 | "unpkg": "lib/vue-smart-widget.umd.min.js", 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/xiaoluoboding/vue-smart-widget.git" 20 | }, 21 | "homepage": "https://github.com/xiaoluoboding/vue-smart-widget", 22 | "files": [ 23 | "lib/*.js", 24 | "vetur/*.json", 25 | "LICENSE", 26 | "README.md" 27 | ], 28 | "keywords": [ 29 | "widget", 30 | "card", 31 | "panel", 32 | "vue", 33 | "grid", 34 | "drag", 35 | "draggable", 36 | "resize", 37 | "resizable" 38 | ], 39 | "vetur": { 40 | "tags": "vetur/tags.json", 41 | "attributes": "vetur/attributes.json" 42 | }, 43 | "license": "MIT", 44 | "dependencies": { 45 | "vue-grid-layout": "^2.3.11" 46 | }, 47 | "devDependencies": { 48 | "@vue/cli-plugin-babel": "^4.5.9", 49 | "@vue/cli-plugin-eslint": "^4.5.9", 50 | "@vue/cli-service": "^4.5.9", 51 | "@vue/eslint-config-standard": "^6.0.0", 52 | "babel-eslint": "^10.1.0", 53 | "core-js": "^3.8.2", 54 | "echarts": "4.9.0", 55 | "element-ui": "^2.14.1", 56 | "eslint": "^7.17.0", 57 | "eslint-plugin-html": "^6.1.1", 58 | "eslint-plugin-import": "^2.22.1", 59 | "eslint-plugin-node": "^11.1.0", 60 | "eslint-plugin-promise": "^4.2.1", 61 | "eslint-plugin-standard": "^5.0.0", 62 | "eslint-plugin-vue": "^7.4.0", 63 | "less": "^4.0.0", 64 | "less-loader": "^7.2.1", 65 | "v-tooltip": "^2.1.1", 66 | "ve-charts": "^0.9.5", 67 | "vue": "^2.6.12", 68 | "vue-router": "^3.4.9", 69 | "vue-template-compiler": "^2.6.12", 70 | "vuex": "^3.6.0" 71 | }, 72 | "postcss": { 73 | "plugins": { 74 | "autoprefixer": {} 75 | } 76 | }, 77 | "browserslist": [ 78 | "> 1%", 79 | "last 2 versions" 80 | ] 81 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoluoboding/vue-smart-widget/a34ab05922c539cf0710693d4496ca6c73f4b4d2/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | vue-smart-widget 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/components/LoadingMask.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 65 | -------------------------------------------------------------------------------- /src/components/collapse-transition.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | exports.__esModule = true 4 | 5 | function trim (string) { 6 | return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '') 7 | } 8 | 9 | function hasClass (el, cls) { 10 | if (!el || !cls) return false 11 | if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.') 12 | if (el.classList) { 13 | return el.classList.contains(cls) 14 | } else { 15 | return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1 16 | } 17 | } 18 | 19 | function addClass (el, cls) { 20 | if (!el) return 21 | let curClass = el.className 22 | const classes = (cls || '').split(' ') 23 | 24 | for (let i = 0, j = classes.length; i < j; i++) { 25 | const clsName = classes[i] 26 | if (!clsName) continue 27 | 28 | if (el.classList) { 29 | el.classList.add(clsName) 30 | } else if (!hasClass(el, clsName)) { 31 | curClass += ' ' + clsName 32 | } 33 | } 34 | if (!el.classList) { 35 | el.className = curClass 36 | } 37 | } 38 | 39 | function removeClass (el, cls) { 40 | if (!el || !cls) return 41 | const classes = cls.split(' ') 42 | let curClass = ' ' + el.className + ' ' 43 | 44 | for (let i = 0, j = classes.length; i < j; i++) { 45 | const clsName = classes[i] 46 | if (!clsName) continue 47 | 48 | if (el.classList) { 49 | el.classList.remove(clsName) 50 | } else if (hasClass(el, clsName)) { 51 | curClass = curClass.replace(' ' + clsName + ' ', ' ') 52 | } 53 | } 54 | if (!el.classList) { 55 | el.className = trim(curClass) 56 | } 57 | } 58 | 59 | function _classCallCheck (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function') } } 60 | 61 | const Transition = (function () { 62 | function Transition () { 63 | _classCallCheck(this, Transition) 64 | } 65 | 66 | Transition.prototype.beforeEnter = function beforeEnter (el) { 67 | (0, addClass)(el, 'collapse-transition') 68 | if (!el.dataset) el.dataset = {} 69 | 70 | el.dataset.oldPaddingTop = el.style.paddingTop 71 | el.dataset.oldPaddingBottom = el.style.paddingBottom 72 | 73 | el.style.height = '0' 74 | el.style.paddingTop = 0 75 | el.style.paddingBottom = 0 76 | } 77 | 78 | Transition.prototype.enter = function enter (el) { 79 | el.dataset.oldOverflow = el.style.overflow 80 | if (el.scrollHeight !== 0) { 81 | el.style.height = el.scrollHeight + 'px' 82 | el.style.paddingTop = el.dataset.oldPaddingTop 83 | el.style.paddingBottom = el.dataset.oldPaddingBottom 84 | } else { 85 | el.style.height = '' 86 | el.style.paddingTop = el.dataset.oldPaddingTop 87 | el.style.paddingBottom = el.dataset.oldPaddingBottom 88 | } 89 | 90 | el.style.overflow = 'hidden' 91 | } 92 | 93 | Transition.prototype.afterEnter = function afterEnter (el) { 94 | // for safari: remove class then reset height is necessary 95 | (0, removeClass)(el, 'collapse-transition') 96 | el.style.height = '' 97 | el.style.overflow = el.dataset.oldOverflow 98 | } 99 | 100 | Transition.prototype.beforeLeave = function beforeLeave (el) { 101 | if (!el.dataset) el.dataset = {} 102 | el.dataset.oldPaddingTop = el.style.paddingTop 103 | el.dataset.oldPaddingBottom = el.style.paddingBottom 104 | el.dataset.oldOverflow = el.style.overflow 105 | 106 | el.style.height = el.scrollHeight + 'px' 107 | el.style.overflow = 'hidden' 108 | } 109 | 110 | Transition.prototype.leave = function leave (el) { 111 | if (el.scrollHeight !== 0) { 112 | // for safari: add class after set height, or it will jump to zero height suddenly, weired 113 | (0, addClass)(el, 'collapse-transition') 114 | el.style.height = 0 115 | el.style.paddingTop = 0 116 | el.style.paddingBottom = 0 117 | } 118 | } 119 | 120 | Transition.prototype.afterLeave = function afterLeave (el) { 121 | (0, removeClass)(el, 'collapse-transition') 122 | el.style.height = '' 123 | el.style.overflow = el.dataset.oldOverflow 124 | el.style.paddingTop = el.dataset.oldPaddingTop 125 | el.style.paddingBottom = el.dataset.oldPaddingBottom 126 | } 127 | 128 | return Transition 129 | }()) 130 | 131 | exports.default = { 132 | name: 'ElCollapseTransition', 133 | functional: true, 134 | render: function render (h, _ref) { 135 | const children = _ref.children 136 | 137 | const data = { 138 | on: new Transition() 139 | } 140 | 141 | return h('transition', data, children) 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import SmartWidgetGrid from './packages/SmartWidgetGrid' 2 | import SmartWidget from './packages/SmartWidget' 3 | 4 | const components = [ 5 | SmartWidgetGrid, 6 | SmartWidget 7 | ] 8 | 9 | function install (Vue, _) { 10 | components.forEach(component => { 11 | Vue.component(component.name, component) 12 | }) 13 | } 14 | 15 | export default install 16 | 17 | export { 18 | SmartWidgetGrid, 19 | SmartWidget 20 | } 21 | 22 | if (typeof window !== 'undefined' && window.Vue) { 23 | window.Vue.use(install) 24 | if (install.installed) { 25 | install.installed = false 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/packages/SmartWidget.vue: -------------------------------------------------------------------------------- 1 | 97 | 98 | 300 | 301 | 315 | 316 | 442 | -------------------------------------------------------------------------------- /src/packages/SmartWidgetGrid.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 127 | 128 | 141 | -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | // Picks the key-value pairs corresponding to the given keys from an object. 2 | export const pick = (obj, arr) => { 3 | return arr.reduce((acc, curr) => { 4 | return (curr in obj && (acc[curr] = obj[curr]), acc) 5 | }, {}) 6 | } 7 | 8 | // Maps the values of an array to an object using a function. 9 | export const mapObject = (arr, fn) => 10 | arr.reduce((acc, el, i) => { 11 | acc[el] = fn(el, i, arr) 12 | return acc 13 | }, {}) 14 | -------------------------------------------------------------------------------- /vetur/attributes.json: -------------------------------------------------------------------------------- 1 | { 2 | "smart-widget/title": { 3 | "description": "set the widget main title", 4 | "type": "string" 5 | }, 6 | "smart-widget/subTitle": { 7 | "description": "set the widget secondary title", 8 | "type": "string" 9 | }, 10 | "smart-widget/padding": { 11 | "description": "set `widget-body__content` padding style, type: number | number[], default: [12, 20]", 12 | "type": "number | array" 13 | }, 14 | "smart-widget/simple": { 15 | "description": "whether show widget header, default: false", 16 | "type": "boolean" 17 | }, 18 | "smart-widget/loading": { 19 | "description": "toggle loading mask, default: false", 20 | "type": "boolean" 21 | }, 22 | "smart-widget/fullscreen": { 23 | "description": "toggle fullscreen button, default: false", 24 | "type": "boolean" 25 | }, 26 | "smart-widget/collapse": { 27 | "description": "toggle collapse button, default: false", 28 | "type": "boolean" 29 | }, 30 | "smart-widget/refresh": { 31 | "description": "toggle refresh button, default: false", 32 | "type": "boolean" 33 | }, 34 | "smart-widget/fixedHeight": { 35 | "description": "toggle `widget-body__content` fixed height, default: false", 36 | "type": "boolean" 37 | }, 38 | "smart-widget/shadow": { 39 | "description": "when to show card shadows, default: 'always'", 40 | "type": "string" 41 | }, 42 | "smart-widget/translateY": { 43 | "description": "when to show card shadows, default: 0", 44 | "type": "number" 45 | }, 46 | "smart-widget/isActived": { 47 | "description": "whether widget actived, default: false", 48 | "type": "boolean" 49 | }, 50 | "smart-widget/activedColor": { 51 | "description": "widget actived color, default: #0076db", 52 | "type": "string" 53 | }, 54 | "smart-widget/headerHeight": { 55 | "description": "widget header height, the value should be a natural number. default: 48", 56 | "type": "number" 57 | }, 58 | "smart-widget-grid/layout": { 59 | "description": "This is the initial layout of the grid. Required. The value must be an Array of Object items. Each item must have i, x, y, w and h properties.", 60 | "type": "array" 61 | }, 62 | "smart-widget-grid/responsiveLayouts": { 63 | "version": ">=0.6.0", 64 | "description": "Says how many columns the grid has. The value should be a natural number. Default: {}", 65 | "type": "object" 66 | }, 67 | "smart-widget-grid/colNum": { 68 | "description": "This is the initial layouts of the grid per breakpoint if responsive is set to true. Default: 12", 69 | "type": "number" 70 | }, 71 | "smart-widget-grid/rowHeight": { 72 | "description": "Says what is a height of a single row in pixels. Default: 48", 73 | "type": "number" 74 | }, 75 | "smart-widget-grid/maxRows": { 76 | "description": "Says what is a maximal number of rows in the grid. Default: Infinity", 77 | "type": "number" 78 | }, 79 | "smart-widget-grid/margin": { 80 | "description": "Says what are the margins of elements inside the grid. The value must be a two-element Array of Number. Each value is expressed in pixels. The first element is a margin horizontally, the second element is a vertical margin.", 81 | "type": "array" 82 | }, 83 | "smart-widget-grid/draggable": { 84 | "description": "Says if the grids items are draggable. Default: true", 85 | "type": "boolean" 86 | }, 87 | "smart-widget-grid/resizable": { 88 | "description": "Says if the grids items are resizable. Default: true", 89 | "type": "boolean" 90 | }, 91 | "smart-widget-grid/isMirrored": { 92 | "description": "Says if the RTL/LTR should be reversed. Default: false", 93 | "type": "boolean" 94 | }, 95 | "smart-widget-grid/autoSize": { 96 | "description": "Says if the container height should swells and contracts to fit contents. Default: true", 97 | "type": "boolean" 98 | }, 99 | "smart-widget-grid/verticalCompact": { 100 | "description": "Says if the layout should be compact vertically. Default: true", 101 | "type": "boolean" 102 | }, 103 | "smart-widget-grid/preventCollision": { 104 | "version": ">=0.6.0", 105 | "description": "Says if grid items will move when being dragged over. Default: false", 106 | "type": "boolean" 107 | }, 108 | "smart-widget-grid/useCssTransforms": { 109 | "description": "Says if the CSS transition-property: transform; should be used. Default: false", 110 | "type": "boolean" 111 | }, 112 | "smart-widget-grid/responsive": { 113 | "description": "Says if the layout should be responsive to window width. Default: false", 114 | "type": "boolean" 115 | }, 116 | "smart-widget-grid/breakpoints": { 117 | "version": ">=0.6.0", 118 | "description": "Breakpoints defined for responsive layout. Sets widths on wich column number changes. Default: { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }", 119 | "type": "object" 120 | }, 121 | "smart-widget-grid/cols": { 122 | "version": ">=0.6.0", 123 | "description": "Defines number of columns for each breakpoint. Default: { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }", 124 | "type": "object" 125 | }, 126 | "smart-widget-grid/useStyleCursor": { 127 | "version": ">=0.6.0", 128 | "description": "Says if set the styleCursor option to true. When dragging freezes, setting this value to false may alleviate problems. This property is not reactive. Default: true", 129 | "type": "boolean" 130 | }, 131 | "smart-widget-grid/isStatic": { 132 | "description": "Says if all grid item is static (won't be draggable, resizable or moved by other items), Default: false", 133 | "type": "boolean" 134 | }, 135 | "smart-widget-grid/layout-created": { "type": "methods" }, 136 | "smart-widget-grid/layout-before-mount": { "type": "methods" }, 137 | "smart-widget-grid/layout-mounted": { "type": "methods" }, 138 | "smart-widget-grid/layout-ready": { "type": "methods" }, 139 | "smart-widget-grid/layout-updated": { "type": "methods" }, 140 | "smart-widget-grid/breakpoint-changed": { "type": "methods" }, 141 | "smart-widget-grid/move": { "type": "methods" }, 142 | "smart-widget-grid/moved": { "type": "methods" }, 143 | "smart-widget-grid/resize": { "type": "methods" }, 144 | "smart-widget-grid/resized": { "type": "methods" }, 145 | "smart-widget-grid/container-resized": { "type": "methods" } 146 | } -------------------------------------------------------------------------------- /vetur/tags.json: -------------------------------------------------------------------------------- 1 | { 2 | "smart-widget": { 3 | "description": "Smart widget is a flexible and extensible content container component.", 4 | "attributes": [ 5 | "title", 6 | "subTitle", 7 | "padding", 8 | "simple", 9 | "loading", 10 | "fullscreen", 11 | "collapse", 12 | "refresh", 13 | "fixedHeight", 14 | "shadow", 15 | "translateY", 16 | "isActived", 17 | "activedColor", 18 | "headerHeight" 19 | ], 20 | "defaults": ["title"] 21 | }, 22 | "smart-widget-grid": { 23 | "description": " is a draggable and resizable grid layout using component.", 24 | "attributes": [ 25 | "layout", 26 | "responsiveLayouts", 27 | "colNum", 28 | "rowHeight", 29 | "maxRows", 30 | "margin", 31 | "draggable", 32 | "resizable", 33 | "isMirrored", 34 | "autoSize", 35 | "verticalCompact", 36 | "preventCollision", 37 | "useCssTransforms", 38 | "responsive", 39 | "breakpoints", 40 | "cols", 41 | "useStyleCursor", 42 | "isStatic" 43 | ], 44 | "defaults": ["layout"] 45 | } 46 | } -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | const isProd = process.env.NODE_ENV === 'production' 4 | const isLib = process.env.VUE_APP_BUILD_MODE === 'lib' 5 | const resolve = dir => path.join(__dirname, dir) 6 | 7 | const setChainWebpack = config => { 8 | config.resolve.alias 9 | .set('@', path.resolve('app')) 10 | config.module 11 | .rule('js') 12 | .include 13 | .add('/app') 14 | .end() 15 | .use('babel') 16 | .loader('babel-loader') 17 | 18 | if (isProd) { 19 | config.performance 20 | .set('maxEntrypointSize', 2500000) 21 | .set('maxAssetSize', 2000000) 22 | // drop console 23 | config.optimization.minimizer('terser').tap((args) => { 24 | args[0].terserOptions.compress.drop_console = true 25 | return args 26 | }) 27 | } 28 | } 29 | 30 | const setConfigureWebpack = config => { 31 | if (isLib) { 32 | config.output = { 33 | ...config.output, 34 | library: 'VueSmartWidget', 35 | libraryExport: 'default' 36 | } 37 | } 38 | } 39 | 40 | module.exports = { 41 | publicPath: './', 42 | pages: { 43 | index: { 44 | entry: resolve('app/main.js') 45 | } 46 | }, 47 | lintOnSave: true, 48 | productionSourceMap: false, 49 | chainWebpack: config => setChainWebpack(config), 50 | configureWebpack: config => setConfigureWebpack(config), 51 | css: { 52 | extract: false 53 | }, 54 | devServer: { 55 | port: 8181, 56 | open: true, 57 | overlay: { 58 | warnings: true, 59 | errors: true 60 | } 61 | } 62 | } 63 | --------------------------------------------------------------------------------