quasar
Version:
Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time
184 lines (155 loc) • 4.64 kB
JavaScript
import { isRuntimeSsrPreHydration, client } from '../platform/Platform.js'
import { createReactivePlugin } from '../../utils/private.create/create.js'
import { listenOpts, noop } from '../../utils/event/event.js'
import debounce from '../../utils/debounce/debounce.js'
const SIZE_LIST = [ 'sm', 'md', 'lg', 'xl' ]
const { passive } = listenOpts
export default createReactivePlugin({
width: 0,
height: 0,
name: 'xs',
sizes: {
sm: 600,
md: 1024,
lg: 1440,
xl: 1920
},
lt: {
sm: true,
md: true,
lg: true,
xl: true
},
gt: {
xs: false,
sm: false,
md: false,
lg: false
},
xs: true,
sm: false,
md: false,
lg: false,
xl: false
}, {
setSizes: noop,
setDebounce: noop,
install ({ $q, onSSRHydrated }) {
$q.screen = this
if (__QUASAR_SSR_SERVER__) return
if (this.__installed === true) {
if ($q.config.screen !== void 0) {
if ($q.config.screen.bodyClasses === false) {
document.body.classList.remove(`screen--${ this.name }`)
}
else {
this.__update(true)
}
}
return
}
const { visualViewport } = window
const target = visualViewport || window
const scrollingElement = document.scrollingElement || document.documentElement
const getSize = visualViewport === void 0 || client.is.mobile === true
? () => [
Math.max(window.innerWidth, scrollingElement.clientWidth),
Math.max(window.innerHeight, scrollingElement.clientHeight)
]
: () => [
visualViewport.width * visualViewport.scale + window.innerWidth - scrollingElement.clientWidth,
visualViewport.height * visualViewport.scale + window.innerHeight - scrollingElement.clientHeight
]
const classes = $q.config.screen !== void 0 && $q.config.screen.bodyClasses === true
this.__update = force => {
const [ w, h ] = getSize()
if (h !== this.height) {
this.height = h
}
if (w !== this.width) {
this.width = w
}
else if (force !== true) {
return
}
let s = this.sizes
this.gt.xs = w >= s.sm
this.gt.sm = w >= s.md
this.gt.md = w >= s.lg
this.gt.lg = w >= s.xl
this.lt.sm = w < s.sm
this.lt.md = w < s.md
this.lt.lg = w < s.lg
this.lt.xl = w < s.xl
this.xs = this.lt.sm
this.sm = this.gt.xs === true && this.lt.md === true
this.md = this.gt.sm === true && this.lt.lg === true
this.lg = this.gt.md === true && this.lt.xl === true
this.xl = this.gt.lg
s = (this.xs === true && 'xs')
|| (this.sm === true && 'sm')
|| (this.md === true && 'md')
|| (this.lg === true && 'lg')
|| 'xl'
if (s !== this.name) {
if (classes === true) {
document.body.classList.remove(`screen--${ this.name }`)
document.body.classList.add(`screen--${ s }`)
}
this.name = s
}
}
let updateEvt, updateSizes = {}, updateDebounce = 16
this.setSizes = sizes => {
SIZE_LIST.forEach(name => {
if (sizes[ name ] !== void 0) {
updateSizes[ name ] = sizes[ name ]
}
})
}
this.setDebounce = deb => {
updateDebounce = deb
}
const start = () => {
const style = getComputedStyle(document.body)
// if css props available
if (style.getPropertyValue('--q-size-sm')) {
SIZE_LIST.forEach(name => {
this.sizes[ name ] = parseInt(style.getPropertyValue(`--q-size-${ name }`), 10)
})
}
this.setSizes = sizes => {
SIZE_LIST.forEach(name => {
if (sizes[ name ]) {
this.sizes[ name ] = sizes[ name ]
}
})
this.__update(true)
}
this.setDebounce = delay => {
updateEvt !== void 0 && target.removeEventListener('resize', updateEvt, passive)
updateEvt = delay > 0
? debounce(this.__update, delay)
: this.__update
target.addEventListener('resize', updateEvt, passive)
}
this.setDebounce(updateDebounce)
if (Object.keys(updateSizes).length !== 0) {
this.setSizes(updateSizes)
updateSizes = void 0 // free up memory
}
else {
this.__update()
}
// due to optimizations, this would be left out otherwise
classes === true && this.name === 'xs'
&& document.body.classList.add('screen--xs')
}
if (isRuntimeSsrPreHydration.value === true) {
onSSRHydrated.push(start)
}
else {
start()
}
}
})