Merge pull request #52 from euvl/height-auto

Height auto
This commit is contained in:
Yev Vlasenko
2017-07-24 19:51:28 +01:00
committed by GitHub
9 changed files with 267 additions and 72 deletions

13
CHANGELOG.md Normal file
View File

@@ -0,0 +1,13 @@
## v1.2.6
* Added `"auto"` value support for `height` property.
* Added `scrollable` flag that allowes modal content to be scrolled when height is "auto".
* Added CHANGELOG file.
## v1.2.5
* `height` and `width` props can be set using percents.
* Better handling of `min-width` and `min-height`

View File

@@ -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,19 @@ 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 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:
```vue
<modal name="foo" height="auto" :scrollable="true">...</modal>
```
#### 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.

View File

@@ -58,27 +58,18 @@
</button>
<button class="blue"
@click="$modal.show('size-modal')">
Demo: Size = 60%
Demo: Width: 60%, Height: auto
</button>
<!--
<button class="green"
@click="$modal.show('input-focus-modal')">
Demo: Focus Input
</button>
-->
<button :class="canBeShown ? 'green' : 'red'"
@click="conditionalShow">
Can <b v-if="!canBeShown">NOT</b> be shown
</button>
</div>
<props-table />
</div>
</template>
<script>
import ModesTable from './components/ModesTable.vue'
import PropsTable from './components/PropsTable.vue'
import DemoErrorModal from './components/DemoErrorModal.vue'
import DemoFocusModal from './components/InputFocusModal.vue'
import DemoLoginModal from './components/DemoLoginModal.vue'
@@ -90,7 +81,6 @@ export default {
name: 'app',
components: {
ModesTable,
PropsTable,
DemoErrorModal,
DemoFocusModal,
DemoLoginModal,

View File

@@ -1,15 +1,51 @@
<template>
<modal name="size-modal"
transition="nice-modal-fade"
:min-width="200"
:min-height="200"
:adaptive="true"
width="60%"
height="60%">
<div style="height: 100%; box-sizing: border-box; padding: 10px; font-size: 13px; overflow: auto">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla dictum purus egestas libero ornare venenatis. Maecenas pharetra tortor eu tortor imperdiet, a faucibus quam finibus. Nulla id lacinia quam. Praesent imperdiet sed magna non finibus. Aenean blandit, mauris vitae lacinia rutrum, nunc mi scelerisque sem, in laoreet sem lectus ut orci. Ut egestas nulla in vehicula feugiat. Vivamus tincidunt nisi vel risus dictum suscipit. Nulla id blandit mi, vulputate aliquam enim.
Praesent sodales diam a tellus imperdiet condimentum. Mauris malesuada libero elit, sed tincidunt velit consectetur sit amet. Praesent consequat lobortis pellentesque. Donec pellentesque eros sit amet arcu bibendum, vel pharetra purus sodales. Morbi aliquam ac augue eu aliquam. Cras id justo sit amet tortor luctus lobortis. Vestibulum risus urna, cursus vitae feugiat non, tincidunt non massa.
transition="nice-modal-fade"
:min-width="200"
:min-height="200"
:pivot-y="0.25"
:adaptive="true"
:scrollable="true"
:reset="true"
width="60%"
height="auto"
@before-open="beforeOpen"
@before-close="beforeClose">
<div class="size-modal-content">
<div>A new paragraph will be added every 5 sec to show how <b>height</b> scales.</div>
<div v-for="(p, i) in paragraphs" :key="i">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla dictum purus egestas libero ornare venenatis. Maecenas pharetra tortor eu tortor imperdiet, a faucibus quam finibus. Nulla id lacinia quam. Praesent imperdiet sed magna non finibus. Aenean blandit, mauris vitae lacinia rutrum, nunc mi scelerisque sem, in laoreet sem lectus ut orci. Ut egestas nulla in vehicula feugiat. Vivamus tincidunt nisi vel risus dictum suscipit. Nulla id blandit mi, vulputate aliquam enim.
</div>
</modal>
</div>
</modal>
</template>
<script>
export default {
name: 'SizeModalTest',
data () {
return {
paragraphs: [true],
timer: null
}
},
methods: {
beforeOpen () {
this.timer = setInterval(() => {
this.paragraphs.push(true)
}, 5000)
},
beforeClose () {
clearInterval(this.timer)
this.timer = null
this.paragraphs = []
}
}
}
</script>
<style>
.size-modal-content {
padding: 10px;
font-style: 13px;
}
</style>

74
dist/index.js vendored

File diff suppressed because one or more lines are too long

74
dist/ssr.index.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
{
"name": "vue-js-modal",
"description": "Modal Component for Vue.js",
"version": "1.2.5",
"version": "1.2.6",
"author": "euvl <yev.vlasenko@gmail.com>",
"main": "dist/index.js",
"repository": {

View File

@@ -2,7 +2,7 @@
<transition name="overlay-fade">
<div v-if="visibility.overlay"
ref="overlay"
class="v--modal-overlay"
:class="overlayClass"
:aria-expanded="visible.toString()"
:data-modal="name"
@mousedown.stop="onBackgroundClick">
@@ -16,7 +16,7 @@
:style="modalStyle"
@mousedown.stop>
<slot/>
<resizer v-if="resizable"
<resizer v-if="resizable && !isAutoHeight"
:min-width="minWidth"
:min-height="minHeight"
@resize="onModalResize"/>
@@ -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 @@
<style>
.v--modal-overlay {
position: fixed;
box-sizing: border-box;
left: 0;
top: 0;
width: 100vw;
@@ -433,12 +468,23 @@
opacity: 1;
}
.v--modal-overlay.scrollable {
height: 100%;
min-height: 100vh;
overflow-y: auto;
padding-bottom: 10px;
}
.v--modal-overlay .v--modal-box {
position: relative;
overflow: hidden;
box-sizing: border-box;
}
.v--modal-overlay.scrollable .v--modal-box {
margin-bottom: 10px;
}
.v--modal {
background-color: white;
text-align: left;

View File

@@ -3,6 +3,7 @@
// "0.001px" => { type: "px", value: 0.001 }
// "0.1%" => { type: "px", value: 0.1 }
// "foo" => { type: "", value: "foo" }
// "auto" => { type: "auto", value: 0 }
var floatRegexp = '[-+]?[0-9]*\.?[0-9]+'
@@ -24,6 +25,13 @@ var types = [
]
var getType = (value) => {
if (value === 'auto') {
return {
type: value,
value: 0
}
}
for (var i = 0; i < types.length; i++) {
let type = types[i]
if (type.regexp.test(value)) {