quasar 2.8.4 → 2.9.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 (165) hide show
  1. package/dist/api/QBreadcrumbsEl.json +52 -0
  2. package/dist/api/QBtn.json +41 -6
  3. package/dist/api/QBtnDropdown.json +1 -1
  4. package/dist/api/QChip.json +1 -1
  5. package/dist/api/QEditor.json +7 -0
  6. package/dist/api/QExpansionItem.json +1 -1
  7. package/dist/api/QItem.json +52 -0
  8. package/dist/api/QRating.json +13 -0
  9. package/dist/api/QRouteTab.json +42 -6
  10. package/dist/icon-set/bootstrap-icons.umd.prod.js +1 -1
  11. package/dist/icon-set/eva-icons.umd.prod.js +1 -1
  12. package/dist/icon-set/fontawesome-v5-pro.umd.prod.js +1 -1
  13. package/dist/icon-set/fontawesome-v5.umd.prod.js +1 -1
  14. package/dist/icon-set/fontawesome-v6-pro.umd.prod.js +1 -1
  15. package/dist/icon-set/fontawesome-v6.umd.prod.js +1 -1
  16. package/dist/icon-set/ionicons-v4.umd.prod.js +1 -1
  17. package/dist/icon-set/line-awesome.umd.prod.js +1 -1
  18. package/dist/icon-set/material-icons-outlined.umd.prod.js +1 -1
  19. package/dist/icon-set/material-icons-round.umd.prod.js +1 -1
  20. package/dist/icon-set/material-icons-sharp.umd.prod.js +1 -1
  21. package/dist/icon-set/material-icons.umd.prod.js +1 -1
  22. package/dist/icon-set/material-symbols-outlined.umd.prod.js +1 -1
  23. package/dist/icon-set/material-symbols-rounded.umd.prod.js +1 -1
  24. package/dist/icon-set/material-symbols-sharp.umd.prod.js +1 -1
  25. package/dist/icon-set/mdi-v3.umd.prod.js +1 -1
  26. package/dist/icon-set/mdi-v4.umd.prod.js +1 -1
  27. package/dist/icon-set/mdi-v5.umd.prod.js +1 -1
  28. package/dist/icon-set/mdi-v6.umd.prod.js +1 -1
  29. package/dist/icon-set/svg-bootstrap-icons.umd.prod.js +1 -1
  30. package/dist/icon-set/svg-eva-icons.umd.prod.js +1 -1
  31. package/dist/icon-set/svg-fontawesome-v5.umd.prod.js +1 -1
  32. package/dist/icon-set/svg-fontawesome-v6.umd.prod.js +1 -1
  33. package/dist/icon-set/svg-ionicons-v4.umd.prod.js +1 -1
  34. package/dist/icon-set/svg-ionicons-v5.umd.prod.js +1 -1
  35. package/dist/icon-set/svg-ionicons-v6.umd.prod.js +1 -1
  36. package/dist/icon-set/svg-line-awesome.umd.prod.js +1 -1
  37. package/dist/icon-set/svg-material-icons-outlined.umd.prod.js +1 -1
  38. package/dist/icon-set/svg-material-icons-round.umd.prod.js +1 -1
  39. package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +1 -1
  40. package/dist/icon-set/svg-material-icons.umd.prod.js +1 -1
  41. package/dist/icon-set/svg-material-symbols-outlined.umd.prod.js +1 -1
  42. package/dist/icon-set/svg-material-symbols-rounded.umd.prod.js +1 -1
  43. package/dist/icon-set/svg-material-symbols-sharp.umd.prod.js +1 -1
  44. package/dist/icon-set/svg-mdi-v6.umd.prod.js +1 -1
  45. package/dist/icon-set/svg-themify.umd.prod.js +1 -1
  46. package/dist/icon-set/themify.umd.prod.js +1 -1
  47. package/dist/lang/ar-TN.umd.prod.js +1 -1
  48. package/dist/lang/ar.umd.prod.js +1 -1
  49. package/dist/lang/az-Latn.umd.prod.js +1 -1
  50. package/dist/lang/bg.umd.prod.js +1 -1
  51. package/dist/lang/bn.umd.prod.js +1 -1
  52. package/dist/lang/ca.umd.prod.js +1 -1
  53. package/dist/lang/cs.umd.prod.js +1 -1
  54. package/dist/lang/da.umd.prod.js +1 -1
  55. package/dist/lang/de.umd.prod.js +1 -1
  56. package/dist/lang/el.umd.prod.js +1 -1
  57. package/dist/lang/en-GB.umd.prod.js +1 -1
  58. package/dist/lang/en-US.umd.prod.js +1 -1
  59. package/dist/lang/eo.umd.prod.js +1 -1
  60. package/dist/lang/es.umd.prod.js +1 -1
  61. package/dist/lang/et.umd.prod.js +1 -1
  62. package/dist/lang/eu.umd.prod.js +1 -1
  63. package/dist/lang/fa-IR.umd.prod.js +1 -1
  64. package/dist/lang/fa.umd.prod.js +1 -1
  65. package/dist/lang/fi.umd.prod.js +1 -1
  66. package/dist/lang/fr.umd.prod.js +1 -1
  67. package/dist/lang/gn.umd.prod.js +1 -1
  68. package/dist/lang/he.umd.prod.js +1 -1
  69. package/dist/lang/hr.umd.prod.js +1 -1
  70. package/dist/lang/hu.umd.prod.js +1 -1
  71. package/dist/lang/id.umd.prod.js +1 -1
  72. package/dist/lang/is.umd.prod.js +1 -1
  73. package/dist/lang/it.umd.prod.js +1 -1
  74. package/dist/lang/ja.umd.prod.js +1 -1
  75. package/dist/lang/km.umd.prod.js +1 -1
  76. package/dist/lang/ko-KR.umd.prod.js +1 -1
  77. package/dist/lang/kur-CKB.umd.prod.js +1 -1
  78. package/dist/lang/kz.umd.prod.js +1 -1
  79. package/dist/lang/lt.umd.prod.js +1 -1
  80. package/dist/lang/lu.umd.prod.js +1 -1
  81. package/dist/lang/lv.umd.prod.js +1 -1
  82. package/dist/lang/ml.umd.prod.js +1 -1
  83. package/dist/lang/mm.umd.prod.js +1 -1
  84. package/dist/lang/ms.umd.prod.js +1 -1
  85. package/dist/lang/my.umd.prod.js +1 -1
  86. package/dist/lang/nb-NO.umd.prod.js +1 -1
  87. package/dist/lang/nl.umd.prod.js +2 -2
  88. package/dist/lang/pl.umd.prod.js +1 -1
  89. package/dist/lang/pt-BR.umd.prod.js +1 -1
  90. package/dist/lang/pt.umd.prod.js +1 -1
  91. package/dist/lang/ro.umd.prod.js +1 -1
  92. package/dist/lang/ru.umd.prod.js +1 -1
  93. package/dist/lang/sk.umd.prod.js +1 -1
  94. package/dist/lang/sl.umd.prod.js +1 -1
  95. package/dist/lang/sm.umd.prod.js +1 -1
  96. package/dist/lang/sr-CYR.umd.prod.js +1 -1
  97. package/dist/lang/sr.umd.prod.js +1 -1
  98. package/dist/lang/sv.umd.prod.js +1 -1
  99. package/dist/lang/ta.umd.prod.js +1 -1
  100. package/dist/lang/th.umd.prod.js +1 -1
  101. package/dist/lang/tr.umd.prod.js +1 -1
  102. package/dist/lang/ug.umd.prod.js +1 -1
  103. package/dist/lang/uk.umd.prod.js +1 -1
  104. package/dist/lang/uz-Cyrl.umd.prod.js +1 -1
  105. package/dist/lang/uz-Latn.umd.prod.js +1 -1
  106. package/dist/lang/vi.umd.prod.js +1 -1
  107. package/dist/lang/zh-CN.umd.prod.js +1 -1
  108. package/dist/lang/zh-TW.umd.prod.js +1 -1
  109. package/dist/quasar.cjs.prod.js +2 -2
  110. package/dist/quasar.esm.js +533 -337
  111. package/dist/quasar.esm.prod.js +2 -2
  112. package/dist/quasar.sass +1 -1
  113. package/dist/quasar.umd.js +532 -336
  114. package/dist/quasar.umd.prod.js +2 -2
  115. package/dist/types/api/qeditor.d.ts +17 -0
  116. package/dist/types/api.d.ts +1 -0
  117. package/dist/types/index.d.ts +93 -8
  118. package/dist/types/utils/run-sequential-promises.d.ts +1 -1
  119. package/dist/vetur/quasar-attributes.json +4 -0
  120. package/dist/vetur/quasar-tags.json +1 -0
  121. package/dist/web-types/web-types.json +60 -9
  122. package/lang/nl.js +2 -2
  123. package/lang/nl.mjs +2 -2
  124. package/package.json +5 -3
  125. package/src/components/breadcrumbs/QBreadcrumbsEl.js +6 -7
  126. package/src/components/breadcrumbs/QBreadcrumbsEl.json +53 -0
  127. package/src/components/btn/QBtn.js +19 -19
  128. package/src/components/btn/QBtn.json +41 -6
  129. package/src/components/btn/use-btn.js +6 -4
  130. package/src/components/btn-dropdown/QBtnDropdown.json +1 -1
  131. package/src/components/checkbox/QCheckbox.js +1 -2
  132. package/src/components/checkbox/use-checkbox.js +2 -1
  133. package/src/components/chip/QChip.json +1 -1
  134. package/src/components/dialog/QDialog.js +6 -4
  135. package/src/components/drawer/QDrawer.js +7 -4
  136. package/src/components/editor/QEditor.json +9 -0
  137. package/src/components/expansion-item/QExpansionItem.json +1 -1
  138. package/src/components/item/QItem.js +4 -5
  139. package/src/components/item/QItem.json +53 -0
  140. package/src/components/menu/QMenu.js +4 -5
  141. package/src/components/menu/__tests__/QMenu.spec.js +7 -0
  142. package/src/components/popup-edit/QPopupEdit.js +2 -5
  143. package/src/components/radio/QRadio.js +3 -3
  144. package/src/components/rating/QRating.js +48 -10
  145. package/src/components/rating/QRating.json +11 -0
  146. package/src/components/stepper/QStep.js +5 -3
  147. package/src/components/table/QTable.js +3 -5
  148. package/src/components/tabs/QRouteTab.js +6 -4
  149. package/src/components/tabs/QRouteTab.json +42 -6
  150. package/src/components/tabs/QTabs.js +188 -108
  151. package/src/components/tabs/use-tab.js +62 -38
  152. package/src/components/tooltip/QTooltip.js +7 -13
  153. package/src/components/tree/QTree.js +1 -1
  154. package/src/composables/private/__tests__/use-model-toggle.spec.js +2 -0
  155. package/src/composables/private/__tests__/use-transition.spec.js +4 -0
  156. package/src/composables/private/use-router-link.js +80 -43
  157. package/src/composables/private/use-tick.js +15 -9
  158. package/src/composables/private/use-timeout.js +20 -7
  159. package/src/directives/TouchPan.js +1 -1
  160. package/src/directives/TouchRepeat.js +1 -1
  161. package/src/directives/TouchSwipe.js +1 -1
  162. package/src/utils/extend.js +19 -19
  163. package/src/utils/private/inject-obj-prop.js +2 -0
  164. package/src/utils/private/rtl.js +10 -7
  165. package/src/utils/run-sequential-promises.js +1 -1
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Quasar Framework v2.8.4
2
+ * Quasar Framework v2.9.0
3
3
  * (c) 2015-present Razvan Stoenescu
4
4
  * Released under the MIT License.
5
5
  */
@@ -16,12 +16,14 @@
16
16
  set,
17
17
  enumerable: true
18
18
  });
19
+ return target
19
20
  }
20
21
 
21
22
  function injectMultipleProps (target, props) {
22
23
  for (const key in props) {
23
24
  injectProp(target, key, props[ key ]);
24
25
  }
26
+ return target
25
27
  }
26
28
 
27
29
  /* eslint-disable no-useless-escape */
@@ -1608,7 +1610,7 @@
1608
1610
  }
1609
1611
 
1610
1612
  var installQuasar = function (parentApp, opts = {}) {
1611
- const $q = { version: '2.8.4' };
1613
+ const $q = { version: '2.9.0' };
1612
1614
 
1613
1615
  if (globalConfigIsFrozen === false) {
1614
1616
  if (opts.config !== void 0) {
@@ -2733,30 +2735,34 @@
2733
2735
 
2734
2736
  // external props: type, tag
2735
2737
 
2736
- function useRouterLink (fallbackTag) {
2738
+ function useRouterLink ({ fallbackTag, useDisableForRouterLinkProps = true } = {}) {
2737
2739
  const vm = vue.getCurrentInstance();
2738
- const { props, proxy } = vm;
2740
+ const { props, proxy, emit } = vm;
2739
2741
 
2740
2742
  const hasRouter = vmHasRouter(vm);
2741
2743
  const hasHrefLink = vue.computed(() => props.disable !== true && props.href !== void 0);
2742
2744
 
2743
- const hasRouterLinkProps = vue.computed(() =>
2744
- hasRouter === true
2745
- && props.disable !== true
2746
- && hasHrefLink.value !== true
2747
- && props.to !== void 0 && props.to !== null && props.to !== ''
2748
- );
2749
-
2750
- const linkRoute = vue.computed(() => {
2751
- if (hasRouterLinkProps.value === true) {
2752
- try { return proxy.$router.resolve(props.to) }
2753
- catch (err) {}
2754
- }
2745
+ // for perf reasons, we use minimum amount of runtime work
2746
+ const hasRouterLinkProps = useDisableForRouterLinkProps === true
2747
+ ? vue.computed(() =>
2748
+ hasRouter === true
2749
+ && props.disable !== true
2750
+ && hasHrefLink.value !== true
2751
+ && props.to !== void 0 && props.to !== null && props.to !== ''
2752
+ )
2753
+ : vue.computed(() =>
2754
+ hasRouter === true
2755
+ && hasHrefLink.value !== true
2756
+ && props.to !== void 0 && props.to !== null && props.to !== ''
2757
+ );
2755
2758
 
2756
- return null
2757
- });
2759
+ const resolvedLink = vue.computed(() => (
2760
+ hasRouterLinkProps.value === true
2761
+ ? getLink(props.to)
2762
+ : null
2763
+ ));
2758
2764
 
2759
- const hasRouterLink = vue.computed(() => linkRoute.value !== null);
2765
+ const hasRouterLink = vue.computed(() => resolvedLink.value !== null);
2760
2766
  const hasLink = vue.computed(() => hasHrefLink.value === true || hasRouterLink.value === true);
2761
2767
 
2762
2768
  const linkTag = vue.computed(() => (
@@ -2765,7 +2771,7 @@
2765
2771
  : (props.tag || fallbackTag || 'div')
2766
2772
  ));
2767
2773
 
2768
- const linkProps = vue.computed(() => (
2774
+ const linkAttrs = vue.computed(() => (
2769
2775
  hasHrefLink.value === true
2770
2776
  ? {
2771
2777
  href: props.href,
@@ -2774,7 +2780,7 @@
2774
2780
  : (
2775
2781
  hasRouterLink.value === true
2776
2782
  ? {
2777
- href: linkRoute.value.href,
2783
+ href: resolvedLink.value.href,
2778
2784
  target: props.target
2779
2785
  }
2780
2786
  : {}
@@ -2783,11 +2789,11 @@
2783
2789
 
2784
2790
  const linkActiveIndex = vue.computed(() => {
2785
2791
  if (hasRouterLink.value === false) {
2786
- return null
2792
+ return -1
2787
2793
  }
2788
2794
 
2789
2795
  const
2790
- { matched } = linkRoute.value,
2796
+ { matched } = resolvedLink.value,
2791
2797
  { length } = matched,
2792
2798
  routeMatched = matched[ length - 1 ];
2793
2799
 
@@ -2830,14 +2836,14 @@
2830
2836
 
2831
2837
  const linkIsActive = vue.computed(() =>
2832
2838
  hasRouterLink.value === true
2833
- && linkActiveIndex.value > -1
2834
- && includesParams(proxy.$route.params, linkRoute.value.params)
2839
+ && linkActiveIndex.value !== -1
2840
+ && includesParams(proxy.$route.params, resolvedLink.value.params)
2835
2841
  );
2836
2842
 
2837
2843
  const linkIsExactActive = vue.computed(() =>
2838
2844
  linkIsActive.value === true
2839
2845
  && linkActiveIndex.value === proxy.$route.matched.length - 1
2840
- && isSameRouteLocationParams(proxy.$route.params, linkRoute.value.params)
2846
+ && isSameRouteLocationParams(proxy.$route.params, resolvedLink.value.params)
2841
2847
  );
2842
2848
 
2843
2849
  const linkClass = vue.computed(() => (
@@ -2854,32 +2860,64 @@
2854
2860
  : ''
2855
2861
  ));
2856
2862
 
2857
- // should match RouterLink from Vue Router
2858
- function navigateToRouterLink (e) {
2859
- if (
2860
- // component is not disabled
2861
- props.disable === true
2863
+ function getLink (to) {
2864
+ try { return proxy.$router.resolve(to) }
2865
+ catch (_) {}
2862
2866
 
2863
- // don't redirect with control keys
2864
- || e.metaKey || e.altKey || e.ctrlKey || e.shiftKey
2867
+ return null
2868
+ }
2865
2869
 
2866
- // don't redirect when preventDefault called
2867
- // ...unless calling go() from @click(e, go)
2868
- || (e.__qNavigate !== true && e.defaultPrevented === true)
2870
+ /**
2871
+ * @returns Promise<RouterError | false | undefined>
2872
+ */
2873
+ function navigateToRouterLink (
2874
+ e,
2875
+ { returnRouterError, to = props.to, replace = props.replace } = {}
2876
+ ) {
2877
+ if (props.disable === true) {
2878
+ // ensure native navigation is prevented in all cases,
2879
+ // like when useDisableForRouterLinkProps === false (QRouteTab)
2880
+ e.preventDefault();
2881
+ return Promise.resolve(false)
2882
+ }
2883
+
2884
+ if (
2885
+ // don't redirect with control keys;
2886
+ // should match RouterLink from Vue Router
2887
+ e.metaKey || e.altKey || e.ctrlKey || e.shiftKey
2869
2888
 
2870
2889
  // don't redirect on right click
2871
- || (e.button !== undefined && e.button !== 0)
2890
+ || (e.button !== void 0 && e.button !== 0)
2872
2891
 
2873
2892
  // don't redirect if it should open in a new window
2874
2893
  || props.target === '_blank'
2875
2894
  ) {
2876
- return false
2895
+ return Promise.resolve(false)
2877
2896
  }
2878
2897
 
2879
- prevent(e);
2898
+ // hinder the native navigation
2899
+ e.preventDefault();
2900
+
2901
+ // then() can also return a "soft" router error (Vue Router behavior)
2902
+ const promise = proxy.$router[ replace === true ? 'replace' : 'push' ](to);
2903
+
2904
+ return returnRouterError === true
2905
+ ? promise
2906
+ // else catching hard errors and also "soft" ones - then(err => ...)
2907
+ : promise.then(() => {}).catch(() => {})
2908
+ }
2909
+
2910
+ // warning! ensure that the component using it has 'click' included in its 'emits' definition prop
2911
+ function navigateOnClick (e) {
2912
+ if (hasRouterLink.value === true) {
2913
+ const go = opts => navigateToRouterLink(e, opts);
2880
2914
 
2881
- return proxy.$router[ props.replace === true ? 'replace' : 'push' ](props.to)
2882
- .catch(err => err)
2915
+ emit('click', e, go);
2916
+ e.defaultPrevented !== true && go();
2917
+ }
2918
+ else {
2919
+ emit('click', e);
2920
+ }
2883
2921
  }
2884
2922
 
2885
2923
  return {
@@ -2888,13 +2926,15 @@
2888
2926
  hasLink,
2889
2927
 
2890
2928
  linkTag,
2891
- linkRoute,
2929
+ resolvedLink,
2892
2930
  linkIsActive,
2893
2931
  linkIsExactActive,
2894
2932
  linkClass,
2895
- linkProps,
2933
+ linkAttrs,
2896
2934
 
2897
- navigateToRouterLink
2935
+ getLink,
2936
+ navigateToRouterLink,
2937
+ navigateOnClick
2898
2938
  }
2899
2939
  }
2900
2940
 
@@ -2913,20 +2953,19 @@
2913
2953
  }
2914
2954
  },
2915
2955
 
2956
+ emits: [ 'click' ],
2957
+
2916
2958
  setup (props, { slots }) {
2917
- const { linkTag, linkProps, linkClass, hasRouterLink, navigateToRouterLink } = useRouterLink();
2959
+ const { linkTag, linkAttrs, linkClass, navigateOnClick } = useRouterLink();
2918
2960
 
2919
2961
  const data = vue.computed(() => {
2920
- const acc = {
2962
+ return {
2921
2963
  class: 'q-breadcrumbs__el q-link '
2922
2964
  + 'flex inline items-center relative-position '
2923
2965
  + (props.disable !== true ? 'q-link--focusable' + linkClass.value : 'q-breadcrumbs__el--disable'),
2924
- ...linkProps.value
2925
- };
2926
- if (hasRouterLink.value === true) {
2927
- acc.onClick = navigateToRouterLink;
2966
+ ...linkAttrs.value,
2967
+ onClick: navigateOnClick
2928
2968
  }
2929
- return acc
2930
2969
  });
2931
2970
 
2932
2971
  const iconClass = vue.computed(() =>
@@ -3337,7 +3376,9 @@
3337
3376
  function useBtn (props) {
3338
3377
  const sizeStyle = useSize(props, defaultSizes$2);
3339
3378
  const alignClass = useAlign(props);
3340
- const { hasRouterLink, hasLink, linkTag, linkProps, navigateToRouterLink } = useRouterLink('button');
3379
+ const { hasRouterLink, hasLink, linkTag, linkAttrs, navigateOnClick } = useRouterLink({
3380
+ fallbackTag: 'button'
3381
+ });
3341
3382
 
3342
3383
  const style = vue.computed(() => {
3343
3384
  const obj = props.fab === false && props.fabMini === false
@@ -3380,7 +3421,7 @@
3380
3421
  const acc = { tabindex: tabIndex.value };
3381
3422
 
3382
3423
  if (hasLink.value === true) {
3383
- Object.assign(acc, linkProps.value);
3424
+ Object.assign(acc, linkAttrs.value);
3384
3425
  }
3385
3426
  else if (formTypes.includes(props.type) === true) {
3386
3427
  acc.type = props.type;
@@ -3393,6 +3434,7 @@
3393
3434
  else if (acc.href === void 0) {
3394
3435
  acc.role = 'button';
3395
3436
  }
3437
+
3396
3438
  if (hasRouterLink.value !== true && mediaTypeRE.test(props.type) === true) {
3397
3439
  acc.type = props.type;
3398
3440
  }
@@ -3455,10 +3497,9 @@
3455
3497
  style,
3456
3498
  innerClasses,
3457
3499
  attributes,
3458
- hasRouterLink,
3459
3500
  hasLink,
3460
3501
  linkTag,
3461
- navigateToRouterLink,
3502
+ navigateOnClick,
3462
3503
  isActionable
3463
3504
  }
3464
3505
  }
@@ -3477,10 +3518,12 @@
3477
3518
  ...useBtnProps,
3478
3519
 
3479
3520
  percentage: Number,
3480
- darkPercentage: Boolean
3521
+ darkPercentage: Boolean,
3522
+
3523
+ onTouchstart: [ Function, Array ]
3481
3524
  },
3482
3525
 
3483
- emits: [ 'click', 'keydown', 'touchstart', 'mousedown', 'keyup' ],
3526
+ emits: [ 'click', 'keydown', 'mousedown', 'keyup' ],
3484
3527
 
3485
3528
  setup (props, { slots, emit }) {
3486
3529
  const { proxy } = vue.getCurrentInstance();
@@ -3488,7 +3531,7 @@
3488
3531
  const {
3489
3532
  classes, style, innerClasses,
3490
3533
  attributes,
3491
- hasRouterLink, hasLink, linkTag, navigateToRouterLink,
3534
+ hasLink, linkTag, navigateOnClick,
3492
3535
  isActionable
3493
3536
  } = useBtn(props);
3494
3537
 
@@ -3523,7 +3566,7 @@
3523
3566
  if (props.loading === true) {
3524
3567
  return {
3525
3568
  onMousedown: onLoadingEvt,
3526
- onTouchstartPassive: onLoadingEvt,
3569
+ onTouchstart: onLoadingEvt,
3527
3570
  onClick: onLoadingEvt,
3528
3571
  onKeydown: onLoadingEvt,
3529
3572
  onKeyup: onLoadingEvt
@@ -3531,12 +3574,21 @@
3531
3574
  }
3532
3575
 
3533
3576
  if (isActionable.value === true) {
3534
- return {
3577
+ const acc = {
3535
3578
  onClick,
3536
3579
  onKeydown,
3537
- onMousedown,
3538
- onTouchstart
3580
+ onMousedown
3581
+ };
3582
+
3583
+ if (proxy.$q.platform.has.touch === true) {
3584
+ const suffix = props.onTouchstart !== void 0
3585
+ ? ''
3586
+ : 'Passive';
3587
+
3588
+ acc[ `onTouchstart${ suffix }` ] = onTouchstart;
3539
3589
  }
3590
+
3591
+ return acc
3540
3592
  }
3541
3593
 
3542
3594
  return {
@@ -3586,18 +3638,7 @@
3586
3638
  }
3587
3639
  }
3588
3640
 
3589
- if (hasRouterLink.value === true) {
3590
- const go = () => {
3591
- e.__qNavigate = true;
3592
- navigateToRouterLink(e);
3593
- };
3594
-
3595
- emit('click', e, go);
3596
- e.defaultPrevented !== true && go();
3597
- }
3598
- else {
3599
- emit('click', e);
3600
- }
3641
+ navigateOnClick(e);
3601
3642
  }
3602
3643
 
3603
3644
  function onKeydown (e) {
@@ -4541,49 +4582,64 @@
4541
4582
  /*
4542
4583
  * Usage:
4543
4584
  * registerTick(fn)
4544
- * registerTick(fn)
4585
+ * removeTick()
4545
4586
  */
4546
4587
 
4547
4588
  function useTick () {
4548
4589
  let tickFn;
4590
+ const vm = vue.getCurrentInstance();
4549
4591
 
4550
- vue.onBeforeUnmount(() => {
4592
+ function removeTick () {
4551
4593
  tickFn = void 0;
4552
- });
4594
+ }
4595
+
4596
+ vue.onDeactivated(removeTick);
4597
+ vue.onBeforeUnmount(removeTick);
4553
4598
 
4554
4599
  return {
4600
+ removeTick,
4601
+
4555
4602
  registerTick (fn) {
4556
4603
  tickFn = fn;
4557
4604
 
4558
4605
  vue.nextTick(() => {
4559
4606
  if (tickFn === fn) {
4560
- tickFn();
4607
+ // we also check if VM is destroyed, since if it
4608
+ // got to trigger one nextTick() we cannot stop it
4609
+ vmIsDestroyed(vm) === false && tickFn();
4561
4610
  tickFn = void 0;
4562
4611
  }
4563
4612
  });
4564
- },
4565
-
4566
- removeTick () {
4567
- tickFn = void 0;
4568
4613
  }
4569
4614
  }
4570
4615
  }
4571
4616
 
4617
+ /*
4618
+ * Usage:
4619
+ * registerTimeout(fn[, delay])
4620
+ * removeTimeout()
4621
+ */
4622
+
4572
4623
  function useTimeout () {
4573
4624
  let timer;
4625
+ const vm = vue.getCurrentInstance();
4574
4626
 
4575
- vue.onBeforeUnmount(() => {
4627
+ function removeTimeout () {
4576
4628
  clearTimeout(timer);
4577
- });
4629
+ }
4630
+
4631
+ vue.onDeactivated(removeTimeout);
4632
+ vue.onBeforeUnmount(removeTimeout);
4578
4633
 
4579
4634
  return {
4635
+ removeTimeout,
4636
+
4580
4637
  registerTimeout (fn, delay) {
4581
4638
  clearTimeout(timer);
4582
- timer = setTimeout(fn, delay);
4583
- },
4584
4639
 
4585
- removeTimeout () {
4586
- clearTimeout(timer);
4640
+ if (vmIsDestroyed(vm) === false) {
4641
+ timer = setTimeout(fn, delay);
4642
+ }
4587
4643
  }
4588
4644
  }
4589
4645
  }
@@ -5260,7 +5316,7 @@
5260
5316
 
5261
5317
  const isDark = useDark(props, $q);
5262
5318
  const { registerTick, removeTick } = useTick();
5263
- const { registerTimeout, removeTimeout } = useTimeout();
5319
+ const { registerTimeout } = useTimeout();
5264
5320
  const { transition, transitionStyle } = useTransition(props, showing);
5265
5321
  const { localScrollTarget, changeScrollEvent, unconfigureScrollTarget } = useScrollTarget(props, configureScrollTarget);
5266
5322
 
@@ -5348,9 +5404,6 @@
5348
5404
  }
5349
5405
 
5350
5406
  function handleShow (evt) {
5351
- removeTick();
5352
- removeTimeout();
5353
-
5354
5407
  refocusTarget = props.noRefocus === false
5355
5408
  ? document.activeElement
5356
5409
  : null;
@@ -5382,11 +5435,13 @@
5382
5435
  document.activeElement.blur();
5383
5436
  }
5384
5437
 
5438
+ // should removeTick() if this gets removed
5385
5439
  registerTick(() => {
5386
5440
  updatePosition();
5387
5441
  props.noFocus !== true && focus();
5388
5442
  });
5389
5443
 
5444
+ // should removeTimeout() if this gets removed
5390
5445
  registerTimeout(() => {
5391
5446
  // required in order to avoid the "double-tap needed" issue
5392
5447
  if ($q.platform.is.ios === true) {
@@ -5404,7 +5459,6 @@
5404
5459
 
5405
5460
  function handleHide (evt) {
5406
5461
  removeTick();
5407
- removeTimeout();
5408
5462
  hidePortal();
5409
5463
 
5410
5464
  anchorCleanup(true);
@@ -5422,6 +5476,7 @@
5422
5476
  refocusTarget = null;
5423
5477
  }
5424
5478
 
5479
+ // should removeTimeout() if this gets removed
5425
5480
  registerTimeout(() => {
5426
5481
  hidePortal(true); // done hiding, now destroy
5427
5482
  emit('hide', evt);
@@ -5591,7 +5646,7 @@
5591
5646
  // or improve speed by increasing this number (try 16384)
5592
5647
  const BUFFER_SIZE = 4096;
5593
5648
 
5594
- function uid$4 () {
5649
+ function uid$3 () {
5595
5650
  // Buffer some random bytes for speed
5596
5651
  if (buf === void 0 || (bufIdx + 16 > BUFFER_SIZE)) {
5597
5652
  bufIdx = 0;
@@ -5655,7 +5710,7 @@
5655
5710
 
5656
5711
  const showing = vue.ref(props.modelValue);
5657
5712
  const menuRef = vue.ref(null);
5658
- const targetUid = uid$4();
5713
+ const targetUid = uid$3();
5659
5714
 
5660
5715
  const attributes = vue.computed(() => {
5661
5716
  const acc = {
@@ -6373,7 +6428,7 @@
6373
6428
 
6374
6429
  client.has.touch === true && addEvt(ctx, 'main', [
6375
6430
  [ el, 'touchstart', 'touchStart', `passive${ modifiers.capture === true ? 'Capture' : '' }` ],
6376
- [ el, 'touchmove', 'noop', 'notPassiveCapture' ]
6431
+ [ el, 'touchmove', 'noop', 'notPassiveCapture' ] // cannot be passive (ex: iOS scroll)
6377
6432
  ]);
6378
6433
  },
6379
6434
 
@@ -7528,7 +7583,8 @@
7528
7583
  const child = [
7529
7584
  vue.h('div', {
7530
7585
  class: innerClass.value,
7531
- style: sizeStyle.value
7586
+ style: sizeStyle.value,
7587
+ 'aria-hidden': 'true'
7532
7588
  }, inner)
7533
7589
  ];
7534
7590
 
@@ -7563,8 +7619,7 @@
7563
7619
  }, [
7564
7620
  vue.h('svg', {
7565
7621
  class: 'q-checkbox__svg fit absolute-full',
7566
- viewBox: '0 0 24 24',
7567
- 'aria-hidden': 'true'
7622
+ viewBox: '0 0 24 24'
7568
7623
  }, [
7569
7624
  vue.h('path', {
7570
7625
  class: 'q-checkbox__truthy',
@@ -8095,7 +8150,7 @@
8095
8150
  }
8096
8151
  }
8097
8152
 
8098
- let uid$3 = 0;
8153
+ let uid$2 = 0;
8099
8154
 
8100
8155
  var TouchPan = createDirective({
8101
8156
  name: 'touch-pan',
@@ -8117,7 +8172,7 @@
8117
8172
  }
8118
8173
 
8119
8174
  const ctx = {
8120
- uid: 'qvtp_' + (uid$3++),
8175
+ uid: 'qvtp_' + (uid$2++),
8121
8176
  handler: value,
8122
8177
  modifiers,
8123
8178
  direction: getModifierDirections(modifiers),
@@ -8364,7 +8419,7 @@
8364
8419
 
8365
8420
  client.has.touch === true && addEvt(ctx, 'main', [
8366
8421
  [ el, 'touchstart', 'touchStart', `passive${ modifiers.capture === true ? 'Capture' : '' }` ],
8367
- [ el, 'touchmove', 'noop', 'notPassiveCapture' ]
8422
+ [ el, 'touchmove', 'noop', 'notPassiveCapture' ] // cannot be passive (ex: iOS scroll)
8368
8423
  ]);
8369
8424
  },
8370
8425
 
@@ -9353,15 +9408,18 @@
9353
9408
  // mobile Chrome takes the crown for this
9354
9409
  {
9355
9410
  const scroller = document.createElement('div');
9356
- const spacer = document.createElement('div');
9357
-
9358
9411
  scroller.setAttribute('dir', 'rtl');
9359
- scroller.style.width = '1px';
9360
- scroller.style.height = '1px';
9361
- scroller.style.overflow = 'auto';
9412
+ Object.assign(scroller.style, {
9413
+ width: '1px',
9414
+ height: '1px',
9415
+ overflow: 'auto'
9416
+ });
9362
9417
 
9363
- spacer.style.width = '1000px';
9364
- spacer.style.height = '1px';
9418
+ const spacer = document.createElement('div');
9419
+ Object.assign(spacer.style, {
9420
+ width: '1000px',
9421
+ height: '1px'
9422
+ });
9365
9423
 
9366
9424
  document.body.appendChild(scroller);
9367
9425
  scroller.appendChild(spacer);
@@ -9381,7 +9439,6 @@
9381
9439
  }
9382
9440
 
9383
9441
  const alignValues$1 = [ 'left', 'center', 'right', 'justify' ];
9384
- const emptyFn = () => {};
9385
9442
 
9386
9443
  var QTabs = createComponent({
9387
9444
  name: 'QTabs',
@@ -9427,12 +9484,15 @@
9427
9484
  },
9428
9485
 
9429
9486
  setup (props, { slots, emit }) {
9430
- const vm = vue.getCurrentInstance();
9431
- const { proxy: { $q } } = vm;
9487
+ const { proxy } = vue.getCurrentInstance();
9488
+ const { $q } = proxy;
9432
9489
 
9433
9490
  const { registerTick: registerScrollTick } = useTick();
9491
+ const { registerTick: registerUpdateArrowsTick } = useTick();
9492
+ const { registerTick: registerAnimateTick } = useTick();
9493
+
9434
9494
  const { registerTimeout: registerFocusTimeout, removeTimeout: removeFocusTimeout } = useTimeout();
9435
- const { registerTimeout } = useTimeout();
9495
+ const { registerTimeout: registerScrollToTabTimeout, removeTimeout: removeScrollToTabTimeout } = useTimeout();
9436
9496
 
9437
9497
  const rootRef = vue.ref(null);
9438
9498
  const contentRef = vue.ref(null);
@@ -9447,10 +9507,11 @@
9447
9507
  $q.platform.is.desktop === true || props.mobileArrows === true
9448
9508
  );
9449
9509
 
9450
- const tabList = [];
9510
+ const tabDataList = [];
9511
+ const tabDataListLen = vue.ref(0);
9451
9512
  const hasFocus = vue.ref(false);
9452
9513
 
9453
- let localFromRoute = false, animateTimer, scrollTimer, unwatchRoute;
9514
+ let animateTimer, scrollTimer, unwatchRoute;
9454
9515
  let localUpdateArrows = arrowsEnabled.value === true
9455
9516
  ? updateArrowsFn
9456
9517
  : noop;
@@ -9469,6 +9530,19 @@
9469
9530
  noCaps: props.noCaps
9470
9531
  }));
9471
9532
 
9533
+ const hasActiveTab = vue.computed(() => {
9534
+ const len = tabDataListLen.value;
9535
+ const val = currentModel.value;
9536
+
9537
+ for (let i = 0; i < len; i++) {
9538
+ if (tabDataList[ i ].name.value === val) {
9539
+ return true
9540
+ }
9541
+ }
9542
+
9543
+ return false
9544
+ });
9545
+
9472
9546
  const alignClass = vue.computed(() => {
9473
9547
  const align = scrollable.value === true
9474
9548
  ? 'left'
@@ -9510,7 +9584,7 @@
9510
9584
  });
9511
9585
 
9512
9586
  vue.watch(() => props.outsideArrows, () => {
9513
- vue.nextTick(recalculateScroll());
9587
+ recalculateScroll();
9514
9588
  });
9515
9589
 
9516
9590
  vue.watch(arrowsEnabled, v => {
@@ -9518,12 +9592,15 @@
9518
9592
  ? updateArrowsFn
9519
9593
  : noop;
9520
9594
 
9521
- vue.nextTick(recalculateScroll());
9595
+ recalculateScroll();
9522
9596
  });
9523
9597
 
9524
9598
  function updateModel ({ name, setCurrent, skipEmit, fromRoute }) {
9525
9599
  if (currentModel.value !== name) {
9526
- skipEmit !== true && emit('update:modelValue', name);
9600
+ if (skipEmit !== true && props[ 'onUpdate:modelValue' ] !== void 0) {
9601
+ emit('update:modelValue', name);
9602
+ }
9603
+
9527
9604
  if (
9528
9605
  setCurrent === true
9529
9606
  || props[ 'onUpdate:modelValue' ] === void 0
@@ -9532,20 +9609,14 @@
9532
9609
  currentModel.value = name;
9533
9610
  }
9534
9611
  }
9535
-
9536
- if (fromRoute !== void 0) {
9537
- localFromRoute = fromRoute;
9538
- }
9539
9612
  }
9540
9613
 
9541
9614
  function recalculateScroll () {
9542
9615
  registerScrollTick(() => {
9543
- if (vmIsDestroyed(vm) === false) {
9544
- updateContainer({
9545
- width: rootRef.value.offsetWidth,
9546
- height: rootRef.value.offsetHeight
9547
- });
9548
- }
9616
+ updateContainer({
9617
+ width: rootRef.value.offsetWidth,
9618
+ height: rootRef.value.offsetHeight
9619
+ });
9549
9620
  });
9550
9621
  }
9551
9622
 
@@ -9567,27 +9638,21 @@
9567
9638
  ),
9568
9639
  scroll = size > 0 && scrollSize > size; // when there is no tab, in Chrome, size === 0 and scrollSize === 1
9569
9640
 
9570
- if (scrollable.value !== scroll) {
9571
- scrollable.value = scroll;
9572
- }
9641
+ scrollable.value = scroll;
9573
9642
 
9574
9643
  // Arrows need to be updated even if the scroll status was already true
9575
- scroll === true && vue.nextTick(localUpdateArrows);
9576
-
9577
- const localJustify = size < parseInt(props.breakpoint, 10);
9644
+ scroll === true && registerUpdateArrowsTick(localUpdateArrows);
9578
9645
 
9579
- if (justify.value !== localJustify) {
9580
- justify.value = localJustify;
9581
- }
9646
+ justify.value = size < parseInt(props.breakpoint, 10);
9582
9647
  }
9583
9648
 
9584
9649
  function animate (oldName, newName) {
9585
9650
  const
9586
9651
  oldTab = oldName !== void 0 && oldName !== null && oldName !== ''
9587
- ? tabList.find(tab => tab.name.value === oldName)
9652
+ ? tabDataList.find(tab => tab.name.value === oldName)
9588
9653
  : null,
9589
9654
  newTab = newName !== void 0 && newName !== null && newName !== ''
9590
- ? tabList.find(tab => tab.name.value === newName)
9655
+ ? tabDataList.find(tab => tab.name.value === newName)
9591
9656
  : null;
9592
9657
 
9593
9658
  if (oldTab && newTab) {
@@ -9611,7 +9676,7 @@
9611
9676
  : `translate3d(${ oldPos.left - newPos.left }px,0,0) scale3d(${ newPos.width ? oldPos.width / newPos.width : 1 },1,1)`;
9612
9677
 
9613
9678
  // allow scope updates to kick in (QRouteTab needs more time)
9614
- vue.nextTick(() => {
9679
+ registerAnimateTick(() => {
9615
9680
  animateTimer = setTimeout(() => {
9616
9681
  newEl.style.transition = 'transform .25s cubic-bezier(.4, 0, .2, 1)';
9617
9682
  newEl.style.transform = 'none';
@@ -9666,8 +9731,6 @@
9666
9731
 
9667
9732
  function animScrollTo (value) {
9668
9733
  stopAnimScroll();
9669
- scrollTowards(value);
9670
-
9671
9734
  scrollTimer = setInterval(() => {
9672
9735
  if (scrollTowards(value) === true) {
9673
9736
  stopAnimScroll();
@@ -9698,10 +9761,12 @@
9698
9761
 
9699
9762
  if (keyCode === 36) { // Home
9700
9763
  scrollToTabEl(tabs[ 0 ]);
9764
+ tabs[ 0 ].focus();
9701
9765
  return true
9702
9766
  }
9703
9767
  if (keyCode === 35) { // End
9704
9768
  scrollToTabEl(tabs[ len - 1 ]);
9769
+ tabs[ len - 1 ].focus();
9705
9770
  return true
9706
9771
  }
9707
9772
 
@@ -9767,77 +9832,113 @@
9767
9832
  return done
9768
9833
  }
9769
9834
 
9770
- function getRouteList () {
9771
- return tabList.filter(tab => tab.routerProps !== void 0 && tab.routerProps.hasRouterLink.value === true)
9835
+ function hasQueryIncluded (targetQuery, matchingQuery) {
9836
+ for (const key in targetQuery) {
9837
+ if (targetQuery[ key ] !== matchingQuery[ key ]) {
9838
+ return false
9839
+ }
9840
+ }
9841
+
9842
+ return true
9772
9843
  }
9773
9844
 
9774
9845
  // do not use directly; use verifyRouteModel() instead
9775
9846
  function updateActiveRoute () {
9776
- let name = null, wasActive = localFromRoute;
9847
+ let name = null, bestScore = { matchedLen: 0, queryDiff: 9999, hrefLen: 0 };
9777
9848
 
9778
- const
9779
- best = { matchedLen: 0, hrefLen: 0, exact: false, found: false },
9780
- { hash } = vm.proxy.$route,
9781
- model = currentModel.value;
9782
-
9783
- let wasItActive = wasActive === true
9784
- ? emptyFn
9785
- : tab => {
9786
- if (model === tab.name.value) {
9787
- wasActive = true;
9788
- wasItActive = emptyFn;
9789
- }
9790
- };
9849
+ const list = tabDataList.filter(tab => tab.routeData !== void 0 && tab.routeData.hasRouterLink.value === true);
9850
+ const { hash: currentHash, query: currentQuery } = proxy.$route;
9851
+ const currentQueryLen = Object.keys(currentQuery).length;
9791
9852
 
9792
- const tabList = getRouteList();
9853
+ // Vue Router does not keep account of hash & query when matching
9854
+ // so we're doing this as well
9793
9855
 
9794
- for (const tab of tabList) {
9795
- const exact = tab.routerProps.exact.value === true;
9856
+ for (const tab of list) {
9857
+ const exact = tab.routeData.exact.value === true;
9796
9858
 
9797
- if (
9798
- tab.routerProps[ exact === true ? 'linkIsExactActive' : 'linkIsActive' ].value !== true
9799
- || (best.exact === true && exact !== true)
9800
- ) {
9801
- wasItActive(tab);
9859
+ if (tab.routeData[ exact === true ? 'linkIsExactActive' : 'linkIsActive' ].value !== true) {
9860
+ // it cannot match anything as it's not active nor exact-active
9802
9861
  continue
9803
9862
  }
9804
9863
 
9805
- const
9806
- linkRoute = tab.routerProps.linkRoute.value,
9807
- tabHash = linkRoute.hash;
9864
+ const { hash, query, matched, href } = tab.routeData.resolvedLink.value;
9865
+ const queryLen = Object.keys(query).length;
9808
9866
 
9809
- // Vue Router does not match the hash too, even if link is set to "exact"
9810
9867
  if (exact === true) {
9811
- if (hash === tabHash) {
9812
- name = tab.name.value;
9813
- break
9868
+ if (hash !== currentHash) {
9869
+ // it's set to exact but it doesn't matches the hash
9870
+ continue
9814
9871
  }
9815
- else if (hash !== '' && tabHash !== '') {
9816
- wasItActive(tab);
9872
+
9873
+ if (
9874
+ queryLen !== currentQueryLen
9875
+ || hasQueryIncluded(currentQuery, query) === false
9876
+ ) {
9877
+ // it's set to exact but it doesn't matches the query
9817
9878
  continue
9818
9879
  }
9880
+
9881
+ // yey, we found the perfect match (route + hash + query)
9882
+ name = tab.name.value;
9883
+ break
9819
9884
  }
9820
9885
 
9821
- const
9822
- matchedLen = linkRoute.matched.length,
9823
- hrefLen = linkRoute.href.length - tabHash.length;
9886
+ if (hash !== '' && hash !== currentHash) {
9887
+ // it has hash and it doesn't matches
9888
+ continue
9889
+ }
9824
9890
 
9825
9891
  if (
9826
- matchedLen === best.matchedLen
9827
- ? hrefLen > best.hrefLen
9828
- : matchedLen > best.matchedLen
9892
+ queryLen !== 0
9893
+ && hasQueryIncluded(query, currentQuery) === false
9829
9894
  ) {
9895
+ // it has query and it doesn't includes the current one
9896
+ continue
9897
+ }
9898
+
9899
+ const newScore = {
9900
+ matchedLen: matched.length,
9901
+ queryDiff: currentQueryLen - queryLen,
9902
+ hrefLen: href.length - hash.length
9903
+ };
9904
+
9905
+ if (newScore.matchedLen > bestScore.matchedLen) {
9906
+ // it matches more routes so it's more specific so we set it as current champion
9907
+ name = tab.name.value;
9908
+ bestScore = newScore;
9909
+ continue
9910
+ }
9911
+ else if (newScore.matchedLen !== bestScore.matchedLen) {
9912
+ // it matches less routes than the current champion so we discard it
9913
+ continue
9914
+ }
9915
+
9916
+ if (newScore.queryDiff < bestScore.queryDiff) {
9917
+ // query is closer to the current one so we set it as current champion
9830
9918
  name = tab.name.value;
9831
- Object.assign(best, { matchedLen, hrefLen, exact });
9919
+ bestScore = newScore;
9920
+ }
9921
+ else if (newScore.queryDiff !== bestScore.queryDiff) {
9922
+ // it matches less routes than the current champion so we discard it
9832
9923
  continue
9833
9924
  }
9834
9925
 
9835
- wasItActive(tab);
9926
+ if (newScore.hrefLen > bestScore.hrefLen) {
9927
+ // href is lengthier so it's more specific so we set it as current champion
9928
+ name = tab.name.value;
9929
+ bestScore = newScore;
9930
+ }
9836
9931
  }
9837
9932
 
9838
- if (wasActive === true || name !== null) {
9839
- updateModel({ name, setCurrent: true, fromRoute: true });
9933
+ if (
9934
+ name === null
9935
+ && tabDataList.some(tab => tab.routeData === void 0 && tab.name.value === currentModel.value) === true
9936
+ ) {
9937
+ // we shouldn't interfere if non-route tab is active
9938
+ return
9840
9939
  }
9940
+
9941
+ updateModel({ name, setCurrent: true });
9841
9942
  }
9842
9943
 
9843
9944
  function onFocusin (e) {
@@ -9855,6 +9956,7 @@
9855
9956
  // (it might be other elements focused, like additional QBtn)
9856
9957
  if (tab && rootRef.value.contains(tab) === true) {
9857
9958
  hasFocus.value = true;
9959
+ scrollable.value === true && scrollToTabEl(tab);
9858
9960
  }
9859
9961
  }
9860
9962
  }
@@ -9864,22 +9966,52 @@
9864
9966
  }
9865
9967
 
9866
9968
  function verifyRouteModel () {
9867
- if ($tabs.avoidRouteWatcher !== true) {
9868
- registerTimeout(updateActiveRoute);
9969
+ if ($tabs.avoidRouteWatcher === false) {
9970
+ registerScrollToTabTimeout(updateActiveRoute);
9971
+ }
9972
+ else {
9973
+ removeScrollToTabTimeout();
9869
9974
  }
9870
9975
  }
9871
9976
 
9872
- function registerTab (getTab) {
9873
- tabList.push(getTab);
9977
+ function watchRoute () {
9978
+ if (unwatchRoute === void 0) {
9979
+ const unwatch = vue.watch(() => proxy.$route.fullPath, verifyRouteModel);
9980
+ unwatchRoute = () => {
9981
+ unwatch();
9982
+ unwatchRoute = void 0;
9983
+ };
9984
+ }
9985
+ }
9874
9986
 
9875
- const routeList = getRouteList();
9987
+ function registerTab (tabData) {
9988
+ tabDataList.push(tabData);
9989
+ tabDataListLen.value++;
9876
9990
 
9877
- if (routeList.length > 0) {
9878
- if (unwatchRoute === void 0) {
9879
- unwatchRoute = vue.watch(() => vm.proxy.$route, verifyRouteModel);
9880
- }
9991
+ recalculateScroll();
9881
9992
 
9882
- verifyRouteModel();
9993
+ // if it's a QTab
9994
+ if (tabData.routeData === void 0) {
9995
+ // we should position to the currently active tab (if any)
9996
+ registerScrollToTabTimeout(() => {
9997
+ if (scrollable.value === true) {
9998
+ const value = currentModel.value;
9999
+ const newTab = value !== void 0 && value !== null && value !== ''
10000
+ ? tabDataList.find(tab => tab.name.value === value)
10001
+ : null;
10002
+
10003
+ newTab && scrollToTabEl(newTab.rootRef.value);
10004
+ }
10005
+ });
10006
+ }
10007
+ // else if it's a QRouteTab with a valid link
10008
+ else {
10009
+ // start watching route
10010
+ watchRoute();
10011
+
10012
+ if (tabData.routeData.hasRouterLink.value === true) {
10013
+ verifyRouteModel();
10014
+ }
9883
10015
  }
9884
10016
  }
9885
10017
 
@@ -9891,16 +10023,18 @@
9891
10023
  * always check the existing list again and infer the changes.
9892
10024
  */
9893
10025
  function unregisterTab (tabData) {
9894
- tabList.splice(tabList.indexOf(tabData), 1);
10026
+ tabDataList.splice(tabDataList.indexOf(tabData), 1);
10027
+ tabDataListLen.value--;
9895
10028
 
9896
- if (unwatchRoute !== void 0) {
9897
- const routeList = getRouteList();
10029
+ recalculateScroll();
9898
10030
 
9899
- if (routeList.length === 0) {
10031
+ if (unwatchRoute !== void 0 && tabData.routeData !== void 0) {
10032
+ // unwatch route if we don't have any QRouteTabs left
10033
+ if (tabDataList.every(tab => tab.routeData === void 0) === true) {
9900
10034
  unwatchRoute();
9901
- unwatchRoute = void 0;
9902
10035
  }
9903
10036
 
10037
+ // then update model
9904
10038
  verifyRouteModel();
9905
10039
  }
9906
10040
  }
@@ -9909,33 +10043,38 @@
9909
10043
  currentModel,
9910
10044
  tabProps,
9911
10045
  hasFocus,
10046
+ hasActiveTab,
9912
10047
 
9913
10048
  registerTab,
9914
10049
  unregisterTab,
9915
10050
 
9916
10051
  verifyRouteModel,
9917
10052
  updateModel,
9918
- recalculateScroll,
9919
10053
  onKbdNavigate,
9920
10054
 
9921
- avoidRouteWatcher: false
10055
+ avoidRouteWatcher: false // false | string (uid)
9922
10056
  };
9923
10057
 
9924
10058
  vue.provide(tabsKey, $tabs);
9925
10059
 
9926
- vue.onBeforeUnmount(() => {
10060
+ function cleanup () {
9927
10061
  clearTimeout(animateTimer);
10062
+ stopAnimScroll();
9928
10063
  unwatchRoute !== void 0 && unwatchRoute();
9929
- });
10064
+ }
9930
10065
 
9931
- let shouldActivate = false;
10066
+ let hadRouteWatcher;
10067
+
10068
+ vue.onBeforeUnmount(cleanup);
9932
10069
 
9933
10070
  vue.onDeactivated(() => {
9934
- shouldActivate = true;
10071
+ hadRouteWatcher = unwatchRoute !== void 0;
10072
+ cleanup();
9935
10073
  });
9936
10074
 
9937
10075
  vue.onActivated(() => {
9938
- shouldActivate === true && recalculateScroll();
10076
+ hadRouteWatcher === true && watchRoute();
10077
+ recalculateScroll();
9939
10078
  });
9940
10079
 
9941
10080
  return () => {
@@ -9954,22 +10093,22 @@
9954
10093
  class: 'q-tabs__arrow q-tabs__arrow--left absolute q-tab__icon'
9955
10094
  + (leftArrow.value === true ? '' : ' q-tabs__arrow--faded'),
9956
10095
  name: props.leftIcon || $q.iconSet.tabs[ props.vertical === true ? 'up' : 'left' ],
9957
- onMousedown: scrollToStart,
10096
+ onMousedownPassive: scrollToStart,
9958
10097
  onTouchstartPassive: scrollToStart,
9959
- onMouseup: stopAnimScroll,
9960
- onMouseleave: stopAnimScroll,
9961
- onTouchend: stopAnimScroll
10098
+ onMouseupPassive: stopAnimScroll,
10099
+ onMouseleavePassive: stopAnimScroll,
10100
+ onTouchendPassive: stopAnimScroll
9962
10101
  }),
9963
10102
 
9964
10103
  vue.h(QIcon, {
9965
10104
  class: 'q-tabs__arrow q-tabs__arrow--right absolute q-tab__icon'
9966
10105
  + (rightArrow.value === true ? '' : ' q-tabs__arrow--faded'),
9967
10106
  name: props.rightIcon || $q.iconSet.tabs[ props.vertical === true ? 'down' : 'right' ],
9968
- onMousedown: scrollToEnd,
10107
+ onMousedownPassive: scrollToEnd,
9969
10108
  onTouchstartPassive: scrollToEnd,
9970
- onMouseup: stopAnimScroll,
9971
- onMouseleave: stopAnimScroll,
9972
- onTouchend: stopAnimScroll
10109
+ onMouseupPassive: stopAnimScroll,
10110
+ onMouseleavePassive: stopAnimScroll,
10111
+ onTouchendPassive: stopAnimScroll
9973
10112
  })
9974
10113
  );
9975
10114
 
@@ -9984,7 +10123,7 @@
9984
10123
  }
9985
10124
  });
9986
10125
 
9987
- let uid$2 = 0;
10126
+ let id$1 = 0;
9988
10127
 
9989
10128
  const useTabEmits = [ 'click', 'keydown' ];
9990
10129
 
@@ -9997,7 +10136,7 @@
9997
10136
 
9998
10137
  name: {
9999
10138
  type: [ Number, String ],
10000
- default: () => `t_${ uid$2++ }`
10139
+ default: () => `t_${ id$1++ }`
10001
10140
  },
10002
10141
 
10003
10142
  noCaps: Boolean,
@@ -10013,7 +10152,7 @@
10013
10152
  }
10014
10153
  };
10015
10154
 
10016
- function useTab (props, slots, emit, routerProps) {
10155
+ function useTab (props, slots, emit, routeData) {
10017
10156
  const $tabs = vue.inject(tabsKey, () => {
10018
10157
  console.error('QTab/QRouteTab component needs to be child of QTabs');
10019
10158
  });
@@ -10050,7 +10189,7 @@
10050
10189
  + (props.icon && props.label && $tabs.tabProps.value.inlineLabel === false ? ' q-tab--full' : '')
10051
10190
  + (props.noCaps === true || $tabs.tabProps.value.noCaps === true ? ' q-tab--no-caps' : '')
10052
10191
  + (props.disable === true ? ' disabled' : ' q-focusable q-hoverable cursor-pointer')
10053
- + (routerProps !== void 0 && routerProps.linkClass.value !== '' ? ` ${ routerProps.linkClass.value }` : '')
10192
+ + (routeData !== void 0 ? routeData.linkClass.value : '')
10054
10193
  );
10055
10194
 
10056
10195
  const innerClass = vue.computed(() =>
@@ -10060,53 +10199,77 @@
10060
10199
  );
10061
10200
 
10062
10201
  const tabIndex = vue.computed(() => (
10063
- props.disable === true || $tabs.hasFocus.value === true
10202
+ (
10203
+ props.disable === true
10204
+ || $tabs.hasFocus.value === true
10205
+ || (isActive.value === false && $tabs.hasActiveTab.value === true)
10206
+ )
10064
10207
  ? -1
10065
10208
  : props.tabindex || 0
10066
10209
  ));
10067
10210
 
10068
10211
  function onClick (e, keyboard) {
10069
- keyboard !== true && blurTargetRef.value !== null && blurTargetRef.value.focus();
10212
+ if (keyboard !== true && blurTargetRef.value !== null) {
10213
+ blurTargetRef.value.focus();
10214
+ }
10070
10215
 
10071
- if (props.disable !== true) {
10072
- let go;
10216
+ if (props.disable === true) {
10217
+ // we should hinder native navigation though
10218
+ if (routeData !== void 0 && routeData.hasRouterLink.value === true) {
10219
+ stopAndPrevent(e);
10220
+ }
10221
+ return
10222
+ }
10073
10223
 
10074
- if (routerProps !== void 0) {
10075
- if (routerProps.hasRouterLink.value === true) {
10076
- go = () => {
10077
- e.__qNavigate = true;
10078
- $tabs.avoidRouteWatcher = true;
10224
+ // do we have a QTab?
10225
+ if (routeData === void 0) {
10226
+ $tabs.updateModel({ name: props.name });
10227
+ emit('click', e);
10228
+ return
10229
+ }
10079
10230
 
10080
- const res = routerProps.navigateToRouterLink(e);
10231
+ if (routeData.hasRouterLink.value === true) {
10232
+ const go = (opts = {}) => {
10233
+ // if requiring to go to another route, then we
10234
+ // let the QTabs route watcher do its job,
10235
+ // otherwise directly select this
10236
+ let hardError;
10237
+ const reqId = opts.to === void 0 || isDeepEqual(opts.to, props.to) === true
10238
+ ? ($tabs.avoidRouteWatcher = uid$3())
10239
+ : null;
10081
10240
 
10082
- if (res === false) {
10241
+ return routeData.navigateToRouterLink(e, { ...opts, returnRouterError: true })
10242
+ .catch(err => { hardError = err; })
10243
+ .then(softError => {
10244
+ if (reqId === $tabs.avoidRouteWatcher) {
10083
10245
  $tabs.avoidRouteWatcher = false;
10246
+
10247
+ // if we don't have any hard errors or any soft errors, except for
10248
+ // when navigating to the same route (on all other soft errors,
10249
+ // like when navigation was aborted in a nav guard, we don't activate this tab)
10250
+ if (
10251
+ hardError === void 0 && (
10252
+ softError === void 0
10253
+ || softError.message.startsWith('Avoided redundant navigation') === true
10254
+ )
10255
+ ) {
10256
+ $tabs.updateModel({ name: props.name });
10257
+ }
10084
10258
  }
10085
- else {
10086
- res.then(err => {
10087
- $tabs.avoidRouteWatcher = false;
10088
10259
 
10089
- if (err === void 0) {
10090
- $tabs.updateModel({ name: props.name, fromRoute: true });
10091
- }
10092
- });
10260
+ if (opts.returnRouterError === true) {
10261
+ return hardError !== void 0 ? Promise.reject(hardError) : softError
10093
10262
  }
10094
- };
10095
- }
10096
- else {
10097
- emit('click', e);
10098
- return
10099
- }
10100
- }
10101
- else {
10102
- go = () => {
10103
- $tabs.updateModel({ name: props.name, fromRoute: false });
10104
- };
10105
- }
10263
+ })
10264
+ };
10106
10265
 
10107
10266
  emit('click', e, go);
10108
10267
  e.defaultPrevented !== true && go();
10268
+
10269
+ return
10109
10270
  }
10271
+
10272
+ emit('click', e);
10110
10273
  }
10111
10274
 
10112
10275
  function onKeydown (e) {
@@ -10180,17 +10343,15 @@
10180
10343
  name: vue.computed(() => props.name),
10181
10344
  rootRef,
10182
10345
  tabIndicatorRef,
10183
- routerProps
10346
+ routeData
10184
10347
  };
10185
10348
 
10186
10349
  vue.onBeforeUnmount(() => {
10187
10350
  $tabs.unregisterTab(tabData);
10188
- $tabs.recalculateScroll();
10189
10351
  });
10190
10352
 
10191
10353
  vue.onMounted(() => {
10192
10354
  $tabs.registerTab(tabData);
10193
- $tabs.recalculateScroll();
10194
10355
  });
10195
10356
 
10196
10357
  function renderTab (tag, customData) {
@@ -14568,7 +14729,7 @@
14568
14729
  );
14569
14730
 
14570
14731
  const { preventBodyScroll } = usePreventScroll();
14571
- const { registerTimeout, removeTimeout } = useTimeout();
14732
+ const { registerTimeout } = useTimeout();
14572
14733
  const { registerTick, removeTick } = useTick();
14573
14734
 
14574
14735
  const { showPortal, hidePortal, portalIsAccessible, renderPortal } = usePortal(
@@ -14653,8 +14814,6 @@
14653
14814
  });
14654
14815
 
14655
14816
  function handleShow (evt) {
14656
- removeTimeout();
14657
- removeTick();
14658
14817
  addToHistory();
14659
14818
 
14660
14819
  refocusTarget = props.noRefocus === false && document.activeElement !== null
@@ -14669,7 +14828,11 @@
14669
14828
  document.activeElement !== null && document.activeElement.blur();
14670
14829
  registerTick(focus);
14671
14830
  }
14831
+ else {
14832
+ removeTick();
14833
+ }
14672
14834
 
14835
+ // should removeTimeout() if this gets removed
14673
14836
  registerTimeout(() => {
14674
14837
  if (vm.proxy.$q.platform.is.ios === true) {
14675
14838
  if (props.seamless !== true && document.activeElement) {
@@ -14705,7 +14868,6 @@
14705
14868
  }
14706
14869
 
14707
14870
  function handleHide (evt) {
14708
- removeTimeout();
14709
14871
  removeTick();
14710
14872
  removeFromHistory();
14711
14873
  cleanup(true);
@@ -14717,6 +14879,7 @@
14717
14879
  refocusTarget = null;
14718
14880
  }
14719
14881
 
14882
+ // should removeTimeout() if this gets removed
14720
14883
  registerTimeout(() => {
14721
14884
  hidePortal(true); // done hiding, now destroy
14722
14885
  animating.value = false;
@@ -14950,7 +15113,7 @@
14950
15113
 
14951
15114
  const isDark = useDark(props, $q);
14952
15115
  const { preventBodyScroll } = usePreventScroll();
14953
- const { registerTimeout } = useTimeout();
15116
+ const { registerTimeout, removeTimeout } = useTimeout();
14954
15117
 
14955
15118
  const $layout = vue.inject(layoutKey, () => {
14956
15119
  console.error('QDrawer needs to be child of QLayout');
@@ -15020,9 +15183,12 @@
15020
15183
 
15021
15184
  cleanup();
15022
15185
 
15023
- noEvent !== true && registerTimeout(() => {
15024
- emit('hide', evt);
15025
- }, duration);
15186
+ if (noEvent !== true) {
15187
+ registerTimeout(() => { emit('hide', evt); }, duration);
15188
+ }
15189
+ else {
15190
+ removeTimeout();
15191
+ }
15026
15192
  }
15027
15193
 
15028
15194
  const { show, hide } = useModelToggle({
@@ -16011,7 +16177,7 @@
16011
16177
  const hideOnRouteChange = vue.computed(() => props.persistent !== true);
16012
16178
 
16013
16179
  const { registerTick, removeTick } = useTick();
16014
- const { registerTimeout, removeTimeout } = useTimeout();
16180
+ const { registerTimeout } = useTimeout();
16015
16181
  const { transition, transitionStyle } = useTransition(props, showing);
16016
16182
  const { localScrollTarget, changeScrollEvent, unconfigureScrollTarget } = useScrollTarget(props, configureScrollTarget);
16017
16183
 
@@ -16065,11 +16231,9 @@
16065
16231
  }
16066
16232
 
16067
16233
  function handleShow (evt) {
16068
- removeTick();
16069
- removeTimeout();
16070
-
16071
16234
  showPortal();
16072
16235
 
16236
+ // should removeTick() if this gets removed
16073
16237
  registerTick(() => {
16074
16238
  observer = new MutationObserver(() => updatePosition());
16075
16239
  observer.observe(innerRef.value, { attributes: false, childList: true, characterData: true, subtree: true });
@@ -16084,6 +16248,7 @@
16084
16248
  );
16085
16249
  }
16086
16250
 
16251
+ // should removeTimeout() if this gets removed
16087
16252
  registerTimeout(() => {
16088
16253
  showPortal(true); // done showing portal
16089
16254
  emit('show', evt);
@@ -16092,11 +16257,11 @@
16092
16257
 
16093
16258
  function handleHide (evt) {
16094
16259
  removeTick();
16095
- removeTimeout();
16096
16260
  hidePortal();
16097
16261
 
16098
16262
  anchorCleanup();
16099
16263
 
16264
+ // should removeTimeout() if this gets removed
16100
16265
  registerTimeout(() => {
16101
16266
  hidePortal(true); // done hiding, now destroy
16102
16267
  emit('hide', evt);
@@ -16148,14 +16313,10 @@
16148
16313
  addEvt(anchorEvents, 'tooltipTemp', evts);
16149
16314
  }
16150
16315
 
16151
- registerTimeout(() => {
16152
- show(evt);
16153
- }, props.delay);
16316
+ registerTimeout(() => { show(evt); }, props.delay);
16154
16317
  }
16155
16318
 
16156
16319
  function delayHide (evt) {
16157
- removeTimeout();
16158
-
16159
16320
  if ($q.platform.is.mobile === true) {
16160
16321
  cleanEvt(anchorEvents, 'tooltipTemp');
16161
16322
  clearSelection();
@@ -16165,9 +16326,8 @@
16165
16326
  }, 10);
16166
16327
  }
16167
16328
 
16168
- registerTimeout(() => {
16169
- hide(evt);
16170
- }, props.hideDelay);
16329
+ // should removeTimeout() if this gets removed
16330
+ registerTimeout(() => { hide(evt); }, props.hideDelay);
16171
16331
  }
16172
16332
 
16173
16333
  function configureAnchorEl () {
@@ -16263,7 +16423,7 @@
16263
16423
  const { proxy: { $q } } = vue.getCurrentInstance();
16264
16424
 
16265
16425
  const isDark = useDark(props, $q);
16266
- const { hasRouterLink, hasLink, linkProps, linkClass, linkTag, navigateToRouterLink } = useRouterLink();
16426
+ const { hasLink, linkAttrs, linkClass, linkTag, navigateOnClick } = useRouterLink();
16267
16427
 
16268
16428
  const rootRef = vue.ref(null);
16269
16429
  const blurTargetRef = vue.ref(null);
@@ -16287,7 +16447,7 @@
16287
16447
  ? linkClass.value
16288
16448
  : (
16289
16449
  props.active === true
16290
- ? `${ props.activeClass !== void 0 ? ` ${ props.activeClass }` : '' } q-item--active`
16450
+ ? ` q-item--active${ props.activeClass !== void 0 ? ` ${ props.activeClass }` : '' }`
16291
16451
  : ''
16292
16452
  )
16293
16453
  )
@@ -16323,8 +16483,7 @@
16323
16483
  }
16324
16484
  }
16325
16485
 
16326
- hasRouterLink.value === true && navigateToRouterLink(e);
16327
- emit('click', e);
16486
+ navigateOnClick(e);
16328
16487
  }
16329
16488
  }
16330
16489
 
@@ -16365,7 +16524,7 @@
16365
16524
 
16366
16525
  if (isClickable.value === true) {
16367
16526
  data.tabindex = props.tabindex || '0';
16368
- Object.assign(data, linkProps.value);
16527
+ Object.assign(data, linkAttrs.value);
16369
16528
  }
16370
16529
  else if (isActionable.value === true) {
16371
16530
  data[ 'aria-disabled' ] = 'true';
@@ -16718,24 +16877,21 @@
16718
16877
  const
16719
16878
  toString = Object.prototype.toString,
16720
16879
  hasOwn = Object.prototype.hasOwnProperty,
16721
- class2type = {};
16722
-
16723
- 'Boolean Number String Function Array Date RegExp Object'.split(' ').forEach(name => {
16724
- class2type[ '[object ' + name + ']' ] = name.toLowerCase();
16725
- });
16726
-
16727
- function type (obj) {
16728
- return obj === null ? String(obj) : class2type[ toString.call(obj) ] || 'object'
16729
- }
16880
+ notPlainObject = new Set(
16881
+ [ 'Boolean', 'Number', 'String', 'Function', 'Array', 'Date', 'RegExp', 'Object' ]
16882
+ .map(name => '[object ' + name + ']')
16883
+ );
16730
16884
 
16731
16885
  function isPlainObject (obj) {
16732
- if (!obj || type(obj) !== 'object') {
16886
+ if (obj !== Object(obj) || notPlainObject.has(toString.call(obj)) === true) {
16733
16887
  return false
16734
16888
  }
16735
16889
 
16736
- if (obj.constructor
16737
- && !hasOwn.call(obj, 'constructor')
16738
- && !hasOwn.call(obj.constructor.prototype, 'isPrototypeOf')) {
16890
+ if (
16891
+ obj.constructor
16892
+ && hasOwn.call(obj, 'constructor') === false
16893
+ && !hasOwn.call(obj.constructor.prototype, 'isPrototypeOf') === false
16894
+ ) {
16739
16895
  return false
16740
16896
  }
16741
16897
 
@@ -16759,7 +16915,7 @@
16759
16915
  i = 2;
16760
16916
  }
16761
16917
 
16762
- if (Object(target) !== target && type(target) !== 'function') {
16918
+ if (Object(target) !== target && typeof target !== 'function') {
16763
16919
  target = {};
16764
16920
  }
16765
16921
 
@@ -16778,13 +16934,16 @@
16778
16934
  continue
16779
16935
  }
16780
16936
 
16781
- if (deep && copy && (isPlainObject(copy) || (copyIsArray = type(copy) === 'array'))) {
16782
- if (copyIsArray) {
16783
- copyIsArray = false;
16784
- clone = src && type(src) === 'array' ? src : [];
16937
+ if (
16938
+ deep === true
16939
+ && copy
16940
+ && ((copyIsArray = Array.isArray(copy)) || isPlainObject(copy) === true)
16941
+ ) {
16942
+ if (copyIsArray === true) {
16943
+ clone = Array.isArray(src) === true ? src : [];
16785
16944
  }
16786
16945
  else {
16787
- clone = src && isPlainObject(src) ? src : {};
16946
+ clone = isPlainObject(src) === true ? src : {};
16788
16947
  }
16789
16948
 
16790
16949
  target[ name ] = extend(deep, clone, copy);
@@ -17606,7 +17765,7 @@
17606
17765
  );
17607
17766
 
17608
17767
  const blurTargetRef = vue.ref(null);
17609
- const targetUid = uid$4();
17768
+ const targetUid = uid$3();
17610
17769
 
17611
17770
  const { show, hide, toggle } = useModelToggle({ showing });
17612
17771
 
@@ -17710,7 +17869,7 @@
17710
17869
 
17711
17870
  function enterGroup () {
17712
17871
  if (uniqueId === void 0) {
17713
- uniqueId = uid$4();
17872
+ uniqueId = uid$3();
17714
17873
  }
17715
17874
 
17716
17875
  if (showing.value === true) {
@@ -18027,7 +18186,7 @@
18027
18186
  setup (props, { slots }) {
18028
18187
  const triggerRef = vue.ref(null);
18029
18188
  const showing = vue.ref(props.modelValue === true);
18030
- const targetUid = uid$4();
18189
+ const targetUid = uid$3();
18031
18190
 
18032
18191
  const { proxy: { $q } } = vue.getCurrentInstance();
18033
18192
  const { formClass, labelProps } = useFab(props, showing);
@@ -18476,7 +18635,7 @@
18476
18635
  }
18477
18636
 
18478
18637
  function getTargetUid (val) {
18479
- return val === void 0 ? `f_${ uid$4() }` : val
18638
+ return val === void 0 ? `f_${ uid$3() }` : val
18480
18639
  }
18481
18640
 
18482
18641
  function fieldValueIsFilled (val) {
@@ -22753,8 +22912,7 @@
22753
22912
  const svg$m = vue.h('svg', {
22754
22913
  key: 'svg',
22755
22914
  class: 'q-radio__bg absolute non-selectable',
22756
- viewBox: '0 0 24 24',
22757
- 'aria-hidden': 'true'
22915
+ viewBox: '0 0 24 24'
22758
22916
  }, [
22759
22917
  vue.h('path', {
22760
22918
  d: 'M12,22a10,10 0 0 1 -10,-10a10,10 0 0 1 10,-10a10,10 0 0 1 10,10a10,10 0 0 1 -10,10m0,-22a12,12 0 0 0 -12,12a12,12 0 0 0 12,12a12,12 0 0 0 12,-12a12,12 0 0 0 -12,-12'
@@ -22899,7 +23057,8 @@
22899
23057
  const child = [
22900
23058
  vue.h('div', {
22901
23059
  class: innerClass.value,
22902
- style: sizeStyle.value
23060
+ style: sizeStyle.value,
23061
+ 'aria-hidden': 'true'
22903
23062
  }, content)
22904
23063
  ];
22905
23064
 
@@ -24076,16 +24235,13 @@
24076
24235
  let validated = false;
24077
24236
 
24078
24237
  const scope = vue.computed(() => {
24079
- const acc = {
24238
+ return injectProp({
24080
24239
  initialValue: initialValue.value,
24081
24240
  validate: props.validate,
24082
24241
  set,
24083
24242
  cancel,
24084
24243
  updatePosition
24085
- };
24086
-
24087
- injectProp(acc, 'value', () => currentModel.value, val => { currentModel.value = val; });
24088
- return acc
24244
+ }, 'value', () => currentModel.value, val => { currentModel.value = val; })
24089
24245
  });
24090
24246
 
24091
24247
  function set () {
@@ -25022,6 +25178,8 @@
25022
25178
  iconHalf: [ String, Array ],
25023
25179
  iconSelected: [ String, Array ],
25024
25180
 
25181
+ iconAriaLabel: [ String, Array ],
25182
+
25025
25183
  color: [ String, Array ],
25026
25184
  colorHalf: [ String, Array ],
25027
25185
  colorSelected: [ String, Array ],
@@ -25087,11 +25245,29 @@
25087
25245
  }
25088
25246
  });
25089
25247
 
25248
+ const iconLabel = vue.computed(() => {
25249
+ if (typeof props.iconAriaLabel === 'string') {
25250
+ const label = props.iconAriaLabel.length > 0 ? `${ props.iconAriaLabel } ` : '';
25251
+ return i => `${ label }${ i }`
25252
+ }
25253
+
25254
+ if (Array.isArray(props.iconAriaLabel) === true) {
25255
+ const iMax = props.iconAriaLabel.length;
25256
+
25257
+ if (iMax > 0) {
25258
+ return i => props.iconAriaLabel[ Math.min(i, iMax) - 1 ]
25259
+ }
25260
+ }
25261
+
25262
+ return (i, label) => `${ label } ${ i }`
25263
+ });
25264
+
25090
25265
  const stars = vue.computed(() => {
25091
25266
  const
25092
25267
  acc = [],
25093
25268
  icons = iconData.value,
25094
- ceil = Math.ceil(props.modelValue);
25269
+ ceil = Math.ceil(props.modelValue),
25270
+ tabindex = editable.value === true ? 0 : null;
25095
25271
 
25096
25272
  const halfIndex = props.iconHalf === void 0 || ceil === props.modelValue
25097
25273
  ? -1
@@ -25108,7 +25284,16 @@
25108
25284
  icons.selColor !== void 0 && active === true
25109
25285
  ? (i <= icons.selColorLen ? props.colorSelected[ i - 1 ] : icons.selColor)
25110
25286
  : (i <= icons.colorLen ? props.color[ i - 1 ] : icons.color)
25111
- );
25287
+ ),
25288
+ name = (
25289
+ half === true
25290
+ ? (i <= icons.halfIconLen ? props.iconHalf[ i - 1 ] : icons.halfIcon)
25291
+ : (
25292
+ icons.selIcon !== void 0 && (active === true || exSelected === true)
25293
+ ? (i <= icons.selIconLen ? props.iconSelected[ i - 1 ] : icons.selIcon)
25294
+ : (i <= icons.iconLen ? props.icon[ i - 1 ] : icons.icon)
25295
+ )
25296
+ ) || $q.iconSet.rating.icon;
25112
25297
 
25113
25298
  acc.push({
25114
25299
  name: (
@@ -25121,7 +25306,14 @@
25121
25306
  )
25122
25307
  ) || $q.iconSet.rating.icon,
25123
25308
 
25124
- classes: 'q-rating__icon'
25309
+ attrs: {
25310
+ tabindex,
25311
+ role: 'radio',
25312
+ 'aria-checked': props.modelValue === i ? 'true' : 'false',
25313
+ 'aria-label': iconLabel.value(i, name)
25314
+ },
25315
+
25316
+ iconClass: 'q-rating__icon'
25125
25317
  + (active === true || half === true ? ' q-rating__icon--active' : '')
25126
25318
  + (exSelected === true ? ' q-rating__icon--exselected' : '')
25127
25319
  + (mouseModel.value === i ? ' q-rating__icon--hovered' : '')
@@ -25133,15 +25325,17 @@
25133
25325
  });
25134
25326
 
25135
25327
  const attributes = vue.computed(() => {
25328
+ const attrs = { role: 'radiogroup' };
25329
+
25136
25330
  if (props.disable === true) {
25137
- return { 'aria-disabled': 'true' }
25331
+ attrs[ 'aria-disabled' ] = 'true';
25138
25332
  }
25139
25333
  if (props.readonly === true) {
25140
- return { 'aria-readonly': 'true' }
25334
+ attrs[ 'aria-readonly' ] = 'true';
25141
25335
  }
25142
- });
25143
25336
 
25144
- const tabindex = vue.computed(() => (editable.value === true ? 0 : null));
25337
+ return attrs
25338
+ });
25145
25339
 
25146
25340
  function set (value) {
25147
25341
  if (editable.value === true) {
@@ -25192,7 +25386,7 @@
25192
25386
  return () => {
25193
25387
  const child = [];
25194
25388
 
25195
- stars.value.forEach(({ classes, name }, index) => {
25389
+ stars.value.forEach(({ iconClass, name, attrs }, index) => {
25196
25390
  const i = index + 1;
25197
25391
 
25198
25392
  child.push(
@@ -25200,7 +25394,7 @@
25200
25394
  key: i,
25201
25395
  ref: vm => { iconRefs[ `rt${ i }` ] = vm; },
25202
25396
  class: 'q-rating__icon-container flex flex-center',
25203
- tabindex: tabindex.value,
25397
+ ...attrs,
25204
25398
  onClick () { set(i); },
25205
25399
  onMouseover () { setHoverValue(i); },
25206
25400
  onMouseout: resetMouseModel,
@@ -25209,7 +25403,7 @@
25209
25403
  onKeyup (e) { onKeyup(e, i); }
25210
25404
  }, hMergeSlot(
25211
25405
  slots[ `tip-${ i }` ],
25212
- [ vue.h(QIcon, { class: classes, name }) ]
25406
+ [ vue.h(QIcon, { class: iconClass, name }) ]
25213
25407
  ))
25214
25408
  );
25215
25409
  });
@@ -30659,10 +30853,12 @@
30659
30853
  default: true
30660
30854
  },
30661
30855
  done: Boolean,
30662
- error: Boolean
30856
+ error: Boolean,
30857
+
30858
+ onScroll: [ Function, Array ]
30663
30859
  },
30664
30860
 
30665
- setup (props, { attrs, slots }) {
30861
+ setup (props, { slots, emit }) {
30666
30862
  const { proxy: { $q } } = vue.getCurrentInstance();
30667
30863
 
30668
30864
  const $stepper = vue.inject(stepperKey, () => {
@@ -30686,7 +30882,7 @@
30686
30882
  if (target.scrollTop > 0) {
30687
30883
  target.scrollTop = 0;
30688
30884
  }
30689
- attrs.onScroll !== void 0 && attrs.onScroll(e);
30885
+ props.onScroll !== void 0 && emit('scroll', e);
30690
30886
  }
30691
30887
  }
30692
30888
  ));
@@ -32155,11 +32351,9 @@
32155
32351
  function getBodyScope (data) {
32156
32352
  injectBodyCommonScope(data);
32157
32353
 
32158
- data.cols = data.cols.map(col => {
32159
- const c = { ...col };
32160
- injectProp(c, 'value', () => getCellValue(col, data.row));
32161
- return c
32162
- });
32354
+ data.cols = data.cols.map(
32355
+ col => injectProp({ ...col }, 'value', () => getCellValue(col, data.row))
32356
+ );
32163
32357
 
32164
32358
  return data
32165
32359
  }
@@ -32798,7 +32992,9 @@
32798
32992
  emits: useTabEmits,
32799
32993
 
32800
32994
  setup (props, { slots, emit }) {
32801
- const rData = useRouterLink();
32995
+ const routeData = useRouterLink({
32996
+ useDisableForRouterLinkProps: false
32997
+ });
32802
32998
 
32803
32999
  const { renderTab, $tabs } = useTab(
32804
33000
  props,
@@ -32806,15 +33002,15 @@
32806
33002
  emit,
32807
33003
  {
32808
33004
  exact: vue.computed(() => props.exact),
32809
- ...rData
33005
+ ...routeData
32810
33006
  }
32811
33007
  );
32812
33008
 
32813
- vue.watch(() => props.name + props.exact + (rData.linkRoute.value || {}).href, () => {
33009
+ vue.watch(() => `${ props.name } | ${ props.exact } | ${ (routeData.resolvedLink.value || {}).href }`, () => {
32814
33010
  $tabs.verifyRouteModel();
32815
33011
  });
32816
33012
 
32817
- return () => renderTab(rData.linkTag.value, rData.linkProps.value)
33013
+ return () => renderTab(routeData.linkTag.value, routeData.linkAttrs.value)
32818
33014
  }
32819
33015
  });
32820
33016
 
@@ -34507,7 +34703,7 @@
34507
34703
  emit('update:selected', meta.key !== props.selected ? meta.key : null);
34508
34704
  }
34509
34705
  else if (meta.key !== props.selected) {
34510
- emit('update:selected', meta.key || null);
34706
+ emit('update:selected', meta.key === void 0 ? null : meta.key);
34511
34707
  }
34512
34708
  }
34513
34709
  else {
@@ -37320,7 +37516,7 @@
37320
37516
 
37321
37517
  client.has.touch === true && addEvt(ctx, 'main', [
37322
37518
  [ el, 'touchstart', 'touchStart', `passive${ modifiers.capture === true ? 'Capture' : '' }` ],
37323
- [ el, 'touchend', 'noop', 'notPassiveCapture' ]
37519
+ [ el, 'touchend', 'noop', 'passiveCapture' ]
37324
37520
  ]);
37325
37521
 
37326
37522
  keyboard.length > 0 && addEvt(ctx, 'main', [
@@ -39867,7 +40063,7 @@
39867
40063
  * Default: { threadsNumber: 1, abortOnFail: true }
39868
40064
  * When configuring threadsNumber AND using http requests, be
39869
40065
  * aware of the maximum threads that the hosting browser
39870
- * supports (usually 3); any number of threads above that
40066
+ * supports (usually 5); any number of threads above that
39871
40067
  * won't add any real benefits
39872
40068
  * @returns Promise<Array<Object> | Object>
39873
40069
  * With opts.abortOnFail set to true (which is default):
@@ -39973,7 +40169,7 @@
39973
40169
  scroll: scroll,
39974
40170
  setCssVar: setCssVar,
39975
40171
  throttle: throttle,
39976
- uid: uid$4
40172
+ uid: uid$3
39977
40173
  });
39978
40174
 
39979
40175
  // To be used for the custom component
@@ -40074,7 +40270,7 @@
40074
40270
  */
40075
40271
 
40076
40272
  var index_umd = {
40077
- version: '2.8.4',
40273
+ version: '2.9.0',
40078
40274
  install (app, opts) {
40079
40275
  installQuasar(app, {
40080
40276
  components,