UNPKG

quasar

Version:

Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time

2,018 lines (1,713 loc) 1.04 MB
/*! * Quasar Framework v1.15.16 * (c) 2015-present Razvan Stoenescu * Released under the MIT License. */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('vue')) : typeof define === 'function' && define.amd ? define(['vue'], factory) : (global = global || self, global.Quasar = factory(global.Vue)); }(this, (function (Vue) { 'use strict'; Vue = Vue && Object.prototype.hasOwnProperty.call(Vue, 'default') ? Vue['default'] : Vue; var version = "1.15.16"; /* eslint-disable no-useless-escape */ const isSSR = typeof window === 'undefined'; let fromSSR = false; let onSSR = isSSR; let iosEmulated = false; let iosCorrection; function getMatch (userAgent, platformMatch) { const match = /(edge|edga|edgios)\/([\w.]+)/.exec(userAgent) || /(opr)[\/]([\w.]+)/.exec(userAgent) || /(vivaldi)[\/]([\w.]+)/.exec(userAgent) || /(chrome|crios)[\/]([\w.]+)/.exec(userAgent) || /(iemobile)[\/]([\w.]+)/.exec(userAgent) || /(version)(applewebkit)[\/]([\w.]+).*(safari)[\/]([\w.]+)/.exec(userAgent) || /(webkit)[\/]([\w.]+).*(version)[\/]([\w.]+).*(safari)[\/]([\w.]+)/.exec(userAgent) || /(firefox|fxios)[\/]([\w.]+)/.exec(userAgent) || /(webkit)[\/]([\w.]+)/.exec(userAgent) || /(opera)(?:.*version|)[\/]([\w.]+)/.exec(userAgent) || /(msie) ([\w.]+)/.exec(userAgent) || (userAgent.indexOf('trident') >= 0 && /(rv)(?::| )([\w.]+)/.exec(userAgent)) || (userAgent.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(userAgent)) || []; return { browser: match[5] || match[3] || match[1] || '', version: match[2] || match[4] || '0', versionNumber: match[4] || match[2] || '0', platform: platformMatch[0] || '' } } function getPlatformMatch (userAgent) { return /(ipad)/.exec(userAgent) || /(ipod)/.exec(userAgent) || /(windows phone)/.exec(userAgent) || /(iphone)/.exec(userAgent) || /(kindle)/.exec(userAgent) || /(silk)/.exec(userAgent) || /(android)/.exec(userAgent) || /(win)/.exec(userAgent) || /(mac)/.exec(userAgent) || /(linux)/.exec(userAgent) || /(cros)/.exec(userAgent) || /(playbook)/.exec(userAgent) || /(bb)/.exec(userAgent) || /(blackberry)/.exec(userAgent) || [] } const hasTouch = isSSR === false ? 'ontouchstart' in window || window.navigator.maxTouchPoints > 0 : false; function applyIosCorrection (is) { iosCorrection = { is: { ...is } }; delete is.mac; delete is.desktop; const platform = Math.min(window.innerHeight, window.innerWidth) > 414 ? 'ipad' : 'iphone'; Object.assign(is, { mobile: true, ios: true, platform, [ platform ]: true }); } function getPlatform (UA) { const userAgent = UA.toLowerCase(), platformMatch = getPlatformMatch(userAgent), matched = getMatch(userAgent, platformMatch), browser = {}; if (matched.browser) { browser[matched.browser] = true; browser.version = matched.version; browser.versionNumber = parseInt(matched.versionNumber, 10); } if (matched.platform) { browser[matched.platform] = true; } const knownMobiles = browser.android || browser.ios || browser.bb || browser.blackberry || browser.ipad || browser.iphone || browser.ipod || browser.kindle || browser.playbook || browser.silk || browser['windows phone']; // These are all considered mobile platforms, meaning they run a mobile browser if (knownMobiles === true || userAgent.indexOf('mobile') > -1) { browser.mobile = true; if (browser.edga || browser.edgios) { browser.edge = true; matched.browser = 'edge'; } else if (browser.crios) { browser.chrome = true; matched.browser = 'chrome'; } else if (browser.fxios) { browser.firefox = true; matched.browser = 'firefox'; } } // If it's not mobile we should consider it's desktop platform, meaning it runs a desktop browser // It's a workaround for anonymized user agents // (browser.cros || browser.mac || browser.linux || browser.win) else { browser.desktop = true; } // Set iOS if on iPod, iPad or iPhone if (browser.ipod || browser.ipad || browser.iphone) { browser.ios = true; } if (browser['windows phone']) { browser.winphone = true; delete browser['windows phone']; } // Chrome, Opera 15+, Vivaldi and Safari are webkit based browsers if ( browser.chrome || browser.opr || browser.safari || browser.vivaldi || // we expect unknown, non iOS mobile browsers to be webkit based ( browser.mobile === true && browser.ios !== true && knownMobiles !== true ) ) { browser.webkit = true; } // IE11 has a new token so we will assign it msie to avoid breaking changes if (browser.rv || browser.iemobile) { matched.browser = 'ie'; browser.ie = true; } // Blackberry browsers are marked as Safari on BlackBerry if (browser.safari && browser.blackberry || browser.bb) { matched.browser = 'blackberry'; browser.blackberry = true; } // Playbook browsers are marked as Safari on Playbook if (browser.safari && browser.playbook) { matched.browser = 'playbook'; browser.playbook = true; } // Opera 15+ are identified as opr if (browser.opr) { matched.browser = 'opera'; browser.opera = true; } // Stock Android browsers are marked as Safari on Android. if (browser.safari && browser.android) { matched.browser = 'android'; browser.android = true; } // Kindle browsers are marked as Safari on Kindle if (browser.safari && browser.kindle) { matched.browser = 'kindle'; browser.kindle = true; } // Kindle Silk browsers are marked as Safari on Kindle if (browser.safari && browser.silk) { matched.browser = 'silk'; browser.silk = true; } if (browser.vivaldi) { matched.browser = 'vivaldi'; browser.vivaldi = true; } // Assign the name and platform variable browser.name = matched.browser; browser.platform = matched.platform; if (isSSR === false) { if (userAgent.indexOf('electron') > -1) { browser.electron = true; } else if (document.location.href.indexOf('-extension://') > -1) { browser.bex = true; } else { if (window.Capacitor !== void 0) { browser.capacitor = true; browser.nativeMobile = true; browser.nativeMobileWrapper = 'capacitor'; } else if (window._cordovaNative !== void 0 || window.cordova !== void 0) { browser.cordova = true; browser.nativeMobile = true; browser.nativeMobileWrapper = 'cordova'; } if ( hasTouch === true && browser.mac === true && ( (browser.desktop === true && browser.safari === true) || ( browser.nativeMobile === true && browser.android !== true && browser.ios !== true && browser.ipad !== true ) ) ) { /* * Correction needed for iOS since the default * setting on iPad is to request desktop view; if we have * touch support and the user agent says it's a * desktop, we infer that it's an iPhone/iPad with desktop view * so we must fix the false positives */ applyIosCorrection(browser); } } fromSSR = browser.nativeMobile === void 0 && browser.electron === void 0 && document.querySelector('[data-server-rendered]') !== null; if (fromSSR === true) { onSSR = true; } } return browser } const userAgent = isSSR !== true ? navigator.userAgent || navigator.vendor || window.opera : ''; const ssrClient = { has: { touch: false, webStorage: false }, within: { iframe: false } }; // We export "client" for hydration error-free parts, // like touch directives who do not (and must NOT) wait // for the client takeover; // Do NOT import this directly in your app, unless you really know // what you are doing. const client = isSSR === false ? { userAgent, is: getPlatform(userAgent), has: { touch: hasTouch, webStorage: (() => { try { if (window.localStorage) { return true } } catch (e) {} return false })() }, within: { iframe: window.self !== window.top } } : ssrClient; const Platform = { install ($q, queues) { if (isSSR === true) { // we're on server-side, so we push // to the server queue instead of // applying directly queues.server.push((q, ctx) => { q.platform = this.parseSSR(ctx.ssr); }); } else if (fromSSR === true) { // must match with server-side before // client taking over in order to prevent // hydration errors Object.assign(this, client, iosCorrection, ssrClient); // takeover should increase accuracy for // the rest of the props; we also avoid // hydration errors queues.takeover.push(q => { onSSR = fromSSR = false; Object.assign(q.platform, client); iosCorrection = void 0; }); // we need to make platform reactive // for the takeover phase Vue.util.defineReactive($q, 'platform', this); } else { // we don't have any business with SSR, so // directly applying... Object.assign(this, client); $q.platform = this; } } }; if (isSSR === true) { Platform.parseSSR = (/* ssrContext */ ssr) => { const userAgent = ssr.req.headers['user-agent'] || ssr.req.headers['User-Agent'] || ''; return { ...client, userAgent, is: getPlatform(userAgent) } }; } else { iosEmulated = client.is.ios === true && window.navigator.vendor.toLowerCase().indexOf('apple') === -1; } const listenOpts = { hasPassive: false, passiveCapture: true, notPassiveCapture: true }; try { var opts = Object.defineProperty({}, 'passive', { get () { Object.assign(listenOpts, { hasPassive: true, passive: { passive: true }, notPassive: { passive: false }, passiveCapture: { passive: true, capture: true }, notPassiveCapture: { passive: false, capture: true } }); } }); window.addEventListener('qtest', null, opts); window.removeEventListener('qtest', null, opts); } catch (e) {} function noop () {} function leftClick (e) { return e.button === 0 } function middleClick (e) { return e.button === 1 } function rightClick (e) { return e.button === 2 } function position (e) { if (e.touches && e.touches[0]) { e = e.touches[0]; } else if (e.changedTouches && e.changedTouches[0]) { e = e.changedTouches[0]; } else if (e.targetTouches && e.targetTouches[0]) { e = e.targetTouches[0]; } return { top: e.clientY, left: e.clientX } } function getEventPath (e) { if (e.path) { return e.path } if (e.composedPath) { return e.composedPath() } const path = []; let el = e.target; while (el) { path.push(el); if (el.tagName === 'HTML') { path.push(document); path.push(window); return path } el = el.parentElement; } } // Reasonable defaults const LINE_HEIGHT = 40, PAGE_HEIGHT = 800; function getMouseWheelDistance (e) { let x = e.deltaX, y = e.deltaY; if ((x || y) && e.deltaMode) { const multiplier = e.deltaMode === 1 ? LINE_HEIGHT : PAGE_HEIGHT; x *= multiplier; y *= multiplier; } if (e.shiftKey && !x) { [y, x] = [x, y]; } return { x, y } } function stop (e) { e.stopPropagation(); } function prevent (e) { e.cancelable !== false && e.preventDefault(); } function stopAndPrevent (e) { e.cancelable !== false && e.preventDefault(); e.stopPropagation(); } function stopAndPreventClick (evt) { stopAndPrevent(evt); if (evt.type === 'mousedown') { const handler = e => { e.target === evt.target && stopAndPrevent(e); document.removeEventListener('click', handler, listenOpts.notPassiveCapture); }; document.addEventListener('click', handler, listenOpts.notPassiveCapture); } } function preventDraggable (el, status) { if (el === void 0 || (status === true && el.__dragPrevented === true)) { return } const fn = status === true ? el => { el.__dragPrevented = true; el.addEventListener('dragstart', prevent, listenOpts.notPassiveCapture); } : el => { delete el.__dragPrevented; el.removeEventListener('dragstart', prevent, listenOpts.notPassiveCapture); }; el.querySelectorAll('a, img').forEach(fn); } function create (name, { bubbles = false, cancelable = false } = {}) { try { return new CustomEvent(name, { bubbles, cancelable }) } catch (e) { // IE doesn't support `new Event()`, so... const evt = document.createEvent('Event'); evt.initEvent(name, bubbles, cancelable); return evt } } function addEvt (ctx, targetName, events) { const name = `__q_${targetName}_evt`; ctx[name] = ctx[name] !== void 0 ? ctx[name].concat(events) : events; events.forEach(evt => { evt[0].addEventListener(evt[1], ctx[evt[2]], listenOpts[evt[3]]); }); } function cleanEvt (ctx, targetName) { const name = `__q_${targetName}_evt`; if (ctx[name] !== void 0) { ctx[name].forEach(evt => { evt[0].removeEventListener(evt[1], ctx[evt[2]], listenOpts[evt[3]]); }); ctx[name] = void 0; } } /* * also update /types/utils/event.d.ts */ var event = { listenOpts, leftClick, middleClick, rightClick, position, getEventPath, getMouseWheelDistance, stop, prevent, stopAndPrevent, preventDraggable, create }; function debounce (fn, wait = 250, immediate) { let timeout; function debounced (/* ...args */) { const args = arguments; const later = () => { timeout = void 0; if (immediate !== true) { fn.apply(this, args); } }; clearTimeout(timeout); if (immediate === true && timeout === void 0) { fn.apply(this, args); } timeout = setTimeout(later, wait); } debounced.cancel = () => { clearTimeout(timeout); }; return debounced } const SIZE_LIST = ['sm', 'md', 'lg', 'xl']; const { passive } = listenOpts; var Screen = { 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, queues, cfg) { if (isSSR === true) { $q.screen = this; return } const classes = cfg.screen !== void 0 && cfg.screen.bodyClasses === true; const update = force => { const w = window.innerWidth, h = window.innerHeight; 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), target = window.visualViewport !== void 0 ? window.visualViewport : window; // 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]; } }); update(true); }; this.setDebounce = delay => { updateEvt !== void 0 && target.removeEventListener('resize', updateEvt, passive); updateEvt = delay > 0 ? debounce(update, delay) : 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 { update(); } // due to optimizations, this would be left out otherwise classes === true && this.name === 'xs' && document.body.classList.add(`screen--xs`); }; if (fromSSR === true) { queues.takeover.push(start); } else { start(); } Vue.util.defineReactive($q, 'screen', this); } }; const Dark = { isActive: false, mode: false, install ($q, queues, { dark }) { this.isActive = dark === true; if (isSSR === true) { queues.server.push((q, ctx) => { q.dark = { isActive: false, mode: false, set: val => { ctx.ssr.Q_BODY_CLASSES = ctx.ssr.Q_BODY_CLASSES .replace(' body--light', '') .replace(' body--dark', '') + ` body--${val === true ? 'dark' : 'light'}`; q.dark.isActive = val === true; q.dark.mode = val; }, toggle: () => { q.dark.set(q.dark.isActive === false); } }; q.dark.set(dark); }); this.set = noop; return } const initialVal = dark !== void 0 ? dark : false; if (fromSSR === true) { const ssrSet = val => { this.__fromSSR = val; }; const originalSet = this.set; this.set = ssrSet; ssrSet(initialVal); queues.takeover.push(() => { this.set = originalSet; this.set(this.__fromSSR); }); } else { this.set(initialVal); } Vue.util.defineReactive(this, 'isActive', this.isActive); Vue.util.defineReactive($q, 'dark', this); }, set (val) { this.mode = val; if (val === 'auto') { if (this.__media === void 0) { this.__media = window.matchMedia('(prefers-color-scheme: dark)'); this.__updateMedia = () => { this.set('auto'); }; this.__media.addListener(this.__updateMedia); } val = this.__media.matches; } else if (this.__media !== void 0) { this.__media.removeListener(this.__updateMedia); this.__media = void 0; } this.isActive = val === true; document.body.classList.remove(`body--${val === true ? 'light' : 'dark'}`); document.body.classList.add(`body--${val === true ? 'dark' : 'light'}`); }, toggle () { Dark.set(Dark.isActive === false); }, __media: void 0 }; const getTrue = () => true; function filterInvalidPath (path) { return typeof path === 'string' && path !== '' && path !== '/' && path !== '#/' } function normalizeExitPath (path) { path.startsWith('#') === true && (path = path.substr(1)); path.startsWith('/') === false && (path = '/' + path); path.endsWith('/') === true && (path = path.substr(0, path.length - 1)); return '#' + path } function getShouldExitFn (cfg) { if (cfg.backButtonExit === false) { return () => false } if (cfg.backButtonExit === '*') { return getTrue } // Add default root path const exitPaths = [ '#/' ]; // Add custom exit paths Array.isArray(cfg.backButtonExit) === true && exitPaths.push( ...cfg.backButtonExit.filter(filterInvalidPath).map(normalizeExitPath) ); return () => exitPaths.includes(window.location.hash) } var History = { __history: [], add: noop, remove: noop, install (cfg) { if (isSSR === true) { return } const { cordova, capacitor } = client.is; if (cordova !== true && capacitor !== true) { return } const qConf = cfg[cordova === true ? 'cordova' : 'capacitor']; if (qConf !== void 0 && qConf.backButton === false) { return } // if the '@capacitor/app' plugin is not installed // then we got nothing to do if ( // if we're on Capacitor mode capacitor === true // and it's also not in Capacitor's main instance && (window.Capacitor === void 0 || window.Capacitor.Plugins.App === void 0) ) { return } this.add = entry => { if (entry.condition === void 0) { entry.condition = getTrue; } this.__history.push(entry); }; this.remove = entry => { const index = this.__history.indexOf(entry); if (index >= 0) { this.__history.splice(index, 1); } }; const shouldExit = getShouldExitFn( Object.assign( { backButtonExit: true }, qConf ) ); const backHandler = () => { if (this.__history.length) { const entry = this.__history[this.__history.length - 1]; if (entry.condition() === true) { this.__history.pop(); entry.handler(); } } else if (shouldExit() === true) { navigator.app.exitApp(); } else { window.history.back(); } }; if (cordova === true) { document.addEventListener('deviceready', () => { document.addEventListener('backbutton', backHandler, false); }); } else { window.Capacitor.Plugins.App.addListener('backButton', backHandler); } } }; var langEn = { isoName: 'en-us', nativeName: 'English (US)', label: { clear: 'Clear', ok: 'OK', cancel: 'Cancel', close: 'Close', set: 'Set', select: 'Select', reset: 'Reset', remove: 'Remove', update: 'Update', create: 'Create', search: 'Search', filter: 'Filter', refresh: 'Refresh' }, date: { days: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), daysShort: 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), monthsShort: 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), firstDayOfWeek: 0, // 0-6, 0 - Sunday, 1 Monday, ... format24h: false, pluralDay: 'days' }, table: { noData: 'No data available', noResults: 'No matching records found', loading: 'Loading...', selectedRecords: function (rows) { return rows === 1 ? '1 record selected.' : (rows === 0 ? 'No' : rows) + ' records selected.' }, recordsPerPage: 'Records per page:', allRows: 'All', pagination: function (start, end, total) { return start + '-' + end + ' of ' + total }, columns: 'Columns' }, editor: { url: 'URL', bold: 'Bold', italic: 'Italic', strikethrough: 'Strikethrough', underline: 'Underline', unorderedList: 'Unordered List', orderedList: 'Ordered List', subscript: 'Subscript', superscript: 'Superscript', hyperlink: 'Hyperlink', toggleFullscreen: 'Toggle Fullscreen', quote: 'Quote', left: 'Left align', center: 'Center align', right: 'Right align', justify: 'Justify align', print: 'Print', outdent: 'Decrease indentation', indent: 'Increase indentation', removeFormat: 'Remove formatting', formatting: 'Formatting', fontSize: 'Font Size', align: 'Align', hr: 'Insert Horizontal Rule', undo: 'Undo', redo: 'Redo', heading1: 'Heading 1', heading2: 'Heading 2', heading3: 'Heading 3', heading4: 'Heading 4', heading5: 'Heading 5', heading6: 'Heading 6', paragraph: 'Paragraph', code: 'Code', size1: 'Very small', size2: 'A bit small', size3: 'Normal', size4: 'Medium-large', size5: 'Big', size6: 'Very big', size7: 'Maximum', defaultFont: 'Default Font', viewSource: 'View Source' }, tree: { noNodes: 'No nodes available', noResults: 'No matching nodes found' } }; function getLocale () { if (isSSR === true) { return } const val = navigator.language || navigator.languages[0] || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage; if (val) { return val.toLowerCase() } } var lang = { getLocale, install ($q, queues, lang) { const initialLang = lang || langEn; this.set = (langObject = langEn, ssrContext) => { const lang = { ...langObject, rtl: langObject.rtl === true, getLocale }; if (isSSR === true) { if (ssrContext === void 0) { console.error('SSR ERROR: second param required: Quasar.lang.set(lang, ssrContext)'); return } const dir = lang.rtl === true ? 'rtl' : 'ltr'; const attrs = `lang=${lang.isoName} dir=${dir}`; lang.set = ssrContext.$q.lang.set; ssrContext.Q_HTML_ATTRS = ssrContext.Q_PREV_LANG !== void 0 ? ssrContext.Q_HTML_ATTRS.replace(ssrContext.Q_PREV_LANG, attrs) : attrs; ssrContext.Q_PREV_LANG = attrs; ssrContext.$q.lang = lang; } else { if (fromSSR === false) { const el = document.documentElement; el.setAttribute('dir', lang.rtl === true ? 'rtl' : 'ltr'); el.setAttribute('lang', lang.isoName); } lang.set = this.set; $q.lang = this.props = lang; this.isoName = lang.isoName; this.nativeName = lang.nativeName; } }; if (isSSR === true) { queues.server.push((q, ctx) => { q.lang = {}; q.lang.set = langObject => { this.set(langObject, ctx.ssr); }; q.lang.set(initialLang); }); this.isoName = initialLang.isoName; this.nativeName = initialLang.nativeName; this.props = initialLang; } else { Vue.util.defineReactive($q, 'lang', {}); this.set(initialLang); } } }; const reRGBA = /^rgb(a)?\((\d{1,3}),(\d{1,3}),(\d{1,3}),?([01]?\.?\d*?)?\)$/; function rgbToHex ({ r, g, b, a }) { const alpha = a !== void 0; r = Math.round(r); g = Math.round(g); b = Math.round(b); if ( r > 255 || g > 255 || b > 255 || (alpha && a > 100) ) { throw new TypeError('Expected 3 numbers below 256 (and optionally one below 100)') } a = alpha ? (Math.round(255 * a / 100) | 1 << 8).toString(16).slice(1) : ''; return '#' + ((b | g << 8 | r << 16) | 1 << 24).toString(16).slice(1) + a } function rgbToString ({ r, g, b, a }) { return `rgb${a !== void 0 ? 'a' : ''}(${r},${g},${b}${a !== void 0 ? ',' + (a / 100) : ''})` } function hexToRgb (hex) { if (typeof hex !== 'string') { throw new TypeError('Expected a string') } hex = hex.replace(/^#/, ''); if (hex.length === 3) { hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; } else if (hex.length === 4) { hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3]; } const num = parseInt(hex, 16); return hex.length > 6 ? { r: num >> 24 & 255, g: num >> 16 & 255, b: num >> 8 & 255, a: Math.round((num & 255) / 2.55) } : { r: num >> 16, g: num >> 8 & 255, b: num & 255 } } function hsvToRgb ({ h, s, v, a }) { let r, g, b; s = s / 100; v = v / 100; h = h / 360; const i = Math.floor(h * 6), f = h * 6 - i, p = v * (1 - s), q = v * (1 - f * s), t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v; g = t; b = p; break case 1: r = q; g = v; b = p; break case 2: r = p; g = v; b = t; break case 3: r = p; g = q; b = v; break case 4: r = t; g = p; b = v; break case 5: r = v; g = p; b = q; break } return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255), a } } function rgbToHsv ({ r, g, b, a }) { const max = Math.max(r, g, b), min = Math.min(r, g, b), d = max - min, s = (max === 0 ? 0 : d / max), v = max / 255; let h; switch (max) { case min: h = 0; break case r: h = (g - b) + d * (g < b ? 6 : 0); h /= 6 * d; break case g: h = (b - r) + d * 2; h /= 6 * d; break case b: h = (r - g) + d * 4; h /= 6 * d; break } return { h: Math.round(h * 360), s: Math.round(s * 100), v: Math.round(v * 100), a } } function textToRgb (str) { if (typeof str !== 'string') { throw new TypeError('Expected a string') } const color = str.replace(/ /g, ''); const m = reRGBA.exec(color); if (m === null) { return hexToRgb(color) } const rgb = { r: Math.min(255, parseInt(m[2], 10)), g: Math.min(255, parseInt(m[3], 10)), b: Math.min(255, parseInt(m[4], 10)) }; if (m[1]) { const alpha = parseFloat(m[5]); rgb.a = Math.min(1, isNaN(alpha) === true ? 1 : alpha) * 100; } return rgb } /* works as darken if percent < 0 */ function lighten (color, percent) { if (typeof color !== 'string') { throw new TypeError('Expected a string as color') } if (typeof percent !== 'number') { throw new TypeError('Expected a numeric percent') } const rgb = textToRgb(color), t = percent < 0 ? 0 : 255, p = Math.abs(percent) / 100, R = rgb.r, G = rgb.g, B = rgb.b; return '#' + ( 0x1000000 + (Math.round((t - R) * p) + R) * 0x10000 + (Math.round((t - G) * p) + G) * 0x100 + (Math.round((t - B) * p) + B) ).toString(16).slice(1) } function luminosity (color) { if (typeof color !== 'string' && (!color || color.r === void 0)) { throw new TypeError('Expected a string or a {r, g, b} object as color') } const rgb = typeof color === 'string' ? textToRgb(color) : color, r = rgb.r / 255, g = rgb.g / 255, b = rgb.b / 255, R = r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4), G = g <= 0.03928 ? g / 12.92 : Math.pow((g + 0.055) / 1.055, 2.4), B = b <= 0.03928 ? b / 12.92 : Math.pow((b + 0.055) / 1.055, 2.4); return 0.2126 * R + 0.7152 * G + 0.0722 * B } function brightness (color) { if (typeof color !== 'string' && (!color || color.r === void 0)) { throw new TypeError('Expected a string or a {r, g, b} object as color') } const rgb = typeof color === 'string' ? textToRgb(color) : color; return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000 } function blend (fgColor, bgColor) { if (typeof fgColor !== 'string' && (!fgColor || fgColor.r === void 0)) { throw new TypeError('Expected a string or a {r, g, b[, a]} object as fgColor') } if (typeof bgColor !== 'string' && (!bgColor || bgColor.r === void 0)) { throw new TypeError('Expected a string or a {r, g, b[, a]} object as bgColor') } const rgb1 = typeof fgColor === 'string' ? textToRgb(fgColor) : fgColor, r1 = rgb1.r / 255, g1 = rgb1.g / 255, b1 = rgb1.b / 255, a1 = rgb1.a !== void 0 ? rgb1.a / 100 : 1, rgb2 = typeof bgColor === 'string' ? textToRgb(bgColor) : bgColor, r2 = rgb2.r / 255, g2 = rgb2.g / 255, b2 = rgb2.b / 255, a2 = rgb2.a !== void 0 ? rgb2.a / 100 : 1, a = a1 + a2 * (1 - a1), r = Math.round(((r1 * a1 + r2 * a2 * (1 - a1)) / a) * 255), g = Math.round(((g1 * a1 + g2 * a2 * (1 - a1)) / a) * 255), b = Math.round(((b1 * a1 + b2 * a2 * (1 - a1)) / a) * 255); const ret = { r, g, b, a: Math.round(a * 100) }; return typeof fgColor === 'string' ? rgbToHex(ret) : ret } function changeAlpha (color, offset) { if (typeof color !== 'string') { throw new TypeError('Expected a string as color') } if (offset === void 0 || offset < -1 || offset > 1) { throw new TypeError('Expected offset to be between -1 and 1') } const { r, g, b, a } = textToRgb(color); const alpha = a !== void 0 ? a / 100 : 0; return rgbToHex({ r, g, b, a: Math.round(Math.min(1, Math.max(0, alpha + offset)) * 100) }) } function setBrand (color, value, element = document.body) { if (typeof color !== 'string') { throw new TypeError('Expected a string as color') } if (typeof value !== 'string') { throw new TypeError('Expected a string as value') } if (!(element instanceof Element)) { throw new TypeError('Expected a DOM element') } element.style.setProperty(`--q-color-${color}`, value); } function getBrand (color, element = document.body) { if (typeof color !== 'string') { throw new TypeError('Expected a string as color') } if (!(element instanceof Element)) { throw new TypeError('Expected a DOM element') } return getComputedStyle(element).getPropertyValue(`--q-color-${color}`).trim() || null } function getPaletteColor (colorName) { if (typeof colorName !== 'string') { throw new TypeError('Expected a string as color') } const el = document.createElement('div'); el.className = `text-${colorName} invisible fixed no-pointer-events`; document.body.appendChild(el); const result = getComputedStyle(el).getPropertyValue('color'); el.remove(); return rgbToHex(textToRgb(result)) } var colors = { rgbToHex, hexToRgb, hsvToRgb, rgbToHsv, textToRgb, lighten, luminosity, brightness, blend, changeAlpha, setBrand, getBrand, getPaletteColor }; let lastKeyCompositionStatus = false; function onKeyDownComposition (evt) { lastKeyCompositionStatus = evt.isComposing === true; } function shouldIgnoreKey (evt) { return lastKeyCompositionStatus === true || evt !== Object(evt) || evt.isComposing === true || evt.qKeyEvent === true } function isKeyCode (evt, keyCodes) { return shouldIgnoreKey(evt) === true ? false : [].concat(keyCodes).includes(evt.keyCode) } function getMobilePlatform (is) { if (is.ios === true) return 'ios' if (is.android === true) return 'android' } function getBodyClasses ({ is, has, within }, cfg) { const cls = [ is.desktop === true ? 'desktop' : 'mobile', `${has.touch === false ? 'no-' : ''}touch` ]; if (is.mobile === true) { const mobile = getMobilePlatform(is); mobile !== void 0 && cls.push('platform-' + mobile); } if (is.nativeMobile === true) { const type = is.nativeMobileWrapper; cls.push(type); cls.push('native-mobile'); if ( is.ios === true && (cfg[type] === void 0 || cfg[type].iosStatusBarPadding !== false) ) { cls.push('q-ios-padding'); } } else if (is.electron === true) { cls.push('electron'); } else if (is.bex === true) { cls.push('bex'); } within.iframe === true && cls.push('within-iframe'); return cls } // SSR takeover corrections function clientUpdate () { const classes = document.body.className; let newCls = classes; if (iosCorrection !== void 0) { newCls = newCls.replace('desktop', 'platform-ios mobile'); } if (client.has.touch === true) { newCls = newCls.replace('no-touch', 'touch'); } if (client.within.iframe === true) { newCls += ' within-iframe'; } if (classes !== newCls) { document.body.className = newCls; } } function setColors (brand) { for (const color in brand) { setBrand(color, brand[color]); } } var Body = { install (queues, cfg) { if (isSSR === true) { queues.server.push((q, ctx) => { const cls = getBodyClasses(q.platform, cfg), fn = ctx.ssr.setBodyClasses; if (cfg.screen !== void 0 && cfg.screen.bodyClass === true) { cls.push('screen--xs'); } if (typeof fn === 'function') { fn(cls); } else { ctx.ssr.Q_BODY_CLASSES = cls.join(' '); } }); return } if (fromSSR === true) { clientUpdate(); } else { const cls = getBodyClasses(client, cfg); if (client.is.ie === true && client.is.versionNumber === 11) { cls.forEach(c => document.body.classList.add(c)); } else { document.body.classList.add.apply(document.body.classList, cls); } } cfg.brand !== void 0 && setColors(cfg.brand); if (client.is.ios === true) { // needed for iOS button active state document.body.addEventListener('touchstart', noop); } window.addEventListener('keydown', onKeyDownComposition, true); } }; var materialIcons = { name: 'material-icons', type: { positive: 'check_circle', negative: 'warning', info: 'info', warning: 'priority_high' }, arrow: { up: 'arrow_upward', right: 'arrow_forward', down: 'arrow_downward', left: 'arrow_back', dropdown: 'arrow_drop_down' }, chevron: { left: 'chevron_left', right: 'chevron_right' }, colorPicker: { spectrum: 'gradient', tune: 'tune', palette: 'style' }, pullToRefresh: { icon: 'refresh' }, carousel: { left: 'chevron_left', right: 'chevron_right', up: 'keyboard_arrow_up', down: 'keyboard_arrow_down', navigationIcon: 'lens' }, chip: { remove: 'cancel', selected: 'check' }, datetime: { arrowLeft: 'chevron_left', arrowRight: 'chevron_right', now: 'access_time', today: 'today' }, editor: { bold: 'format_bold', italic: 'format_italic', strikethrough: 'strikethrough_s', underline: 'format_underlined', unorderedList: 'format_list_bulleted', orderedList: 'format_list_numbered', subscript: 'vertical_align_bottom', superscript: 'vertical_align_top', hyperlink: 'link', toggleFullscreen: 'fullscreen', quote: 'format_quote', left: 'format_align_left', center: 'format_align_center', right: 'format_align_right', justify: 'format_align_justify', print: 'print', outdent: 'format_indent_decrease', indent: 'format_indent_increase', removeFormat: 'format_clear', formatting: 'text_format', fontSize: 'format_size', align: 'format_align_left', hr: 'remove', undo: 'undo', redo: 'redo', heading: 'format_size', code: 'code', size: 'format_size', font: 'font_download', viewSource: 'code' }, expansionItem: { icon: 'keyboard_arrow_down', denseIcon: 'arrow_drop_down' }, fab: { icon: 'add', activeIcon: 'close' }, field: { clear: 'cancel', error: 'error' }, pagination: { first: 'first_page', prev: 'keyboard_arrow_left', next: 'keyboard_arrow_right', last: 'last_page' }, rating: { icon: 'grade' }, stepper: { done: 'check', active: 'edit', error: 'warning' }, tabs: { left: 'chevron_left', right: 'chevron_right', up: 'keyboard_arrow_up', down: 'keyboard_arrow_down' }, table: { arrowUp: 'arrow_upward', warning: 'warning', firstPage: 'first_page', prevPage: 'chevron_left', nextPage: 'chevron_right', lastPage: 'last_page' }, tree: { icon: 'play_arrow' }, uploader: { done: 'done', clear: 'clear', add: 'add_box', upload: 'cloud_upload', removeQueue: 'clear_all', removeUploaded: 'done_all' } }; var iconSet = { install ($q, queues, iconSet) { const initialSet = iconSet || materialIcons; this.set = (setObject, ssrContext) => { const def = { ...setObject }; if (isSSR === true) { if (ssrContext === void 0) { console.error('SSR ERROR: second param required: Quasar.iconSet.set(iconSet, ssrContext)'); return } def.set = ssrContext.$q.iconSet.set; ssrContext.$q.iconSet = def; } else { def.set = this.set; $q.iconSet = def; } }; if (isSSR === true) { queues.server.push((q, ctx) => { q.iconSet = {}; q.iconSet.set = setObject => { this.set(setObject, ctx.ssr); }; q.iconSet.set(initialSet); }); } else { Vue.util.defineReactive($q, 'iconMapFn', void 0); Vue.util.defineReactive($q, 'iconSet', {}); this.set(initialSet); } } }; const autoInstalled = [ Platform, Screen, Dark ]; const queues = { server: [], // on SSR update takeover: [] // on client takeover }; const $q = { version, config: {} }; function install (Vue, opts = {}) { if (this.__qInstalled === true) { return } this.__qInstalled = true; const cfg = $q.config = Object.freeze(opts.config || {}); // required plugins Platform.install($q, queues); Body.install(queues, cfg); Dark.install($q, queues, cfg); Screen.install($q, queues, cfg); History.install(cfg); lang.install($q, queues, opts.lang); iconSet.install($q, queues, opts.iconSet); if (isSSR === true) { Vue.mixin({ beforeCreate () { this.$q = this.$root.$options.$q; } }); } else { Vue.prototype.$q = $q; } opts.components && Object.keys(opts.components).forEach(key => { const c = opts.components[key]; if (typeof c === 'function') { Vue.component(c.options.name, c); } }); opts.directives && Object.keys(opts.directives).forEach(key => { const d = opts.directives[key]; if (d.name !== undefined && d.unbind !== void 0) { Vue.directive(d.name, d); } }); if (opts.plugins) { const param = { $q, queues, cfg }; Object.keys(opts.plugins).forEach(key => { const p = opts.plugins[key]; if (typeof p.install === 'function' && autoInstalled.includes(p) === false) { p.install(param); } }); } } const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; function humanStorageSize (bytes) { let u = 0; while (parseInt(bytes, 10) >= 1024 && u < units.length - 1) { bytes /= 1024; ++u; } return `${bytes.toFixed(1)}${units[u]}` } function capitalize (str) { return str.charAt(0).toUpperCase() + str.slice(1) } function between (v, min, max) { return max <= min ? min : Math.min(max, Math.max(min, v)) } function normalizeToInterval (v, min, max) { if (max <= min) { return min } const size = (max - min + 1); let index = min + (v - min) % size; if (index < min) { index = size + index; } return index === 0 ? 0 : index // fix for (-a % a) => -0 } function pad (v, length = 2, char = '0') { if (v === void 0 || v === null) { return v } const val = '' + v; return val.length >= length ? val : new Array(length - val.length + 1).join(char) + val } var format = { humanStorageSize, capitalize, between, normalizeToInterval, pad }; function cache (vm, key, obj) { if (isSSR === true) return obj const k = `__qcache_${key}`; return vm[k] === void 0 ? (vm[k] = obj) : vm[k] } function cacheWithFn (vm, key, fn) { if (isSSR === true) return fn() const k = `__qcache_${key}`; return vm[k] === void 0 ? (vm[k] = fn()) : vm[k] } function getPropCacheMixin (propName, proxyPropName) { return { data () { const target = {}; const source = this[propName]; for (const prop in source) { target[prop] = source[prop]; } return { [proxyPropName]: target } }, watch: { [propName] (newObj, oldObj) { const target = this[proxyPropName]; if (oldObj !== void 0) { // we first delete obsolete events for (const prop in oldObj) { if (newObj[prop] === void 0) { this.$delete(target, prop); } } } for (const prop in newObj) { // we then update changed events if (target[prop] !== newObj[prop]) { this.$set(target, prop, newObj[prop]); } } } } } } const ariaHidden = { 'aria-hidden': 'true' }; var AttrsMixin = getPropCacheMixin('$attrs', 'qAttrs'); const xhr = isSSR ? null : XMLHttpRequest, send = isSSR ? null : xhr.prototype.send, stackStart = [], stackStop = []; let highjackCount = 0; function translate ({ p, pos, active, horiz, reverse, dir }) { let x = 1, y = 1; if (horiz) { if (reverse) { x = -1; } if (pos === 'bottom') { y = -1; } return { transform: `translate3d(${x * (p - 100)}%,${active ? 0 : y * -200}%,0)` } } if (reverse) { y = -1; } if (pos === 'right') { x = -1; } return { transform: `translate3d(${active ? 0 : dir * x * -200}%,${y * (p - 100)}%,0)` } } function inc (p, amount) { if (typeof amount !== 'number') { if (p < 25) { amount = Math.random() * 3 + 3; } else if (p < 65) { amount = Math.random() * 3; } else if (p < 85) { amount = Math.random() * 2; } else if (p < 99) { amount = 0.6; } else { amount = 0; } } return between(p + amount, 0, 100) } function highjackAjax (start, stop) { stackStart.push(start); stackStop.push(stop); highjackCount++; if (highjackCount > 1) { return } function endHandler () { stackStop.forEach(fn => { fn(); }); } xhr.prototype.send = function (/* ...args */) { stackStart.forEach(fn => { fn(); }); this.addEventListener('loadend', endHandler, false); send.apply(this, arguments); }; } function restoreAjax (start, stop) { stackStart.splice(stackStart.indexOf(start), 1); stackStop.splice(stackStop.indexOf(stop), 1); highjackCount = Math.max(0, highjackCount - 1); if (!highjackCount) { xhr.prototype.send = send; } } var QAjaxBar = Vue.extend({