quasar 2.21.4 → 2.23.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 (193) hide show
  1. package/README.md +1 -1
  2. package/dist/api/Mutation.json +1 -1
  3. package/dist/api/QLinearProgress.json +1 -1
  4. package/dist/api/QUploader.json +1 -1
  5. package/dist/icon-set/bootstrap-icons.umd.prod.js +1 -1
  6. package/dist/icon-set/eva-icons.umd.prod.js +1 -1
  7. package/dist/icon-set/fontawesome-v5-pro.umd.prod.js +1 -1
  8. package/dist/icon-set/fontawesome-v5.umd.prod.js +1 -1
  9. package/dist/icon-set/fontawesome-v6-pro.umd.prod.js +1 -1
  10. package/dist/icon-set/fontawesome-v6.umd.prod.js +1 -1
  11. package/dist/icon-set/fontawesome-v7-pro.umd.prod.js +1 -1
  12. package/dist/icon-set/fontawesome-v7.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/mdi-v7.umd.prod.js +1 -1
  27. package/dist/icon-set/svg-bootstrap-icons.umd.prod.js +1 -1
  28. package/dist/icon-set/svg-eva-icons.umd.prod.js +1 -1
  29. package/dist/icon-set/svg-fontawesome-v5.umd.prod.js +1 -1
  30. package/dist/icon-set/svg-fontawesome-v6.umd.prod.js +1 -1
  31. package/dist/icon-set/svg-fontawesome-v7.umd.prod.js +1 -1
  32. package/dist/icon-set/svg-ionicons-v4.umd.prod.js +1 -1
  33. package/dist/icon-set/svg-ionicons-v5.umd.prod.js +1 -1
  34. package/dist/icon-set/svg-ionicons-v6.umd.prod.js +1 -1
  35. package/dist/icon-set/svg-ionicons-v7.umd.prod.js +1 -1
  36. package/dist/icon-set/svg-ionicons-v8.umd.prod.js +1 -1
  37. package/dist/icon-set/svg-line-awesome.umd.prod.js +1 -1
  38. package/dist/icon-set/svg-material-icons-outlined.umd.prod.js +1 -1
  39. package/dist/icon-set/svg-material-icons-round.umd.prod.js +1 -1
  40. package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +1 -1
  41. package/dist/icon-set/svg-material-icons.umd.prod.js +1 -1
  42. package/dist/icon-set/svg-material-symbols-outlined.umd.prod.js +1 -1
  43. package/dist/icon-set/svg-material-symbols-rounded.umd.prod.js +1 -1
  44. package/dist/icon-set/svg-material-symbols-sharp.umd.prod.js +1 -1
  45. package/dist/icon-set/svg-mdi-v6.umd.prod.js +1 -1
  46. package/dist/icon-set/svg-mdi-v7.umd.prod.js +1 -1
  47. package/dist/icon-set/svg-themify.umd.prod.js +1 -1
  48. package/dist/icon-set/themify.umd.prod.js +1 -1
  49. package/dist/lang/ar-TN.umd.prod.js +1 -1
  50. package/dist/lang/ar.umd.prod.js +1 -1
  51. package/dist/lang/az-Latn.umd.prod.js +1 -1
  52. package/dist/lang/bg.umd.prod.js +1 -1
  53. package/dist/lang/bn.umd.prod.js +1 -1
  54. package/dist/lang/bs-BA.umd.prod.js +1 -1
  55. package/dist/lang/ca.umd.prod.js +1 -1
  56. package/dist/lang/cs.umd.prod.js +1 -1
  57. package/dist/lang/da.umd.prod.js +1 -1
  58. package/dist/lang/de-CH.umd.prod.js +1 -1
  59. package/dist/lang/de-DE.umd.prod.js +1 -1
  60. package/dist/lang/de.umd.prod.js +1 -1
  61. package/dist/lang/el.umd.prod.js +1 -1
  62. package/dist/lang/en-GB.umd.prod.js +1 -1
  63. package/dist/lang/en-US.umd.prod.js +1 -1
  64. package/dist/lang/eo.umd.prod.js +1 -1
  65. package/dist/lang/es.umd.prod.js +1 -1
  66. package/dist/lang/et.umd.prod.js +1 -1
  67. package/dist/lang/eu.umd.prod.js +1 -1
  68. package/dist/lang/fa-IR.umd.prod.js +1 -1
  69. package/dist/lang/fa.umd.prod.js +1 -1
  70. package/dist/lang/fi.umd.prod.js +1 -1
  71. package/dist/lang/fr.umd.prod.js +1 -1
  72. package/dist/lang/gn.umd.prod.js +1 -1
  73. package/dist/lang/he.umd.prod.js +1 -1
  74. package/dist/lang/hi.umd.prod.js +1 -1
  75. package/dist/lang/hr.umd.prod.js +1 -1
  76. package/dist/lang/hu.umd.prod.js +1 -1
  77. package/dist/lang/id.umd.prod.js +1 -1
  78. package/dist/lang/is.umd.prod.js +1 -1
  79. package/dist/lang/it.umd.prod.js +1 -1
  80. package/dist/lang/ja.umd.prod.js +1 -1
  81. package/dist/lang/kk.umd.prod.js +1 -1
  82. package/dist/lang/km.umd.prod.js +1 -1
  83. package/dist/lang/ko-KR.umd.prod.js +1 -1
  84. package/dist/lang/kur-CKB.umd.prod.js +1 -1
  85. package/dist/lang/lb.umd.prod.js +1 -1
  86. package/dist/lang/lt.umd.prod.js +1 -1
  87. package/dist/lang/lu.umd.prod.js +1 -1
  88. package/dist/lang/lv.umd.prod.js +1 -1
  89. package/dist/lang/mk.umd.prod.js +1 -1
  90. package/dist/lang/ml.umd.prod.js +1 -1
  91. package/dist/lang/mm.umd.prod.js +1 -1
  92. package/dist/lang/ms-MY.umd.prod.js +1 -1
  93. package/dist/lang/ms.umd.prod.js +1 -1
  94. package/dist/lang/my.umd.prod.js +1 -1
  95. package/dist/lang/nb-NO.umd.prod.js +1 -1
  96. package/dist/lang/nl.umd.prod.js +1 -1
  97. package/dist/lang/pl.umd.prod.js +1 -1
  98. package/dist/lang/pt-BR.umd.prod.js +1 -1
  99. package/dist/lang/pt.umd.prod.js +1 -1
  100. package/dist/lang/ro.umd.prod.js +1 -1
  101. package/dist/lang/ru.umd.prod.js +1 -1
  102. package/dist/lang/sk.umd.prod.js +1 -1
  103. package/dist/lang/sl.umd.prod.js +1 -1
  104. package/dist/lang/sm.umd.prod.js +1 -1
  105. package/dist/lang/sq.umd.prod.js +1 -1
  106. package/dist/lang/sr-CYR.umd.prod.js +1 -1
  107. package/dist/lang/sr.umd.prod.js +1 -1
  108. package/dist/lang/sv.umd.prod.js +1 -1
  109. package/dist/lang/ta.umd.prod.js +1 -1
  110. package/dist/lang/th.umd.prod.js +1 -1
  111. package/dist/lang/tl.umd.prod.js +1 -1
  112. package/dist/lang/tr.umd.prod.js +1 -1
  113. package/dist/lang/ug.umd.prod.js +1 -1
  114. package/dist/lang/uk.umd.prod.js +1 -1
  115. package/dist/lang/ur-PK.umd.prod.js +1 -1
  116. package/dist/lang/uz-Cyrl.umd.prod.js +1 -1
  117. package/dist/lang/uz-Latn.umd.prod.js +1 -1
  118. package/dist/lang/vi.umd.prod.js +1 -1
  119. package/dist/lang/zh-CN.umd.prod.js +1 -1
  120. package/dist/lang/zh-TW.umd.prod.js +1 -1
  121. package/dist/quasar.client.js +654 -207
  122. package/dist/quasar.css +20 -11
  123. package/dist/quasar.prod.css +1 -1
  124. package/dist/quasar.rtl.css +25 -20
  125. package/dist/quasar.rtl.prod.css +1 -1
  126. package/dist/quasar.sass +21 -12
  127. package/dist/quasar.server.prod.cjs +35 -35
  128. package/dist/quasar.server.prod.js +25 -25
  129. package/dist/quasar.umd.js +654 -206
  130. package/dist/quasar.umd.prod.js +19 -19
  131. package/dist/transforms/import-map.json +1 -1
  132. package/dist/types/composables.d.ts +15 -5
  133. package/dist/types/index.d.ts +5 -5
  134. package/dist/web-types/web-types.json +1 -1
  135. package/package.json +6 -6
  136. package/src/components/btn/QBtn.js +1 -1
  137. package/src/components/carousel/QCarousel.js +2 -0
  138. package/src/components/chip/QChip.js +20 -4
  139. package/src/components/date/QDate.js +9 -2
  140. package/src/components/dialog/QDialog.js +9 -2
  141. package/src/components/editor/QEditor.js +18 -3
  142. package/src/components/expansion-item/QExpansionItem.js +6 -1
  143. package/src/components/fab/QFab.sass +11 -9
  144. package/src/components/input/QInput.js +42 -1
  145. package/src/components/input/QInput.json +7 -0
  146. package/src/components/input/use-mask.js +12 -4
  147. package/src/components/item/QItem.js +10 -1
  148. package/src/components/linear-progress/QLinearProgress.js +4 -11
  149. package/src/components/linear-progress/QLinearProgress.json +1 -1
  150. package/src/components/linear-progress/QLinearProgress.sass +7 -2
  151. package/src/components/menu/QMenu.js +9 -2
  152. package/src/components/range/QRange.js +2 -1
  153. package/src/components/rating/QRating.js +27 -8
  154. package/src/components/rating/QRating.sass +4 -0
  155. package/src/components/resize-observer/QResizeObserver.js +14 -3
  156. package/src/components/scroll-area/QScrollArea.js +69 -17
  157. package/src/components/slide-item/QSlideItem.js +3 -2
  158. package/src/components/slider/use-slider.js +7 -3
  159. package/src/components/stepper/StepHeader.js +11 -2
  160. package/src/components/table/QTable.js +11 -9
  161. package/src/components/table/QTh.js +20 -1
  162. package/src/components/table/table-column-selection.js +9 -1
  163. package/src/components/table/table-pagination.js +5 -2
  164. package/src/components/table/table-row-selection.js +10 -10
  165. package/src/components/tabs/QTabs.js +5 -6
  166. package/src/components/time/QTime.js +35 -10
  167. package/src/components/tooltip/QTooltip.js +112 -6
  168. package/src/components/tree/QTree.js +124 -4
  169. package/src/components/uploader/uploader-core.js +19 -4
  170. package/src/components/uploader/xhr-uploader-plugin.js +93 -43
  171. package/src/components/uploader/xhr-uploader-plugin.json +4 -4
  172. package/src/composables/private.use-field/use-field.js +2 -0
  173. package/src/composables/private.use-file/use-file.js +21 -12
  174. package/src/composables/private.use-fullscreen/use-fullscreen.js +71 -11
  175. package/src/composables/private.use-fullscreen/use-fullscreen.test.js +158 -0
  176. package/src/composables/private.use-model-toggle/use-model-toggle.js +2 -0
  177. package/src/composables/private.use-panel/use-panel.js +6 -2
  178. package/src/composables/use-animation-frame/use-animation-frame.js +47 -0
  179. package/src/composables/use-animation-frame/use-animation-frame.test.js +122 -0
  180. package/src/composables/use-interval/use-interval.js +8 -0
  181. package/src/composables/use-render-cache/use-render-cache.js +15 -10
  182. package/src/composables/use-timeout/use-timeout.js +8 -0
  183. package/src/composables.js +1 -1
  184. package/src/directives/intersection/Intersection.js +2 -2
  185. package/src/directives/mutation/Mutation.json +1 -1
  186. package/src/directives/touch-repeat/TouchRepeat.js +3 -1
  187. package/src/plugins/cookies/Cookies.js +29 -13
  188. package/src/plugins/meta/Meta.js +57 -9
  189. package/src/utils/extend/extend.js +4 -0
  190. package/src/utils/extend/extend.test.js +29 -0
  191. package/src/utils/private.click-outside/click-outside.js +27 -12
  192. package/src/utils/private.click-outside/click-outside.test.js +132 -0
  193. package/src/utils/scroll/prevent-scroll.js +4 -4
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Quasar Framework v2.21.4
2
+ * Quasar Framework v2.23.0
3
3
  * (c) 2015-present Razvan Stoenescu
4
4
  * Released under the MIT License.
5
5
  */
@@ -1101,7 +1101,7 @@
1101
1101
  };
1102
1102
  }
1103
1103
  var install_quasar_default = function installQuasar(parentApp, opts = {}) {
1104
- const $q = { version: "2.21.4" };
1104
+ const $q = { version: "2.23.0" };
1105
1105
  if (!globalConfigIsFrozen) {
1106
1106
  if (opts.config !== void 0) Object.assign(globalConfig, opts.config);
1107
1107
  $q.config = { ...globalConfig };
@@ -2441,7 +2441,7 @@
2441
2441
  const blurTarget = blurTargetRef.value;
2442
2442
  if (!destroying && (touchTarget === rootRef.value || mouseTarget === rootRef.value) && blurTarget !== null && blurTarget !== document.activeElement) {
2443
2443
  blurTarget.setAttribute("tabindex", -1);
2444
- blurTarget.focus();
2444
+ blurTarget.focus({ preventScroll: true });
2445
2445
  }
2446
2446
  if (touchTarget === rootRef.value) {
2447
2447
  if (localTouchTargetEl !== null) {
@@ -2771,7 +2771,7 @@
2771
2771
  "beforeHide",
2772
2772
  "hide"
2773
2773
  ];
2774
- function useModelToggle({ showing, canShow, hideOnRouteChange, handleShow, handleHide, processOnMount }) {
2774
+ function useModelToggle({ showing, canShow, hideOnRouteChange, handleShow, handleHide, handleRouteChange, processOnMount }) {
2775
2775
  const vm = (0, vue.getCurrentInstance)();
2776
2776
  const { props, emit, proxy } = vm;
2777
2777
  let payload;
@@ -2824,7 +2824,10 @@
2824
2824
  }
2825
2825
  (0, vue.watch)(() => props.modelValue, processModelChange);
2826
2826
  if (hideOnRouteChange !== void 0 && vmHasRouter(vm)) (0, vue.watch)(() => proxy.$route.fullPath, () => {
2827
- if (hideOnRouteChange.value && showing.value) hide();
2827
+ if (hideOnRouteChange.value && showing.value) {
2828
+ handleRouteChange?.();
2829
+ hide();
2830
+ }
2828
2831
  });
2829
2832
  if (processOnMount) (0, vue.onMounted)(() => {
2830
2833
  processModelChange(props.modelValue);
@@ -3282,19 +3285,25 @@
3282
3285
  }
3283
3286
  const target = evt.target;
3284
3287
  if (target === void 0 || target.nodeType === 8 || target.classList.contains("no-pointer-events")) return;
3285
- let portalIndex = portalProxyList.length - 1;
3286
- while (portalIndex >= 0) {
3287
- const proxy = portalProxyList[portalIndex].$;
3288
- if (proxy.type.name === "QTooltip") {
3289
- portalIndex--;
3288
+ let closableContentEls = null;
3289
+ let sawClosablePortal = false;
3290
+ for (let i = portalProxyList.length - 1; i >= 0; i--) {
3291
+ const proxy = portalProxyList[i].$;
3292
+ const name = proxy.type.name;
3293
+ if (name === "QTooltip") continue;
3294
+ if (name === "QDialog") {
3295
+ if (proxy.props.seamless !== true) {
3296
+ if (sawClosablePortal === false) return;
3297
+ closableContentEls = new Set(portalProxyList.slice(i + 1).map((vm) => vm.contentEl));
3298
+ break;
3299
+ }
3290
3300
  continue;
3291
3301
  }
3292
- if (proxy.type.name !== "QDialog") break;
3293
- if (!proxy.props.seamless) return;
3294
- portalIndex--;
3302
+ sawClosablePortal = true;
3295
3303
  }
3296
3304
  for (let i = registeredList.length - 1; i >= 0; i--) {
3297
3305
  const state = registeredList[i];
3306
+ if (closableContentEls !== null && !closableContentEls.has(state.innerRef.value)) return;
3298
3307
  if ((state.anchorEl.value === null || !state.anchorEl.value.contains(target)) && (target === document.body || state.innerRef.value !== null && !state.innerRef.value.contains(target))) {
3299
3308
  evt.qClickOutside = true;
3300
3309
  state.onClickOutside(evt);
@@ -3625,6 +3634,7 @@
3625
3634
  canShow,
3626
3635
  handleShow,
3627
3636
  handleHide,
3637
+ handleRouteChange,
3628
3638
  hideOnRouteChange,
3629
3639
  processOnMount: true
3630
3640
  });
@@ -3700,14 +3710,20 @@
3700
3710
  hidePortal();
3701
3711
  anchorCleanup(true);
3702
3712
  if (refocusTarget !== null && (evt === void 0 || !evt.qClickOutside)) {
3703
- ((evt?.type.indexOf("key") === 0 ? refocusTarget.closest("[tabindex]:not([tabindex^=\"-\"])") : void 0) || refocusTarget).focus();
3713
+ const target = (evt?.type.indexOf("key") === 0 ? refocusTarget.closest("[tabindex]:not([tabindex^=\"-\"])") : void 0) || refocusTarget;
3704
3714
  refocusTarget = null;
3715
+ addFocusFn(() => {
3716
+ if (target.isConnected) target.focus();
3717
+ });
3705
3718
  }
3706
3719
  registerTimeout(() => {
3707
3720
  hidePortal(true);
3708
3721
  emit("hide", evt);
3709
3722
  }, props.transitionDuration);
3710
3723
  }
3724
+ function handleRouteChange() {
3725
+ refocusTarget = null;
3726
+ }
3711
3727
  function anchorCleanup(hiding) {
3712
3728
  absoluteOffset = void 0;
3713
3729
  if (unwatchPosition !== void 0) {
@@ -4421,7 +4437,7 @@
4421
4437
  function useRenderCache() {
4422
4438
  let cache = Object.create(null);
4423
4439
  return {
4424
- getCache: (key, defaultValue) => cache[key] === void 0 ? cache[key] = typeof defaultValue === "function" ? defaultValue() : defaultValue : cache[key],
4440
+ getCache: (key, defaultValue) => Object.hasOwn(cache, key) ? cache[key] : cache[key] = typeof defaultValue === "function" ? defaultValue() : defaultValue,
4425
4441
  setCache(key, obj) {
4426
4442
  cache[key] = obj;
4427
4443
  },
@@ -4500,8 +4516,8 @@
4500
4516
  mouse: true
4501
4517
  }
4502
4518
  ]]);
4503
- const transitionPrev = (0, vue.computed)(() => props.transitionPrev || `slide-${props.vertical ? "down" : "right"}`);
4504
- const transitionNext = (0, vue.computed)(() => props.transitionNext || `slide-${props.vertical ? "up" : "left"}`);
4519
+ const transitionPrev = (0, vue.computed)(() => props.transitionPrev || `slide-${props.vertical ? "down" : proxy.$q.lang.rtl ? "left" : "right"}`);
4520
+ const transitionNext = (0, vue.computed)(() => props.transitionNext || `slide-${props.vertical ? "up" : proxy.$q.lang.rtl ? "right" : "left"}`);
4505
4521
  const transitionStyle = (0, vue.computed)(() => `--q-transition-duration: ${props.transitionDuration}ms`);
4506
4522
  const contentKey = (0, vue.computed)(() => typeof props.modelValue === "string" || typeof props.modelValue === "number" ? props.modelValue : String(props.modelValue));
4507
4523
  const keepAliveProps = (0, vue.computed)(() => ({
@@ -4611,8 +4627,33 @@
4611
4627
  };
4612
4628
  }
4613
4629
  //#endregion
4630
+ //#region src/composables/use-animation-frame/use-animation-frame.js
4631
+ function useAnimationFrame() {
4632
+ let frameId = null;
4633
+ const vm = (0, vue.getCurrentInstance)();
4634
+ function removeAnimationFrame() {
4635
+ if (frameId !== null) {
4636
+ cancelAnimationFrame(frameId);
4637
+ frameId = null;
4638
+ }
4639
+ }
4640
+ (0, vue.onDeactivated)(removeAnimationFrame);
4641
+ (0, vue.onBeforeUnmount)(removeAnimationFrame);
4642
+ return {
4643
+ removeAnimationFrame,
4644
+ registerAnimationFrame(fn) {
4645
+ removeAnimationFrame();
4646
+ if (!vmIsDestroyed(vm)) frameId = requestAnimationFrame(() => {
4647
+ frameId = null;
4648
+ fn();
4649
+ });
4650
+ }
4651
+ };
4652
+ }
4653
+ //#endregion
4614
4654
  //#region src/composables/private.use-fullscreen/use-fullscreen.js
4615
4655
  let counter = 0;
4656
+ let restoreState = null;
4616
4657
  const useFullscreenProps = {
4617
4658
  fullscreen: Boolean,
4618
4659
  noRouteFullscreenExit: Boolean
@@ -4623,6 +4664,8 @@
4623
4664
  const { props, emit, proxy } = vm;
4624
4665
  let historyEntry, fullscreenFillerNode;
4625
4666
  const inFullscreen = (0, vue.ref)(false);
4667
+ const { registerTick, removeTick } = useTick();
4668
+ const { registerAnimationFrame, removeAnimationFrame } = useAnimationFrame();
4626
4669
  if (vmHasRouter(vm)) (0, vue.watch)(() => proxy.$route.fullPath, () => {
4627
4670
  if (!props.noRouteFullscreenExit) exitFullscreen();
4628
4671
  });
@@ -4638,7 +4681,15 @@
4638
4681
  else setFullscreen();
4639
4682
  }
4640
4683
  function setFullscreen() {
4641
- if (inFullscreen.value) return;
4684
+ if (vmIsDestroyed(vm) || inFullscreen.value) return;
4685
+ removeAnimationFrame();
4686
+ removeTick();
4687
+ if (counter === 0) restoreState = {
4688
+ left: getHorizontalScrollPosition(window),
4689
+ top: getVerticalScrollPosition(window),
4690
+ width: window.innerWidth,
4691
+ height: window.innerHeight
4692
+ };
4642
4693
  inFullscreen.value = true;
4643
4694
  proxy.$el.replaceWith(fullscreenFillerNode);
4644
4695
  document.body.append(proxy.$el);
@@ -4647,21 +4698,40 @@
4647
4698
  historyEntry = { handler: exitFullscreen };
4648
4699
  History_default.add(historyEntry);
4649
4700
  }
4650
- function exitFullscreen() {
4701
+ function exitFullscreenImpl(shouldRestoreElement) {
4651
4702
  if (!inFullscreen.value) return;
4652
4703
  if (historyEntry !== void 0) {
4653
4704
  History_default.remove(historyEntry);
4654
4705
  historyEntry = void 0;
4655
4706
  }
4656
- fullscreenFillerNode.replaceWith(proxy.$el);
4707
+ if (shouldRestoreElement === true) fullscreenFillerNode.replaceWith(proxy.$el);
4708
+ else fullscreenFillerNode.remove();
4657
4709
  inFullscreen.value = false;
4658
4710
  counter = Math.max(0, counter - 1);
4659
- if (counter === 0) {
4660
- document.body.classList.remove("q-body--fullscreen-mixin");
4661
- if (proxy.$el.scrollIntoView !== void 0) setTimeout(() => {
4711
+ if (counter !== 0) return;
4712
+ document.body.classList.remove("q-body--fullscreen-mixin");
4713
+ if (restoreState === null) return;
4714
+ const { left, top, width, height } = restoreState;
4715
+ restoreState = null;
4716
+ if (vmIsDestroyed(vm)) return;
4717
+ registerTick(() => {
4718
+ if (counter !== 0) return;
4719
+ registerAnimationFrame(() => {
4720
+ if (counter !== 0) return;
4721
+ if (window.innerWidth !== width || window.innerHeight !== height)
4722
+ /**
4723
+ * If user has resized the window while in fullscreen mode,
4724
+ * we cannot restore the scroll position because it will be wrong.
4725
+ * So we just scroll the element into view instead,
4726
+ * which is the best we can do.
4727
+ */
4662
4728
  proxy.$el.scrollIntoView();
4663
- }, 0);
4664
- }
4729
+ else window.scrollTo(left, top);
4730
+ });
4731
+ });
4732
+ }
4733
+ function exitFullscreen() {
4734
+ exitFullscreenImpl(true);
4665
4735
  }
4666
4736
  (0, vue.onBeforeMount)(() => {
4667
4737
  fullscreenFillerNode = document.createElement("span");
@@ -4669,6 +4739,12 @@
4669
4739
  (0, vue.onMounted)(() => {
4670
4740
  if (props.fullscreen) setFullscreen();
4671
4741
  });
4742
+ (0, vue.onDeactivated)(() => {
4743
+ exitFullscreenImpl(proxy.$el.isConnected);
4744
+ });
4745
+ (0, vue.onActivated)(() => {
4746
+ if (props.fullscreen) setFullscreen();
4747
+ });
4672
4748
  (0, vue.onBeforeUnmount)(exitFullscreen);
4673
4749
  Object.assign(proxy, {
4674
4750
  toggleFullscreen,
@@ -4736,7 +4812,7 @@
4736
4812
  const { proxy: { $q } } = (0, vue.getCurrentInstance)();
4737
4813
  const isDark = useDark(props, $q);
4738
4814
  let timer = null, panelsLen;
4739
- const { updatePanelsList, getPanelContent, panelDirectives, goToPanel, previousPanel, nextPanel, getEnabledPanels, panelIndex } = usePanel();
4815
+ const { updatePanelsList, updatePanelIndex, getPanelContent, panelDirectives, goToPanel, previousPanel, nextPanel, getEnabledPanels, panelIndex } = usePanel();
4740
4816
  const { inFullscreen } = useFullscreen();
4741
4817
  const style = (0, vue.computed)(() => !inFullscreen.value && props.height !== void 0 ? { height: props.height } : {});
4742
4818
  const direction = (0, vue.computed)(() => props.vertical ? "vertical" : "horizontal");
@@ -4847,6 +4923,7 @@
4847
4923
  }
4848
4924
  return () => {
4849
4925
  panelsLen = updatePanelsList(slots);
4926
+ updatePanelIndex();
4850
4927
  return (0, vue.h)("div", {
4851
4928
  class: classes.value,
4852
4929
  style: style.value
@@ -5171,6 +5248,9 @@
5171
5248
  });
5172
5249
  //#endregion
5173
5250
  //#region src/components/chip/QChip.js
5251
+ function preventSpace$3(e) {
5252
+ if (e.keyCode === 32) stopAndPrevent(e);
5253
+ }
5174
5254
  const defaultSizes$1 = {
5175
5255
  xs: 8,
5176
5256
  sm: 10,
@@ -5233,7 +5313,11 @@
5233
5313
  const chip = props.disable ? {
5234
5314
  tabindex: -1,
5235
5315
  "aria-disabled": "true"
5236
- } : { tabindex: props.tabindex || 0 };
5316
+ } : {
5317
+ tabindex: props.tabindex || 0,
5318
+ role: "button",
5319
+ "aria-pressed": props.selected ? "true" : "false"
5320
+ };
5237
5321
  return {
5238
5322
  chip,
5239
5323
  remove: {
@@ -5245,7 +5329,10 @@
5245
5329
  };
5246
5330
  });
5247
5331
  function onKeyup(e) {
5248
- if (e.keyCode === 13) onClick(e);
5332
+ if ([13, 32].includes(e.keyCode)) {
5333
+ onClick(e);
5334
+ stopAndPrevent(e);
5335
+ }
5249
5336
  }
5250
5337
  function onClick(e) {
5251
5338
  if (!props.disable) {
@@ -5254,7 +5341,7 @@
5254
5341
  }
5255
5342
  }
5256
5343
  function onRemove(e) {
5257
- if (e.keyCode === void 0 || e.keyCode === 13) {
5344
+ if (e.keyCode === void 0 || [13, 32].includes(e.keyCode)) {
5258
5345
  stopAndPrevent(e);
5259
5346
  if (!props.disable) {
5260
5347
  emit("update:modelValue", false);
@@ -5280,6 +5367,7 @@
5280
5367
  name: removeIcon.value,
5281
5368
  ...attributes.value.remove,
5282
5369
  onClick: onRemove,
5370
+ onKeydown: preventSpace$3,
5283
5371
  onKeyup: onRemove
5284
5372
  }));
5285
5373
  return child;
@@ -5292,6 +5380,7 @@
5292
5380
  };
5293
5381
  if (isClickable.value) Object.assign(data, attributes.value.chip, {
5294
5382
  onClick,
5383
+ onKeydown: preventSpace$3,
5295
5384
  onKeyup
5296
5385
  });
5297
5386
  return hDir("div", data, getContent(), "ripple", props.ripple !== false && !props.disable, () => [[Ripple_default, props.ripple]]);
@@ -6054,16 +6143,14 @@
6054
6143
  viewBox: "0 0 20 20",
6055
6144
  "aria-hidden": "true"
6056
6145
  }, [(0, vue.h)("path", { d: props.thumbPath })]), (0, vue.h)("div", { class: "q-slider__focus-ring fit" })];
6057
- if (props.label || props.labelAlways) {
6058
- thumbContent.push((0, vue.h)("div", { class: pinClass.value + " absolute fit no-pointer-events" + pinColor.value }, [(0, vue.h)("div", {
6059
- class: labelClass.value,
6060
- style: { minWidth: props.thumbSize }
6061
- }, [(0, vue.h)("div", {
6062
- class: textContainerClass.value,
6063
- style: textContainerStyle.value
6064
- }, [(0, vue.h)("span", { class: textClass.value }, thumb.label.value)])])]));
6065
- if (props.name !== void 0 && !props.disable) injectFormInput(thumbContent, "push");
6066
- }
6146
+ if (props.label || props.labelAlways) thumbContent.push((0, vue.h)("div", { class: pinClass.value + " absolute fit no-pointer-events" + pinColor.value }, [(0, vue.h)("div", {
6147
+ class: labelClass.value,
6148
+ style: { minWidth: props.thumbSize }
6149
+ }, [(0, vue.h)("div", {
6150
+ class: textContainerClass.value,
6151
+ style: textContainerStyle.value
6152
+ }, [(0, vue.h)("span", { class: textClass.value }, thumb.label.value)])])]));
6153
+ if (thumb.injectFormInput !== false && props.name !== void 0 && !props.disable) injectFormInput(thumbContent, "push");
6067
6154
  return (0, vue.h)("div", {
6068
6155
  class: thumbClasses.value,
6069
6156
  style: style.value,
@@ -6290,8 +6377,9 @@
6290
6377
  const { proxy } = (0, vue.getCurrentInstance)();
6291
6378
  proxy.trigger = trigger;
6292
6379
  if (hasObserver) {
6293
- let observer;
6380
+ let observer, isDestroyed = false;
6294
6381
  const init = (stop) => {
6382
+ if (isDestroyed) return;
6295
6383
  targetEl = proxy.$el.parentNode;
6296
6384
  if (targetEl) {
6297
6385
  observer = new ResizeObserver(trigger);
@@ -6305,6 +6393,7 @@
6305
6393
  init();
6306
6394
  });
6307
6395
  (0, vue.onBeforeUnmount)(() => {
6396
+ isDestroyed = true;
6308
6397
  if (timer !== null) clearTimeout(timer);
6309
6398
  if (observer !== void 0) {
6310
6399
  if (observer.disconnect !== void 0) observer.disconnect();
@@ -6314,7 +6403,7 @@
6314
6403
  return noop;
6315
6404
  }
6316
6405
  const { isHydrated } = useHydration();
6317
- let curDocView;
6406
+ let curDocView, isDestroyed = false;
6318
6407
  const cleanup = () => {
6319
6408
  if (timer !== null) {
6320
6409
  clearTimeout(timer);
@@ -6335,11 +6424,15 @@
6335
6424
  };
6336
6425
  (0, vue.onMounted)(() => {
6337
6426
  (0, vue.nextTick)(() => {
6427
+ if (isDestroyed) return;
6338
6428
  targetEl = proxy.$el;
6339
6429
  if (targetEl) onObjLoad();
6340
6430
  });
6341
6431
  });
6342
- (0, vue.onBeforeUnmount)(cleanup);
6432
+ (0, vue.onBeforeUnmount)(() => {
6433
+ isDestroyed = true;
6434
+ cleanup();
6435
+ });
6343
6436
  return () => {
6344
6437
  if (isHydrated.value) return (0, vue.h)("object", {
6345
6438
  class: "q--avoid-card-border",
@@ -6592,12 +6685,10 @@
6592
6685
  const dirNext = keyCode === (props.vertical ? 40 : 39);
6593
6686
  const dir = dirPrev ? -1 : dirNext ? 1 : void 0;
6594
6687
  if (dir !== void 0) {
6595
- const rtlDir = isRTL.value ? -1 : 1;
6596
- const index = tabs.indexOf(fromEl) + dir * rtlDir;
6597
- if (index >= 0 && index < len) {
6598
- scrollToTabEl(tabs[index]);
6599
- tabs[index].focus({ preventScroll: true });
6600
- }
6688
+ const rtlDir = props.vertical !== true && isRTL.value ? -1 : 1;
6689
+ const index = (tabs.indexOf(fromEl) + dir * rtlDir + len) % len;
6690
+ scrollToTabEl(tabs[index]);
6691
+ tabs[index].focus({ preventScroll: true });
6601
6692
  return true;
6602
6693
  }
6603
6694
  }
@@ -6772,6 +6863,7 @@
6772
6863
  ref: rootRef,
6773
6864
  class: classes.value,
6774
6865
  role: "tablist",
6866
+ "aria-orientation": props.vertical ? "vertical" : "horizontal",
6775
6867
  onFocusin,
6776
6868
  onFocusout
6777
6869
  }, [
@@ -8728,6 +8820,7 @@
8728
8820
  const { $q } = proxy;
8729
8821
  const isDark = useDark(props, $q);
8730
8822
  const { getCache } = useRenderCache();
8823
+ const { isHydrated } = useHydration();
8731
8824
  const { tabindex, headerClass, getLocale, getCurrentDate } = useDatetime(props, $q);
8732
8825
  let lastEmitValue;
8733
8826
  const injectFormInput = useFormInject(useFormAttrs(props));
@@ -9041,7 +9134,7 @@
9041
9134
  if (rangeView.value.includeFrom) res[from].editRangeFrom = true;
9042
9135
  if (rangeView.value.includeTo) res[to].editRangeTo = true;
9043
9136
  }
9044
- if (viewModel.value.year === today.value.year && viewModel.value.month === today.value.month) res[index + today.value.day - 1].today = true;
9137
+ if (isHydrated.value && viewModel.value.year === today.value.year && viewModel.value.month === today.value.month) res[index + today.value.day - 1].today = true;
9045
9138
  const left = res.length % 7;
9046
9139
  if (left > 0) {
9047
9140
  const afterDays = 7 - left;
@@ -9432,7 +9525,7 @@
9432
9525
  }, day.event ? () => (0, vue.h)("div", { class: "q-date__event bg-" + day.event }) : null) : (0, vue.h)("div", String(day.i))]))))])
9433
9526
  ])],
9434
9527
  Months() {
9435
- const currentYear = viewModel.value.year === today.value.year;
9528
+ const currentYear = isHydrated.value && viewModel.value.year === today.value.year;
9436
9529
  const isDisabled = (month) => minNav.value !== null && viewModel.value.year === minNav.value.year && minNav.value.month > month || maxNav.value !== null && viewModel.value.year === maxNav.value.year && maxNav.value.month < month;
9437
9530
  const content = innerLocale.value.monthsShort.map((month, i) => {
9438
9531
  const active = viewModel.value.month === i + 1;
@@ -9471,7 +9564,7 @@
9471
9564
  const active = viewModel.value.year === i;
9472
9565
  years.push((0, vue.h)("div", { class: "q-date__years-item flex flex-center" }, [(0, vue.h)(QBtn_default, {
9473
9566
  key: "yr" + i,
9474
- class: today.value.year === i ? "q-date__today" : null,
9567
+ class: isHydrated.value && today.value.year === i ? "q-date__today" : null,
9475
9568
  flat: !active,
9476
9569
  label: i,
9477
9570
  dense: true,
@@ -9632,7 +9725,7 @@
9632
9725
  let vpPendingUpdate = false;
9633
9726
  let bodyLeft;
9634
9727
  let bodyTop;
9635
- let href;
9728
+ let routePath;
9636
9729
  let closeTimer = null;
9637
9730
  function onAppleScroll(e) {
9638
9731
  if (e.target === document) document.scrollingElement.scrollTop = document.scrollingElement.scrollTop;
@@ -9658,7 +9751,7 @@
9658
9751
  scrollPositionY = getVerticalScrollPosition(window);
9659
9752
  bodyLeft = body.style.left;
9660
9753
  bodyTop = body.style.top;
9661
- href = window.location.href;
9754
+ routePath = window.location.pathname;
9662
9755
  body.style.left = `-${scrollPositionX}px`;
9663
9756
  body.style.top = `-${scrollPositionY}px`;
9664
9757
  if (overflowX !== "hidden" && (overflowX === "scroll" || body.scrollWidth > window.innerWidth)) body.classList.add("q-body--force-scrollbar-x");
@@ -9681,7 +9774,7 @@
9681
9774
  document.qScrollPrevented = false;
9682
9775
  body.style.left = bodyLeft;
9683
9776
  body.style.top = bodyTop;
9684
- if (window.location.href === href) window.scrollTo(scrollPositionX, scrollPositionY);
9777
+ if (window.location.pathname === routePath) window.scrollTo(scrollPositionX, scrollPositionY);
9685
9778
  maxScrollTop = void 0;
9686
9779
  }
9687
9780
  }
@@ -9798,6 +9891,7 @@
9798
9891
  hideOnRouteChange,
9799
9892
  handleShow,
9800
9893
  handleHide,
9894
+ handleRouteChange,
9801
9895
  processOnMount: true
9802
9896
  });
9803
9897
  const { addToHistory, removeFromHistory } = useHistory(showing, hide, hideOnRouteChange);
@@ -9852,8 +9946,11 @@
9852
9946
  animating.value = true;
9853
9947
  hidePortal();
9854
9948
  if (refocusTarget !== null) {
9855
- ((evt?.type.indexOf("key") === 0 ? refocusTarget.closest("[tabindex]:not([tabindex^=\"-\"])") : void 0) || refocusTarget).focus();
9949
+ const target = (evt?.type.indexOf("key") === 0 ? refocusTarget.closest("[tabindex]:not([tabindex^=\"-\"])") : void 0) || refocusTarget;
9856
9950
  refocusTarget = null;
9951
+ addFocusFn(() => {
9952
+ if (target.isConnected) target.focus();
9953
+ });
9857
9954
  }
9858
9955
  registerTimeout(() => {
9859
9956
  hidePortal(true);
@@ -9861,6 +9958,9 @@
9861
9958
  emit("hide", evt);
9862
9959
  }, props.transitionDuration);
9863
9960
  }
9961
+ function handleRouteChange() {
9962
+ refocusTarget = null;
9963
+ }
9864
9964
  function focus(selector) {
9865
9965
  addFocusFn(() => {
9866
9966
  let node = innerRef.value;
@@ -10588,6 +10688,7 @@
10588
10688
  };
10589
10689
  //#endregion
10590
10690
  //#region src/components/tooltip/QTooltip.js
10691
+ let nonSelectableCount = 0;
10591
10692
  var QTooltip_default = createComponent({
10592
10693
  name: "QTooltip",
10593
10694
  inheritAttrs: false,
@@ -10639,11 +10740,13 @@
10639
10740
  },
10640
10741
  emits: [...useModelToggleEmits],
10641
10742
  setup(props, { slots, emit, attrs }) {
10642
- let unwatchPosition, observer;
10743
+ let unwatchPosition, observer, removeNonSelectableTimer, hasNonSelectable = false, describedBy;
10643
10744
  const vm = (0, vue.getCurrentInstance)();
10644
10745
  const { proxy: { $q } } = vm;
10645
10746
  const innerRef = (0, vue.ref)(null);
10646
10747
  const showing = (0, vue.ref)(false);
10748
+ const targetUid = useId();
10749
+ const tooltipId = (0, vue.computed)(() => attrs.id || targetUid.value);
10647
10750
  const anchorOrigin = (0, vue.computed)(() => parsePosition(props.anchor, $q.lang.rtl));
10648
10751
  const selfOrigin = (0, vue.computed)(() => parsePosition(props.self, $q.lang.rtl));
10649
10752
  const hideOnRouteChange = (0, vue.computed)(() => !props.persistent);
@@ -10665,7 +10768,8 @@
10665
10768
  });
10666
10769
  Object.assign(anchorEvents, {
10667
10770
  delayShow,
10668
- delayHide
10771
+ delayHide,
10772
+ onFocusin
10669
10773
  });
10670
10774
  const { showPortal, hidePortal, renderPortal } = usePortal(vm, innerRef, renderPortalContent, "tooltip");
10671
10775
  if ($q.platform.is.mobile) {
@@ -10684,9 +10788,12 @@
10684
10788
  (0, vue.onBeforeUnmount)(() => {
10685
10789
  removeClickOutside(clickOutsideProps);
10686
10790
  });
10687
- }
10791
+ } else (0, vue.watch)(() => (props.modelValue === null || props["onUpdate:modelValue"]) && showing.value === true && props.persistent !== true, (val) => {
10792
+ (val === true ? addEscapeKey : removeEscapeKey)(onEscapeKey);
10793
+ });
10688
10794
  function handleShow(evt) {
10689
10795
  showPortal();
10796
+ addAriaDescription();
10690
10797
  registerTick(() => {
10691
10798
  observer?.disconnect();
10692
10799
  if (innerRef.value === null) {
@@ -10728,7 +10835,10 @@
10728
10835
  unwatchPosition = void 0;
10729
10836
  }
10730
10837
  unconfigureScrollTarget();
10838
+ removeEscapeKey(onEscapeKey);
10731
10839
  cleanEvt(anchorEvents, "tooltipTemp");
10840
+ removeAriaDescription();
10841
+ setNonSelectable(false);
10732
10842
  }
10733
10843
  function updatePosition() {
10734
10844
  setPosition({
@@ -10743,8 +10853,12 @@
10743
10853
  }
10744
10854
  function delayShow(evt) {
10745
10855
  if ($q.platform.is.mobile) {
10856
+ if (removeNonSelectableTimer !== void 0) {
10857
+ clearTimeout(removeNonSelectableTimer);
10858
+ removeNonSelectableTimer = void 0;
10859
+ }
10746
10860
  clearSelection();
10747
- document.body.classList.add("non-selectable");
10861
+ setNonSelectable(true);
10748
10862
  const target = anchorEl.value;
10749
10863
  const evts = [
10750
10864
  "touchmove",
@@ -10767,14 +10881,26 @@
10767
10881
  if ($q.platform.is.mobile) {
10768
10882
  cleanEvt(anchorEvents, "tooltipTemp");
10769
10883
  clearSelection();
10770
- setTimeout(() => {
10771
- document.body.classList.remove("non-selectable");
10884
+ removeNonSelectableTimer = setTimeout(() => {
10885
+ removeNonSelectableTimer = void 0;
10886
+ setNonSelectable(false);
10772
10887
  }, 10);
10773
10888
  }
10774
10889
  registerTimeout(() => {
10775
10890
  hide(evt);
10776
10891
  }, props.hideDelay);
10777
10892
  }
10893
+ function onFocusin(evt) {
10894
+ const el = evt.target;
10895
+ if (!el) return;
10896
+ try {
10897
+ if (el.matches(":focus-visible") === false) return;
10898
+ } catch {}
10899
+ delayShow(evt);
10900
+ }
10901
+ function onEscapeKey(evt) {
10902
+ hide(evt);
10903
+ }
10778
10904
  function configureAnchorEl() {
10779
10905
  if (props.noParentEvent || anchorEl.value === null) return;
10780
10906
  const evts = $q.platform.is.mobile ? [[
@@ -10782,19 +10908,66 @@
10782
10908
  "touchstart",
10783
10909
  "delayShow",
10784
10910
  "passive"
10785
- ]] : [[
10786
- anchorEl.value,
10787
- "mouseenter",
10788
- "delayShow",
10789
- "passive"
10790
- ], [
10791
- anchorEl.value,
10792
- "mouseleave",
10793
- "delayHide",
10794
- "passive"
10795
- ]];
10911
+ ]] : [
10912
+ [
10913
+ anchorEl.value,
10914
+ "mouseenter",
10915
+ "delayShow",
10916
+ "passive"
10917
+ ],
10918
+ [
10919
+ anchorEl.value,
10920
+ "mouseleave",
10921
+ "delayHide",
10922
+ "passive"
10923
+ ],
10924
+ [
10925
+ anchorEl.value,
10926
+ "focusin",
10927
+ "onFocusin",
10928
+ "passive"
10929
+ ],
10930
+ [
10931
+ anchorEl.value,
10932
+ "focusout",
10933
+ "delayHide",
10934
+ "passive"
10935
+ ]
10936
+ ];
10796
10937
  addEvt(anchorEvents, "anchor", evts);
10797
10938
  }
10939
+ function setNonSelectable(state) {
10940
+ if (hasNonSelectable === state) return;
10941
+ hasNonSelectable = state;
10942
+ nonSelectableCount += state ? 1 : -1;
10943
+ document.body.classList.toggle("non-selectable", nonSelectableCount > 0);
10944
+ if (!state && removeNonSelectableTimer !== void 0) {
10945
+ clearTimeout(removeNonSelectableTimer);
10946
+ removeNonSelectableTimer = void 0;
10947
+ }
10948
+ }
10949
+ function addAriaDescription() {
10950
+ const el = anchorEl.value, id = tooltipId.value;
10951
+ if (el === null || id === void 0) return;
10952
+ const ids = (el.getAttribute("aria-describedby") || "").split(/\s+/).filter(Boolean);
10953
+ describedBy = {
10954
+ el,
10955
+ id,
10956
+ added: !ids.includes(id)
10957
+ };
10958
+ if (describedBy.added) {
10959
+ ids.push(id);
10960
+ el.setAttribute("aria-describedby", ids.join(" "));
10961
+ }
10962
+ }
10963
+ function removeAriaDescription() {
10964
+ if (describedBy?.added === true) {
10965
+ const { el, id } = describedBy, value = (el.getAttribute("aria-describedby") || "").split(/\s+/).filter((entry) => entry !== "" && entry !== id);
10966
+ if (value.length === 0) el.removeAttribute("aria-describedby");
10967
+ else el.setAttribute("aria-describedby", value.join(" "));
10968
+ }
10969
+ describedBy = void 0;
10970
+ }
10798
10971
  function configureScrollTarget() {
10799
10972
  if (anchorEl.value !== null || props.scrollTarget !== void 0) {
10800
10973
  localScrollTarget.value = getScrollTarget(anchorEl.value, props.scrollTarget);
@@ -10805,6 +10978,7 @@
10805
10978
  function getTooltipContent() {
10806
10979
  return showing.value ? (0, vue.h)("div", {
10807
10980
  ...attrs,
10981
+ id: tooltipId.value,
10808
10982
  ref: innerRef,
10809
10983
  class: ["q-tooltip q-tooltip--style q-position-engine no-pointer-events", attrs.class],
10810
10984
  style: [attrs.style, transitionStyle.value],
@@ -10874,6 +11048,9 @@
10874
11048
  }
10875
11049
  emit("keyup", e);
10876
11050
  }
11051
+ function onKeydown(e) {
11052
+ if (isClickable.value && e.keyCode === 32) stopAndPrevent(e);
11053
+ }
10877
11054
  function getContent() {
10878
11055
  const child = hUniqueSlot(slots.default, []);
10879
11056
  if (isClickable.value) child.unshift((0, vue.h)("div", {
@@ -10888,8 +11065,9 @@
10888
11065
  ref: rootRef,
10889
11066
  class: classes.value,
10890
11067
  style: style.value,
10891
- role: "listitem",
11068
+ role: hasLink.value ? void 0 : isClickable.value ? "button" : "listitem",
10892
11069
  onClick,
11070
+ onKeydown,
10893
11071
  onKeyup
10894
11072
  };
10895
11073
  if (isClickable.value) {
@@ -11152,6 +11330,7 @@
11152
11330
  i--;
11153
11331
  }
11154
11332
  for (; i < length; i++) if ((options = args[i]) !== null) for (name in options) {
11333
+ if (name === "__proto__") continue;
11155
11334
  src = target[name];
11156
11335
  copy = options[name];
11157
11336
  if (target === copy) continue;
@@ -11254,8 +11433,9 @@
11254
11433
  const editLinkUrl = (0, vue.ref)(null);
11255
11434
  const isViewingSource = (0, vue.ref)(false);
11256
11435
  const editable = (0, vue.computed)(() => !props.readonly && !props.disable);
11257
- let defaultFont, offsetBottom;
11436
+ let defaultFont, offsetBottom, refreshToolbarTimer = null;
11258
11437
  let lastEmit = props.modelValue;
11438
+ const renderInitialContent = isRuntimeSsrPreHydration.value;
11259
11439
  document.execCommand("defaultParagraphSeparator", false, props.paragraphTag);
11260
11440
  defaultFont = window.getComputedStyle(document.body).fontFamily;
11261
11441
  const toolbarBackgroundClass = (0, vue.computed)(() => props.toolbarBg ? ` bg-${props.toolbarBg}` : "");
@@ -11686,7 +11866,9 @@
11686
11866
  });
11687
11867
  }
11688
11868
  function refreshToolbar() {
11689
- setTimeout(() => {
11869
+ if (refreshToolbarTimer !== null) clearTimeout(refreshToolbarTimer);
11870
+ refreshToolbarTimer = setTimeout(() => {
11871
+ refreshToolbarTimer = null;
11690
11872
  editLinkUrl.value = null;
11691
11873
  proxy.$forceUpdate();
11692
11874
  }, 1);
@@ -11706,6 +11888,7 @@
11706
11888
  document.addEventListener("selectionchange", onSelectionchange);
11707
11889
  });
11708
11890
  (0, vue.onBeforeUnmount)(() => {
11891
+ if (refreshToolbarTimer !== null) clearTimeout(refreshToolbarTimer);
11709
11892
  document.removeEventListener("selectionchange", onSelectionchange);
11710
11893
  });
11711
11894
  Object.assign(proxy, {
@@ -11743,6 +11926,7 @@
11743
11926
  class: innerClass.value,
11744
11927
  contenteditable: editable.value,
11745
11928
  placeholder: props.placeholder,
11929
+ ...renderInitialContent ? { innerHTML: props.modelValue } : {},
11746
11930
  ...splitAttrs.listeners.value,
11747
11931
  onInput,
11748
11932
  onKeydown,
@@ -11927,6 +12111,9 @@
11927
12111
  //#endregion
11928
12112
  //#region src/components/expansion-item/QExpansionItem.js
11929
12113
  const itemGroups = (0, vue.shallowReactive)({});
12114
+ function preventSpace$2(e) {
12115
+ if (e.keyCode === 32) stopAndPrevent(e);
12116
+ }
11930
12117
  const LINK_PROPS = Object.keys(useRouterLinkProps);
11931
12118
  var QExpansionItem_default = createComponent({
11932
12119
  name: "QExpansionItem",
@@ -12025,7 +12212,7 @@
12025
12212
  emit("click", e);
12026
12213
  }
12027
12214
  function toggleIconKeyboard(e) {
12028
- if (e.keyCode === 13) toggleIcon(e, true);
12215
+ if ([13, 32].includes(e.keyCode)) toggleIcon(e, true);
12029
12216
  }
12030
12217
  function toggleIcon(e, keyboard) {
12031
12218
  if (!keyboard && !e.qAvoidFocus) blurTargetRef.value?.focus();
@@ -12070,6 +12257,7 @@
12070
12257
  tabindex: 0,
12071
12258
  ...toggleAriaAttrs.value,
12072
12259
  onClick: toggleIcon,
12260
+ onKeydown: preventSpace$2,
12073
12261
  onKeyup: toggleIconKeyboard
12074
12262
  });
12075
12263
  child.unshift((0, vue.h)("div", {
@@ -12705,6 +12893,7 @@
12705
12893
  if (!$q.platform.is.mobile) (state.targetRef?.value || state.rootRef.value).focus();
12706
12894
  else if (state.rootRef.value.contains(document.activeElement)) document.activeElement.blur();
12707
12895
  if (props.type === "file") state.inputRef.value.value = null;
12896
+ state.onClear?.();
12708
12897
  emit("update:modelValue", null);
12709
12898
  if (state.changeEvent) emit("change", null);
12710
12899
  emit("clear", props.modelValue);
@@ -12915,7 +13104,7 @@
12915
13104
  if (rejectedFiles.length !== 0) emit("rejected", rejectedFiles);
12916
13105
  };
12917
13106
  if (props.accept !== void 0 && !extensions.value.includes("*/")) {
12918
- files = filterFiles(files, rejectedFiles, "accept", (file) => extensions.value.some((ext) => file.type.toUpperCase().startsWith(ext) || file.name.toUpperCase().endsWith(ext)));
13107
+ files = filterFiles(files, rejectedFiles, "accept", (file) => extensions.value.some((ext) => (ext.endsWith("/") ? file.type.toUpperCase().startsWith(ext) : file.type.toUpperCase() === ext) || file.name.toUpperCase().endsWith(ext)));
12919
13108
  if (files.length === 0) return done();
12920
13109
  }
12921
13110
  if (props.maxFileSize !== void 0) {
@@ -12925,18 +13114,29 @@
12925
13114
  }
12926
13115
  if (!props.multiple && files.length !== 0) files = [files[0]];
12927
13116
  files.forEach((file) => {
12928
- file.__key = file.webkitRelativePath + file.lastModified + file.name + file.size;
13117
+ file.__key = JSON.stringify([
13118
+ file.webkitRelativePath,
13119
+ file.lastModified,
13120
+ file.name,
13121
+ file.size
13122
+ ]);
12929
13123
  });
12930
13124
  if (append) {
12931
- const filenameMap = currentFileList.map((entry) => entry.__key);
12932
- files = filterFiles(files, rejectedFiles, "duplicate", (file) => !filenameMap.includes(file.__key));
13125
+ const filenameSet = new Set(currentFileList.map((entry) => entry.__key));
13126
+ files = filterFiles(files, rejectedFiles, "duplicate", (file) => {
13127
+ if (filenameSet.has(file.__key)) return false;
13128
+ filenameSet.add(file.__key);
13129
+ return true;
13130
+ });
12933
13131
  }
12934
13132
  if (files.length === 0) return done();
12935
13133
  if (props.maxTotalSize !== void 0) {
12936
13134
  let size = append ? currentFileList.reduce((total, file) => total + file.size, 0) : 0;
12937
13135
  files = filterFiles(files, rejectedFiles, "max-total-size", (file) => {
12938
- size += file.size;
12939
- return size <= maxTotalSizeNumber.value;
13136
+ const newSize = size + file.size;
13137
+ if (newSize > maxTotalSizeNumber.value) return false;
13138
+ size = newSize;
13139
+ return true;
12940
13140
  });
12941
13141
  if (files.length === 0) return done();
12942
13142
  }
@@ -14104,6 +14304,9 @@
14104
14304
  (0, vue.watch)(() => props.unmaskedValue, () => {
14105
14305
  if (hasMask.value) updateMaskValue(innerValue.value);
14106
14306
  });
14307
+ (0, vue.watch)(() => props.maskTokens, () => {
14308
+ if (hasMask.value) updateMaskValue(innerValue.value, true);
14309
+ }, { deep: true });
14107
14310
  function getInitialMaskedValue() {
14108
14311
  updateMaskInternals();
14109
14312
  if (hasMask.value) {
@@ -14177,12 +14380,12 @@
14177
14380
  maskReplaced = maskMarked.split(MARKER).join(fillChar);
14178
14381
  }
14179
14382
  function updateMaskValue(rawVal, updateMaskInternalsFlag, inputType) {
14180
- const inp = inputRef.value, end = inp.selectionEnd, endReverse = inp.value.length - end, unmasked = unmaskValue(rawVal);
14383
+ const inp = inputRef.value, end = inp?.selectionEnd ?? 0, endReverse = inp === null ? 0 : inp.value.length - end, unmasked = unmaskValue(rawVal);
14181
14384
  if (updateMaskInternalsFlag === true) updateMaskInternals();
14182
14385
  const preMasked = maskValue(unmasked, updateMaskInternalsFlag), masked = props.fillMask !== false ? fillWithMask(preMasked) : preMasked, changed = innerValue.value !== masked;
14183
- if (inp.value !== masked) inp.value = masked;
14386
+ if (inp !== null && inp.value !== masked) inp.value = masked;
14184
14387
  if (changed) innerValue.value = masked;
14185
- if (document.activeElement === inp) (0, vue.nextTick)(() => {
14388
+ if (inp !== null && document.activeElement === inp) (0, vue.nextTick)(() => {
14186
14389
  if (masked === maskReplaced) {
14187
14390
  const cursor = props.reverseFillMask ? maskReplaced.length : 0;
14188
14391
  inp.setSelectionRange(cursor, cursor, "forward");
@@ -14380,6 +14583,7 @@
14380
14583
  Number,
14381
14584
  FileList
14382
14585
  ],
14586
+ modelModifiers: Object,
14383
14587
  shadowText: String,
14384
14588
  type: {
14385
14589
  type: String,
@@ -14464,6 +14668,12 @@
14464
14668
  if (inputRef.value) inputRef.value.value = props.modelValue;
14465
14669
  });
14466
14670
  (0, vue.watch)(() => props.modelValue, (v) => {
14671
+ if (emitTimer !== null) {
14672
+ cancelPendingValueEmission();
14673
+ typedNumber = false;
14674
+ stopValueWatcher = false;
14675
+ delete temp.value;
14676
+ }
14467
14677
  if (hasMask.value) {
14468
14678
  if (stopValueWatcher) {
14469
14679
  stopValueWatcher = false;
@@ -14474,6 +14684,7 @@
14474
14684
  innerValue.value = v;
14475
14685
  if (props.type === "number" && Object.hasOwn(temp, "value")) if (typedNumber) typedNumber = false;
14476
14686
  else delete temp.value;
14687
+ if (props.modelModifiers?.trim === true && Object.hasOwn(temp, "value") && (typeof temp.value !== "string" || temp.value.trim() !== v)) delete temp.value;
14477
14688
  }
14478
14689
  if (props.autogrow) (0, vue.nextTick)(adjustHeight);
14479
14690
  });
@@ -14513,6 +14724,7 @@
14513
14724
  }
14514
14725
  if (hasMask.value) updateMaskValue(val, false, e.inputType);
14515
14726
  else {
14727
+ if (props.modelModifiers?.trim === true) temp.value = val;
14516
14728
  emitValue(val);
14517
14729
  if (isTypeText.value && e.target === document.activeElement) {
14518
14730
  const { selectionStart, selectionEnd } = e.target;
@@ -14530,7 +14742,7 @@
14530
14742
  function emitValue(val, stopWatcher) {
14531
14743
  emitValueFn = () => {
14532
14744
  emitTimer = null;
14533
- if (props.type !== "number" && Object.hasOwn(temp, "value")) delete temp.value;
14745
+ if (props.type !== "number" && (props.modelModifiers?.trim !== true || hasMask.value) && Object.hasOwn(temp, "value")) delete temp.value;
14534
14746
  if (props.modelValue !== val && emitCachedValue !== val) {
14535
14747
  emitCachedValue = val;
14536
14748
  if (stopWatcher === true) stopValueWatcher = true;
@@ -14551,6 +14763,19 @@
14551
14763
  emitTimer = setTimeout(emitValueFn, props.debounce);
14552
14764
  } else emitValueFn();
14553
14765
  }
14766
+ function cancelPendingValueEmission() {
14767
+ if (emitTimer !== null) {
14768
+ clearTimeout(emitTimer);
14769
+ emitTimer = null;
14770
+ }
14771
+ emitValueFn = void 0;
14772
+ }
14773
+ function onClear() {
14774
+ cancelPendingValueEmission();
14775
+ typedNumber = false;
14776
+ stopValueWatcher = false;
14777
+ delete temp.value;
14778
+ }
14554
14779
  function adjustHeight() {
14555
14780
  requestAnimationFrame(() => {
14556
14781
  const inp = inputRef.value;
@@ -14607,6 +14832,7 @@
14607
14832
  hasShadow: (0, vue.computed)(() => props.type !== "file" && typeof props.shadowText === "string" && props.shadowText.length !== 0),
14608
14833
  inputRef,
14609
14834
  emitValue,
14835
+ onClear,
14610
14836
  hasValue,
14611
14837
  floatingLabel: (0, vue.computed)(() => hasValue.value && (props.type !== "number" || Number.isFinite(Number(innerValue.value))) || fieldValueIsFilled(props.displayValue)),
14612
14838
  getControl: () => (0, vue.h)(isTextarea.value ? "textarea" : "input", {
@@ -14653,7 +14879,7 @@
14653
14879
  if (ctx.handler !== handler) ctx.handler = handler;
14654
14880
  if (changed) {
14655
14881
  ctx.cfg = cfg;
14656
- ctx.observer?.unobserve(el);
14882
+ ctx.observer?.disconnect();
14657
14883
  ctx.observer = new IntersectionObserver(([entry]) => {
14658
14884
  if (typeof ctx.handler === "function") {
14659
14885
  if (entry.rootBounds === null && document.body.contains(el)) {
@@ -14670,7 +14896,7 @@
14670
14896
  function destroy$1(el) {
14671
14897
  const ctx = el.__qvisible;
14672
14898
  if (ctx !== void 0) {
14673
- ctx.observer?.unobserve(el);
14899
+ ctx.observer?.disconnect();
14674
14900
  delete el.__qvisible;
14675
14901
  }
14676
14902
  }
@@ -15232,8 +15458,8 @@
15232
15458
  lg: 10,
15233
15459
  xl: 14
15234
15460
  };
15235
- function width(val, reverse, $q) {
15236
- return { transform: reverse ? `translateX(${$q.lang.rtl ? "-" : ""}100%) scale3d(${-val},1,1)` : `scale3d(${val},1,1)` };
15461
+ function width(val) {
15462
+ return { transform: `scale3d(${val},1,1)` };
15237
15463
  }
15238
15464
  var QLinearProgress_default = createComponent({
15239
15465
  name: "QLinearProgress",
@@ -15263,16 +15489,15 @@
15263
15489
  const isDark = useDark(props, proxy.$q);
15264
15490
  const sizeStyle = useSize(props, defaultSizes);
15265
15491
  const motion = (0, vue.computed)(() => props.indeterminate || props.query);
15266
- const widthReverse = (0, vue.computed)(() => props.reverse !== props.query);
15267
15492
  const style = (0, vue.computed)(() => ({
15268
15493
  ...sizeStyle.value !== null ? sizeStyle.value : {},
15269
15494
  "--q-linear-progress-speed": `${props.animationSpeed}ms`
15270
15495
  }));
15271
15496
  const classes = (0, vue.computed)(() => "q-linear-progress" + (props.color !== void 0 ? ` text-${props.color}` : "") + (props.reverse || props.query ? " q-linear-progress--reverse" : "") + (props.rounded ? " rounded-borders" : ""));
15272
- const trackStyle = (0, vue.computed)(() => width(props.buffer !== void 0 ? props.buffer : 1, widthReverse.value, proxy.$q));
15497
+ const trackStyle = (0, vue.computed)(() => width(props.buffer !== void 0 ? props.buffer : 1));
15273
15498
  const transitionSuffix = (0, vue.computed)(() => `with${props.instantFeedback ? "out" : ""}-transition`);
15274
15499
  const trackClass = (0, vue.computed)(() => `q-linear-progress__track absolute-full q-linear-progress__track--${transitionSuffix.value} q-linear-progress__track--${isDark.value ? "dark" : "light"}` + (props.trackColor !== void 0 ? ` bg-${props.trackColor}` : ""));
15275
- const modelStyle = (0, vue.computed)(() => width(motion.value ? 1 : props.value, widthReverse.value, proxy.$q));
15500
+ const modelStyle = (0, vue.computed)(() => width(motion.value ? 1 : props.value));
15276
15501
  const modelClass = (0, vue.computed)(() => `q-linear-progress__model absolute-full q-linear-progress__model--${transitionSuffix.value} q-linear-progress__model--${motion.value ? "in" : ""}determinate`);
15277
15502
  const stripeStyle = (0, vue.computed)(() => ({ width: `${props.value * 100}%` }));
15278
15503
  const stripeClass = (0, vue.computed)(() => `q-linear-progress__stripe absolute-${props.reverse ? "right" : "left"} q-linear-progress__stripe--${transitionSuffix.value}`);
@@ -16732,6 +16957,7 @@
16732
16957
  });
16733
16958
  const maxEvents = (0, vue.computed)(() => getEvents("max"));
16734
16959
  const getMaxThumb = methods.getThumbRenderFn({
16960
+ injectFormInput: false,
16735
16961
  focusValue: "max",
16736
16962
  getNodeData: () => ({
16737
16963
  ...maxEvents.value,
@@ -16830,8 +17056,8 @@
16830
17056
  }
16831
17057
  }
16832
17058
  model.value = model.value.min === null || model.value.max === null ? {
16833
- min: pos.min || props.min,
16834
- max: pos.max || props.max
17059
+ min: pos.min ?? props.min,
17060
+ max: pos.max ?? props.max
16835
17061
  } : {
16836
17062
  min: pos.min,
16837
17063
  max: pos.max
@@ -16926,7 +17152,7 @@
16926
17152
  selIconLen,
16927
17153
  selIcon: selIconLen > 0 ? props.iconSelected[selIconLen - 1] : props.iconSelected,
16928
17154
  halfIconLen,
16929
- halfIcon: halfIconLen > 0 ? props.iconHalf[selIconLen - 1] : props.iconHalf,
17155
+ halfIcon: halfIconLen > 0 ? props.iconHalf[halfIconLen - 1] : props.iconHalf,
16930
17156
  colorLen,
16931
17157
  color: colorLen > 0 ? props.color[colorLen - 1] : props.color,
16932
17158
  selColorLen,
@@ -16947,14 +17173,14 @@
16947
17173
  return (i, label) => `${label} ${i}`;
16948
17174
  });
16949
17175
  const stars = (0, vue.computed)(() => {
16950
- const acc = [], icons = iconData.value, ceil = Math.ceil(props.modelValue), tabindex = editable.value ? 0 : null;
17176
+ const acc = [], icons = iconData.value, ceil = Math.ceil(props.modelValue), tabIndex = Number.isInteger(props.modelValue) && props.modelValue >= 1 && props.modelValue <= props.max ? props.modelValue : 1;
16951
17177
  const halfIndex = props.iconHalf === void 0 || ceil === props.modelValue ? -1 : ceil;
16952
17178
  for (let i = 1; i <= props.max; i++) {
16953
17179
  const active = mouseModel.value === 0 && props.modelValue >= i || mouseModel.value > 0 && mouseModel.value >= i, half = halfIndex === i && mouseModel.value < i, exSelected = mouseModel.value > 0 && (half ? ceil : props.modelValue) >= i && mouseModel.value < i, color = half ? i <= icons.halfColorLen ? props.colorHalf[i - 1] : icons.halfColor : icons.selColor !== void 0 && active ? i <= icons.selColorLen ? props.colorSelected[i - 1] : icons.selColor : i <= icons.colorLen ? props.color[i - 1] : icons.color, name = (half ? i <= icons.halfIconLen ? props.iconHalf[i - 1] : icons.halfIcon : icons.selIcon !== void 0 && (active || exSelected) ? i <= icons.selIconLen ? props.iconSelected[i - 1] : icons.selIcon : i <= icons.iconLen ? props.icon[i - 1] : icons.icon) || $q.iconSet.rating.icon;
16954
17180
  acc.push({
16955
17181
  name: (half ? i <= icons.halfIconLen ? props.iconHalf[i - 1] : icons.halfIcon : icons.selIcon !== void 0 && (active || exSelected) ? i <= icons.selIconLen ? props.iconSelected[i - 1] : icons.selIcon : i <= icons.iconLen ? props.icon[i - 1] : icons.icon) || $q.iconSet.rating.icon,
16956
17182
  attrs: {
16957
- tabindex,
17183
+ tabindex: editable.value ? i === tabIndex ? 0 : -1 : null,
16958
17184
  role: "radio",
16959
17185
  "aria-checked": props.modelValue === i ? "true" : "false",
16960
17186
  "aria-label": iconLabel.value(i, name)
@@ -16980,17 +17206,25 @@
16980
17206
  function setHoverValue(value) {
16981
17207
  if (editable.value) mouseModel.value = value;
16982
17208
  }
16983
- function onKeyup(e, i) {
17209
+ function onKeydown(e, i) {
16984
17210
  switch (e.keyCode) {
16985
17211
  case 13:
16986
17212
  case 32:
16987
17213
  set(i);
16988
17214
  return stopAndPrevent(e);
16989
- case 37:
17215
+ case 37: {
17216
+ const index = i + ($q.lang.rtl ? 1 : -1);
17217
+ if (iconRefs[`rt${index}`]) iconRefs[`rt${index}`].focus();
17218
+ return stopAndPrevent(e);
17219
+ }
17220
+ case 39: {
17221
+ const index = i + ($q.lang.rtl ? -1 : 1);
17222
+ if (iconRefs[`rt${index}`]) iconRefs[`rt${index}`].focus();
17223
+ return stopAndPrevent(e);
17224
+ }
16990
17225
  case 40:
16991
17226
  if (iconRefs[`rt${i - 1}`]) iconRefs[`rt${i - 1}`].focus();
16992
17227
  return stopAndPrevent(e);
16993
- case 39:
16994
17228
  case 38:
16995
17229
  if (iconRefs[`rt${i + 1}`]) iconRefs[`rt${i + 1}`].focus();
16996
17230
  return stopAndPrevent(e);
@@ -17024,8 +17258,8 @@
17024
17258
  setHoverValue(i);
17025
17259
  },
17026
17260
  onBlur: resetMouseModel,
17027
- onKeyup(e) {
17028
- onKeyup(e, i);
17261
+ onKeydown(e) {
17262
+ onKeydown(e, i);
17029
17263
  }
17030
17264
  }, hMergeSlot(slots[`tip-${i}`], [(0, vue.h)(QIcon_default, {
17031
17265
  class: iconClass,
@@ -17140,11 +17374,11 @@
17140
17374
  ],
17141
17375
  verticalOffset: {
17142
17376
  type: Array,
17143
- default: [0, 0]
17377
+ default: () => [0, 0]
17144
17378
  },
17145
17379
  horizontalOffset: {
17146
17380
  type: Array,
17147
- default: [0, 0]
17381
+ default: () => [0, 0]
17148
17382
  },
17149
17383
  contentStyle: [
17150
17384
  Array,
@@ -17217,11 +17451,11 @@
17217
17451
  scroll.horizontal.percentage = (0, vue.computed)(() => {
17218
17452
  const diff = scroll.horizontal.size.value - container.horizontal.value;
17219
17453
  if (diff <= 0) return 0;
17220
- const p = between(Math.abs(scroll.horizontal.position.value) / diff, 0, 1);
17454
+ const p = between(getHorizontalLogicalPosition(scroll.horizontal.position.value) / diff, 0, 1);
17221
17455
  return Math.round(p * 1e4) / 1e4;
17222
17456
  });
17223
17457
  scroll.horizontal.thumbHidden = (0, vue.computed)(() => !(props.visible === null ? hover.value : props.visible) && !tempShowing.value && !panning.value || scroll.horizontal.size.value <= container.horizontal.value + 1);
17224
- scroll.horizontal.thumbStart = (0, vue.computed)(() => props.horizontalOffset[0] + scroll.horizontal.percentage.value * (container.horizontalInner.value - scroll.horizontal.thumbSize.value));
17458
+ scroll.horizontal.thumbStart = (0, vue.computed)(() => props.horizontalOffset[proxy.$q.lang.rtl ? 1 : 0] + scroll.horizontal.percentage.value * (container.horizontalInner.value - scroll.horizontal.thumbSize.value));
17225
17459
  scroll.horizontal.thumbSize = (0, vue.computed)(() => Math.round(between(container.horizontalInner.value * container.horizontalInner.value / scroll.horizontal.size.value, getMinThumbSize(container.horizontalInner.value), container.horizontalInner.value)));
17226
17460
  scroll.horizontal.style = (0, vue.computed)(() => ({
17227
17461
  ...props.thumbStyle,
@@ -17297,22 +17531,28 @@
17297
17531
  const data = scroll[axis];
17298
17532
  if (e.isFirst) {
17299
17533
  if (data.thumbHidden.value) return;
17300
- panRefPos = data.position.value;
17534
+ panRefPos = axis === "horizontal" ? getHorizontalLogicalPosition(data.position.value) : data.position.value;
17301
17535
  panning.value = true;
17302
17536
  } else if (!panning.value) return;
17303
17537
  if (e.isFinal) panning.value = false;
17304
17538
  const dProp = dirProps[axis];
17305
17539
  const multiplier = (data.size.value - container[axis].value) / (container[axis + "Inner"].value - data.thumbSize.value);
17306
17540
  const distance = e.distance[dProp.dist];
17307
- setScroll(panRefPos + (e.direction === dProp.dir ? 1 : -1) * distance * multiplier, axis);
17541
+ const direction = (e.direction === dProp.dir ? 1 : -1) * (axis === "horizontal" && proxy.$q.lang.rtl ? -1 : 1);
17542
+ const pos = panRefPos + direction * distance * multiplier;
17543
+ setScroll(axis === "horizontal" ? getHorizontalNativePosition(pos) : pos, axis);
17308
17544
  }
17309
17545
  function onMousedown(evt, axis) {
17310
17546
  const data = scroll[axis];
17311
17547
  if (!data.thumbHidden.value) {
17312
- const startOffset = axis === "vertical" ? props.verticalOffset[0] : props.horizontalOffset[0];
17313
- const offset = evt[dirProps[axis].offset] - startOffset;
17548
+ const isHorizontalRtl = axis === "horizontal" && proxy.$q.lang.rtl;
17549
+ const startOffset = axis === "vertical" ? props.verticalOffset[0] : props.horizontalOffset[isHorizontalRtl ? 1 : 0];
17550
+ const offset = (isHorizontalRtl ? container.horizontal.value - evt.offsetX : evt[dirProps[axis].offset]) - startOffset;
17314
17551
  const thumbStart = data.thumbStart.value - startOffset;
17315
- if (offset < thumbStart || offset > thumbStart + data.thumbSize.value) setScroll(between((offset - data.thumbSize.value / 2) / (container[axis + "Inner"].value - data.thumbSize.value), 0, 1) * Math.max(0, data.size.value - container[axis].value), axis);
17552
+ if (offset < thumbStart || offset > thumbStart + data.thumbSize.value) {
17553
+ const percentage = between((offset - data.thumbSize.value / 2) / (container[axis + "Inner"].value - data.thumbSize.value), 0, 1);
17554
+ setScroll(isHorizontalRtl ? getHorizontalNativePosition(percentage * Math.max(0, data.size.value - container[axis].value)) : percentage * Math.max(0, data.size.value - container[axis].value), axis);
17555
+ }
17316
17556
  if (data.ref.value !== null) data.ref.value.dispatchEvent(new MouseEvent(evt.type, evt));
17317
17557
  }
17318
17558
  }
@@ -17328,6 +17568,14 @@
17328
17568
  function setScroll(offset, axis) {
17329
17569
  targetRef.value[dirProps[axis].scroll] = offset;
17330
17570
  }
17571
+ function getHorizontalLogicalPosition(position, rtl = proxy.$q.lang.rtl) {
17572
+ if (!rtl) return position;
17573
+ return rtlHasScrollBug ? Math.max(0, scroll.horizontal.size.value - container.horizontal.value) - position : -position;
17574
+ }
17575
+ function getHorizontalNativePosition(position, rtl = proxy.$q.lang.rtl) {
17576
+ if (!rtl) return position;
17577
+ return rtlHasScrollBug ? Math.max(0, scroll.horizontal.size.value - container.horizontal.value) - position : -position;
17578
+ }
17331
17579
  let mouseEventTimer = null;
17332
17580
  function onMouseenter() {
17333
17581
  if (mouseEventTimer !== null) clearTimeout(mouseEventTimer);
@@ -17344,8 +17592,8 @@
17344
17592
  hover.value = false;
17345
17593
  }
17346
17594
  let scrollPosition = null;
17347
- (0, vue.watch)(() => proxy.$q.lang.rtl, (rtl) => {
17348
- if (targetRef.value !== null) setHorizontalScrollPosition(targetRef.value, Math.abs(scroll.horizontal.position.value) * (rtl ? -1 : 1));
17595
+ (0, vue.watch)(() => proxy.$q.lang.rtl, (rtl, oldRtl) => {
17596
+ if (targetRef.value !== null) setHorizontalScrollPosition(targetRef.value, getHorizontalNativePosition(getHorizontalLogicalPosition(scroll.horizontal.position.value, oldRtl), rtl));
17349
17597
  });
17350
17598
  (0, vue.onDeactivated)(() => {
17351
17599
  scrollPosition = {
@@ -17375,7 +17623,8 @@
17375
17623
  }),
17376
17624
  setScrollPosition: localSetScrollPosition,
17377
17625
  setScrollPercentage(axis, percentage, duration) {
17378
- localSetScrollPosition(axis, percentage * (scroll[axis].size.value - container[axis].value) * (axis === "horizontal" && proxy.$q.lang.rtl ? -1 : 1), duration);
17626
+ const offset = percentage * (scroll[axis].size.value - container[axis].value);
17627
+ localSetScrollPosition(axis, axis === "horizontal" ? getHorizontalNativePosition(offset) : offset, duration);
17379
17628
  }
17380
17629
  });
17381
17630
  const store = {
@@ -18966,11 +19215,12 @@
18966
19215
  if (pan.scale === 1) {
18967
19216
  node.style.transform = `translate${pan.axis}(${pan.dir * 100}%)`;
18968
19217
  if (timer !== null) clearTimeout(timer);
19218
+ const showing = pan.showing;
18969
19219
  timer = setTimeout(() => {
18970
19220
  timer = null;
18971
- emit(pan.showing, { reset });
19221
+ emit(showing, { reset });
18972
19222
  emit("action", {
18973
- side: pan.showing,
19223
+ side: showing,
18974
19224
  reset
18975
19225
  });
18976
19226
  }, 230);
@@ -19627,6 +19877,9 @@
19627
19877
  });
19628
19878
  //#endregion
19629
19879
  //#region src/components/stepper/StepHeader.js
19880
+ function preventSpace$1(e) {
19881
+ if (e.keyCode === 32) stopAndPrevent(e);
19882
+ }
19630
19883
  var StepHeader_default = createComponent({
19631
19884
  name: "StepHeader",
19632
19885
  props: {
@@ -19688,13 +19941,19 @@
19688
19941
  if (!isActive.value) props.goToPanel(props.step.name);
19689
19942
  }
19690
19943
  function onKeyup(e) {
19691
- if (e.keyCode === 13 && !isActive.value) props.goToPanel(props.step.name);
19944
+ if ([13, 32].includes(e.keyCode)) {
19945
+ if (!isActive.value) props.goToPanel(props.step.name);
19946
+ stopAndPrevent(e);
19947
+ }
19692
19948
  }
19693
19949
  return () => {
19694
19950
  const data = { class: classes.value };
19695
19951
  if (headerNav.value) {
19696
19952
  data.onClick = onActivate;
19953
+ data.onKeydown = preventSpace$1;
19697
19954
  data.onKeyup = onKeyup;
19955
+ data.role = "button";
19956
+ data["aria-current"] = isActive.value ? "step" : void 0;
19698
19957
  Object.assign(data, isDisable.value ? {
19699
19958
  tabindex: -1,
19700
19959
  "aria-disabled": "true"
@@ -19877,6 +20136,13 @@
19877
20136
  const onClick = (evt) => {
19878
20137
  emit("click", evt);
19879
20138
  };
20139
+ const onKeyup = (evt, col) => {
20140
+ if (evt.key === "Enter" || evt.key === " ") {
20141
+ props.props.sort(col);
20142
+ onClick(evt);
20143
+ evt.preventDefault();
20144
+ }
20145
+ };
19880
20146
  return () => {
19881
20147
  if (props.props === void 0) return (0, vue.h)("th", {
19882
20148
  class: props.autoWidth ? "q-table--col-auto-width" : "",
@@ -19884,7 +20150,7 @@
19884
20150
  }, hSlot(slots.default));
19885
20151
  let col, child;
19886
20152
  const name = vm.vnode.key;
19887
- if (name) {
20153
+ if (name !== null) {
19888
20154
  col = props.props.colsMap[name];
19889
20155
  if (col === void 0) return;
19890
20156
  } else col = props.props.col;
@@ -19896,14 +20162,25 @@
19896
20162
  name: $q.iconSet.table.arrowUp
19897
20163
  }));
19898
20164
  } else child = hSlot(slots.default);
19899
- return (0, vue.h)("th", {
20165
+ const data = {
19900
20166
  class: col.__thClass + (props.autoWidth ? " q-table--col-auto-width" : ""),
19901
20167
  style: col.headerStyle,
19902
20168
  onClick: (evt) => {
19903
20169
  if (col.sortable) props.props.sort(col);
19904
20170
  onClick(evt);
19905
20171
  }
19906
- }, child);
20172
+ };
20173
+ if (col.sortable) {
20174
+ data.tabindex = 0;
20175
+ data["aria-sort"] = col.__ariaSort;
20176
+ data.onKeydown = (evt) => {
20177
+ if (evt.key === " ") evt.preventDefault();
20178
+ };
20179
+ data.onKeyup = (evt) => {
20180
+ onKeyup(evt, col);
20181
+ };
20182
+ }
20183
+ return (0, vue.h)("th", data, child);
19907
20184
  };
19908
20185
  }
19909
20186
  });
@@ -20161,8 +20438,8 @@
20161
20438
  function requestServerInteraction(prop = {}) {
20162
20439
  (0, vue.nextTick)(() => {
20163
20440
  emit("request", {
20164
- pagination: prop.pagination || computedPagination.value,
20165
- filter: prop.filter || props.filter,
20441
+ pagination: prop.pagination === void 0 ? computedPagination.value : prop.pagination,
20442
+ filter: prop.filter === void 0 ? props.filter : prop.filter,
20166
20443
  getCellValue
20167
20444
  });
20168
20445
  });
@@ -20265,21 +20542,15 @@
20265
20542
  };
20266
20543
  const useTableRowSelectionEmits = ["update:selected", "selection"];
20267
20544
  function useTableRowSelection(props, emit, computedRows, getRowKey) {
20268
- const selectedKeys = (0, vue.computed)(() => {
20269
- const keys = {};
20270
- props.selected.map(getRowKey.value).forEach((key) => {
20271
- keys[key] = true;
20272
- });
20273
- return keys;
20274
- });
20545
+ const selectedKeys = (0, vue.computed)(() => new Set(props.selected.map(getRowKey.value)));
20275
20546
  const hasSelectionMode = (0, vue.computed)(() => props.selection !== "none");
20276
20547
  const singleSelection = (0, vue.computed)(() => props.selection === "single");
20277
20548
  const multipleSelection = (0, vue.computed)(() => props.selection === "multiple");
20278
- const allRowsSelected = (0, vue.computed)(() => computedRows.value.length !== 0 && computedRows.value.every((row) => selectedKeys.value[getRowKey.value(row)]));
20279
- const someRowsSelected = (0, vue.computed)(() => !allRowsSelected.value && computedRows.value.some((row) => selectedKeys.value[getRowKey.value(row)]));
20549
+ const allRowsSelected = (0, vue.computed)(() => computedRows.value.length !== 0 && computedRows.value.every((row) => selectedKeys.value.has(getRowKey.value(row))));
20550
+ const someRowsSelected = (0, vue.computed)(() => !allRowsSelected.value && computedRows.value.some((row) => selectedKeys.value.has(getRowKey.value(row))));
20280
20551
  const rowsSelectedNumber = (0, vue.computed)(() => props.selected.length);
20281
20552
  function isRowSelected(key) {
20282
- return selectedKeys.value[key] === true;
20553
+ return selectedKeys.value.has(key);
20283
20554
  }
20284
20555
  function clearSelection() {
20285
20556
  emit("update:selected", []);
@@ -20367,6 +20638,7 @@
20367
20638
  ...col,
20368
20639
  align,
20369
20640
  __iconClass: `q-table__sort-icon q-table__sort-icon--${align}`,
20641
+ __ariaSort: col.sortable === true ? col.name === sortBy ? descending ? "descending" : "ascending" : "none" : void 0,
20370
20642
  __thClass: alignClass + (col.headerClasses !== void 0 ? " " + col.headerClasses : "") + (col.sortable ? " sortable" : "") + (col.name === sortBy ? ` sorted ${descending ? "sort-desc" : ""}` : ""),
20371
20643
  __tdStyle: col.style !== void 0 ? typeof col.style !== "function" ? () => col.style : col.style : () => null,
20372
20644
  __tdClass: col.classes !== void 0 ? typeof col.classes !== "function" ? () => alignClass + " " + col.classes : (row) => alignClass + " " + col.classes(row) : () => alignClass
@@ -20377,7 +20649,7 @@
20377
20649
  colList,
20378
20650
  computedCols,
20379
20651
  computedColsMap: (0, vue.computed)(() => {
20380
- const names = {};
20652
+ const names = Object.create(null);
20381
20653
  computedCols.value.forEach((col) => {
20382
20654
  names[col.name] = col;
20383
20655
  });
@@ -20530,9 +20802,15 @@
20530
20802
  const cardDefaultClass = (0, vue.computed)(() => " q-table__card" + (isDark.value ? " q-table__card--dark q-dark" : "") + (props.square ? " q-table--square" : "") + (props.flat ? " q-table--flat" : "") + (props.bordered ? " q-table--bordered" : ""));
20531
20803
  const containerClass = (0, vue.computed)(() => `q-table__container q-table--${props.separator}-separator column no-wrap` + (props.grid ? " q-table--grid" : cardDefaultClass.value) + (isDark.value ? " q-table--dark" : "") + (props.dense ? " q-table--dense" : "") + (props.wrapCells ? "" : " q-table--no-wrap") + (inFullscreen.value ? " fullscreen scroll" : ""));
20532
20804
  const rootContainerClass = (0, vue.computed)(() => containerClass.value + (props.loading ? " q-table--loading" : ""));
20533
- (0, vue.watch)(() => props.tableStyle + props.tableClass + props.tableHeaderStyle + props.tableHeaderClass + containerClass.value, () => {
20805
+ (0, vue.watch)([
20806
+ () => props.tableStyle,
20807
+ () => props.tableClass,
20808
+ () => props.tableHeaderStyle,
20809
+ () => props.tableHeaderClass,
20810
+ containerClass
20811
+ ], () => {
20534
20812
  if (hasVirtScroll.value) virtScrollRef.value?.reset();
20535
- });
20813
+ }, { deep: true });
20536
20814
  const { innerPagination, computedPagination, isServerSide, requestServerInteraction, setPagination } = useTablePaginationState(vm, getCellValue);
20537
20815
  const { computedFilterMethod } = useTableFilter(props, setPagination);
20538
20816
  const { isRowExpanded, setExpanded, updateExpanded } = useTableRowExpand(props, emit);
@@ -20956,10 +21234,10 @@
20956
21234
  if (props.onRowClick !== void 0 || props.onRowDblclick !== void 0 || props.onRowContextmenu !== void 0) {
20957
21235
  data.class[0] += " cursor-pointer";
20958
21236
  if (props.onRowClick !== void 0) data.onClick = (evt) => {
20959
- emit("RowClick", evt, scope.row, scope.pageIndex);
21237
+ emit("rowClick", evt, scope.row, scope.pageIndex);
20960
21238
  };
20961
21239
  if (props.onRowDblclick !== void 0) data.onDblclick = (evt) => {
20962
- emit("RowDblclick", evt, scope.row, scope.pageIndex);
21240
+ emit("rowDblclick", evt, scope.row, scope.pageIndex);
20963
21241
  };
20964
21242
  if (props.onRowContextmenu !== void 0) data.onContextmenu = (evt) => {
20965
21243
  emit("rowContextmenu", evt, scope.row, scope.pageIndex);
@@ -21096,6 +21374,9 @@
21096
21374
  millisecond: d.getMilliseconds()
21097
21375
  };
21098
21376
  }
21377
+ function preventSpace(e) {
21378
+ if (e.keyCode === 32) stopAndPrevent(e);
21379
+ }
21099
21380
  function getWheelDist(a, b, threshold) {
21100
21381
  const diff = Math.abs(a - b);
21101
21382
  return Math.min(diff, threshold - diff);
@@ -21336,10 +21617,16 @@
21336
21617
  }
21337
21618
  };
21338
21619
  function setAmOnKey(e) {
21339
- if (e.keyCode === 13) setAm();
21620
+ if ([13, 32].includes(e.keyCode)) {
21621
+ setAm();
21622
+ stopAndPrevent(e);
21623
+ }
21340
21624
  }
21341
21625
  function setPmOnKey(e) {
21342
- if (e.keyCode === 13) setPm();
21626
+ if ([13, 32].includes(e.keyCode)) {
21627
+ setPm();
21628
+ stopAndPrevent(e);
21629
+ }
21343
21630
  }
21344
21631
  function onClick(evt) {
21345
21632
  if (!shouldAbortInteraction()) {
@@ -21351,8 +21638,10 @@
21351
21638
  if (!shouldAbortInteraction()) updateClock(evt, getClockRect());
21352
21639
  }
21353
21640
  function onKeyupHour(e) {
21354
- if (e.keyCode === 13) view.value = "hour";
21355
- else if ([37, 39].includes(e.keyCode)) {
21641
+ if ([13, 32].includes(e.keyCode)) {
21642
+ view.value = "hour";
21643
+ stopAndPrevent(e);
21644
+ } else if ([37, 39].includes(e.keyCode)) {
21356
21645
  const payload = e.keyCode === 37 ? -1 : 1;
21357
21646
  if (validHours.value !== null) {
21358
21647
  const values = computedFormat24h.value ? validHours.value.values : validHours.value[isAM.value ? "am" : "pm"].values;
@@ -21366,8 +21655,10 @@
21366
21655
  }
21367
21656
  }
21368
21657
  function onKeyupMinute(e) {
21369
- if (e.keyCode === 13) view.value = "minute";
21370
- else if ([37, 39].includes(e.keyCode)) {
21658
+ if ([13, 32].includes(e.keyCode)) {
21659
+ view.value = "minute";
21660
+ stopAndPrevent(e);
21661
+ } else if ([37, 39].includes(e.keyCode)) {
21371
21662
  const payload = e.keyCode === 37 ? -1 : 1;
21372
21663
  if (validMinutes.value !== null) {
21373
21664
  const values = validMinutes.value.values;
@@ -21378,13 +21669,15 @@
21378
21669
  }
21379
21670
  }
21380
21671
  function onKeyupSecond(e) {
21381
- if (e.keyCode === 13) view.value = "second";
21382
- else if ([37, 39].includes(e.keyCode)) {
21672
+ if ([13, 32].includes(e.keyCode)) {
21673
+ view.value = "second";
21674
+ stopAndPrevent(e);
21675
+ } else if ([37, 39].includes(e.keyCode)) {
21383
21676
  const payload = e.keyCode === 37 ? -1 : 1;
21384
21677
  if (validSeconds.value !== null) {
21385
21678
  const values = validSeconds.value.values;
21386
21679
  if (values.length === 0) return;
21387
- if (innerModel.value.seconds === null) setSecond(values[0]);
21680
+ if (innerModel.value.second === null) setSecond(values[0]);
21388
21681
  else setSecond(values[(values.length + values.indexOf(innerModel.value.second) + payload) % values.length]);
21389
21682
  } else setSecond((60 + (innerModel.value.second === null ? -payload : innerModel.value.second) + payload) % 60);
21390
21683
  }
@@ -21468,13 +21761,19 @@
21468
21761
  (0, vue.h)("div", {
21469
21762
  class: "q-time__link " + (view.value === "hour" ? "q-time__link--active" : "cursor-pointer"),
21470
21763
  tabindex: tabindex.value,
21764
+ role: "button",
21765
+ "aria-pressed": view.value === "hour" ? "true" : "false",
21471
21766
  onClick: setView.hour,
21767
+ onKeydown: preventSpace,
21472
21768
  onKeyup: onKeyupHour
21473
21769
  }, stringModel.value.hour),
21474
21770
  (0, vue.h)("div", ":"),
21475
21771
  (0, vue.h)("div", minLink.value ? {
21476
21772
  class: "q-time__link " + (view.value === "minute" ? "q-time__link--active" : "cursor-pointer"),
21477
21773
  tabindex: tabindex.value,
21774
+ role: "button",
21775
+ "aria-pressed": view.value === "minute" ? "true" : "false",
21776
+ onKeydown: preventSpace,
21478
21777
  onKeyup: onKeyupMinute,
21479
21778
  onClick: setView.minute
21480
21779
  } : { class: "q-time__link" }, stringModel.value.minute)
@@ -21482,6 +21781,9 @@
21482
21781
  if (props.withSeconds) label.push((0, vue.h)("div", ":"), (0, vue.h)("div", secLink.value ? {
21483
21782
  class: "q-time__link " + (view.value === "second" ? "q-time__link--active" : "cursor-pointer"),
21484
21783
  tabindex: tabindex.value,
21784
+ role: "button",
21785
+ "aria-pressed": view.value === "second" ? "true" : "false",
21786
+ onKeydown: preventSpace,
21485
21787
  onKeyup: onKeyupSecond,
21486
21788
  onClick: setView.second
21487
21789
  } : { class: "q-time__link" }, stringModel.value.second));
@@ -21492,12 +21794,18 @@
21492
21794
  if (!computedFormat24h.value) child.push((0, vue.h)("div", { class: "q-time__header-ampm column items-between no-wrap" }, [(0, vue.h)("div", {
21493
21795
  class: "q-time__link " + (isAM.value ? "q-time__link--active" : "cursor-pointer"),
21494
21796
  tabindex: tabindex.value,
21797
+ role: "button",
21798
+ "aria-pressed": isAM.value ? "true" : "false",
21495
21799
  onClick: setAm,
21800
+ onKeydown: preventSpace,
21496
21801
  onKeyup: setAmOnKey
21497
21802
  }, "AM"), (0, vue.h)("div", {
21498
21803
  class: "q-time__link " + (isAM.value ? "cursor-pointer" : "q-time__link--active"),
21499
21804
  tabindex: tabindex.value,
21805
+ role: "button",
21806
+ "aria-pressed": isAM.value ? "false" : "true",
21500
21807
  onClick: setPm,
21808
+ onKeydown: preventSpace,
21501
21809
  onKeyup: setPmOnKey
21502
21810
  }, "PM")]));
21503
21811
  return (0, vue.h)("div", { class: "q-time__header flex flex-center no-wrap " + headerClass.value }, child);
@@ -21739,9 +22047,11 @@
21739
22047
  const lazy = (0, vue.ref)({});
21740
22048
  const innerTicked = (0, vue.ref)(props.ticked || []);
21741
22049
  const innerExpanded = (0, vue.ref)(props.expanded || []);
21742
- let blurTargets = {};
22050
+ const focusedKey = (0, vue.ref)(null);
22051
+ let blurTargets = {}, headerTargets = {};
21743
22052
  (0, vue.onBeforeUpdate)(() => {
21744
22053
  blurTargets = {};
22054
+ headerTargets = {};
21745
22055
  });
21746
22056
  const classes = (0, vue.computed)(() => `q-tree q-tree--${props.dense ? "dense" : "standard"}` + (props.noConnectors ? " q-tree--no-connectors" : "") + (isDark.value ? " q-tree--dark" : "") + (props.color !== void 0 ? ` text-${props.color}` : ""));
21747
22057
  const hasSelection = (0, vue.computed)(() => props.selected !== void 0);
@@ -21814,6 +22124,25 @@
21814
22124
  props.nodes.forEach((node) => travel(node, null));
21815
22125
  return acc;
21816
22126
  });
22127
+ const focusableKeys = (0, vue.computed)(() => {
22128
+ const acc = [];
22129
+ function travel(nodes) {
22130
+ nodes.forEach((node) => {
22131
+ const localMeta = meta.value[node[props.nodeKey]];
22132
+ if (props.filter && localMeta.matchesFilter !== true) return;
22133
+ if (localMeta.link === true) acc.push(localMeta.key);
22134
+ if (localMeta.expanded === true && Array.isArray(node[props.childrenKey])) travel(node[props.childrenKey]);
22135
+ });
22136
+ }
22137
+ travel(props.nodes);
22138
+ return acc;
22139
+ });
22140
+ const tabKey = (0, vue.computed)(() => {
22141
+ const keys = focusableKeys.value;
22142
+ if (keys.includes(focusedKey.value)) return focusedKey.value;
22143
+ const selected = keys.find((key) => meta.value[key].selected === true);
22144
+ return selected !== void 0 ? selected : keys[0];
22145
+ });
21817
22146
  (0, vue.watch)(() => props.ticked, (val) => {
21818
22147
  innerTicked.value = val;
21819
22148
  });
@@ -21944,16 +22273,25 @@
21944
22273
  class: `q-tree__node relative-position q-tree__node--${isParent ? "parent" : "child"}`
21945
22274
  }, [(0, vue.h)("div", {
21946
22275
  class: "q-tree__node-header relative-position row no-wrap items-center" + (m.link === true ? " q-tree__node--link q-hoverable q-focusable" : "") + (m.selected === true ? " q-tree__node--selected" : "") + (m.disabled === true ? " q-tree__node--disabled" : ""),
21947
- tabindex: m.link === true ? 0 : -1,
21948
- ariaExpanded: children.length !== 0 ? m.expanded : null,
22276
+ ref: (el) => {
22277
+ headerTargets[m.key] = el;
22278
+ },
22279
+ tabindex: m.link === true && m.key === tabKey.value ? 0 : -1,
22280
+ "aria-expanded": isParent ? m.expanded ? "true" : "false" : null,
22281
+ "aria-selected": m.selectable ? m.selected ? "true" : "false" : null,
22282
+ "aria-disabled": m.disabled === true ? "true" : null,
21949
22283
  role: "treeitem",
22284
+ onFocus() {
22285
+ if (m.link === true) focusedKey.value = m.key;
22286
+ },
21950
22287
  onClick: (e) => {
21951
22288
  onClick(node, m, e);
21952
22289
  },
21953
- onKeypress(e) {
22290
+ onKeydown(e) {
21954
22291
  if (shouldIgnoreKey(e) !== true) {
21955
22292
  if (e.keyCode === 13) onClick(node, m, e, true);
21956
22293
  else if (e.keyCode === 32) onExpandClick(node, m, e, true);
22294
+ else if (onNavigationKey(m, e.keyCode)) stopAndPrevent(e);
21957
22295
  }
21958
22296
  }
21959
22297
  }, [
@@ -22009,7 +22347,59 @@
22009
22347
  function blur(key) {
22010
22348
  blurTargets[key]?.focus();
22011
22349
  }
22350
+ function focusNode(key) {
22351
+ if (key !== void 0) {
22352
+ focusedKey.value = key;
22353
+ headerTargets[key]?.focus();
22354
+ }
22355
+ }
22356
+ function getFirstFocusableChild(children) {
22357
+ for (const child of children) {
22358
+ if (props.filter && child.matchesFilter !== true) continue;
22359
+ if (child.link === true) return child.key;
22360
+ if (child.expanded === true) {
22361
+ const key = getFirstFocusableChild(child.children);
22362
+ if (key !== void 0) return key;
22363
+ }
22364
+ }
22365
+ }
22366
+ function onNavigationKey(localMeta, keyCode) {
22367
+ const keys = focusableKeys.value, index = keys.indexOf(localMeta.key);
22368
+ if (keyCode === 36) {
22369
+ focusNode(keys[0]);
22370
+ return true;
22371
+ }
22372
+ if (keyCode === 35) {
22373
+ focusNode(keys.at(-1));
22374
+ return true;
22375
+ }
22376
+ if (keyCode === 38) {
22377
+ focusNode(keys[index - 1]);
22378
+ return true;
22379
+ }
22380
+ if (keyCode === 40) {
22381
+ focusNode(keys[index + 1]);
22382
+ return true;
22383
+ }
22384
+ if (keyCode === 39) {
22385
+ if (localMeta.isParent !== true && !localMeta.lazy) return true;
22386
+ if (localMeta.expanded !== true) setExpanded(localMeta.key, true);
22387
+ else focusNode(getFirstFocusableChild(localMeta.children));
22388
+ return true;
22389
+ }
22390
+ if (keyCode === 37) {
22391
+ if (localMeta.expanded === true) setExpanded(localMeta.key, false);
22392
+ else {
22393
+ let parent = localMeta.parent;
22394
+ while (parent !== null && parent.link !== true) parent = parent.parent;
22395
+ focusNode(parent?.key);
22396
+ }
22397
+ return true;
22398
+ }
22399
+ return false;
22400
+ }
22012
22401
  function onClick(node, localMeta, e, keyboard) {
22402
+ if (localMeta.link === true) focusedKey.value = localMeta.key;
22013
22403
  if (keyboard !== true && localMeta.selectable !== false) blur(localMeta.key);
22014
22404
  if (hasSelection.value && localMeta.selectable) {
22015
22405
  if (!props.noSelectionUnset) emit("update:selected", localMeta.key !== props.selected ? localMeta.key : null);
@@ -22018,6 +22408,7 @@
22018
22408
  if (typeof node.handler === "function") node.handler(node);
22019
22409
  }
22020
22410
  function onExpandClick(node, localMeta, e, keyboard) {
22411
+ if (localMeta.link === true) focusedKey.value = localMeta.key;
22021
22412
  if (e !== void 0) stopAndPrevent(e);
22022
22413
  if (keyboard !== true && localMeta.selectable !== false) blur(localMeta.key);
22023
22414
  setExpanded(localMeta.key, !localMeta.expanded, node, localMeta);
@@ -22108,7 +22499,7 @@
22108
22499
  return;
22109
22500
  }
22110
22501
  file.__uploaded = status === "uploaded" ? file.size : uploadedSize;
22111
- file.__progress = status === "uploaded" ? 1 : Math.min(.9999, file.__uploaded / file.size);
22502
+ file.__progress = status === "uploaded" ? 1 : file.size === 0 ? 0 : Math.min(.9999, file.__uploaded / file.size);
22112
22503
  file.__progressLabel = getProgressLabel(file.__progress);
22113
22504
  proxy.$forceUpdate();
22114
22505
  }
@@ -22165,7 +22556,9 @@
22165
22556
  }
22166
22557
  }
22167
22558
  function removeUploadedFiles() {
22168
- if (!props.disable) batchRemoveFiles(["uploaded"], () => {
22559
+ if (!props.disable) batchRemoveFiles(["uploaded"], ({ size }) => {
22560
+ state.uploadedSize.value -= size;
22561
+ uploadSize.value -= size;
22169
22562
  state.uploadedFiles.value = [];
22170
22563
  });
22171
22564
  }
@@ -22196,8 +22589,12 @@
22196
22589
  }
22197
22590
  function removeFile(file) {
22198
22591
  if (props.disable) return;
22199
- if (file.__status === "uploaded") state.uploadedFiles.value = state.uploadedFiles.value.filter((f) => f.__key !== file.__key);
22200
- else if (file.__status === "uploading") file.__abort();
22592
+ const isUploading = file.__status === "uploading";
22593
+ if (file.__status === "uploaded") {
22594
+ state.uploadedSize.value -= file.size;
22595
+ uploadSize.value -= file.size;
22596
+ state.uploadedFiles.value = state.uploadedFiles.value.filter((f) => f.__key !== file.__key);
22597
+ } else if (isUploading) uploadSize.value -= file.size;
22201
22598
  else uploadSize.value -= file.size;
22202
22599
  state.files.value = state.files.value.filter((f) => {
22203
22600
  if (f.__key !== file.__key) return true;
@@ -22205,6 +22602,7 @@
22205
22602
  return false;
22206
22603
  });
22207
22604
  state.queuedFiles.value = state.queuedFiles.value.filter((f) => f.__key !== file.__key);
22605
+ if (isUploading) file.__abort();
22208
22606
  emit("removed", [file]);
22209
22607
  }
22210
22608
  function revokeImgURLs() {
@@ -22429,6 +22827,7 @@
22429
22827
  const xhrs = (0, vue.ref)([]);
22430
22828
  const promises = (0, vue.ref)([]);
22431
22829
  const workingThreads = (0, vue.ref)(0);
22830
+ const abortedPromises = /* @__PURE__ */ new WeakSet();
22432
22831
  const xhrProps = (0, vue.computed)(() => ({
22433
22832
  url: getFn(props.url),
22434
22833
  method: getFn(props.method),
@@ -22441,12 +22840,14 @@
22441
22840
  }));
22442
22841
  const isUploading = (0, vue.computed)(() => workingThreads.value > 0);
22443
22842
  const isBusy = (0, vue.computed)(() => promises.value.length !== 0);
22444
- let abortPromises;
22843
+ const getLiveFiles = (files) => files.filter((file) => helpers.files.value.includes(file));
22445
22844
  function abort() {
22446
22845
  xhrs.value.forEach((x) => {
22447
22846
  x.abort();
22448
22847
  });
22449
- if (promises.value.length !== 0) abortPromises = true;
22848
+ promises.value.forEach((promise) => {
22849
+ abortedPromises.add(promise);
22850
+ });
22450
22851
  }
22451
22852
  function upload() {
22452
22853
  const queue = [...helpers.queuedFiles.value];
@@ -22458,36 +22859,57 @@
22458
22859
  }
22459
22860
  function runFactory(files) {
22460
22861
  workingThreads.value++;
22862
+ const failed = (err, promise) => {
22863
+ if (helpers.isAlive()) {
22864
+ if (promise !== void 0) promises.value = promises.value.filter((p) => p !== promise);
22865
+ const liveFiles = getLiveFiles(files);
22866
+ if (liveFiles.length !== 0) {
22867
+ helpers.queuedFiles.value.push(...liveFiles);
22868
+ liveFiles.forEach((f) => {
22869
+ helpers.updateFileStatus(f, "failed");
22870
+ });
22871
+ emit("factoryFailed", err, liveFiles);
22872
+ }
22873
+ workingThreads.value--;
22874
+ }
22875
+ };
22461
22876
  if (typeof props.factory !== "function") {
22462
- performUpload(files, {});
22877
+ startUpload({});
22463
22878
  return;
22464
22879
  }
22465
- const res = props.factory(files);
22466
- if (!res) {
22467
- emit("factoryFailed", /* @__PURE__ */ new Error("QUploader: factory() does not return properly"), files);
22468
- workingThreads.value--;
22469
- } else if (typeof res.catch === "function" && typeof res.then === "function") {
22880
+ let res;
22881
+ try {
22882
+ res = props.factory(files);
22883
+ } catch (err) {
22884
+ failed(err);
22885
+ return;
22886
+ }
22887
+ if (Object(res) !== res) failed(/* @__PURE__ */ new Error("QUploader: factory() does not return properly"));
22888
+ else if (typeof res.catch === "function" && typeof res.then === "function") {
22470
22889
  promises.value.push(res);
22471
- const failed = (err) => {
22472
- if (helpers.isAlive()) {
22473
- promises.value = promises.value.filter((p) => p !== res);
22474
- if (promises.value.length === 0) abortPromises = false;
22475
- helpers.queuedFiles.value.push(...files);
22476
- files.forEach((f) => {
22477
- helpers.updateFileStatus(f, "failed");
22478
- });
22479
- emit("factoryFailed", err, files);
22480
- workingThreads.value--;
22481
- }
22482
- };
22483
22890
  res.then((factory) => {
22484
- if (abortPromises) failed(/* @__PURE__ */ new Error("Aborted"));
22891
+ if (abortedPromises.has(res)) failed(/* @__PURE__ */ new Error("Aborted"), res);
22892
+ else if (Object(factory) !== factory) failed(/* @__PURE__ */ new Error("QUploader: factory() does not return properly"), res);
22485
22893
  else if (helpers.isAlive()) {
22486
22894
  promises.value = promises.value.filter((p) => p !== res);
22487
- performUpload(files, factory);
22895
+ startUpload(factory);
22488
22896
  }
22489
- }).catch(failed);
22490
- } else performUpload(files, res || {});
22897
+ }).catch((err) => {
22898
+ failed(err, res);
22899
+ });
22900
+ } else startUpload(res);
22901
+ function startUpload(factory) {
22902
+ const liveFiles = getLiveFiles(files);
22903
+ if (liveFiles.length === 0) {
22904
+ workingThreads.value--;
22905
+ return;
22906
+ }
22907
+ try {
22908
+ performUpload(liveFiles, factory);
22909
+ } catch (err) {
22910
+ failed(err);
22911
+ }
22912
+ }
22491
22913
  }
22492
22914
  function performUpload(files, factory) {
22493
22915
  const form = new FormData(), xhr = new XMLHttpRequest();
@@ -22495,6 +22917,10 @@
22495
22917
  const url = getProp("url", files);
22496
22918
  if (!url) {
22497
22919
  console.error("q-uploader: invalid or no URL specified");
22920
+ helpers.queuedFiles.value.push(...files);
22921
+ files.forEach((f) => {
22922
+ helpers.updateFileStatus(f, "failed");
22923
+ });
22498
22924
  workingThreads.value--;
22499
22925
  return;
22500
22926
  }
@@ -22511,7 +22937,7 @@
22511
22937
  let size = localUploadedSize - uploadIndexSize;
22512
22938
  for (let i = uploadIndex; size > 0 && i < files.length; i++) {
22513
22939
  const file = files[i];
22514
- if (size > file.size) {
22940
+ if (size >= file.size) {
22515
22941
  size -= file.size;
22516
22942
  uploadIndex++;
22517
22943
  uploadIndexSize += file.size;
@@ -22525,25 +22951,33 @@
22525
22951
  xhr.addEventListener("readystatechange", () => {
22526
22952
  if (xhr.readyState < 4) return;
22527
22953
  if (xhr.status && xhr.status < 400) {
22528
- helpers.uploadedFiles.value.push(...files);
22529
- files.forEach((f) => {
22530
- helpers.updateFileStatus(f, "uploaded");
22531
- });
22532
- emit("uploaded", {
22533
- files,
22534
- xhr
22535
- });
22954
+ const liveFiles = getLiveFiles(files);
22955
+ const liveUploadSize = liveFiles.reduce((total, file) => total + file.size, 0);
22956
+ helpers.uploadedSize.value += liveUploadSize - localUploadedSize;
22957
+ if (liveFiles.length !== 0) {
22958
+ helpers.uploadedFiles.value.push(...liveFiles);
22959
+ liveFiles.forEach((f) => {
22960
+ helpers.updateFileStatus(f, "uploaded");
22961
+ });
22962
+ emit("uploaded", {
22963
+ files: liveFiles,
22964
+ xhr
22965
+ });
22966
+ }
22536
22967
  } else {
22537
22968
  aborted = true;
22538
22969
  helpers.uploadedSize.value -= localUploadedSize;
22539
- helpers.queuedFiles.value.push(...files);
22540
- files.forEach((f) => {
22541
- helpers.updateFileStatus(f, "failed");
22542
- });
22543
- emit("failed", {
22544
- files,
22545
- xhr
22546
- });
22970
+ const liveFiles = getLiveFiles(files);
22971
+ if (liveFiles.length !== 0) {
22972
+ helpers.queuedFiles.value.push(...liveFiles);
22973
+ liveFiles.forEach((f) => {
22974
+ helpers.updateFileStatus(f, "failed");
22975
+ });
22976
+ emit("failed", {
22977
+ files: liveFiles,
22978
+ xhr
22979
+ });
22980
+ }
22547
22981
  }
22548
22982
  workingThreads.value--;
22549
22983
  xhrs.value = xhrs.value.filter((x) => x !== xhr);
@@ -23945,7 +24379,7 @@
23945
24379
  if (keyRegex.test(key)) {
23946
24380
  const parsedKey = Number.parseInt(key, 10);
23947
24381
  const keyCode = Number.isNaN(parsedKey) ? keyCodes[key.toLowerCase()] : parsedKey;
23948
- if (keyCode >= 0) acc.push(keyCode);
24382
+ if (keyCode !== void 0) acc.push(...[keyCode].flat());
23949
24383
  }
23950
24384
  return acc;
23951
24385
  }, []);
@@ -24526,7 +24960,11 @@
24526
24960
  function read(string) {
24527
24961
  if (string === "") return string;
24528
24962
  if (string.indexOf("\"") === 0) string = string.slice(1, -1).replaceAll(String.raw`\"`, "\"").replaceAll(String.raw`\\`, "\\");
24529
- string = decodeURIComponent(string.replaceAll("+", " "));
24963
+ try {
24964
+ string = decodeURIComponent(string.replaceAll("+", " "));
24965
+ } catch {
24966
+ return;
24967
+ }
24530
24968
  try {
24531
24969
  const parsed = JSON.parse(string);
24532
24970
  if (parsed === Object(parsed) || Array.isArray(parsed)) string = parsed;
@@ -24550,15 +24988,19 @@
24550
24988
  const unit = match[2];
24551
24989
  totalSeconds += value * numberUnitMultiplierMap[unit];
24552
24990
  }
24553
- return hasMatch ? totalSeconds : void 0;
24991
+ if (hasMatch) return totalSeconds;
24992
+ const timestamp = Date.parse(str);
24993
+ return Number.isNaN(timestamp) ? void 0 : Math.round((timestamp - Date.now()) / 1e3);
24554
24994
  }
24555
24995
  function set(key, val, opts = {}, ssr) {
24556
24996
  let maxAge;
24557
24997
  let isDeletion = false;
24558
24998
  if (opts.expires !== void 0) {
24559
24999
  if (Number.isFinite(opts.expires)) maxAge = Math.round(opts.expires * 86400);
24560
- else if (opts.expires instanceof Date) maxAge = Math.round((opts.expires.getTime() - Date.now()) / 1e3);
24561
- else if (typeof opts.expires === "string") maxAge = parseExpireToSeconds(opts.expires);
25000
+ else if (opts.expires instanceof Date) {
25001
+ const timestamp = opts.expires.getTime();
25002
+ if (Number.isFinite(timestamp)) maxAge = Math.round((timestamp - Date.now()) / 1e3);
25003
+ } else if (typeof opts.expires === "string") maxAge = parseExpireToSeconds(opts.expires);
24562
25004
  if (maxAge !== void 0) isDeletion = maxAge <= 0;
24563
25005
  }
24564
25006
  const keyValue = `${encodeURIComponent(key)}=${stringifyCookieValue(val)}`;
@@ -24578,8 +25020,8 @@
24578
25020
  ssr.res.setHeader("Set-Cookie", ssr.req.qCookies);
24579
25021
  let all = ssr.req.headers.cookie || "";
24580
25022
  if (maxAge !== void 0 && isDeletion) {
24581
- const localVal = get(key, ssr);
24582
- if (localVal !== void 0) all = all.replace(`${key}=${localVal}; `, "").replace(`; ${key}=${localVal}`, "").replace(`${key}=${localVal}`, "");
25023
+ const encodedKey = encodeURIComponent(key);
25024
+ all = all.split("; ").filter((entry) => entry.split("=", 1)[0] !== encodedKey).join("; ");
24583
25025
  } else all = all ? `${keyValue}; ${all}` : keyValue;
24584
25026
  ssr.req.headers.cookie = all;
24585
25027
  } else document.cookie = cookie;
@@ -24589,11 +25031,15 @@
24589
25031
  let result = key ? null : {}, i = 0, parts, name, cookie;
24590
25032
  for (; i < l; i++) {
24591
25033
  parts = cookies[i].split("=");
24592
- name = decodeURIComponent(parts.shift());
25034
+ try {
25035
+ name = decodeURIComponent(parts.shift());
25036
+ } catch {
25037
+ continue;
25038
+ }
24593
25039
  cookie = parts.join("=");
24594
25040
  if (!key) result[name] = cookie;
24595
25041
  else if (key === name) {
24596
- result = read(cookie);
25042
+ result = read(cookie) ?? null;
24597
25043
  break;
24598
25044
  }
24599
25045
  }
@@ -24989,6 +25435,7 @@
24989
25435
  //#region src/plugins/meta/Meta.js
24990
25436
  let updateId = null;
24991
25437
  let currentClientMeta;
25438
+ String.raw`\u003C`, String.raw`\u003E`, String.raw`\u0026`, String.raw`\u2028`, String.raw`\u2029`;
24992
25439
  const clientList = [];
24993
25440
  function normalize(meta) {
24994
25441
  if (meta.title) {
@@ -25983,6 +26430,7 @@
25983
26430
  //#endregion
25984
26431
  //#region src/composables.js
25985
26432
  var composables_exports = /* @__PURE__ */ __exportAll({
26433
+ useAnimationFrame: () => useAnimationFrame,
25986
26434
  useDialogPluginComponent: () => useDialogPluginComponent,
25987
26435
  useFormChild: () => useFormChild,
25988
26436
  useHydration: () => useHydration,
@@ -26002,7 +26450,7 @@
26002
26450
  */
26003
26451
  if (window.Vue === void 0) console.error("[ Quasar ] Vue is required to run. Please add a script tag for it before loading Quasar.");
26004
26452
  window.Quasar = {
26005
- version: "2.21.4",
26453
+ version: "2.23.0",
26006
26454
  install(app, opts) {
26007
26455
  install_quasar_default(app, {
26008
26456
  components: components_exports,