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.
- package/README.md +1 -1
- package/dist/api/Mutation.json +1 -1
- package/dist/api/QLinearProgress.json +1 -1
- package/dist/api/QUploader.json +1 -1
- package/dist/icon-set/bootstrap-icons.umd.prod.js +1 -1
- package/dist/icon-set/eva-icons.umd.prod.js +1 -1
- package/dist/icon-set/fontawesome-v5-pro.umd.prod.js +1 -1
- package/dist/icon-set/fontawesome-v5.umd.prod.js +1 -1
- package/dist/icon-set/fontawesome-v6-pro.umd.prod.js +1 -1
- package/dist/icon-set/fontawesome-v6.umd.prod.js +1 -1
- package/dist/icon-set/fontawesome-v7-pro.umd.prod.js +1 -1
- package/dist/icon-set/fontawesome-v7.umd.prod.js +1 -1
- package/dist/icon-set/ionicons-v4.umd.prod.js +1 -1
- package/dist/icon-set/line-awesome.umd.prod.js +1 -1
- package/dist/icon-set/material-icons-outlined.umd.prod.js +1 -1
- package/dist/icon-set/material-icons-round.umd.prod.js +1 -1
- package/dist/icon-set/material-icons-sharp.umd.prod.js +1 -1
- package/dist/icon-set/material-icons.umd.prod.js +1 -1
- package/dist/icon-set/material-symbols-outlined.umd.prod.js +1 -1
- package/dist/icon-set/material-symbols-rounded.umd.prod.js +1 -1
- package/dist/icon-set/material-symbols-sharp.umd.prod.js +1 -1
- package/dist/icon-set/mdi-v3.umd.prod.js +1 -1
- package/dist/icon-set/mdi-v4.umd.prod.js +1 -1
- package/dist/icon-set/mdi-v5.umd.prod.js +1 -1
- package/dist/icon-set/mdi-v6.umd.prod.js +1 -1
- package/dist/icon-set/mdi-v7.umd.prod.js +1 -1
- package/dist/icon-set/svg-bootstrap-icons.umd.prod.js +1 -1
- package/dist/icon-set/svg-eva-icons.umd.prod.js +1 -1
- package/dist/icon-set/svg-fontawesome-v5.umd.prod.js +1 -1
- package/dist/icon-set/svg-fontawesome-v6.umd.prod.js +1 -1
- package/dist/icon-set/svg-fontawesome-v7.umd.prod.js +1 -1
- package/dist/icon-set/svg-ionicons-v4.umd.prod.js +1 -1
- package/dist/icon-set/svg-ionicons-v5.umd.prod.js +1 -1
- package/dist/icon-set/svg-ionicons-v6.umd.prod.js +1 -1
- package/dist/icon-set/svg-ionicons-v7.umd.prod.js +1 -1
- package/dist/icon-set/svg-ionicons-v8.umd.prod.js +1 -1
- package/dist/icon-set/svg-line-awesome.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-icons-outlined.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-icons-round.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-icons.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-symbols-outlined.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-symbols-rounded.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-symbols-sharp.umd.prod.js +1 -1
- package/dist/icon-set/svg-mdi-v6.umd.prod.js +1 -1
- package/dist/icon-set/svg-mdi-v7.umd.prod.js +1 -1
- package/dist/icon-set/svg-themify.umd.prod.js +1 -1
- package/dist/icon-set/themify.umd.prod.js +1 -1
- package/dist/lang/ar-TN.umd.prod.js +1 -1
- package/dist/lang/ar.umd.prod.js +1 -1
- package/dist/lang/az-Latn.umd.prod.js +1 -1
- package/dist/lang/bg.umd.prod.js +1 -1
- package/dist/lang/bn.umd.prod.js +1 -1
- package/dist/lang/bs-BA.umd.prod.js +1 -1
- package/dist/lang/ca.umd.prod.js +1 -1
- package/dist/lang/cs.umd.prod.js +1 -1
- package/dist/lang/da.umd.prod.js +1 -1
- package/dist/lang/de-CH.umd.prod.js +1 -1
- package/dist/lang/de-DE.umd.prod.js +1 -1
- package/dist/lang/de.umd.prod.js +1 -1
- package/dist/lang/el.umd.prod.js +1 -1
- package/dist/lang/en-GB.umd.prod.js +1 -1
- package/dist/lang/en-US.umd.prod.js +1 -1
- package/dist/lang/eo.umd.prod.js +1 -1
- package/dist/lang/es.umd.prod.js +1 -1
- package/dist/lang/et.umd.prod.js +1 -1
- package/dist/lang/eu.umd.prod.js +1 -1
- package/dist/lang/fa-IR.umd.prod.js +1 -1
- package/dist/lang/fa.umd.prod.js +1 -1
- package/dist/lang/fi.umd.prod.js +1 -1
- package/dist/lang/fr.umd.prod.js +1 -1
- package/dist/lang/gn.umd.prod.js +1 -1
- package/dist/lang/he.umd.prod.js +1 -1
- package/dist/lang/hi.umd.prod.js +1 -1
- package/dist/lang/hr.umd.prod.js +1 -1
- package/dist/lang/hu.umd.prod.js +1 -1
- package/dist/lang/id.umd.prod.js +1 -1
- package/dist/lang/is.umd.prod.js +1 -1
- package/dist/lang/it.umd.prod.js +1 -1
- package/dist/lang/ja.umd.prod.js +1 -1
- package/dist/lang/kk.umd.prod.js +1 -1
- package/dist/lang/km.umd.prod.js +1 -1
- package/dist/lang/ko-KR.umd.prod.js +1 -1
- package/dist/lang/kur-CKB.umd.prod.js +1 -1
- package/dist/lang/lb.umd.prod.js +1 -1
- package/dist/lang/lt.umd.prod.js +1 -1
- package/dist/lang/lu.umd.prod.js +1 -1
- package/dist/lang/lv.umd.prod.js +1 -1
- package/dist/lang/mk.umd.prod.js +1 -1
- package/dist/lang/ml.umd.prod.js +1 -1
- package/dist/lang/mm.umd.prod.js +1 -1
- package/dist/lang/ms-MY.umd.prod.js +1 -1
- package/dist/lang/ms.umd.prod.js +1 -1
- package/dist/lang/my.umd.prod.js +1 -1
- package/dist/lang/nb-NO.umd.prod.js +1 -1
- package/dist/lang/nl.umd.prod.js +1 -1
- package/dist/lang/pl.umd.prod.js +1 -1
- package/dist/lang/pt-BR.umd.prod.js +1 -1
- package/dist/lang/pt.umd.prod.js +1 -1
- package/dist/lang/ro.umd.prod.js +1 -1
- package/dist/lang/ru.umd.prod.js +1 -1
- package/dist/lang/sk.umd.prod.js +1 -1
- package/dist/lang/sl.umd.prod.js +1 -1
- package/dist/lang/sm.umd.prod.js +1 -1
- package/dist/lang/sq.umd.prod.js +1 -1
- package/dist/lang/sr-CYR.umd.prod.js +1 -1
- package/dist/lang/sr.umd.prod.js +1 -1
- package/dist/lang/sv.umd.prod.js +1 -1
- package/dist/lang/ta.umd.prod.js +1 -1
- package/dist/lang/th.umd.prod.js +1 -1
- package/dist/lang/tl.umd.prod.js +1 -1
- package/dist/lang/tr.umd.prod.js +1 -1
- package/dist/lang/ug.umd.prod.js +1 -1
- package/dist/lang/uk.umd.prod.js +1 -1
- package/dist/lang/ur-PK.umd.prod.js +1 -1
- package/dist/lang/uz-Cyrl.umd.prod.js +1 -1
- package/dist/lang/uz-Latn.umd.prod.js +1 -1
- package/dist/lang/vi.umd.prod.js +1 -1
- package/dist/lang/zh-CN.umd.prod.js +1 -1
- package/dist/lang/zh-TW.umd.prod.js +1 -1
- package/dist/quasar.client.js +654 -207
- package/dist/quasar.css +20 -11
- package/dist/quasar.prod.css +1 -1
- package/dist/quasar.rtl.css +25 -20
- package/dist/quasar.rtl.prod.css +1 -1
- package/dist/quasar.sass +21 -12
- package/dist/quasar.server.prod.cjs +35 -35
- package/dist/quasar.server.prod.js +25 -25
- package/dist/quasar.umd.js +654 -206
- package/dist/quasar.umd.prod.js +19 -19
- package/dist/transforms/import-map.json +1 -1
- package/dist/types/composables.d.ts +15 -5
- package/dist/types/index.d.ts +5 -5
- package/dist/web-types/web-types.json +1 -1
- package/package.json +6 -6
- package/src/components/btn/QBtn.js +1 -1
- package/src/components/carousel/QCarousel.js +2 -0
- package/src/components/chip/QChip.js +20 -4
- package/src/components/date/QDate.js +9 -2
- package/src/components/dialog/QDialog.js +9 -2
- package/src/components/editor/QEditor.js +18 -3
- package/src/components/expansion-item/QExpansionItem.js +6 -1
- package/src/components/fab/QFab.sass +11 -9
- package/src/components/input/QInput.js +42 -1
- package/src/components/input/QInput.json +7 -0
- package/src/components/input/use-mask.js +12 -4
- package/src/components/item/QItem.js +10 -1
- package/src/components/linear-progress/QLinearProgress.js +4 -11
- package/src/components/linear-progress/QLinearProgress.json +1 -1
- package/src/components/linear-progress/QLinearProgress.sass +7 -2
- package/src/components/menu/QMenu.js +9 -2
- package/src/components/range/QRange.js +2 -1
- package/src/components/rating/QRating.js +27 -8
- package/src/components/rating/QRating.sass +4 -0
- package/src/components/resize-observer/QResizeObserver.js +14 -3
- package/src/components/scroll-area/QScrollArea.js +69 -17
- package/src/components/slide-item/QSlideItem.js +3 -2
- package/src/components/slider/use-slider.js +7 -3
- package/src/components/stepper/StepHeader.js +11 -2
- package/src/components/table/QTable.js +11 -9
- package/src/components/table/QTh.js +20 -1
- package/src/components/table/table-column-selection.js +9 -1
- package/src/components/table/table-pagination.js +5 -2
- package/src/components/table/table-row-selection.js +10 -10
- package/src/components/tabs/QTabs.js +5 -6
- package/src/components/time/QTime.js +35 -10
- package/src/components/tooltip/QTooltip.js +112 -6
- package/src/components/tree/QTree.js +124 -4
- package/src/components/uploader/uploader-core.js +19 -4
- package/src/components/uploader/xhr-uploader-plugin.js +93 -43
- package/src/components/uploader/xhr-uploader-plugin.json +4 -4
- package/src/composables/private.use-field/use-field.js +2 -0
- package/src/composables/private.use-file/use-file.js +21 -12
- package/src/composables/private.use-fullscreen/use-fullscreen.js +71 -11
- package/src/composables/private.use-fullscreen/use-fullscreen.test.js +158 -0
- package/src/composables/private.use-model-toggle/use-model-toggle.js +2 -0
- package/src/composables/private.use-panel/use-panel.js +6 -2
- package/src/composables/use-animation-frame/use-animation-frame.js +47 -0
- package/src/composables/use-animation-frame/use-animation-frame.test.js +122 -0
- package/src/composables/use-interval/use-interval.js +8 -0
- package/src/composables/use-render-cache/use-render-cache.js +15 -10
- package/src/composables/use-timeout/use-timeout.js +8 -0
- package/src/composables.js +1 -1
- package/src/directives/intersection/Intersection.js +2 -2
- package/src/directives/mutation/Mutation.json +1 -1
- package/src/directives/touch-repeat/TouchRepeat.js +3 -1
- package/src/plugins/cookies/Cookies.js +29 -13
- package/src/plugins/meta/Meta.js +57 -9
- package/src/utils/extend/extend.js +4 -0
- package/src/utils/extend/extend.test.js +29 -0
- package/src/utils/private.click-outside/click-outside.js +27 -12
- package/src/utils/private.click-outside/click-outside.test.js +132 -0
- package/src/utils/scroll/prevent-scroll.js +4 -4
|
@@ -29,7 +29,7 @@ import useDatetime, {
|
|
|
29
29
|
import { createComponent } from '../../utils/private.create/create.js'
|
|
30
30
|
import { hSlot } from '../../utils/private.render/render.js'
|
|
31
31
|
import { __splitDate, formatDate } from '../../utils/date/date.js'
|
|
32
|
-
import { position } from '../../utils/event/event.js'
|
|
32
|
+
import { position, stopAndPrevent } from '../../utils/event/event.js'
|
|
33
33
|
import { pad } from '../../utils/format/format.js'
|
|
34
34
|
import { vmIsDestroyed } from '../../utils/private.vm/vm.js'
|
|
35
35
|
|
|
@@ -58,6 +58,10 @@ function getCurrentTime() {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
function preventSpace(e) {
|
|
62
|
+
if (e.keyCode === 32) stopAndPrevent(e)
|
|
63
|
+
}
|
|
64
|
+
|
|
61
65
|
function getWheelDist(a, b, threshold) {
|
|
62
66
|
const diff = Math.abs(a - b)
|
|
63
67
|
return Math.min(diff, threshold - diff)
|
|
@@ -536,11 +540,17 @@ export default createComponent({
|
|
|
536
540
|
}
|
|
537
541
|
|
|
538
542
|
function setAmOnKey(e) {
|
|
539
|
-
if (e.keyCode
|
|
543
|
+
if ([13, 32].includes(e.keyCode)) {
|
|
544
|
+
setAm()
|
|
545
|
+
stopAndPrevent(e)
|
|
546
|
+
}
|
|
540
547
|
}
|
|
541
548
|
|
|
542
549
|
function setPmOnKey(e) {
|
|
543
|
-
if (e.keyCode
|
|
550
|
+
if ([13, 32].includes(e.keyCode)) {
|
|
551
|
+
setPm()
|
|
552
|
+
stopAndPrevent(e)
|
|
553
|
+
}
|
|
544
554
|
}
|
|
545
555
|
|
|
546
556
|
function onClick(evt) {
|
|
@@ -562,9 +572,9 @@ export default createComponent({
|
|
|
562
572
|
}
|
|
563
573
|
|
|
564
574
|
function onKeyupHour(e) {
|
|
565
|
-
if (e.keyCode
|
|
566
|
-
// ENTER
|
|
575
|
+
if ([13, 32].includes(e.keyCode)) {
|
|
567
576
|
view.value = 'hour'
|
|
577
|
+
stopAndPrevent(e)
|
|
568
578
|
} else if ([37, 39].includes(e.keyCode)) {
|
|
569
579
|
const payload = e.keyCode === 37 ? -1 : 1
|
|
570
580
|
|
|
@@ -598,9 +608,9 @@ export default createComponent({
|
|
|
598
608
|
}
|
|
599
609
|
|
|
600
610
|
function onKeyupMinute(e) {
|
|
601
|
-
if (e.keyCode
|
|
602
|
-
// ENTER
|
|
611
|
+
if ([13, 32].includes(e.keyCode)) {
|
|
603
612
|
view.value = 'minute'
|
|
613
|
+
stopAndPrevent(e)
|
|
604
614
|
} else if ([37, 39].includes(e.keyCode)) {
|
|
605
615
|
const payload = e.keyCode === 37 ? -1 : 1
|
|
606
616
|
|
|
@@ -631,9 +641,9 @@ export default createComponent({
|
|
|
631
641
|
}
|
|
632
642
|
|
|
633
643
|
function onKeyupSecond(e) {
|
|
634
|
-
if (e.keyCode
|
|
635
|
-
// ENTER
|
|
644
|
+
if ([13, 32].includes(e.keyCode)) {
|
|
636
645
|
view.value = 'second'
|
|
646
|
+
stopAndPrevent(e)
|
|
637
647
|
} else if ([37, 39].includes(e.keyCode)) {
|
|
638
648
|
const payload = e.keyCode === 37 ? -1 : 1
|
|
639
649
|
|
|
@@ -642,7 +652,7 @@ export default createComponent({
|
|
|
642
652
|
|
|
643
653
|
if (values.length === 0) return
|
|
644
654
|
|
|
645
|
-
if (innerModel.value.
|
|
655
|
+
if (innerModel.value.second === null) {
|
|
646
656
|
setSecond(values[0])
|
|
647
657
|
} else {
|
|
648
658
|
const index =
|
|
@@ -806,7 +816,10 @@ export default createComponent({
|
|
|
806
816
|
? 'q-time__link--active'
|
|
807
817
|
: 'cursor-pointer'),
|
|
808
818
|
tabindex: tabindex.value,
|
|
819
|
+
role: 'button',
|
|
820
|
+
'aria-pressed': view.value === 'hour' ? 'true' : 'false',
|
|
809
821
|
onClick: setView.hour,
|
|
822
|
+
onKeydown: preventSpace,
|
|
810
823
|
onKeyup: onKeyupHour
|
|
811
824
|
},
|
|
812
825
|
stringModel.value.hour
|
|
@@ -824,6 +837,9 @@ export default createComponent({
|
|
|
824
837
|
? 'q-time__link--active'
|
|
825
838
|
: 'cursor-pointer'),
|
|
826
839
|
tabindex: tabindex.value,
|
|
840
|
+
role: 'button',
|
|
841
|
+
'aria-pressed': view.value === 'minute' ? 'true' : 'false',
|
|
842
|
+
onKeydown: preventSpace,
|
|
827
843
|
onKeyup: onKeyupMinute,
|
|
828
844
|
onClick: setView.minute
|
|
829
845
|
}
|
|
@@ -846,6 +862,9 @@ export default createComponent({
|
|
|
846
862
|
? 'q-time__link--active'
|
|
847
863
|
: 'cursor-pointer'),
|
|
848
864
|
tabindex: tabindex.value,
|
|
865
|
+
role: 'button',
|
|
866
|
+
'aria-pressed': view.value === 'second' ? 'true' : 'false',
|
|
867
|
+
onKeydown: preventSpace,
|
|
849
868
|
onKeyup: onKeyupSecond,
|
|
850
869
|
onClick: setView.second
|
|
851
870
|
}
|
|
@@ -881,7 +900,10 @@ export default createComponent({
|
|
|
881
900
|
'q-time__link ' +
|
|
882
901
|
(isAM.value ? 'q-time__link--active' : 'cursor-pointer'),
|
|
883
902
|
tabindex: tabindex.value,
|
|
903
|
+
role: 'button',
|
|
904
|
+
'aria-pressed': isAM.value ? 'true' : 'false',
|
|
884
905
|
onClick: setAm,
|
|
906
|
+
onKeydown: preventSpace,
|
|
885
907
|
onKeyup: setAmOnKey
|
|
886
908
|
},
|
|
887
909
|
'AM'
|
|
@@ -894,7 +916,10 @@ export default createComponent({
|
|
|
894
916
|
'q-time__link ' +
|
|
895
917
|
(isAM.value ? 'cursor-pointer' : 'q-time__link--active'),
|
|
896
918
|
tabindex: tabindex.value,
|
|
919
|
+
role: 'button',
|
|
920
|
+
'aria-pressed': isAM.value ? 'false' : 'true',
|
|
897
921
|
onClick: setPm,
|
|
922
|
+
onKeydown: preventSpace,
|
|
898
923
|
onKeyup: setPmOnKey
|
|
899
924
|
},
|
|
900
925
|
'PM'
|
|
@@ -22,10 +22,15 @@ import useTransition, {
|
|
|
22
22
|
} from '../../composables/private.use-transition/use-transition.js'
|
|
23
23
|
import useTick from '../../composables/use-tick/use-tick.js'
|
|
24
24
|
import useTimeout from '../../composables/use-timeout/use-timeout.js'
|
|
25
|
+
import useId from '../../composables/use-id/use-id.js'
|
|
25
26
|
|
|
26
27
|
import { createComponent } from '../../utils/private.create/create.js'
|
|
27
28
|
import { getScrollTarget, scrollTargetProp } from '../../utils/scroll/scroll.js'
|
|
28
29
|
import { addEvt, cleanEvt, stopAndPrevent } from '../../utils/event/event.js'
|
|
30
|
+
import {
|
|
31
|
+
addEscapeKey,
|
|
32
|
+
removeEscapeKey
|
|
33
|
+
} from '../../utils/private.keyboard/escape-key.js'
|
|
29
34
|
import { clearSelection } from '../../utils/private.selection/selection.js'
|
|
30
35
|
import { hSlot } from '../../utils/private.render/render.js'
|
|
31
36
|
import {
|
|
@@ -39,6 +44,8 @@ import {
|
|
|
39
44
|
validatePosition
|
|
40
45
|
} from '../../utils/private.position-engine/position-engine.js'
|
|
41
46
|
|
|
47
|
+
let nonSelectableCount = 0
|
|
48
|
+
|
|
42
49
|
export default createComponent({
|
|
43
50
|
name: 'QTooltip',
|
|
44
51
|
|
|
@@ -101,7 +108,11 @@ export default createComponent({
|
|
|
101
108
|
emits: [...useModelToggleEmits],
|
|
102
109
|
|
|
103
110
|
setup(props, { slots, emit, attrs }) {
|
|
104
|
-
let unwatchPosition,
|
|
111
|
+
let unwatchPosition,
|
|
112
|
+
observer,
|
|
113
|
+
removeNonSelectableTimer,
|
|
114
|
+
hasNonSelectable = false,
|
|
115
|
+
describedBy
|
|
105
116
|
|
|
106
117
|
const vm = getCurrentInstance()
|
|
107
118
|
const {
|
|
@@ -110,6 +121,8 @@ export default createComponent({
|
|
|
110
121
|
|
|
111
122
|
const innerRef = ref(null)
|
|
112
123
|
const showing = ref(false)
|
|
124
|
+
const targetUid = useId()
|
|
125
|
+
const tooltipId = computed(() => attrs.id || targetUid.value)
|
|
113
126
|
|
|
114
127
|
const anchorOrigin = computed(() =>
|
|
115
128
|
parsePosition(props.anchor, $q.lang.rtl)
|
|
@@ -137,7 +150,7 @@ export default createComponent({
|
|
|
137
150
|
processOnMount: true
|
|
138
151
|
})
|
|
139
152
|
|
|
140
|
-
Object.assign(anchorEvents, { delayShow, delayHide })
|
|
153
|
+
Object.assign(anchorEvents, { delayShow, delayHide, onFocusin })
|
|
141
154
|
|
|
142
155
|
const { showPortal, hidePortal, renderPortal } = usePortal(
|
|
143
156
|
vm,
|
|
@@ -182,10 +195,26 @@ export default createComponent({
|
|
|
182
195
|
onBeforeUnmount(() => {
|
|
183
196
|
removeClickOutside(clickOutsideProps)
|
|
184
197
|
})
|
|
198
|
+
} else {
|
|
199
|
+
// dismiss with the ESC key (WCAG 1.4.13) without moving focus;
|
|
200
|
+
// uses the shared escape stack so only the top-most popup reacts
|
|
201
|
+
watch(
|
|
202
|
+
() =>
|
|
203
|
+
// trigger only if it doesn't have external model
|
|
204
|
+
// or else only if the model can be updated (otherwise respect the external model)
|
|
205
|
+
(props.modelValue === null || props['onUpdate:modelValue']) &&
|
|
206
|
+
showing.value === true &&
|
|
207
|
+
props.persistent !== true,
|
|
208
|
+
val => {
|
|
209
|
+
const fn = val === true ? addEscapeKey : removeEscapeKey
|
|
210
|
+
fn(onEscapeKey)
|
|
211
|
+
}
|
|
212
|
+
)
|
|
185
213
|
}
|
|
186
214
|
|
|
187
215
|
function handleShow(evt) {
|
|
188
216
|
showPortal()
|
|
217
|
+
addAriaDescription()
|
|
189
218
|
|
|
190
219
|
// should removeTick() if this gets removed
|
|
191
220
|
registerTick(() => {
|
|
@@ -254,7 +283,10 @@ export default createComponent({
|
|
|
254
283
|
}
|
|
255
284
|
|
|
256
285
|
unconfigureScrollTarget()
|
|
286
|
+
removeEscapeKey(onEscapeKey)
|
|
257
287
|
cleanEvt(anchorEvents, 'tooltipTemp')
|
|
288
|
+
removeAriaDescription()
|
|
289
|
+
setNonSelectable(false)
|
|
258
290
|
}
|
|
259
291
|
|
|
260
292
|
function updatePosition() {
|
|
@@ -271,8 +303,13 @@ export default createComponent({
|
|
|
271
303
|
|
|
272
304
|
function delayShow(evt) {
|
|
273
305
|
if ($q.platform.is.mobile) {
|
|
306
|
+
if (removeNonSelectableTimer !== void 0) {
|
|
307
|
+
clearTimeout(removeNonSelectableTimer)
|
|
308
|
+
removeNonSelectableTimer = void 0
|
|
309
|
+
}
|
|
310
|
+
|
|
274
311
|
clearSelection()
|
|
275
|
-
|
|
312
|
+
setNonSelectable(true)
|
|
276
313
|
|
|
277
314
|
const target = anchorEl.value
|
|
278
315
|
const evts = ['touchmove', 'touchcancel', 'touchend', 'click'].map(
|
|
@@ -292,8 +329,9 @@ export default createComponent({
|
|
|
292
329
|
cleanEvt(anchorEvents, 'tooltipTemp')
|
|
293
330
|
clearSelection()
|
|
294
331
|
// delay needed otherwise selection still occurs
|
|
295
|
-
setTimeout(() => {
|
|
296
|
-
|
|
332
|
+
removeNonSelectableTimer = setTimeout(() => {
|
|
333
|
+
removeNonSelectableTimer = void 0
|
|
334
|
+
setNonSelectable(false)
|
|
297
335
|
}, 10)
|
|
298
336
|
}
|
|
299
337
|
|
|
@@ -303,6 +341,26 @@ export default createComponent({
|
|
|
303
341
|
}, props.hideDelay)
|
|
304
342
|
}
|
|
305
343
|
|
|
344
|
+
function onFocusin(evt) {
|
|
345
|
+
const el = evt.target
|
|
346
|
+
if (!el) return
|
|
347
|
+
|
|
348
|
+
// only react to keyboard focus, not to focus coming from a pointer,
|
|
349
|
+
// so the tooltip doesn't pop up when the target is clicked;
|
|
350
|
+
// guard the call for engines that don't support :focus-visible
|
|
351
|
+
try {
|
|
352
|
+
if (el.matches(':focus-visible') === false) return
|
|
353
|
+
} catch {}
|
|
354
|
+
|
|
355
|
+
delayShow(evt)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// trigger only if it doesn't have external model
|
|
359
|
+
// or else only if the model can be updated (otherwise respect the external model)
|
|
360
|
+
function onEscapeKey(evt) {
|
|
361
|
+
hide(evt)
|
|
362
|
+
}
|
|
363
|
+
|
|
306
364
|
function configureAnchorEl() {
|
|
307
365
|
if (props.noParentEvent || anchorEl.value === null) return
|
|
308
366
|
|
|
@@ -310,12 +368,59 @@ export default createComponent({
|
|
|
310
368
|
? [[anchorEl.value, 'touchstart', 'delayShow', 'passive']]
|
|
311
369
|
: [
|
|
312
370
|
[anchorEl.value, 'mouseenter', 'delayShow', 'passive'],
|
|
313
|
-
[anchorEl.value, 'mouseleave', 'delayHide', 'passive']
|
|
371
|
+
[anchorEl.value, 'mouseleave', 'delayHide', 'passive'],
|
|
372
|
+
[anchorEl.value, 'focusin', 'onFocusin', 'passive'],
|
|
373
|
+
[anchorEl.value, 'focusout', 'delayHide', 'passive']
|
|
314
374
|
]
|
|
315
375
|
|
|
316
376
|
addEvt(anchorEvents, 'anchor', evts)
|
|
317
377
|
}
|
|
318
378
|
|
|
379
|
+
function setNonSelectable(state) {
|
|
380
|
+
if (hasNonSelectable === state) return
|
|
381
|
+
|
|
382
|
+
hasNonSelectable = state
|
|
383
|
+
nonSelectableCount += state ? 1 : -1
|
|
384
|
+
document.body.classList.toggle('non-selectable', nonSelectableCount > 0)
|
|
385
|
+
|
|
386
|
+
if (!state && removeNonSelectableTimer !== void 0) {
|
|
387
|
+
clearTimeout(removeNonSelectableTimer)
|
|
388
|
+
removeNonSelectableTimer = void 0
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function addAriaDescription() {
|
|
393
|
+
const el = anchorEl.value,
|
|
394
|
+
id = tooltipId.value
|
|
395
|
+
|
|
396
|
+
if (el === null || id === void 0) return
|
|
397
|
+
|
|
398
|
+
const ids = (el.getAttribute('aria-describedby') || '')
|
|
399
|
+
.split(/\s+/)
|
|
400
|
+
.filter(Boolean)
|
|
401
|
+
|
|
402
|
+
describedBy = { el, id, added: !ids.includes(id) }
|
|
403
|
+
|
|
404
|
+
if (describedBy.added) {
|
|
405
|
+
ids.push(id)
|
|
406
|
+
el.setAttribute('aria-describedby', ids.join(' '))
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function removeAriaDescription() {
|
|
411
|
+
if (describedBy?.added === true) {
|
|
412
|
+
const { el, id } = describedBy,
|
|
413
|
+
value = (el.getAttribute('aria-describedby') || '')
|
|
414
|
+
.split(/\s+/)
|
|
415
|
+
.filter(entry => entry !== '' && entry !== id)
|
|
416
|
+
|
|
417
|
+
if (value.length === 0) el.removeAttribute('aria-describedby')
|
|
418
|
+
else el.setAttribute('aria-describedby', value.join(' '))
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
describedBy = void 0
|
|
422
|
+
}
|
|
423
|
+
|
|
319
424
|
function configureScrollTarget() {
|
|
320
425
|
if (anchorEl.value !== null || props.scrollTarget !== void 0) {
|
|
321
426
|
localScrollTarget.value = getScrollTarget(
|
|
@@ -334,6 +439,7 @@ export default createComponent({
|
|
|
334
439
|
'div',
|
|
335
440
|
{
|
|
336
441
|
...attrs,
|
|
442
|
+
id: tooltipId.value,
|
|
337
443
|
ref: innerRef,
|
|
338
444
|
class: [
|
|
339
445
|
'q-tooltip q-tooltip--style q-position-engine no-pointer-events',
|
|
@@ -118,11 +118,14 @@ export default createComponent({
|
|
|
118
118
|
const lazy = ref({})
|
|
119
119
|
const innerTicked = ref(props.ticked || [])
|
|
120
120
|
const innerExpanded = ref(props.expanded || [])
|
|
121
|
+
const focusedKey = ref(null)
|
|
121
122
|
|
|
122
|
-
let blurTargets = {}
|
|
123
|
+
let blurTargets = {},
|
|
124
|
+
headerTargets = {}
|
|
123
125
|
|
|
124
126
|
onBeforeUpdate(() => {
|
|
125
127
|
blurTargets = {}
|
|
128
|
+
headerTargets = {}
|
|
126
129
|
})
|
|
127
130
|
|
|
128
131
|
const classes = computed(
|
|
@@ -306,6 +309,38 @@ export default createComponent({
|
|
|
306
309
|
return acc
|
|
307
310
|
})
|
|
308
311
|
|
|
312
|
+
const focusableKeys = computed(() => {
|
|
313
|
+
const acc = []
|
|
314
|
+
|
|
315
|
+
function travel(nodes) {
|
|
316
|
+
nodes.forEach(node => {
|
|
317
|
+
const localMeta = meta.value[node[props.nodeKey]]
|
|
318
|
+
|
|
319
|
+
if (props.filter && localMeta.matchesFilter !== true) return
|
|
320
|
+
if (localMeta.link === true) acc.push(localMeta.key)
|
|
321
|
+
|
|
322
|
+
if (
|
|
323
|
+
localMeta.expanded === true &&
|
|
324
|
+
Array.isArray(node[props.childrenKey])
|
|
325
|
+
) {
|
|
326
|
+
travel(node[props.childrenKey])
|
|
327
|
+
}
|
|
328
|
+
})
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
travel(props.nodes)
|
|
332
|
+
return acc
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
const tabKey = computed(() => {
|
|
336
|
+
const keys = focusableKeys.value
|
|
337
|
+
|
|
338
|
+
if (keys.includes(focusedKey.value)) return focusedKey.value
|
|
339
|
+
|
|
340
|
+
const selected = keys.find(key => meta.value[key].selected === true)
|
|
341
|
+
return selected !== void 0 ? selected : keys[0]
|
|
342
|
+
})
|
|
343
|
+
|
|
309
344
|
watch(
|
|
310
345
|
() => props.ticked,
|
|
311
346
|
val => {
|
|
@@ -576,18 +611,36 @@ export default createComponent({
|
|
|
576
611
|
: '') +
|
|
577
612
|
(m.selected === true ? ' q-tree__node--selected' : '') +
|
|
578
613
|
(m.disabled === true ? ' q-tree__node--disabled' : ''),
|
|
579
|
-
|
|
580
|
-
|
|
614
|
+
ref: el => {
|
|
615
|
+
headerTargets[m.key] = el
|
|
616
|
+
},
|
|
617
|
+
tabindex: m.link === true && m.key === tabKey.value ? 0 : -1,
|
|
618
|
+
'aria-expanded': isParent
|
|
619
|
+
? m.expanded
|
|
620
|
+
? 'true'
|
|
621
|
+
: 'false'
|
|
622
|
+
: null,
|
|
623
|
+
'aria-selected': m.selectable
|
|
624
|
+
? m.selected
|
|
625
|
+
? 'true'
|
|
626
|
+
: 'false'
|
|
627
|
+
: null,
|
|
628
|
+
'aria-disabled': m.disabled === true ? 'true' : null,
|
|
581
629
|
role: 'treeitem',
|
|
630
|
+
onFocus() {
|
|
631
|
+
if (m.link === true) focusedKey.value = m.key
|
|
632
|
+
},
|
|
582
633
|
onClick: e => {
|
|
583
634
|
onClick(node, m, e)
|
|
584
635
|
},
|
|
585
|
-
|
|
636
|
+
onKeydown(e) {
|
|
586
637
|
if (shouldIgnoreKey(e) !== true) {
|
|
587
638
|
if (e.keyCode === 13) {
|
|
588
639
|
onClick(node, m, e, true)
|
|
589
640
|
} else if (e.keyCode === 32) {
|
|
590
641
|
onExpandClick(node, m, e, true)
|
|
642
|
+
} else if (onNavigationKey(m, e.keyCode)) {
|
|
643
|
+
stopAndPrevent(e)
|
|
591
644
|
}
|
|
592
645
|
}
|
|
593
646
|
}
|
|
@@ -722,7 +775,72 @@ export default createComponent({
|
|
|
722
775
|
blurTargets[key]?.focus()
|
|
723
776
|
}
|
|
724
777
|
|
|
778
|
+
function focusNode(key) {
|
|
779
|
+
if (key !== void 0) {
|
|
780
|
+
focusedKey.value = key
|
|
781
|
+
headerTargets[key]?.focus()
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
function getFirstFocusableChild(children) {
|
|
786
|
+
for (const child of children) {
|
|
787
|
+
if (props.filter && child.matchesFilter !== true) continue
|
|
788
|
+
if (child.link === true) return child.key
|
|
789
|
+
|
|
790
|
+
if (child.expanded === true) {
|
|
791
|
+
const key = getFirstFocusableChild(child.children)
|
|
792
|
+
if (key !== void 0) return key
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
function onNavigationKey(localMeta, keyCode) {
|
|
798
|
+
const keys = focusableKeys.value,
|
|
799
|
+
index = keys.indexOf(localMeta.key)
|
|
800
|
+
|
|
801
|
+
if (keyCode === 36) {
|
|
802
|
+
focusNode(keys[0])
|
|
803
|
+
return true
|
|
804
|
+
}
|
|
805
|
+
if (keyCode === 35) {
|
|
806
|
+
focusNode(keys.at(-1))
|
|
807
|
+
return true
|
|
808
|
+
}
|
|
809
|
+
if (keyCode === 38) {
|
|
810
|
+
focusNode(keys[index - 1])
|
|
811
|
+
return true
|
|
812
|
+
}
|
|
813
|
+
if (keyCode === 40) {
|
|
814
|
+
focusNode(keys[index + 1])
|
|
815
|
+
return true
|
|
816
|
+
}
|
|
817
|
+
if (keyCode === 39) {
|
|
818
|
+
if (localMeta.isParent !== true && !localMeta.lazy) return true
|
|
819
|
+
|
|
820
|
+
if (localMeta.expanded !== true) {
|
|
821
|
+
setExpanded(localMeta.key, true)
|
|
822
|
+
} else {
|
|
823
|
+
focusNode(getFirstFocusableChild(localMeta.children))
|
|
824
|
+
}
|
|
825
|
+
return true
|
|
826
|
+
}
|
|
827
|
+
if (keyCode === 37) {
|
|
828
|
+
if (localMeta.expanded === true) {
|
|
829
|
+
setExpanded(localMeta.key, false)
|
|
830
|
+
} else {
|
|
831
|
+
let parent = localMeta.parent
|
|
832
|
+
while (parent !== null && parent.link !== true) parent = parent.parent
|
|
833
|
+
focusNode(parent?.key)
|
|
834
|
+
}
|
|
835
|
+
return true
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
return false
|
|
839
|
+
}
|
|
840
|
+
|
|
725
841
|
function onClick(node, localMeta, e, keyboard) {
|
|
842
|
+
if (localMeta.link === true) focusedKey.value = localMeta.key
|
|
843
|
+
|
|
726
844
|
if (keyboard !== true && localMeta.selectable !== false) {
|
|
727
845
|
blur(localMeta.key)
|
|
728
846
|
}
|
|
@@ -749,6 +867,8 @@ export default createComponent({
|
|
|
749
867
|
}
|
|
750
868
|
|
|
751
869
|
function onExpandClick(node, localMeta, e, keyboard) {
|
|
870
|
+
if (localMeta.link === true) focusedKey.value = localMeta.key
|
|
871
|
+
|
|
752
872
|
if (e !== void 0) {
|
|
753
873
|
stopAndPrevent(e)
|
|
754
874
|
}
|
|
@@ -93,7 +93,11 @@ export function getRenderer(getPlugin, expose) {
|
|
|
93
93
|
file.__uploaded = status === 'uploaded' ? file.size : uploadedSize
|
|
94
94
|
|
|
95
95
|
file.__progress =
|
|
96
|
-
status === 'uploaded'
|
|
96
|
+
status === 'uploaded'
|
|
97
|
+
? 1
|
|
98
|
+
: file.size === 0
|
|
99
|
+
? 0
|
|
100
|
+
: Math.min(0.9999, file.__uploaded / file.size)
|
|
97
101
|
|
|
98
102
|
file.__progressLabel = getProgressLabel(file.__progress)
|
|
99
103
|
proxy.$forceUpdate()
|
|
@@ -216,7 +220,9 @@ export function getRenderer(getPlugin, expose) {
|
|
|
216
220
|
|
|
217
221
|
function removeUploadedFiles() {
|
|
218
222
|
if (!props.disable) {
|
|
219
|
-
batchRemoveFiles(['uploaded'], () => {
|
|
223
|
+
batchRemoveFiles(['uploaded'], ({ size }) => {
|
|
224
|
+
state.uploadedSize.value -= size
|
|
225
|
+
uploadSize.value -= size
|
|
220
226
|
state.uploadedFiles.value = []
|
|
221
227
|
})
|
|
222
228
|
}
|
|
@@ -258,12 +264,16 @@ export function getRenderer(getPlugin, expose) {
|
|
|
258
264
|
function removeFile(file) {
|
|
259
265
|
if (props.disable) return
|
|
260
266
|
|
|
267
|
+
const isUploading = file.__status === 'uploading'
|
|
268
|
+
|
|
261
269
|
if (file.__status === 'uploaded') {
|
|
270
|
+
state.uploadedSize.value -= file.size
|
|
271
|
+
uploadSize.value -= file.size
|
|
262
272
|
state.uploadedFiles.value = state.uploadedFiles.value.filter(
|
|
263
273
|
f => f.__key !== file.__key
|
|
264
274
|
)
|
|
265
|
-
} else if (
|
|
266
|
-
file.
|
|
275
|
+
} else if (isUploading) {
|
|
276
|
+
uploadSize.value -= file.size
|
|
267
277
|
} else {
|
|
268
278
|
uploadSize.value -= file.size
|
|
269
279
|
}
|
|
@@ -281,6 +291,11 @@ export function getRenderer(getPlugin, expose) {
|
|
|
281
291
|
state.queuedFiles.value = state.queuedFiles.value.filter(
|
|
282
292
|
f => f.__key !== file.__key
|
|
283
293
|
)
|
|
294
|
+
|
|
295
|
+
if (isUploading) {
|
|
296
|
+
file.__abort()
|
|
297
|
+
}
|
|
298
|
+
|
|
284
299
|
emit('removed', [file])
|
|
285
300
|
}
|
|
286
301
|
|