From 31ac33e206e8c1af1e381a56f76436d98a03d102 Mon Sep 17 00:00:00 2001 From: euvl Date: Mon, 24 Jul 2017 13:35:25 +0100 Subject: [PATCH 1/5] Added support fro height: auto and scrollable flag --- demo/client_side_rendering/src/App.vue | 12 +-- .../src/components/SizeModal.vue | 61 +++++++++++--- dist/index.js | 74 +++++++++++++---- src/Modal.vue | 80 +++++++++++++++---- src/parser.js | 8 ++ 5 files changed, 180 insertions(+), 55 deletions(-) diff --git a/demo/client_side_rendering/src/App.vue b/demo/client_side_rendering/src/App.vue index 88e15a3..32c2c5c 100644 --- a/demo/client_side_rendering/src/App.vue +++ b/demo/client_side_rendering/src/App.vue @@ -58,27 +58,18 @@ - - - + \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 8b35690..66f6e77 100644 --- a/dist/index.js +++ b/dist/index.js @@ -566,6 +566,10 @@ exports.default = { type: [Boolean, String], default: false }, + scrollable: { + type: Boolean, + default: false + }, reset: { type: Boolean, default: false @@ -612,6 +616,10 @@ exports.default = { default: 300, validator: function validator(value) { if (typeof value === 'string') { + if (value === 'auto') { + return true; + } + var height = (0, _parser2.default)(value); return (height.type === '%' || height.type === 'px') && height.value > 0; } @@ -672,7 +680,6 @@ exports.default = { if (value) { this.visibility.overlay = true; - setTimeout(function () { _this.visibility.modal = true; _this.$nextTick(function () { @@ -709,44 +716,74 @@ exports.default = { window.addEventListener('resize', this.onWindowResize); this.onWindowResize(); + + if (this.scrollable && !this.isAutoHeight) { + console.warn('Modal "' + this.name + '" has scrollable flag set to true ' + ('but height is not "auto" (' + this.height + ')')); + } }, beforeDestroy: function beforeDestroy() { window.removeEventListener('resize', this.onWindowResize); }, computed: { + isAutoHeight: function isAutoHeight() { + return this.modal.heightType === 'auto'; + }, position: function position() { var window = this.window, modal = this.modal, - shift = this.shift; + shift = this.shift, + pivotX = this.pivotX, + pivotY = this.pivotY, + trueModalWidth = this.trueModalWidth, + trueModalHeight = this.trueModalHeight, + isAutoHeight = this.isAutoHeight; - var maxLeft = window.width - this.trueModalWidth; - var maxTop = window.height - this.trueModalHeight; + var maxLeft = window.width - trueModalWidth; + var maxTop = window.height - trueModalHeight; - var left = shift.left + this.pivotX * (window.width - this.trueModalWidth); - var top = shift.top + this.pivotY * (window.height - this.trueModalHeight); + var minTop = this.scrollable ? Number.NEGATIVE_INFINITY : 0; + + var left = shift.left + pivotX * maxLeft; + var top = shift.top + pivotY * maxTop; return { left: (0, _util.inRange)(0, maxLeft, left), - top: (0, _util.inRange)(0, maxTop, top) + top: (0, _util.inRange)(minTop, maxTop, top) }; }, trueModalWidth: function trueModalWidth() { var window = this.window, - modal = this.modal; + modal = this.modal, + adaptive = this.adaptive, + minWidth = this.minWidth; + var value = modal.widthType === '%' ? window.width / 100 * modal.width : modal.width; - return this.adaptive ? (0, _util.inRange)(this.minWidth, this.window.width, value) : value; + return adaptive ? (0, _util.inRange)(minWidth, window.width, value) : value; }, trueModalHeight: function trueModalHeight() { var window = this.window, - modal = this.modal; + modal = this.modal, + isAutoHeight = this.isAutoHeight, + adaptive = this.adaptive; + var value = modal.heightType === '%' ? window.height / 100 * modal.height : modal.height; - return this.adaptive ? (0, _util.inRange)(this.minHeight, this.window.height, value) : value; + if (isAutoHeight) { + return 0; + } + + return adaptive ? (0, _util.inRange)(this.minHeight, this.window.height, value) : value; + }, + overlayClass: function overlayClass() { + return { + 'v--modal-overlay': true, + 'scrollable': this.scrollable && this.isAutoHeight + }; }, modalClass: function modalClass() { return ['v--modal-box', this.classes]; @@ -756,7 +793,7 @@ exports.default = { top: this.position.top + 'px', left: this.position.left + 'px', width: this.trueModalWidth + 'px', - height: this.trueModalHeight + 'px' + height: this.isAutoHeight ? 'auto' : this.trueModalHeight + 'px' }; } }, @@ -1034,6 +1071,13 @@ var types = [{ }]; var getType = function getType(value) { + if (value === 'auto') { + return { + type: value, + value: 0 + }; + } + for (var i = 0; i < types.length; i++) { var type = types[i]; if (type.regexp.test(value)) { @@ -1072,7 +1116,7 @@ exports = module.exports = __webpack_require__(2)(); // module -exports.push([module.i, "\n.v--modal-overlay {\n position: fixed;\n left: 0;\n top: 0;\n width: 100vw;\n height: 100vh;\n background: rgba(0, 0, 0, 0.2);\n z-index: 999;\n opacity: 1;\n}\n.v--modal-overlay .v--modal-box {\n position: relative;\n overflow: hidden;\n box-sizing: border-box;\n}\n.v--modal {\n background-color: white;\n text-align: left;\n border-radius: 3px;\n box-shadow: 0 20px 60px -2px rgba(27, 33, 58, .4);\n padding: 0;\n}\n.v--modal.v--modal-fullscreen {\n width: 100vw;\n height: 100vh;\n margin: 0;\n left: 0;\n top: 0;\n}\n.v--modal-top-right {\n display: block;\n position: absolute;\n right: 0;\n top: 0;\n}\n.overlay-fade-enter-active, .overlay-fade-leave-active {\n transition: all 0.2s;\n}\n.overlay-fade-enter, .overlay-fade-leave-active {\n opacity: 0;\n}\n.nice-modal-fade-enter-active, .nice-modal-fade-leave-active {\n transition: all 0.4s;\n}\n.nice-modal-fade-enter, .nice-modal-fade-leave-active {\n opacity: 0;\n transform: translateY(-20px);\n}\n", "", {"version":3,"sources":["/./src/Modal.vue?17bbad80"],"names":[],"mappings":";AAwaA;EACA,gBAAA;EACA,QAAA;EACA,OAAA;EACA,aAAA;EACA,cAAA;EACA,+BAAA;EACA,aAAA;EACA,WAAA;CACA;AAEA;EACA,mBAAA;EACA,iBAAA;EACA,uBAAA;CACA;AAEA;EACA,wBAAA;EACA,iBAAA;EACA,mBAAA;EACA,kDAAA;EACA,WAAA;CACA;AAEA;EACA,aAAA;EACA,cAAA;EACA,UAAA;EACA,QAAA;EACA,OAAA;CACA;AAEA;EACA,eAAA;EACA,mBAAA;EACA,SAAA;EACA,OAAA;CACA;AAEA;EACA,qBAAA;CACA;AAEA;EACA,WAAA;CACA;AAEA;EACA,qBAAA;CACA;AAEA;EACA,WAAA;EACA,6BAAA;CACA","file":"Modal.vue","sourcesContent":["\n\n\n"],"sourceRoot":"webpack://"}]); +exports.push([module.i, "\n.v--modal-overlay {\n position: fixed;\n box-sizing: border-box;\n left: 0;\n top: 0;\n width: 100vw;\n height: 100vh;\n background: rgba(0, 0, 0, 0.2);\n z-index: 999;\n opacity: 1;\n}\n.v--modal-overlay.scrollable {\n height: 100%;\n min-height: 100vh;\n overflow-y: auto;\n padding-bottom: 10px;\n}\n.v--modal-overlay .v--modal-box {\n position: relative;\n overflow: hidden;\n box-sizing: border-box;\n}\n.v--modal-overlay.scrollable .v--modal-box {\n margin-bottom: 10px;\n}\n.v--modal {\n background-color: white;\n text-align: left;\n border-radius: 3px;\n box-shadow: 0 20px 60px -2px rgba(27, 33, 58, .4);\n padding: 0;\n}\n.v--modal.v--modal-fullscreen {\n width: 100vw;\n height: 100vh;\n margin: 0;\n left: 0;\n top: 0;\n}\n.v--modal-top-right {\n display: block;\n position: absolute;\n right: 0;\n top: 0;\n}\n.overlay-fade-enter-active, .overlay-fade-leave-active {\n transition: all 0.2s;\n}\n.overlay-fade-enter, .overlay-fade-leave-active {\n opacity: 0;\n}\n.nice-modal-fade-enter-active, .nice-modal-fade-leave-active {\n transition: all 0.4s;\n}\n.nice-modal-fade-enter, .nice-modal-fade-leave-active {\n opacity: 0;\n transform: translateY(-20px);\n}\n", "", {"version":3,"sources":["/./src/Modal.vue?79cb8c95"],"names":[],"mappings":";AA0cA;EACA,gBAAA;EACA,uBAAA;EACA,QAAA;EACA,OAAA;EACA,aAAA;EACA,cAAA;EACA,+BAAA;EACA,aAAA;EACA,WAAA;CACA;AAEA;EACA,aAAA;EACA,kBAAA;EACA,iBAAA;EACA,qBAAA;CACA;AAEA;EACA,mBAAA;EACA,iBAAA;EACA,uBAAA;CACA;AAEA;EACA,oBAAA;CACA;AAEA;EACA,wBAAA;EACA,iBAAA;EACA,mBAAA;EACA,kDAAA;EACA,WAAA;CACA;AAEA;EACA,aAAA;EACA,cAAA;EACA,UAAA;EACA,QAAA;EACA,OAAA;CACA;AAEA;EACA,eAAA;EACA,mBAAA;EACA,SAAA;EACA,OAAA;CACA;AAEA;EACA,qBAAA;CACA;AAEA;EACA,WAAA;CACA;AAEA;EACA,qBAAA;CACA;AAEA;EACA,WAAA;EACA,6BAAA;CACA","file":"Modal.vue","sourcesContent":["\n\n\n"],"sourceRoot":"webpack://"}]); // exports @@ -1140,7 +1184,7 @@ module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c } }, [(_vm.visibility.overlay) ? _c('div', { ref: "overlay", - staticClass: "v--modal-overlay", + class: _vm.overlayClass, attrs: { "aria-expanded": _vm.visible.toString(), "data-modal": _vm.name @@ -1166,7 +1210,7 @@ module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c $event.stopPropagation(); } } - }, [_vm._t("default"), _vm._v(" "), (_vm.resizable) ? _c('resizer', { + }, [_vm._t("default"), _vm._v(" "), (_vm.resizable && !_vm.isAutoHeight) ? _c('resizer', { attrs: { "min-width": _vm.minWidth, "min-height": _vm.minHeight diff --git a/src/Modal.vue b/src/Modal.vue index f583092..7b84761 100644 --- a/src/Modal.vue +++ b/src/Modal.vue @@ -2,7 +2,7 @@
@@ -16,7 +16,7 @@ :style="modalStyle" @mousedown.stop> - @@ -55,6 +55,10 @@ type: [Boolean, String], default: false }, + scrollable: { + type: Boolean, + default: false + }, reset: { type: Boolean, default: false @@ -102,6 +106,10 @@ default: 300, validator (value) { if (typeof value === 'string') { + if (value === 'auto') { + return true + } + let height = parseNumber(value) return (height.type === '%' || height.type === 'px') && height.value > 0 @@ -159,7 +167,6 @@ visible (value) { if (value) { this.visibility.overlay = true - // this.adaptSize() setTimeout(() => { this.visibility.modal = true @@ -195,50 +202,75 @@ window.addEventListener('resize', this.onWindowResize) this.onWindowResize() + + if (this.scrollable && !this.isAutoHeight) { + console.warn(`Modal "${this.name}" has scrollable flag set to true ` + + `but height is not "auto" (${this.height})`) + } }, beforeDestroy () { window.removeEventListener('resize', this.onWindowResize) }, computed: { + isAutoHeight () { + return this.modal.heightType === 'auto' + }, + position () { - const { window, modal, shift } = this + const { window, modal, shift, pivotX, pivotY, + trueModalWidth, trueModalHeight, isAutoHeight } = this - const maxLeft = window.width - this.trueModalWidth - const maxTop = window.height - this.trueModalHeight + const maxLeft = window.width - trueModalWidth + const maxTop = window.height - trueModalHeight - const left = shift.left + - this.pivotX * (window.width - this.trueModalWidth) - const top = shift.top + - this.pivotY * (window.height - this.trueModalHeight) + const minTop = this.scrollable + ? Number.NEGATIVE_INFINITY + : 0 + + const left = shift.left + pivotX * maxLeft + const top = shift.top + pivotY * maxTop return { left: inRange(0, maxLeft, left), - top: inRange(0, maxTop, top) + top: inRange(minTop, maxTop, top) } }, trueModalWidth () { - const { window, modal } = this + const { window, modal, adaptive, minWidth } = this + const value = modal.widthType === '%' ? window.width / 100 * modal.width : modal.width - return this.adaptive - ? inRange(this.minWidth, this.window.width, value) + return adaptive + ? inRange(minWidth, window.width, value) : value }, trueModalHeight () { - const { window, modal } = this + const { window, modal, isAutoHeight, adaptive } = this + const value = (modal.heightType === '%') ? window.height / 100 * modal.height : modal.height - return this.adaptive + if (isAutoHeight) { + return 0 + } + + return adaptive ? inRange(this.minHeight, this.window.height, value) : value }, + overlayClass () { + return { + 'v--modal-overlay': true, + 'scrollable': this.scrollable && this.isAutoHeight + } + }, + modalClass () { return ['v--modal-box', this.classes] }, @@ -248,7 +280,9 @@ top: this.position.top + 'px', left: this.position.left + 'px', width: this.trueModalWidth + 'px', - height: this.trueModalHeight + 'px' + height: this.isAutoHeight + ? 'auto' + : (this.trueModalHeight + 'px') } } }, @@ -424,6 +458,7 @@ \n"],"sourceRoot":"webpack://"}]); +exports.push([module.i, "\n.v--modal-overlay {\n position: fixed;\n box-sizing: border-box;\n left: 0;\n top: 0;\n width: 100vw;\n height: 100vh;\n background: rgba(0, 0, 0, 0.2);\n z-index: 999;\n opacity: 1;\n}\n.v--modal-overlay.scrollable {\n height: 100%;\n min-height: 100vh;\n overflow-y: auto;\n padding-bottom: 10px;\n}\n.v--modal-overlay .v--modal-box {\n position: relative;\n overflow: hidden;\n box-sizing: border-box;\n}\n.v--modal-overlay.scrollable .v--modal-box {\n margin-bottom: 10px;\n}\n.v--modal {\n background-color: white;\n text-align: left;\n border-radius: 3px;\n box-shadow: 0 20px 60px -2px rgba(27, 33, 58, .4);\n padding: 0;\n}\n.v--modal.v--modal-fullscreen {\n width: 100vw;\n height: 100vh;\n margin: 0;\n left: 0;\n top: 0;\n}\n.v--modal-top-right {\n display: block;\n position: absolute;\n right: 0;\n top: 0;\n}\n.overlay-fade-enter-active, .overlay-fade-leave-active {\n transition: all 0.2s;\n}\n.overlay-fade-enter, .overlay-fade-leave-active {\n opacity: 0;\n}\n.nice-modal-fade-enter-active, .nice-modal-fade-leave-active {\n transition: all 0.4s;\n}\n.nice-modal-fade-enter, .nice-modal-fade-leave-active {\n opacity: 0;\n transform: translateY(-20px);\n}\n", "", {"version":3,"sources":["/./src/Modal.vue?79cb8c95"],"names":[],"mappings":";AA0cA;EACA,gBAAA;EACA,uBAAA;EACA,QAAA;EACA,OAAA;EACA,aAAA;EACA,cAAA;EACA,+BAAA;EACA,aAAA;EACA,WAAA;CACA;AAEA;EACA,aAAA;EACA,kBAAA;EACA,iBAAA;EACA,qBAAA;CACA;AAEA;EACA,mBAAA;EACA,iBAAA;EACA,uBAAA;CACA;AAEA;EACA,oBAAA;CACA;AAEA;EACA,wBAAA;EACA,iBAAA;EACA,mBAAA;EACA,kDAAA;EACA,WAAA;CACA;AAEA;EACA,aAAA;EACA,cAAA;EACA,UAAA;EACA,QAAA;EACA,OAAA;CACA;AAEA;EACA,eAAA;EACA,mBAAA;EACA,SAAA;EACA,OAAA;CACA;AAEA;EACA,qBAAA;CACA;AAEA;EACA,WAAA;CACA;AAEA;EACA,qBAAA;CACA;AAEA;EACA,WAAA;EACA,6BAAA;CACA","file":"Modal.vue","sourcesContent":["\n\n\n"],"sourceRoot":"webpack://"}]); // exports @@ -978,7 +1022,7 @@ module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c } }, [(_vm.visibility.overlay) ? _c('div', { ref: "overlay", - staticClass: "v--modal-overlay", + class: _vm.overlayClass, attrs: { "aria-expanded": _vm.visible.toString(), "data-modal": _vm.name @@ -1004,7 +1048,7 @@ module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c $event.stopPropagation(); } } - }, [_vm._t("default"), _vm._v(" "), (_vm.resizable) ? _c('resizer', { + }, [_vm._t("default"), _vm._v(" "), (_vm.resizable && !_vm.isAutoHeight) ? _c('resizer', { attrs: { "min-width": _vm.minWidth, "min-height": _vm.minHeight diff --git a/package.json b/package.json index dcb9907..8290aad 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vue-js-modal", "description": "Modal Component for Vue.js", - "version": "1.2.5", + "version": "1.2.6", "author": "euvl ", "main": "dist/index.js", "repository": { From 788ee03206f7852f31789125f7c0738e1470df02 Mon Sep 17 00:00:00 2001 From: Yev Vlasenko Date: Mon, 24 Jul 2017 19:39:09 +0100 Subject: [PATCH 3/5] Update README.md --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c1738d8..b5c5de1 100644 --- a/README.md +++ b/README.md @@ -77,12 +77,13 @@ For full demo please look at `demo/server_side_rendering` | resizable | false | Boolean | false | If true, allows to resize modal window, keeping it in the center of the screen. | | adaptive | false | Boolean | false | If true, modal box will try to adapt to the window size | | draggable | false | [Boolean, String]| false | If true, modal box will be draggable. | +| scrollable | false | Boolean | false | If `height` property is `auto` and the modal height exceeds window height - you will be able to scroll modal | | reset | false | Boolean | false | Resets position and size before showing modal | | clickToClose | false | Boolean | true | If set to `false`, it will not be possible to close modal by clicking on the background | | transition| false | String | | Transition name | | classes | false | [String, Array] | 'vue--modal'| Classes that will be applied to the actual modal box, if not specified, the default 'vue--modal' class will be applied | | width | false | [String, Number] | 600 | Width in pixels or percents (e.g. 50 or "50px", "50%") | -| height | false | [String, Number] | 300 | Height in pixels or percents (e.g. 50 or "50px", "50%") | +| height | false | [String, Number] | 300 | Height in pixels or percents (e.g. 50 or "50px", "50%") or `"auto"` | | minWidth | false | Number | 0 | The minimum width to which modal can be resized | | minHeight | false | Number | 0 | The minimum height to which modal can be resized | | pivotX | false | Number (0 - 1.0) | 0.5 | Horizontal position in %, default is 0.5 (meaning that modal box will be in the middle (50% from top) of the window | @@ -140,6 +141,17 @@ And then forbits closing it for the next 5000 ms ### Other +#### Height: "auto" + +From `v1.2.6` height can be set to "auto". If you want to be able to scoll modal content when your it's height exceeds window height - you can set flag `scrollable="true"`. + +Example: + +```vue +... +``` + + #### Close button If you want to have a Close (x) button in the top-right corner, you can use "top-right" slot for it. There is deliberately no predefined Close button style - you will have to implement/use your own button. From 517969696140e9ce6be67a9a8d5f7657036842dc Mon Sep 17 00:00:00 2001 From: Yev Vlasenko Date: Mon, 24 Jul 2017 19:41:16 +0100 Subject: [PATCH 4/5] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b5c5de1..d2d3336 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,9 @@ And then forbits closing it for the next 5000 ms #### Height: "auto" -From `v1.2.6` height can be set to "auto". If you want to be able to scoll modal content when your it's height exceeds window height - you can set flag `scrollable="true"`. +From `v1.2.6` height can be set to "auto". If you want to be able to scroll modal in case it's height exceeds window height - you can set flag `scrollable="true"`. + +p.s. `scrollable` will only work with `height="auto"`. Example: From 7575a27ceb2139a5745e63369e0e0dca3a9fbf95 Mon Sep 17 00:00:00 2001 From: euvl Date: Mon, 24 Jul 2017 19:49:24 +0100 Subject: [PATCH 5/5] Removed not needed prop in example --- demo/client_side_rendering/src/components/SizeModal.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/demo/client_side_rendering/src/components/SizeModal.vue b/demo/client_side_rendering/src/components/SizeModal.vue index 4a6327c..f90b8b8 100644 --- a/demo/client_side_rendering/src/components/SizeModal.vue +++ b/demo/client_side_rendering/src/components/SizeModal.vue @@ -5,7 +5,6 @@ :min-height="200" :pivot-y="0.25" :adaptive="true" - :draggable="true" :scrollable="true" :reset="true" width="60%"