quasar 2.9.1 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/dist/api/QBreadcrumbsEl.json +0 -14
  2. package/dist/api/QBtnDropdown.json +36 -0
  3. package/dist/api/QPagination.json +134 -102
  4. package/dist/api/QTabs.json +1 -1
  5. package/dist/api/QTree.json +6 -0
  6. package/dist/api/TouchPan.json +0 -4
  7. package/dist/icon-set/bootstrap-icons.umd.prod.js +1 -1
  8. package/dist/icon-set/eva-icons.umd.prod.js +1 -1
  9. package/dist/icon-set/fontawesome-v5-pro.umd.prod.js +1 -1
  10. package/dist/icon-set/fontawesome-v5.umd.prod.js +1 -1
  11. package/dist/icon-set/fontawesome-v6-pro.umd.prod.js +1 -1
  12. package/dist/icon-set/fontawesome-v6.umd.prod.js +1 -1
  13. package/dist/icon-set/ionicons-v4.umd.prod.js +1 -1
  14. package/dist/icon-set/line-awesome.umd.prod.js +1 -1
  15. package/dist/icon-set/material-icons-outlined.umd.prod.js +1 -1
  16. package/dist/icon-set/material-icons-round.umd.prod.js +1 -1
  17. package/dist/icon-set/material-icons-sharp.umd.prod.js +1 -1
  18. package/dist/icon-set/material-icons.umd.prod.js +1 -1
  19. package/dist/icon-set/material-symbols-outlined.umd.prod.js +1 -1
  20. package/dist/icon-set/material-symbols-rounded.umd.prod.js +1 -1
  21. package/dist/icon-set/material-symbols-sharp.umd.prod.js +1 -1
  22. package/dist/icon-set/mdi-v3.umd.prod.js +1 -1
  23. package/dist/icon-set/mdi-v4.umd.prod.js +1 -1
  24. package/dist/icon-set/mdi-v5.umd.prod.js +1 -1
  25. package/dist/icon-set/mdi-v6.umd.prod.js +1 -1
  26. package/dist/icon-set/svg-bootstrap-icons.umd.prod.js +1 -1
  27. package/dist/icon-set/svg-eva-icons.umd.prod.js +1 -1
  28. package/dist/icon-set/svg-fontawesome-v5.umd.prod.js +1 -1
  29. package/dist/icon-set/svg-fontawesome-v6.umd.prod.js +1 -1
  30. package/dist/icon-set/svg-ionicons-v4.umd.prod.js +1 -1
  31. package/dist/icon-set/svg-ionicons-v5.umd.prod.js +1 -1
  32. package/dist/icon-set/svg-ionicons-v6.umd.prod.js +1 -1
  33. package/dist/icon-set/svg-line-awesome.umd.prod.js +1 -1
  34. package/dist/icon-set/svg-material-icons-outlined.umd.prod.js +1 -1
  35. package/dist/icon-set/svg-material-icons-round.umd.prod.js +1 -1
  36. package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +1 -1
  37. package/dist/icon-set/svg-material-icons.umd.prod.js +1 -1
  38. package/dist/icon-set/svg-material-symbols-outlined.umd.prod.js +1 -1
  39. package/dist/icon-set/svg-material-symbols-rounded.umd.prod.js +1 -1
  40. package/dist/icon-set/svg-material-symbols-sharp.umd.prod.js +1 -1
  41. package/dist/icon-set/svg-mdi-v6.umd.prod.js +1 -1
  42. package/dist/icon-set/svg-themify.umd.prod.js +1 -1
  43. package/dist/icon-set/themify.umd.prod.js +1 -1
  44. package/dist/lang/ar-TN.umd.prod.js +1 -1
  45. package/dist/lang/ar.umd.prod.js +1 -1
  46. package/dist/lang/az-Latn.umd.prod.js +1 -1
  47. package/dist/lang/bg.umd.prod.js +1 -1
  48. package/dist/lang/bn.umd.prod.js +1 -1
  49. package/dist/lang/ca.umd.prod.js +1 -1
  50. package/dist/lang/cs.umd.prod.js +1 -1
  51. package/dist/lang/da.umd.prod.js +1 -1
  52. package/dist/lang/de.umd.prod.js +1 -1
  53. package/dist/lang/el.umd.prod.js +1 -1
  54. package/dist/lang/en-GB.umd.prod.js +1 -1
  55. package/dist/lang/en-US.umd.prod.js +1 -1
  56. package/dist/lang/eo.umd.prod.js +1 -1
  57. package/dist/lang/es.umd.prod.js +1 -1
  58. package/dist/lang/et.umd.prod.js +1 -1
  59. package/dist/lang/eu.umd.prod.js +1 -1
  60. package/dist/lang/fa-IR.umd.prod.js +1 -1
  61. package/dist/lang/fa.umd.prod.js +1 -1
  62. package/dist/lang/fi.umd.prod.js +1 -1
  63. package/dist/lang/fr.umd.prod.js +1 -1
  64. package/dist/lang/gn.umd.prod.js +1 -1
  65. package/dist/lang/he.umd.prod.js +1 -1
  66. package/dist/lang/hr.umd.prod.js +1 -1
  67. package/dist/lang/hu.umd.prod.js +1 -1
  68. package/dist/lang/id.umd.prod.js +1 -1
  69. package/dist/lang/is.umd.prod.js +1 -1
  70. package/dist/lang/it.umd.prod.js +1 -1
  71. package/dist/lang/ja.umd.prod.js +1 -1
  72. package/dist/lang/km.umd.prod.js +1 -1
  73. package/dist/lang/ko-KR.umd.prod.js +1 -1
  74. package/dist/lang/kur-CKB.umd.prod.js +1 -1
  75. package/dist/lang/kz.umd.prod.js +1 -1
  76. package/dist/lang/lt.umd.prod.js +1 -1
  77. package/dist/lang/lu.umd.prod.js +1 -1
  78. package/dist/lang/lv.umd.prod.js +1 -1
  79. package/dist/lang/ml.umd.prod.js +1 -1
  80. package/dist/lang/mm.umd.prod.js +1 -1
  81. package/dist/lang/ms.umd.prod.js +1 -1
  82. package/dist/lang/my.umd.prod.js +1 -1
  83. package/dist/lang/nb-NO.umd.prod.js +1 -1
  84. package/dist/lang/nl.umd.prod.js +1 -1
  85. package/dist/lang/pl.umd.prod.js +1 -1
  86. package/dist/lang/pt-BR.umd.prod.js +1 -1
  87. package/dist/lang/pt.umd.prod.js +1 -1
  88. package/dist/lang/ro.umd.prod.js +1 -1
  89. package/dist/lang/ru.umd.prod.js +1 -1
  90. package/dist/lang/sk.umd.prod.js +1 -1
  91. package/dist/lang/sl.umd.prod.js +1 -1
  92. package/dist/lang/sm.umd.prod.js +1 -1
  93. package/dist/lang/sr-CYR.umd.prod.js +1 -1
  94. package/dist/lang/sr.umd.prod.js +1 -1
  95. package/dist/lang/sv.umd.prod.js +1 -1
  96. package/dist/lang/ta.umd.prod.js +1 -1
  97. package/dist/lang/th.umd.prod.js +1 -1
  98. package/dist/lang/tr.umd.prod.js +1 -1
  99. package/dist/lang/ug.umd.prod.js +1 -1
  100. package/dist/lang/uk.umd.prod.js +1 -1
  101. package/dist/lang/uz-Cyrl.umd.prod.js +1 -1
  102. package/dist/lang/uz-Latn.umd.prod.js +1 -1
  103. package/dist/lang/vi.umd.prod.js +1 -1
  104. package/dist/lang/zh-CN.umd.prod.js +1 -1
  105. package/dist/lang/zh-TW.umd.prod.js +1 -1
  106. package/dist/quasar.cjs.prod.js +2 -2
  107. package/dist/quasar.css +10 -0
  108. package/dist/quasar.esm.js +554 -349
  109. package/dist/quasar.esm.prod.js +2 -2
  110. package/dist/quasar.prod.css +1 -1
  111. package/dist/quasar.rtl.css +26 -0
  112. package/dist/quasar.rtl.prod.css +1 -1
  113. package/dist/quasar.sass +11 -1
  114. package/dist/quasar.umd.js +554 -349
  115. package/dist/quasar.umd.prod.js +2 -2
  116. package/dist/transforms/auto-import.json +7 -3
  117. package/dist/transforms/import-map.json +2 -0
  118. package/dist/types/index.d.ts +70 -51
  119. package/dist/vetur/quasar-attributes.json +65 -49
  120. package/dist/vetur/quasar-tags.json +17 -13
  121. package/dist/web-types/web-types.json +131 -97
  122. package/package.json +1 -1
  123. package/src/components/badge/QBadge.js +1 -1
  124. package/src/components/badge/__tests__/QBadge.spec.js +98 -23
  125. package/src/components/breadcrumbs/QBreadcrumbsEl.json +0 -4
  126. package/src/components/breadcrumbs/__tests__/BasicBreadcrumbs.vue +7 -0
  127. package/src/components/breadcrumbs/__tests__/BreadcrumbWithSeparatorSlot.vue +11 -0
  128. package/src/components/breadcrumbs/__tests__/QBreadcrumbs.spec.js +112 -0
  129. package/src/components/breadcrumbs/__tests__/QBreadcrumbsEl.spec.js +87 -0
  130. package/src/components/btn/use-btn.js +24 -14
  131. package/src/components/btn-dropdown/QBtnDropdown.js +39 -16
  132. package/src/components/btn-dropdown/QBtnDropdown.json +1 -1
  133. package/src/components/btn-toggle/QBtnToggle.js +14 -14
  134. package/src/components/checkbox/use-checkbox.js +1 -1
  135. package/src/components/chip/QChip.js +14 -11
  136. package/src/components/dialog/QDialog.js +2 -1
  137. package/src/components/dialog-bottom-sheet/BottomSheet.js +6 -2
  138. package/src/components/drawer/QDrawer.js +5 -3
  139. package/src/components/footer/QFooter.js +5 -3
  140. package/src/components/header/QHeader.js +5 -3
  141. package/src/components/input/use-mask.js +1 -1
  142. package/src/components/item/QItem.js +1 -0
  143. package/src/components/item/QList.js +1 -1
  144. package/src/components/option-group/QOptionGroup.js +1 -1
  145. package/src/components/page/QPage.js +11 -4
  146. package/src/components/page/QPageContainer.js +5 -3
  147. package/src/components/page-sticky/use-page-sticky.js +5 -3
  148. package/src/components/pagination/QPagination.js +265 -188
  149. package/src/components/pagination/QPagination.json +82 -65
  150. package/src/components/pagination/QPagination.sass +14 -0
  151. package/src/components/pull-to-refresh/QPullToRefresh.js +1 -4
  152. package/src/components/resize-observer/QResizeObserver.js +14 -10
  153. package/src/components/stepper/QStep.js +7 -5
  154. package/src/components/tab-panels/QTabPanel.js +1 -1
  155. package/src/components/tabs/QTabs.js +2 -9
  156. package/src/components/tabs/QTabs.json +1 -1
  157. package/src/components/tabs/use-tab.js +5 -3
  158. package/src/components/timeline/QTimelineEntry.js +5 -3
  159. package/src/components/toolbar/QToolbar.js +1 -1
  160. package/src/components/tooltip/QTooltip.js +1 -1
  161. package/src/components/tree/QTree.js +33 -20
  162. package/src/components/tree/QTree.json +7 -0
  163. package/src/components/uploader/QUploaderAddTrigger.js +7 -3
  164. package/src/composables/private/use-file.js +10 -1
  165. package/src/directives/TouchHold.js +10 -3
  166. package/src/directives/TouchPan.js +21 -8
  167. package/src/directives/TouchPan.json +0 -5
  168. package/src/directives/TouchRepeat.js +20 -6
  169. package/src/directives/TouchSwipe.js +10 -3
  170. package/src/utils/morph.js +7 -3
  171. package/src/utils/private/symbols.js +2 -0
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Quasar Framework v2.9.1
2
+ * Quasar Framework v2.10.0
3
3
  * (c) 2015-present Razvan Stoenescu
4
4
  * Released under the MIT License.
5
5
  */
@@ -1398,6 +1398,8 @@
1398
1398
  const tabsKey = '_q_tabs_';
1399
1399
  const uploaderKey = '_q_u_';
1400
1400
 
1401
+ const emptyRenderFn = () => {};
1402
+
1401
1403
  const globalConfig = {};
1402
1404
  let globalConfigIsFrozen = false;
1403
1405
 
@@ -1610,7 +1612,7 @@
1610
1612
  }
1611
1613
 
1612
1614
  var installQuasar = function (parentApp, opts = {}) {
1613
- const $q = { version: '2.9.1' };
1615
+ const $q = { version: '2.10.0' };
1614
1616
 
1615
1617
  if (globalConfigIsFrozen === false) {
1616
1618
  if (opts.config !== void 0) {
@@ -2369,7 +2371,7 @@
2369
2371
  return () => vue.h('div', {
2370
2372
  class: classes.value,
2371
2373
  style: style.value,
2372
- role: 'alert',
2374
+ role: 'status',
2373
2375
  'aria-label': props.label
2374
2376
  }, hMergeSlot(slots.default, props.label !== void 0 ? [ props.label ] : []))
2375
2377
  }
@@ -3300,7 +3302,7 @@
3300
3302
  }
3301
3303
  );
3302
3304
 
3303
- const padding = {
3305
+ const btnPadding = {
3304
3306
  none: 0,
3305
3307
  xs: 4,
3306
3308
  sm: 8,
@@ -3320,6 +3322,21 @@
3320
3322
  const formTypes = [ 'button', 'submit', 'reset' ];
3321
3323
  const mediaTypeRE = /[^\s]\/[^\s]/;
3322
3324
 
3325
+ const btnDesignOptions = [ 'flat', 'outline', 'push', 'unelevated' ];
3326
+ const getBtnDesign = (props, defaultValue) => {
3327
+ if (props.flat === true) return 'flat'
3328
+ if (props.outline === true) return 'outline'
3329
+ if (props.push === true) return 'push'
3330
+ if (props.unelevated === true) return 'unelevated'
3331
+ return defaultValue
3332
+ };
3333
+ const getBtnDesignAttr = props => {
3334
+ const design = getBtnDesign(props);
3335
+ return design !== void 0
3336
+ ? { [ design ]: true }
3337
+ : {}
3338
+ };
3339
+
3323
3340
  const useBtnProps = {
3324
3341
  ...useSizeProps,
3325
3342
  ...useRouterLinkProps,
@@ -3333,13 +3350,14 @@
3333
3350
  icon: String,
3334
3351
  iconRight: String,
3335
3352
 
3336
- round: Boolean,
3353
+ ...btnDesignOptions.reduce(
3354
+ (acc, val) => (acc[ val ] = Boolean) && acc,
3355
+ {}
3356
+ ),
3357
+
3337
3358
  square: Boolean,
3338
- outline: Boolean,
3339
- flat: Boolean,
3340
- unelevated: Boolean,
3359
+ round: Boolean,
3341
3360
  rounded: Boolean,
3342
- push: Boolean,
3343
3361
  glossy: Boolean,
3344
3362
 
3345
3363
  size: String,
@@ -3389,7 +3407,7 @@
3389
3407
  ? Object.assign({}, obj, {
3390
3408
  padding: props.padding
3391
3409
  .split(/\s+/)
3392
- .map(v => (v in padding ? padding[ v ] + 'px' : v))
3410
+ .map(v => (v in btnPadding ? btnPadding[ v ] + 'px' : v))
3393
3411
  .join(' '),
3394
3412
  minWidth: '0',
3395
3413
  minHeight: '0'
@@ -3409,13 +3427,7 @@
3409
3427
  isActionable.value === true ? props.tabindex || 0 : -1
3410
3428
  ));
3411
3429
 
3412
- const design = vue.computed(() => {
3413
- if (props.flat === true) return 'flat'
3414
- if (props.outline === true) return 'outline'
3415
- if (props.push === true) return 'push'
3416
- if (props.unelevated === true) return 'unelevated'
3417
- return 'standard'
3418
- });
3430
+ const design = vue.computed(() => getBtnDesign(props, 'standard'));
3419
3431
 
3420
3432
  const attributes = vue.computed(() => {
3421
3433
  const acc = { tabindex: tabIndex.value };
@@ -5667,11 +5679,32 @@
5667
5679
  + hexBytes[ b[ 14 ] ] + hexBytes[ b[ 15 ] ]
5668
5680
  }
5669
5681
 
5682
+ const btnPropsList = Object.keys(useBtnProps);
5683
+
5684
+ // let's not duplicate type checking and prop validations
5685
+ // so just specify the props here with no type description
5686
+ const btnProps = btnPropsList.reduce(
5687
+ (acc, key) => (acc[ key ] = {}) && acc,
5688
+ {}
5689
+ );
5690
+
5691
+ const passBtnProps = props => btnPropsList.reduce(
5692
+ (acc, key) => {
5693
+ const val = props[ key ];
5694
+ if (val !== void 0) {
5695
+ acc[ key ] = val;
5696
+ }
5697
+ return acc
5698
+ },
5699
+ {}
5700
+ );
5701
+
5670
5702
  var QBtnDropdown = createComponent({
5671
5703
  name: 'QBtnDropdown',
5672
5704
 
5673
5705
  props: {
5674
- ...useBtnProps,
5706
+ ...btnProps,
5707
+ ...useTransitionProps,
5675
5708
 
5676
5709
  modelValue: Boolean,
5677
5710
  split: Boolean,
@@ -5712,7 +5745,7 @@
5712
5745
  const menuRef = vue.ref(null);
5713
5746
  const targetUid = uid$3();
5714
5747
 
5715
- const attributes = vue.computed(() => {
5748
+ const ariaAttrs = vue.computed(() => {
5716
5749
  const acc = {
5717
5750
  'aria-expanded': showing.value === true ? 'true' : 'false',
5718
5751
  'aria-haspopup': 'true',
@@ -5740,6 +5773,9 @@
5740
5773
  + (props.split === false ? ' q-btn-dropdown__arrow-container' : '')
5741
5774
  );
5742
5775
 
5776
+ const btnDesignAttr = vue.computed(() => getBtnDesignAttr(props));
5777
+ const btnProps = vue.computed(() => passBtnProps(props));
5778
+
5743
5779
  vue.watch(() => props.modelValue, val => {
5744
5780
  menuRef.value !== null && menuRef.value[ val ? 'show' : 'hide' ]();
5745
5781
  });
@@ -5820,6 +5856,9 @@
5820
5856
  self: props.menuSelf,
5821
5857
  offset: props.menuOffset,
5822
5858
  separateClosePopup: true,
5859
+ transitionShow: props.transitionShow,
5860
+ transitionHide: props.transitionHide,
5861
+ transitionDuration: props.transitionDuration,
5823
5862
  onBeforeShow,
5824
5863
  onShow,
5825
5864
  onBeforeHide,
@@ -5830,11 +5869,11 @@
5830
5869
  if (props.split === false) {
5831
5870
  return vue.h(QBtn, {
5832
5871
  class: 'q-btn-dropdown q-btn-dropdown--simple',
5833
- ...props,
5872
+ ...btnProps.value,
5873
+ ...ariaAttrs.value,
5834
5874
  disable: props.disable === true || props.disableMainBtn === true,
5835
5875
  noWrap: true,
5836
5876
  round: false,
5837
- ...attributes.value,
5838
5877
  onClick
5839
5878
  }, {
5840
5879
  default: () => hSlot(slots.label, []).concat(Arrow),
@@ -5844,21 +5883,17 @@
5844
5883
 
5845
5884
  return vue.h(QBtnGroup, {
5846
5885
  class: 'q-btn-dropdown q-btn-dropdown--split no-wrap q-btn-item',
5847
- outline: props.outline,
5848
- flat: props.flat,
5849
5886
  rounded: props.rounded,
5850
5887
  square: props.square,
5851
- push: props.push,
5852
- unelevated: props.unelevated,
5888
+ ...btnDesignAttr.value,
5853
5889
  glossy: props.glossy,
5854
5890
  stretch: props.stretch
5855
5891
  }, () => [
5856
5892
  vue.h(QBtn, {
5857
5893
  class: 'q-btn-dropdown--current',
5858
- ...props,
5894
+ ...btnProps.value,
5859
5895
  disable: props.disable === true || props.disableMainBtn === true,
5860
5896
  noWrap: true,
5861
- iconRight: props.iconRight,
5862
5897
  round: false,
5863
5898
  onClick: onClickHide
5864
5899
  }, {
@@ -5868,16 +5903,15 @@
5868
5903
 
5869
5904
  vue.h(QBtn, {
5870
5905
  class: 'q-btn-dropdown__arrow-container q-anchor--skip',
5871
- ...attributes.value,
5906
+ ...ariaAttrs.value,
5907
+ ...btnDesignAttr.value,
5872
5908
  disable: props.disable === true || props.disableDropdown === true,
5873
- outline: props.outline,
5874
- flat: props.flat,
5875
5909
  rounded: props.rounded,
5876
- push: props.push,
5877
- size: props.size,
5878
5910
  color: props.color,
5879
5911
  textColor: props.textColor,
5880
5912
  dense: props.dense,
5913
+ size: props.size,
5914
+ padding: props.padding,
5881
5915
  ripple: props.ripple
5882
5916
  }, () => Arrow)
5883
5917
  ])
@@ -5984,6 +6018,14 @@
5984
6018
 
5985
6019
  const injectFormInput = useFormInject(formAttrs);
5986
6020
 
6021
+ const btnDesignAttr = vue.computed(() => getBtnDesignAttr(props));
6022
+
6023
+ const btnOptionDesign = vue.computed(() => ({
6024
+ rounded: props.rounded,
6025
+ dense: props.dense,
6026
+ ...btnDesignAttr.value
6027
+ }));
6028
+
5987
6029
  const btnOptions = vue.computed(() => props.options.map((item, i) => {
5988
6030
  const { attrs, value, slot, ...opt } = item;
5989
6031
 
@@ -5991,19 +6033,11 @@
5991
6033
  slot,
5992
6034
  props: {
5993
6035
  key: i,
5994
- onClick (e) { set(value, item, e); },
5995
6036
 
5996
6037
  'aria-pressed': value === props.modelValue ? 'true' : 'false',
5997
-
5998
6038
  ...attrs,
5999
6039
  ...opt,
6000
-
6001
- outline: props.outline,
6002
- flat: props.flat,
6003
- rounded: props.rounded,
6004
- push: props.push,
6005
- unelevated: props.unelevated,
6006
- dense: props.dense,
6040
+ ...btnOptionDesign.value,
6007
6041
 
6008
6042
  disable: props.disable === true || opt.disable === true,
6009
6043
 
@@ -6021,7 +6055,9 @@
6021
6055
  padding: mergeOpt(opt, 'padding'),
6022
6056
  ripple: mergeOpt(opt, 'ripple'),
6023
6057
  stack: mergeOpt(opt, 'stack') === true,
6024
- stretch: mergeOpt(opt, 'stretch') === true
6058
+ stretch: mergeOpt(opt, 'stretch') === true,
6059
+
6060
+ onClick (e) { set(value, item, e); }
6025
6061
  }
6026
6062
  }
6027
6063
  }));
@@ -6060,12 +6096,9 @@
6060
6096
 
6061
6097
  return () => vue.h(QBtnGroup, {
6062
6098
  class: 'q-btn-toggle',
6063
- outline: props.outline,
6064
- flat: props.flat,
6099
+ ...btnDesignAttr.value,
6065
6100
  rounded: props.rounded,
6066
- push: props.push,
6067
6101
  stretch: props.stretch,
6068
- unelevated: props.unelevated,
6069
6102
  glossy: props.glossy,
6070
6103
  spread: props.spread
6071
6104
  }, getContent)
@@ -6422,9 +6455,16 @@
6422
6455
 
6423
6456
  el.__qtouchswipe = ctx;
6424
6457
 
6425
- modifiers.mouse === true && addEvt(ctx, 'main', [
6426
- [ el, 'mousedown', 'mouseStart', `passive${ mouseCapture }` ]
6427
- ]);
6458
+ if (modifiers.mouse === true) {
6459
+ // account for UMD too where modifiers will be lowercased to work
6460
+ const capture = modifiers.mouseCapture === true || modifiers.mousecapture === true
6461
+ ? 'Capture'
6462
+ : '';
6463
+
6464
+ addEvt(ctx, 'main', [
6465
+ [ el, 'mousedown', 'mouseStart', `passive${ capture }` ]
6466
+ ]);
6467
+ }
6428
6468
 
6429
6469
  client.has.touch === true && addEvt(ctx, 'main', [
6430
6470
  [ el, 'touchstart', 'touchStart', `passive${ modifiers.capture === true ? 'Capture' : '' }` ],
@@ -7499,7 +7539,7 @@
7499
7539
  const attributes = vue.computed(() => {
7500
7540
  const attrs = {
7501
7541
  tabindex: tabindex.value,
7502
- role: 'checkbox',
7542
+ role: type === 'toggle' ? 'switch' : 'checkbox',
7503
7543
  'aria-label': props.label,
7504
7544
  'aria-checked': isIndeterminate.value === true
7505
7545
  ? 'mixed'
@@ -7764,16 +7804,19 @@
7764
7804
  + (isDark.value === true ? ' q-chip--dark q-dark' : '')
7765
7805
  });
7766
7806
 
7767
- const attributes = vue.computed(() => (
7768
- props.disable === true
7807
+ const attributes = vue.computed(() => {
7808
+ const chip = props.disable === true
7769
7809
  ? { tabindex: -1, 'aria-disabled': 'true' }
7770
- : {
7771
- tabindex: props.tabindex || 0,
7772
- role: 'button',
7773
- 'aria-hidden': 'false',
7774
- 'aria-label': props.removeAriaLabel || $q.lang.label.remove
7775
- }
7776
- ));
7810
+ : { tabindex: props.tabindex || 0 };
7811
+ const remove = {
7812
+ ...chip,
7813
+ role: 'button',
7814
+ 'aria-hidden': 'false',
7815
+ 'aria-label': props.removeAriaLabel || $q.lang.label.remove
7816
+ };
7817
+
7818
+ return { chip, remove }
7819
+ });
7777
7820
 
7778
7821
  function onKeyup (e) {
7779
7822
  e.keyCode === 13 /* ENTER */ && onClick(e);
@@ -7831,7 +7874,7 @@
7831
7874
  vue.h(QIcon, {
7832
7875
  class: 'q-chip__icon q-chip__icon--remove cursor-pointer',
7833
7876
  name: removeIcon.value,
7834
- ...attributes.value,
7877
+ ...attributes.value.remove,
7835
7878
  onClick: onRemove,
7836
7879
  onKeyup: onRemove
7837
7880
  })
@@ -7850,7 +7893,7 @@
7850
7893
 
7851
7894
  isClickable.value === true && Object.assign(
7852
7895
  data,
7853
- attributes.value,
7896
+ attributes.value.chip,
7854
7897
  { onClick, onKeyup }
7855
7898
  );
7856
7899
 
@@ -8219,7 +8262,8 @@
8219
8262
  */
8220
8263
  if (
8221
8264
  ctx.direction.all !== true
8222
- && (mouseEvent !== true || ctx.modifiers.mouseAllDir !== true)
8265
+ // account for UMD too where modifiers will be lowercased to work
8266
+ && (mouseEvent !== true || (ctx.modifiers.mouseAllDir !== true && ctx.modifiers.mousealldir !== true))
8223
8267
  ) {
8224
8268
  const clone = evt.type.indexOf('mouse') > -1
8225
8269
  ? new MouseEvent(evt.type, evt)
@@ -8286,9 +8330,12 @@
8286
8330
  const start = () => {
8287
8331
  handleEvent(evt, isMouseEvt);
8288
8332
 
8289
- if (modifiers.preserveCursor !== true) {
8333
+ let cursor;
8334
+ if (modifiers.preserveCursor !== true && modifiers.preservecursor !== true) {
8335
+ cursor = document.documentElement.style.cursor || '';
8290
8336
  document.documentElement.style.cursor = 'grabbing';
8291
8337
  }
8338
+
8292
8339
  isMouseEvt === true && document.body.classList.add('no-pointer-events--children');
8293
8340
  document.body.classList.add('non-selectable');
8294
8341
  clearSelection();
@@ -8296,9 +8343,10 @@
8296
8343
  ctx.styleCleanup = withDelayedFn => {
8297
8344
  ctx.styleCleanup = void 0;
8298
8345
 
8299
- if (modifiers.preserveCursor !== true) {
8300
- document.documentElement.style.cursor = '';
8346
+ if (cursor !== void 0) {
8347
+ document.documentElement.style.cursor = cursor;
8301
8348
  }
8349
+
8302
8350
  document.body.classList.remove('non-selectable');
8303
8351
 
8304
8352
  if (isMouseEvt === true) {
@@ -8346,7 +8394,8 @@
8346
8394
 
8347
8395
  if (
8348
8396
  ctx.direction.all === true
8349
- || (isMouseEvt === true && ctx.modifiers.mouseAllDir === true)
8397
+ // account for UMD too where modifiers will be lowercased to work
8398
+ || (isMouseEvt === true && (ctx.modifiers.mouseAllDir === true || ctx.modifiers.mousealldir === true))
8350
8399
  ) {
8351
8400
  start();
8352
8401
  ctx.event.detected = true;
@@ -8413,9 +8462,16 @@
8413
8462
 
8414
8463
  el.__qtouchpan = ctx;
8415
8464
 
8416
- modifiers.mouse === true && addEvt(ctx, 'main', [
8417
- [ el, 'mousedown', 'mouseStart', `passive${ modifiers.mouseCapture === true ? 'Capture' : '' }` ]
8418
- ]);
8465
+ if (modifiers.mouse === true) {
8466
+ // account for UMD too where modifiers will be lowercased to work
8467
+ const capture = modifiers.mouseCapture === true || modifiers.mousecapture === true
8468
+ ? 'Capture'
8469
+ : '';
8470
+
8471
+ addEvt(ctx, 'main', [
8472
+ [ el, 'mousedown', 'mouseStart', `passive${ capture }` ]
8473
+ ]);
8474
+ }
8419
8475
 
8420
8476
  client.has.touch === true && addEvt(ctx, 'main', [
8421
8477
  [ el, 'touchstart', 'touchStart', `passive${ modifiers.capture === true ? 'Capture' : '' }` ],
@@ -9321,17 +9377,21 @@
9321
9377
  if (hasObserver === true) {
9322
9378
  let observer;
9323
9379
 
9324
- vue.onMounted(() => {
9325
- vue.nextTick(() => {
9326
- targetEl = proxy.$el.parentNode;
9380
+ // initialize as soon as possible
9381
+ const init = stop => {
9382
+ targetEl = proxy.$el.parentNode;
9327
9383
 
9328
- if (targetEl) {
9329
- observer = new ResizeObserver(trigger);
9330
- observer.observe(targetEl);
9331
- emitEvent();
9332
- }
9333
- });
9334
- });
9384
+ if (targetEl) {
9385
+ observer = new ResizeObserver(trigger);
9386
+ observer.observe(targetEl);
9387
+ emitEvent();
9388
+ }
9389
+ else if (stop !== true) {
9390
+ vue.nextTick(() => { init(true); });
9391
+ }
9392
+ };
9393
+
9394
+ vue.onMounted(() => { init(); });
9335
9395
 
9336
9396
  vue.onBeforeUnmount(() => {
9337
9397
  clearTimeout(timer);
@@ -9990,8 +10050,8 @@
9990
10050
 
9991
10051
  recalculateScroll();
9992
10052
 
9993
- // if it's a QTab
9994
- if (tabData.routeData === void 0) {
10053
+ // if it's a QTab or we don't have Vue Router
10054
+ if (tabData.routeData === void 0 || proxy.$route === void 0) {
9995
10055
  // we should position to the currently active tab (if any)
9996
10056
  registerScrollToTabTimeout(() => {
9997
10057
  if (scrollable.value === true) {
@@ -10015,13 +10075,6 @@
10015
10075
  }
10016
10076
  }
10017
10077
 
10018
- /*
10019
- * Vue has an aggressive diff (in-place replacement) so we cannot
10020
- * ensure that the instance getting destroyed is the actual tab
10021
- * reported here. As a result, we cannot use its name or check
10022
- * if it's a route one to make the necessary updates. We need to
10023
- * always check the existing list again and infer the changes.
10024
- */
10025
10078
  function unregisterTab (tabData) {
10026
10079
  tabDataList.splice(tabDataList.indexOf(tabData), 1);
10027
10080
  tabDataListLen.value--;
@@ -10153,9 +10206,11 @@
10153
10206
  };
10154
10207
 
10155
10208
  function useTab (props, slots, emit, routeData) {
10156
- const $tabs = vue.inject(tabsKey, () => {
10209
+ const $tabs = vue.inject(tabsKey, emptyRenderFn);
10210
+ if ($tabs === emptyRenderFn) {
10157
10211
  console.error('QTab/QRouteTab component needs to be child of QTabs');
10158
- });
10212
+ return emptyRenderFn
10213
+ }
10159
10214
 
10160
10215
  const { proxy } = vue.getCurrentInstance();
10161
10216
 
@@ -10431,7 +10486,7 @@
10431
10486
  props: usePanelChildProps,
10432
10487
 
10433
10488
  setup (_, { slots }) {
10434
- return () => vue.h('div', { class: 'q-tab-panel' }, hSlot(slots.default))
10489
+ return () => vue.h('div', { class: 'q-tab-panel', role: 'tabpanel' }, hSlot(slots.default))
10435
10490
  }
10436
10491
  });
10437
10492
 
@@ -15011,7 +15066,8 @@
15011
15066
 
15012
15067
  function renderPortalContent () {
15013
15068
  return vue.h('div', {
15014
- 'aria-modal': 'true',
15069
+ role: 'dialog',
15070
+ 'aria-modal': useBackdrop.value === true ? 'true' : 'false',
15015
15071
  ...attrs,
15016
15072
  class: rootClasses.value
15017
15073
  }, [
@@ -15115,9 +15171,11 @@
15115
15171
  const { preventBodyScroll } = usePreventScroll();
15116
15172
  const { registerTimeout, removeTimeout } = useTimeout();
15117
15173
 
15118
- const $layout = vue.inject(layoutKey, () => {
15174
+ const $layout = vue.inject(layoutKey, emptyRenderFn);
15175
+ if ($layout === emptyRenderFn) {
15119
15176
  console.error('QDrawer needs to be child of QLayout');
15120
- });
15177
+ return emptyRenderFn
15178
+ }
15121
15179
 
15122
15180
  let lastDesktopState, timerMini, layoutTotalWidthWatcher;
15123
15181
 
@@ -16369,7 +16427,7 @@
16369
16427
  attrs.style,
16370
16428
  transitionStyle.value
16371
16429
  ],
16372
- role: 'complementary'
16430
+ role: 'tooltip'
16373
16431
  }, hSlot(slots.default))
16374
16432
  : null
16375
16433
  }
@@ -16518,6 +16576,7 @@
16518
16576
  ref: rootRef,
16519
16577
  class: classes.value,
16520
16578
  style: style.value,
16579
+ role: 'listitem',
16521
16580
  onClick,
16522
16581
  onKeyup
16523
16582
  };
@@ -19422,7 +19481,14 @@
19422
19481
 
19423
19482
  function onDragleave (e) {
19424
19483
  stopAndPrevent(e);
19425
- e.relatedTarget !== dndRef.value && (dnd.value = false);
19484
+
19485
+ // Safari bug: relatedTarget is null for over 10 years
19486
+ // https://bugs.webkit.org/show_bug.cgi?id=66547
19487
+ const gone = e.relatedTarget !== null || client.is.safari !== true
19488
+ ? e.relatedTarget !== dndRef.value
19489
+ : document.elementsFromPoint(e.clientX, e.clientY).includes(dndRef.value) === false;
19490
+
19491
+ gone === true && (dnd.value = false);
19426
19492
  }
19427
19493
 
19428
19494
  function onDrop (e) {
@@ -19456,6 +19522,7 @@
19456
19522
  pickFiles,
19457
19523
  addFiles,
19458
19524
  onDragover,
19525
+ onDragleave,
19459
19526
  processFiles,
19460
19527
  getDndNode,
19461
19528
 
@@ -19809,9 +19876,11 @@
19809
19876
  setup (props, { slots, emit }) {
19810
19877
  const { proxy: { $q } } = vue.getCurrentInstance();
19811
19878
 
19812
- const $layout = vue.inject(layoutKey, () => {
19879
+ const $layout = vue.inject(layoutKey, emptyRenderFn);
19880
+ if ($layout === emptyRenderFn) {
19813
19881
  console.error('QFooter needs to be child of QLayout');
19814
- });
19882
+ return emptyRenderFn
19883
+ }
19815
19884
 
19816
19885
  const size = vue.ref(parseInt(props.heightHint, 10));
19817
19886
  const revealed = vue.ref(true);
@@ -20229,9 +20298,11 @@
20229
20298
  setup (props, { slots, emit }) {
20230
20299
  const { proxy: { $q } } = vue.getCurrentInstance();
20231
20300
 
20232
- const $layout = vue.inject(layoutKey, () => {
20301
+ const $layout = vue.inject(layoutKey, emptyRenderFn);
20302
+ if ($layout === emptyRenderFn) {
20233
20303
  console.error('QHeader needs to be child of QLayout');
20234
- });
20304
+ return emptyRenderFn
20305
+ }
20235
20306
 
20236
20307
  const size = vue.ref(parseInt(props.heightHint, 10));
20237
20308
  const revealed = vue.ref(true);
@@ -21135,7 +21206,7 @@
21135
21206
  '^'
21136
21207
  + unmask.join('')
21137
21208
  + '(' + (unmaskChar === '' ? '.' : '[^' + unmaskChar + ']') + '+)?'
21138
- + '$'
21209
+ + (unmaskChar === '' ? '' : '[' + unmaskChar + ']*') + '$'
21139
21210
  ),
21140
21211
  extractLast = extract.length - 1,
21141
21212
  extractMatcher = extract.map((re, index) => {
@@ -22161,7 +22232,7 @@
22161
22232
  + (props.padding === true ? ' q-list--padding' : '')
22162
22233
  );
22163
22234
 
22164
- return () => vue.h('div', { class: classes.value }, hSlot(slots.default))
22235
+ return () => vue.h('div', { class: classes.value, role: 'list' }, hSlot(slots.default))
22165
22236
  }
22166
22237
  });
22167
22238
 
@@ -23202,7 +23273,7 @@
23202
23273
  );
23203
23274
 
23204
23275
  const attrs = vue.computed(() => {
23205
- const attrs = {};
23276
+ const attrs = { role: 'group' };
23206
23277
 
23207
23278
  if (props.type === 'radio') {
23208
23279
  attrs.role = 'radiogroup';
@@ -23267,10 +23338,17 @@
23267
23338
  setup (props, { slots }) {
23268
23339
  const { proxy: { $q } } = vue.getCurrentInstance();
23269
23340
 
23270
- const $layout = vue.inject(layoutKey);
23271
- vue.inject(pageContainerKey, () => {
23341
+ const $layout = vue.inject(layoutKey, emptyRenderFn);
23342
+ if ($layout === emptyRenderFn) {
23343
+ console.error('QPage needs to be a deep child of QLayout');
23344
+ return emptyRenderFn
23345
+ }
23346
+
23347
+ const $pageContainer = vue.inject(pageContainerKey, emptyRenderFn);
23348
+ if ($pageContainer === emptyRenderFn) {
23272
23349
  console.error('QPage needs to be child of QPageContainer');
23273
- });
23350
+ return emptyRenderFn
23351
+ }
23274
23352
 
23275
23353
  const style = vue.computed(() => {
23276
23354
  const offset
@@ -23313,9 +23391,11 @@
23313
23391
  setup (_, { slots }) {
23314
23392
  const { proxy: { $q } } = vue.getCurrentInstance();
23315
23393
 
23316
- const $layout = vue.inject(layoutKey, () => {
23394
+ const $layout = vue.inject(layoutKey, emptyRenderFn);
23395
+ if ($layout === emptyRenderFn) {
23317
23396
  console.error('QPageContainer needs to be child of QLayout');
23318
- });
23397
+ return emptyRenderFn
23398
+ }
23319
23399
 
23320
23400
  vue.provide(pageContainerKey, true);
23321
23401
 
@@ -23365,9 +23445,11 @@
23365
23445
  function usePageSticky () {
23366
23446
  const { props, proxy: { $q } } = vue.getCurrentInstance();
23367
23447
 
23368
- const $layout = vue.inject(layoutKey, () => {
23448
+ const $layout = vue.inject(layoutKey, emptyRenderFn);
23449
+ if ($layout === emptyRenderFn) {
23369
23450
  console.error('QPageSticky needs to be child of QLayout');
23370
- });
23451
+ return emptyRenderFn
23452
+ }
23371
23453
 
23372
23454
  const attach = vue.computed(() => {
23373
23455
  const pos = props.position;
@@ -23580,6 +23662,12 @@
23580
23662
  }
23581
23663
  });
23582
23664
 
23665
+ function getBool (val, otherwise) {
23666
+ return [ true, false ].includes(val)
23667
+ ? val
23668
+ : otherwise
23669
+ }
23670
+
23583
23671
  var QPagination = createComponent({
23584
23672
  name: 'QPagination',
23585
23673
 
@@ -23591,22 +23679,20 @@
23591
23679
  required: true
23592
23680
  },
23593
23681
  min: {
23594
- type: Number,
23682
+ type: [ Number, String ],
23595
23683
  default: 1
23596
23684
  },
23597
23685
  max: {
23598
- type: Number,
23686
+ type: [ Number, String ],
23599
23687
  required: true
23600
23688
  },
23601
-
23602
- color: {
23603
- type: String,
23604
- default: 'primary'
23689
+ maxPages: {
23690
+ type: [ Number, String ],
23691
+ default: 0,
23692
+ validator: v => (
23693
+ (typeof v === 'string' ? parseInt(v, 10) : v) >= 0
23694
+ )
23605
23695
  },
23606
- textColor: String,
23607
-
23608
- activeColor: String,
23609
- activeTextColor: String,
23610
23696
 
23611
23697
  inputStyle: [ Array, String, Object ],
23612
23698
  inputClass: [ Array, String, Object ],
@@ -23640,11 +23726,6 @@
23640
23726
  type: Boolean,
23641
23727
  default: null
23642
23728
  },
23643
- maxPages: {
23644
- type: Number,
23645
- default: 0,
23646
- validator: v => v >= 0
23647
- },
23648
23729
 
23649
23730
  ripple: {
23650
23731
  type: [ Boolean, Object ],
@@ -23660,7 +23741,21 @@
23660
23741
  push: Boolean,
23661
23742
  glossy: Boolean,
23662
23743
 
23663
- dense: Boolean,
23744
+ color: {
23745
+ type: String,
23746
+ default: 'primary'
23747
+ },
23748
+ textColor: String,
23749
+
23750
+ activeDesign: {
23751
+ type: String,
23752
+ default: '',
23753
+ values: v => v === '' || btnDesignOptions.includes(v)
23754
+ },
23755
+ activeColor: String,
23756
+ activeTextColor: String,
23757
+
23758
+ gutter: String,
23664
23759
  padding: {
23665
23760
  type: String,
23666
23761
  default: '3px 2px'
@@ -23675,6 +23770,16 @@
23675
23770
 
23676
23771
  const isDark = useDark(props, $q);
23677
23772
 
23773
+ const minProp = vue.computed(() => parseInt(props.min, 10));
23774
+ const maxProp = vue.computed(() => parseInt(props.max, 10));
23775
+ const maxPagesProp = vue.computed(() => parseInt(props.maxPages, 10));
23776
+
23777
+ const inputPlaceholder = vue.computed(() => model.value + ' / ' + maxProp.value);
23778
+ const boundaryLinksProp = vue.computed(() => getBool(props.boundaryLinks, props.input));
23779
+ const boundaryNumbersProp = vue.computed(() => getBool(props.boundaryNumbers, !props.input));
23780
+ const directionLinksProp = vue.computed(() => getBool(props.directionLinks, props.input));
23781
+ const ellipsesProp = vue.computed(() => getBool(props.ellipses, !props.input));
23782
+
23678
23783
  const newPage = vue.ref(null);
23679
23784
  const model = vue.computed({
23680
23785
  get: () => props.modelValue,
@@ -23683,32 +23788,33 @@
23683
23788
  if (props.disable || isNaN(val)) {
23684
23789
  return
23685
23790
  }
23686
- const value = between(val, props.min, props.max);
23791
+ const value = between(val, minProp.value, maxProp.value);
23687
23792
  if (props.modelValue !== value) {
23688
23793
  emit('update:modelValue', value);
23689
23794
  }
23690
23795
  }
23691
23796
  });
23692
23797
 
23693
- vue.watch(() => props.min + props.max, () => {
23798
+ vue.watch(() => `${ minProp.value }|${ maxProp.value }`, () => {
23694
23799
  model.value = props.modelValue;
23695
23800
  });
23696
23801
 
23697
- function getBool (val, otherwise) {
23698
- return [ true, false ].includes(val)
23699
- ? val
23700
- : otherwise
23701
- }
23702
-
23703
23802
  const classes = vue.computed(() =>
23704
23803
  'q-pagination row no-wrap items-center'
23705
23804
  + (props.disable === true ? ' disabled' : '')
23706
23805
  );
23707
- const inputPlaceholder = vue.computed(() => model.value + ' / ' + props.max);
23708
- const __boundaryLinks = vue.computed(() => getBool(props.boundaryLinks, props.input));
23709
- const __boundaryNumbers = vue.computed(() => getBool(props.boundaryNumbers, !props.input));
23710
- const __directionLinks = vue.computed(() => getBool(props.directionLinks, props.input));
23711
- const __ellipses = vue.computed(() => getBool(props.ellipses, !props.input));
23806
+
23807
+ const gutterProp = vue.computed(() => (
23808
+ props.gutter in btnPadding
23809
+ ? `${ btnPadding[ props.gutter ] }px`
23810
+ : props.gutter || null
23811
+ ));
23812
+ const gutterStyle = vue.computed(() => (
23813
+ gutterProp.value !== null
23814
+ ? `--q-pagination-gutter-parent:-${ gutterProp.value };--q-pagination-gutter-child:${ gutterProp.value }`
23815
+ : null
23816
+ ));
23817
+
23712
23818
  const icons = vue.computed(() => {
23713
23819
  const ico = [
23714
23820
  props.iconFirst || $q.iconSet.pagination.first,
@@ -23719,38 +23825,90 @@
23719
23825
  return $q.lang.rtl === true ? ico.reverse() : ico
23720
23826
  });
23721
23827
 
23722
- const attrs = vue.computed(() => (
23723
- props.disable === true
23724
- ? { 'aria-disabled': 'true' }
23725
- : {}
23726
- ));
23828
+ const attrs = vue.computed(() => ({
23829
+ 'aria-disabled': props.disable === true ? 'true' : 'false',
23830
+ role: 'navigation'
23831
+ }));
23727
23832
 
23833
+ const btnDesignProp = vue.computed(() => getBtnDesign(props, 'flat'));
23728
23834
  const btnProps = vue.computed(() => ({
23835
+ [ btnDesignProp.value ]: true,
23836
+
23729
23837
  round: props.round,
23730
23838
  rounded: props.rounded,
23731
23839
 
23732
- outline: props.outline,
23733
- unelevated: props.unelevated,
23734
- push: props.push,
23735
- glossy: props.glossy,
23736
-
23737
- dense: props.dense,
23738
23840
  padding: props.padding,
23739
23841
 
23740
23842
  color: props.color,
23741
- flat: true,
23843
+ textColor: props.textColor,
23844
+
23742
23845
  size: props.size,
23743
23846
  ripple: props.ripple !== null
23744
23847
  ? props.ripple
23745
23848
  : true
23746
23849
  }));
23747
23850
 
23851
+ const btnActiveDesignProp = vue.computed(() => {
23852
+ // we also reset non-active design
23853
+ const acc = { [ btnDesignProp.value ]: false };
23854
+ if (props.activeDesign !== '') {
23855
+ acc[ props.activeDesign ] = true;
23856
+ }
23857
+ return acc
23858
+ });
23748
23859
  const activeBtnProps = vue.computed(() => ({
23749
- flat: props.flat,
23860
+ ...btnActiveDesignProp.value,
23750
23861
  color: props.activeColor || props.color,
23751
23862
  textColor: props.activeTextColor || props.textColor
23752
23863
  }));
23753
23864
 
23865
+ const btnConfig = vue.computed(() => {
23866
+ let maxPages = Math.max(
23867
+ maxPagesProp.value,
23868
+ 1 + (ellipsesProp.value ? 2 : 0) + (boundaryNumbersProp.value ? 2 : 0)
23869
+ );
23870
+
23871
+ const acc = {
23872
+ pgFrom: minProp.value,
23873
+ pgTo: maxProp.value,
23874
+ ellipsesStart: false,
23875
+ ellipsesEnd: false,
23876
+ boundaryStart: false,
23877
+ boundaryEnd: false,
23878
+ marginalStyle: {
23879
+ minWidth: `${ Math.max(2, String(maxProp.value).length) }em`
23880
+ }
23881
+ };
23882
+
23883
+ if (maxPagesProp.value && maxPages < (maxProp.value - minProp.value + 1)) {
23884
+ maxPages = 1 + Math.floor(maxPages / 2) * 2;
23885
+ acc.pgFrom = Math.max(minProp.value, Math.min(maxProp.value - maxPages + 1, props.modelValue - Math.floor(maxPages / 2)));
23886
+ acc.pgTo = Math.min(maxProp.value, acc.pgFrom + maxPages - 1);
23887
+
23888
+ if (boundaryNumbersProp.value) {
23889
+ acc.boundaryStart = true;
23890
+ acc.pgFrom++;
23891
+ }
23892
+
23893
+ if (ellipsesProp.value && acc.pgFrom > (minProp.value + (boundaryNumbersProp.value ? 1 : 0))) {
23894
+ acc.ellipsesStart = true;
23895
+ acc.pgFrom++;
23896
+ }
23897
+
23898
+ if (boundaryNumbersProp.value) {
23899
+ acc.boundaryEnd = true;
23900
+ acc.pgTo--;
23901
+ }
23902
+
23903
+ if (ellipsesProp.value && acc.pgTo < (maxProp.value - (boundaryNumbersProp.value ? 1 : 0))) {
23904
+ acc.ellipsesEnd = true;
23905
+ acc.pgTo--;
23906
+ }
23907
+ }
23908
+
23909
+ return acc
23910
+ });
23911
+
23754
23912
  function set (value) {
23755
23913
  model.value = value;
23756
23914
  }
@@ -23759,20 +23917,40 @@
23759
23917
  model.value = model.value + offset;
23760
23918
  }
23761
23919
 
23762
- function updateModel () {
23763
- model.value = newPage.value;
23764
- newPage.value = null;
23765
- }
23920
+ const inputEvents = vue.computed(() => {
23921
+ function updateModel () {
23922
+ model.value = newPage.value;
23923
+ newPage.value = null;
23924
+ }
23766
23925
 
23767
- function getBtn (cfg, page) {
23768
- const data = { ...btnProps.value, ...cfg };
23926
+ return {
23927
+ 'onUpdate:modelValue': val => { newPage.value = val; },
23928
+ onKeyup: e => { isKeyCode(e, 13) === true && updateModel(); },
23929
+ onBlur: updateModel
23930
+ }
23931
+ });
23932
+
23933
+ function getBtn (cfg, page, active) {
23934
+ const data = {
23935
+ 'aria-label': page,
23936
+ 'aria-current': 'false',
23937
+ ...btnProps.value,
23938
+ ...cfg
23939
+ };
23940
+
23941
+ if (active === true) {
23942
+ Object.assign(data, {
23943
+ 'aria-current': 'true',
23944
+ ...activeBtnProps.value
23945
+ });
23946
+ }
23769
23947
 
23770
23948
  if (page !== void 0) {
23771
23949
  if (props.toFn !== void 0) {
23772
23950
  data.to = props.toFn(page);
23773
23951
  }
23774
23952
  else {
23775
- data.onClick = () => set(page);
23953
+ data.onClick = () => { set(page); };
23776
23954
  }
23777
23955
  }
23778
23956
 
@@ -23783,147 +23961,107 @@
23783
23961
  Object.assign(proxy, { set, setByOffset });
23784
23962
 
23785
23963
  return () => {
23786
- const
23787
- contentStart = [],
23788
- contentEnd = [],
23789
- contentMiddle = [];
23964
+ const contentStart = [];
23965
+ const contentEnd = [];
23966
+ let contentMiddle;
23967
+
23968
+ if (boundaryLinksProp.value === true) {
23969
+ contentStart.push(
23970
+ getBtn({
23971
+ key: 'bls',
23972
+ disable: props.disable || props.modelValue <= minProp.value,
23973
+ icon: icons.value[ 0 ]
23974
+ }, minProp.value)
23975
+ );
23790
23976
 
23791
- if (__boundaryLinks.value) {
23792
- contentStart.push(getBtn({
23793
- key: 'bls',
23794
- disable: props.disable || props.modelValue <= props.min,
23795
- icon: icons.value[ 0 ]
23796
- }, props.min));
23797
- contentEnd.unshift(getBtn({
23798
- key: 'ble',
23799
- disable: props.disable || props.modelValue >= props.max,
23800
- icon: icons.value[ 3 ]
23801
- }, props.max));
23802
- }
23803
-
23804
- if (__directionLinks.value) {
23805
- contentStart.push(getBtn({
23806
- key: 'bdp',
23807
- disable: props.disable || props.modelValue <= props.min,
23808
- icon: icons.value[ 1 ]
23809
- }, props.modelValue - 1));
23810
- contentEnd.unshift(getBtn({
23811
- key: 'bdn',
23812
- disable: props.disable || props.modelValue >= props.max,
23813
- icon: icons.value[ 2 ]
23814
- }, props.modelValue + 1));
23815
- }
23816
-
23817
- if (props.input === true) {
23818
- contentMiddle.push(vue.h(QInput, {
23819
- class: 'inline',
23820
- style: {
23821
- width: `${ inputPlaceholder.value.length / 1.5 }em`
23822
- },
23823
- type: 'number',
23824
- dense: true,
23825
- value: newPage.value,
23826
- disable: props.disable,
23827
- dark: isDark.value,
23828
- borderless: true,
23829
- inputClass: props.inputClass,
23830
- inputStyle: props.inputStyle,
23831
- placeholder: inputPlaceholder.value,
23832
- min: props.min,
23833
- max: props.max,
23834
- 'onUpdate:modelValue' (value) { newPage.value = value; },
23835
- onKeyup (e) { isKeyCode(e, 13) === true && updateModel(); },
23836
- onBlur: updateModel
23837
- }));
23977
+ contentEnd.unshift(
23978
+ getBtn({
23979
+ key: 'ble',
23980
+ disable: props.disable || props.modelValue >= maxProp.value,
23981
+ icon: icons.value[ 3 ]
23982
+ }, maxProp.value)
23983
+ );
23838
23984
  }
23839
- else { // is type select
23840
- let
23841
- maxPages = Math.max(
23842
- props.maxPages,
23843
- 1 + (__ellipses.value ? 2 : 0) + (__boundaryNumbers.value ? 2 : 0)
23844
- ),
23845
- pgFrom = props.min,
23846
- pgTo = props.max,
23847
- ellipsesStart = false,
23848
- ellipsesEnd = false,
23849
- boundaryStart = false,
23850
- boundaryEnd = false;
23851
-
23852
- if (props.maxPages && maxPages < (props.max - props.min + 1)) {
23853
- maxPages = 1 + Math.floor(maxPages / 2) * 2;
23854
- pgFrom = Math.max(props.min, Math.min(props.max - maxPages + 1, props.modelValue - Math.floor(maxPages / 2)));
23855
- pgTo = Math.min(props.max, pgFrom + maxPages - 1);
23856
- if (__boundaryNumbers.value) {
23857
- boundaryStart = true;
23858
- pgFrom += 1;
23859
- }
23860
- if (__ellipses.value && pgFrom > (props.min + (__boundaryNumbers.value ? 1 : 0))) {
23861
- ellipsesStart = true;
23862
- pgFrom += 1;
23863
- }
23864
- if (__boundaryNumbers.value) {
23865
- boundaryEnd = true;
23866
- pgTo -= 1;
23867
- }
23868
- if (__ellipses.value && pgTo < (props.max - (__boundaryNumbers.value ? 1 : 0))) {
23869
- ellipsesEnd = true;
23870
- pgTo -= 1;
23871
- }
23985
+
23986
+ if (directionLinksProp.value === true) {
23987
+ contentStart.push(
23988
+ getBtn({
23989
+ key: 'bdp',
23990
+ disable: props.disable || props.modelValue <= minProp.value,
23991
+ icon: icons.value[ 1 ]
23992
+ }, props.modelValue - 1)
23993
+ );
23994
+
23995
+ contentEnd.unshift(
23996
+ getBtn({
23997
+ key: 'bdn',
23998
+ disable: props.disable || props.modelValue >= maxProp.value,
23999
+ icon: icons.value[ 2 ]
24000
+ }, props.modelValue + 1)
24001
+ );
24002
+ }
24003
+
24004
+ if (props.input !== true) { // has buttons instead of inputbox
24005
+ contentMiddle = [];
24006
+ const { pgFrom, pgTo, marginalStyle: style } = btnConfig.value;
24007
+
24008
+ if (btnConfig.value.boundaryStart === true) {
24009
+ const active = minProp.value === props.modelValue;
24010
+ contentStart.push(
24011
+ getBtn({
24012
+ key: 'bns',
24013
+ style,
24014
+ disable: props.disable,
24015
+ label: minProp.value
24016
+ }, minProp.value, active)
24017
+ );
23872
24018
  }
23873
- const style = {
23874
- minWidth: `${ Math.max(2, String(props.max).length) }em`
23875
- };
23876
- if (boundaryStart) {
23877
- const active = props.min === props.modelValue;
23878
- contentStart.push(getBtn({
23879
- key: 'bns',
23880
- style,
23881
- disable: props.disable,
23882
- flat: !active,
23883
- label: props.min,
23884
- ...(active ? activeBtnProps.value : {})
23885
- }, props.min));
23886
- }
23887
- if (boundaryEnd) {
23888
- const active = props.max === props.modelValue;
23889
- contentEnd.unshift(getBtn({
23890
- key: 'bne',
23891
- style,
23892
- disable: props.disable,
23893
- flat: !active,
23894
- label: props.max,
23895
- ...(active ? activeBtnProps.value : {})
23896
- }, props.max));
23897
- }
23898
- if (ellipsesStart) {
23899
- contentStart.push(getBtn({
23900
- key: 'bes',
23901
- style,
23902
- disable: props.disable,
23903
- label: '…',
23904
- ripple: false
23905
- }, pgFrom - 1));
23906
- }
23907
- if (ellipsesEnd) {
23908
- contentEnd.unshift(getBtn({
23909
- key: 'bee',
23910
- style,
23911
- disable: props.disable,
23912
- label: '…',
23913
- ripple: false
23914
- }, pgTo + 1));
24019
+
24020
+ if (btnConfig.value.boundaryEnd === true) {
24021
+ const active = maxProp.value === props.modelValue;
24022
+ contentEnd.unshift(
24023
+ getBtn({
24024
+ key: 'bne',
24025
+ style,
24026
+ disable: props.disable,
24027
+ label: maxProp.value
24028
+ }, maxProp.value, active)
24029
+ );
24030
+ }
24031
+
24032
+ if (btnConfig.value.ellipsesStart === true) {
24033
+ contentStart.push(
24034
+ getBtn({
24035
+ key: 'bes',
24036
+ style,
24037
+ disable: props.disable,
24038
+ label: '…',
24039
+ ripple: false
24040
+ }, pgFrom - 1)
24041
+ );
23915
24042
  }
24043
+
24044
+ if (btnConfig.value.ellipsesEnd === true) {
24045
+ contentEnd.unshift(
24046
+ getBtn({
24047
+ key: 'bee',
24048
+ style,
24049
+ disable: props.disable,
24050
+ label: '…',
24051
+ ripple: false
24052
+ }, pgTo + 1)
24053
+ );
24054
+ }
24055
+
23916
24056
  for (let i = pgFrom; i <= pgTo; i++) {
23917
- const btn = {
23918
- key: `bpg${ i }`,
23919
- style,
23920
- disable: props.disable,
23921
- label: i
23922
- };
23923
- if (i === props.modelValue) {
23924
- Object.assign(btn, activeBtnProps.value);
23925
- }
23926
- contentMiddle.push(getBtn(btn, i));
24057
+ contentMiddle.push(
24058
+ getBtn({
24059
+ key: `bpg${ i }`,
24060
+ style,
24061
+ disable: props.disable,
24062
+ label: i
24063
+ }, i, i === props.modelValue)
24064
+ );
23927
24065
  }
23928
24066
  }
23929
24067
 
@@ -23931,15 +24069,35 @@
23931
24069
  class: classes.value,
23932
24070
  ...attrs.value
23933
24071
  }, [
23934
- contentStart,
23935
-
23936
24072
  vue.h('div', {
23937
- class: 'row justify-center'
24073
+ class: 'q-pagination__content row no-wrap items-center',
24074
+ style: gutterStyle.value
23938
24075
  }, [
23939
- contentMiddle
23940
- ]),
24076
+ ...contentStart,
24077
+
24078
+ props.input === true
24079
+ ? vue.h(QInput, {
24080
+ class: 'inline',
24081
+ style: { width: `${ inputPlaceholder.value.length / 1.5 }em` },
24082
+ type: 'number',
24083
+ dense: true,
24084
+ value: newPage.value,
24085
+ disable: props.disable,
24086
+ dark: isDark.value,
24087
+ borderless: true,
24088
+ inputClass: props.inputClass,
24089
+ inputStyle: props.inputStyle,
24090
+ placeholder: inputPlaceholder.value,
24091
+ min: minProp.value,
24092
+ max: maxProp.value,
24093
+ ...inputEvents.value
24094
+ })
24095
+ : vue.h('div', {
24096
+ class: 'q-pagination__middle row justify-center'
24097
+ }, contentMiddle),
23941
24098
 
23942
- contentEnd
24099
+ ...contentEnd
24100
+ ])
23943
24101
  ])
23944
24102
  }
23945
24103
  }
@@ -24673,10 +24831,7 @@
24673
24831
 
24674
24832
  const directives = vue.computed(() => {
24675
24833
  // if props.disable === false
24676
- const modifiers = {
24677
- down: true,
24678
- mightPrevent: true
24679
- };
24834
+ const modifiers = { down: true };
24680
24835
 
24681
24836
  if (props.noMouse !== true) {
24682
24837
  modifiers.mouse = true;
@@ -30861,9 +31016,11 @@
30861
31016
  setup (props, { slots, emit }) {
30862
31017
  const { proxy: { $q } } = vue.getCurrentInstance();
30863
31018
 
30864
- const $stepper = vue.inject(stepperKey, () => {
30865
- console.error('QStep needs to be child of QStepper');
30866
- });
31019
+ const $stepper = vue.inject(stepperKey, emptyRenderFn);
31020
+ if ($stepper === emptyRenderFn) {
31021
+ console.error('QStep needs to be a child of QStepper');
31022
+ return emptyRenderFn
31023
+ }
30867
31024
 
30868
31025
  const { getCacheWithFn } = useCache();
30869
31026
 
@@ -30921,7 +31078,7 @@
30921
31078
 
30922
31079
  return () => vue.h(
30923
31080
  'div',
30924
- { ref: rootRef, class: 'q-stepper__step', ...scrollEvent.value },
31081
+ { ref: rootRef, class: 'q-stepper__step', role: 'tabpanel', ...scrollEvent.value },
30925
31082
  $stepper.value.vertical === true
30926
31083
  ? [
30927
31084
  vue.h(StepHeader, {
@@ -33986,9 +34143,11 @@
33986
34143
  },
33987
34144
 
33988
34145
  setup (props, { slots }) {
33989
- const $timeline = vue.inject(timelineKey, () => {
34146
+ const $timeline = vue.inject(timelineKey, emptyRenderFn);
34147
+ if ($timeline === emptyRenderFn) {
33990
34148
  console.error('QTimelineEntry needs to be child of QTimeline');
33991
- });
34149
+ return emptyRenderFn
34150
+ }
33992
34151
 
33993
34152
  const classes = vue.computed(() =>
33994
34153
  `q-timeline__entry q-timeline__entry--${ props.side }`
@@ -34077,7 +34236,7 @@
34077
34236
  + (props.inset === true ? ' q-toolbar--inset' : '')
34078
34237
  );
34079
34238
 
34080
- return () => vue.h('div', { class: classes.value }, hSlot(slots.default))
34239
+ return () => vue.h('div', { class: classes.value, role: 'toolbar' }, hSlot(slots.default))
34081
34240
  }
34082
34241
  });
34083
34242
 
@@ -34151,6 +34310,7 @@
34151
34310
 
34152
34311
  duration: Number,
34153
34312
  noConnectors: Boolean,
34313
+ noTransition: Boolean,
34154
34314
 
34155
34315
  noNodesLabel: String,
34156
34316
  noResultsLabel: String
@@ -34223,7 +34383,6 @@
34223
34383
  const
34224
34384
  key = node[ props.nodeKey ],
34225
34385
  isParent = node[ props.childrenKey ] && node[ props.childrenKey ].length > 0,
34226
- isLeaf = isParent !== true,
34227
34386
  selectable = node.disabled !== true && hasSelection.value === true && node.selectable !== false,
34228
34387
  expandable = node.disabled !== true && node.expandable !== false,
34229
34388
  hasTicking = tickStrategy !== 'none',
@@ -34249,7 +34408,6 @@
34249
34408
  key,
34250
34409
  parent,
34251
34410
  isParent,
34252
- isLeaf,
34253
34411
  lazy: localLazy,
34254
34412
  disabled: node.disabled,
34255
34413
  link: node.disabled !== true && (selectable === true || (expandable === true && (isParent === true || localLazy === true))),
@@ -34269,7 +34427,7 @@
34269
34427
  leafTicking,
34270
34428
  ticked: strictTicking === true
34271
34429
  ? innerTicked.value.includes(key)
34272
- : (isLeaf === true ? innerTicked.value.includes(key) : false)
34430
+ : (isParent === true ? false : innerTicked.value.includes(key))
34273
34431
  };
34274
34432
 
34275
34433
  meta[ key ] = m;
@@ -34669,23 +34827,37 @@
34669
34827
  ]),
34670
34828
 
34671
34829
  isParent === true
34672
- ? vue.h(QSlideTransition, {
34673
- duration: props.duration,
34674
- onShow,
34675
- onHide
34676
- }, () => vue.withDirectives(
34677
- vue.h('div', {
34678
- class: 'q-tree__node-collapsible' + textColorClass.value,
34679
- key: `${ key }__q`
34680
- }, [
34681
- body,
34682
- vue.h('div', {
34683
- class: 'q-tree__children'
34684
- + (m.disabled === true ? ' q-tree__node--disabled' : '')
34685
- }, children)
34686
- ]),
34687
- [ [ vue.vShow, m.expanded ] ]
34688
- ))
34830
+ ? (
34831
+ props.noTransition === true
34832
+ ? vue.h('div', {
34833
+ class: 'q-tree__node-collapsible' + textColorClass.value,
34834
+ key: `${ key }__q`
34835
+ }, [
34836
+ body,
34837
+ vue.h('div', {
34838
+ class: 'q-tree__children'
34839
+ + (m.disabled === true ? ' q-tree__node--disabled' : '')
34840
+ }, m.expanded ? children : null)
34841
+ ])
34842
+
34843
+ : vue.h(QSlideTransition, {
34844
+ duration: props.duration,
34845
+ onShow,
34846
+ onHide
34847
+ }, () => vue.withDirectives(
34848
+ vue.h('div', {
34849
+ class: 'q-tree__node-collapsible' + textColorClass.value,
34850
+ key: `${ key }__q`
34851
+ }, [
34852
+ body,
34853
+ vue.h('div', {
34854
+ class: 'q-tree__children'
34855
+ + (m.disabled === true ? ' q-tree__node--disabled' : '')
34856
+ }, children)
34857
+ ]),
34858
+ [ [ vue.vShow, m.expanded ] ]
34859
+ ))
34860
+ )
34689
34861
  : body
34690
34862
  ])
34691
34863
  }
@@ -35552,9 +35724,13 @@
35552
35724
  name: 'QUploaderAddTrigger',
35553
35725
 
35554
35726
  setup () {
35555
- return vue.inject(uploaderKey, () => {
35727
+ const $trigger = vue.inject(uploaderKey, emptyRenderFn);
35728
+
35729
+ if ($trigger === emptyRenderFn) {
35556
35730
  console.error('QUploaderAddTrigger needs to be child of QUploader');
35557
- })
35731
+ }
35732
+
35733
+ return $trigger
35558
35734
  }
35559
35735
  });
35560
35736
 
@@ -35953,9 +36129,13 @@
35953
36129
  fill: typeof options.fill === 'string' && options.fill.length > 0 ? options.fill : 'none',
35954
36130
 
35955
36131
  resize: options.resize === true,
35956
- useCSS: options.useCSS === true,
35957
- hideFromClone: options.hideFromClone === true,
35958
- keepToClone: options.keepToClone === true,
36132
+
36133
+ // account for UMD too where modifiers will be lowercased to work
36134
+ useCSS: options.useCSS === true || options.usecss === true,
36135
+ // account for UMD too where modifiers will be lowercased to work
36136
+ hideFromClone: options.hideFromClone === true || options.hidefromclone === true,
36137
+ // account for UMD too where modifiers will be lowercased to work
36138
+ keepToClone: options.keepToClone === true || options.keeptoclone === true,
35959
36139
 
35960
36140
  tween: options.tween === true,
35961
36141
  tweenFromOpacity: isNaN(options.tweenFromOpacity) === true ? 0.6 : parseFloat(options.tweenFromOpacity),
@@ -37280,9 +37460,16 @@
37280
37460
 
37281
37461
  el.__qtouchhold = ctx;
37282
37462
 
37283
- modifiers.mouse === true && addEvt(ctx, 'main', [
37284
- [ el, 'mousedown', 'mouseStart', `passive${ modifiers.mouseCapture === true ? 'Capture' : '' }` ]
37285
- ]);
37463
+ if (modifiers.mouse === true) {
37464
+ // account for UMD too where modifiers will be lowercased to work
37465
+ const capture = modifiers.mouseCapture === true || modifiers.mousecapture === true
37466
+ ? 'Capture'
37467
+ : '';
37468
+
37469
+ addEvt(ctx, 'main', [
37470
+ [ el, 'mousedown', 'mouseStart', `passive${ capture }` ]
37471
+ ]);
37472
+ }
37286
37473
 
37287
37474
  client.has.touch === true && addEvt(ctx, 'main', [
37288
37475
  [ el, 'touchstart', 'touchStart', `passive${ modifiers.capture === true ? 'Capture' : '' }` ],
@@ -37510,18 +37697,32 @@
37510
37697
 
37511
37698
  el.__qtouchrepeat = ctx;
37512
37699
 
37513
- modifiers.mouse === true && addEvt(ctx, 'main', [
37514
- [ el, 'mousedown', 'mouseStart', `passive${ modifiers.mouseCapture === true ? 'Capture' : '' }` ]
37515
- ]);
37700
+ if (modifiers.mouse === true) {
37701
+ // account for UMD too where modifiers will be lowercased to work
37702
+ const capture = modifiers.mouseCapture === true || modifiers.mousecapture === true
37703
+ ? 'Capture'
37704
+ : '';
37705
+
37706
+ addEvt(ctx, 'main', [
37707
+ [ el, 'mousedown', 'mouseStart', `passive${ capture }` ]
37708
+ ]);
37709
+ }
37516
37710
 
37517
37711
  client.has.touch === true && addEvt(ctx, 'main', [
37518
37712
  [ el, 'touchstart', 'touchStart', `passive${ modifiers.capture === true ? 'Capture' : '' }` ],
37519
37713
  [ el, 'touchend', 'noop', 'passiveCapture' ]
37520
37714
  ]);
37521
37715
 
37522
- keyboard.length > 0 && addEvt(ctx, 'main', [
37523
- [ el, 'keydown', 'keyboardStart', `notPassive${ modifiers.keyCapture === true ? 'Capture' : '' }` ]
37524
- ]);
37716
+ if (keyboard.length !== 0) {
37717
+ // account for UMD too where modifiers will be lowercased to work
37718
+ const capture = modifiers.keyCapture === true || modifiers.keycapture === true
37719
+ ? 'Capture'
37720
+ : '';
37721
+
37722
+ addEvt(ctx, 'main', [
37723
+ [ el, 'keydown', 'keyboardStart', `notPassive${ capture }` ]
37724
+ ]);
37725
+ }
37525
37726
  },
37526
37727
 
37527
37728
  updated (el, { oldValue, value }) {
@@ -37849,6 +38050,7 @@
37849
38050
  action.class
37850
38051
  ],
37851
38052
  tabindex: 0,
38053
+ role: 'listitem',
37852
38054
  onClick () { onOk(action); },
37853
38055
  onKeyup (e) { e.keyCode === 13 && onOk(action); }
37854
38056
  }, [
@@ -37924,9 +38126,12 @@
37924
38126
  child.push(
37925
38127
  props.grid === true
37926
38128
  ? vue.h('div', {
37927
- class: 'row items-stretch justify-start'
38129
+ class: 'row items-stretch justify-start',
38130
+ role: 'list'
37928
38131
  }, getGrid())
37929
- : vue.h('div', getList())
38132
+ : vue.h('div', {
38133
+ role: 'list'
38134
+ }, getList())
37930
38135
  );
37931
38136
 
37932
38137
  return child
@@ -40270,7 +40475,7 @@
40270
40475
  */
40271
40476
 
40272
40477
  var index_umd = {
40273
- version: '2.9.1',
40478
+ version: '2.10.0',
40274
40479
  install (app, opts) {
40275
40480
  installQuasar(app, {
40276
40481
  components,