quasar 2.14.2 → 2.14.3

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 (133) hide show
  1. package/dist/icon-set/bootstrap-icons.umd.prod.js +1 -1
  2. package/dist/icon-set/eva-icons.umd.prod.js +1 -1
  3. package/dist/icon-set/fontawesome-v5-pro.umd.prod.js +1 -1
  4. package/dist/icon-set/fontawesome-v5.umd.prod.js +1 -1
  5. package/dist/icon-set/fontawesome-v6-pro.umd.prod.js +1 -1
  6. package/dist/icon-set/fontawesome-v6.umd.prod.js +1 -1
  7. package/dist/icon-set/ionicons-v4.umd.prod.js +1 -1
  8. package/dist/icon-set/line-awesome.umd.prod.js +1 -1
  9. package/dist/icon-set/material-icons-outlined.umd.prod.js +1 -1
  10. package/dist/icon-set/material-icons-round.umd.prod.js +1 -1
  11. package/dist/icon-set/material-icons-sharp.umd.prod.js +1 -1
  12. package/dist/icon-set/material-icons.umd.prod.js +1 -1
  13. package/dist/icon-set/material-symbols-outlined.umd.prod.js +1 -1
  14. package/dist/icon-set/material-symbols-rounded.umd.prod.js +1 -1
  15. package/dist/icon-set/material-symbols-sharp.umd.prod.js +1 -1
  16. package/dist/icon-set/mdi-v3.umd.prod.js +1 -1
  17. package/dist/icon-set/mdi-v4.umd.prod.js +1 -1
  18. package/dist/icon-set/mdi-v5.umd.prod.js +1 -1
  19. package/dist/icon-set/mdi-v6.umd.prod.js +1 -1
  20. package/dist/icon-set/mdi-v7.umd.prod.js +1 -1
  21. package/dist/icon-set/svg-bootstrap-icons.umd.prod.js +1 -1
  22. package/dist/icon-set/svg-eva-icons.umd.prod.js +1 -1
  23. package/dist/icon-set/svg-fontawesome-v5.umd.prod.js +1 -1
  24. package/dist/icon-set/svg-fontawesome-v6.umd.prod.js +1 -1
  25. package/dist/icon-set/svg-ionicons-v4.umd.prod.js +1 -1
  26. package/dist/icon-set/svg-ionicons-v5.umd.prod.js +1 -1
  27. package/dist/icon-set/svg-ionicons-v6.umd.prod.js +1 -1
  28. package/dist/icon-set/svg-line-awesome.umd.prod.js +1 -1
  29. package/dist/icon-set/svg-material-icons-outlined.umd.prod.js +1 -1
  30. package/dist/icon-set/svg-material-icons-round.umd.prod.js +1 -1
  31. package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +1 -1
  32. package/dist/icon-set/svg-material-icons.umd.prod.js +1 -1
  33. package/dist/icon-set/svg-material-symbols-outlined.umd.prod.js +1 -1
  34. package/dist/icon-set/svg-material-symbols-rounded.umd.prod.js +1 -1
  35. package/dist/icon-set/svg-material-symbols-sharp.umd.prod.js +1 -1
  36. package/dist/icon-set/svg-mdi-v6.umd.prod.js +1 -1
  37. package/dist/icon-set/svg-mdi-v7.umd.prod.js +1 -1
  38. package/dist/icon-set/svg-themify.umd.prod.js +1 -1
  39. package/dist/icon-set/themify.umd.prod.js +1 -1
  40. package/dist/lang/ar-TN.umd.prod.js +1 -1
  41. package/dist/lang/ar.umd.prod.js +1 -1
  42. package/dist/lang/az-Latn.umd.prod.js +1 -1
  43. package/dist/lang/bg.umd.prod.js +1 -1
  44. package/dist/lang/bn.umd.prod.js +1 -1
  45. package/dist/lang/ca.umd.prod.js +1 -1
  46. package/dist/lang/cs.umd.prod.js +1 -1
  47. package/dist/lang/da.umd.prod.js +1 -1
  48. package/dist/lang/de-CH.umd.prod.js +1 -1
  49. package/dist/lang/de-DE.umd.prod.js +1 -1
  50. package/dist/lang/de.umd.prod.js +1 -1
  51. package/dist/lang/el.umd.prod.js +1 -1
  52. package/dist/lang/en-GB.umd.prod.js +1 -1
  53. package/dist/lang/en-US.umd.prod.js +1 -1
  54. package/dist/lang/eo.umd.prod.js +1 -1
  55. package/dist/lang/es.umd.prod.js +1 -1
  56. package/dist/lang/et.umd.prod.js +1 -1
  57. package/dist/lang/eu.umd.prod.js +1 -1
  58. package/dist/lang/fa-IR.umd.prod.js +1 -1
  59. package/dist/lang/fa.umd.prod.js +1 -1
  60. package/dist/lang/fi.umd.prod.js +1 -1
  61. package/dist/lang/fr.umd.prod.js +1 -1
  62. package/dist/lang/gn.umd.prod.js +1 -1
  63. package/dist/lang/he.umd.prod.js +1 -1
  64. package/dist/lang/hi.umd.prod.js +1 -1
  65. package/dist/lang/hr.umd.prod.js +1 -1
  66. package/dist/lang/hu.umd.prod.js +1 -1
  67. package/dist/lang/id.umd.prod.js +1 -1
  68. package/dist/lang/is.umd.prod.js +1 -1
  69. package/dist/lang/it.umd.prod.js +1 -1
  70. package/dist/lang/ja.umd.prod.js +1 -1
  71. package/dist/lang/kk.umd.prod.js +1 -1
  72. package/dist/lang/km.umd.prod.js +1 -1
  73. package/dist/lang/ko-KR.umd.prod.js +1 -1
  74. package/dist/lang/kur-CKB.umd.prod.js +1 -1
  75. package/dist/lang/lt.umd.prod.js +1 -1
  76. package/dist/lang/lu.umd.prod.js +1 -1
  77. package/dist/lang/lv.umd.prod.js +1 -1
  78. package/dist/lang/mk.umd.prod.js +1 -1
  79. package/dist/lang/ml.umd.prod.js +1 -1
  80. package/dist/lang/mm.umd.prod.js +1 -1
  81. package/dist/lang/ms.umd.prod.js +1 -1
  82. package/dist/lang/my.umd.prod.js +1 -1
  83. package/dist/lang/nb-NO.umd.prod.js +1 -1
  84. package/dist/lang/nl.umd.prod.js +1 -1
  85. package/dist/lang/pl.umd.prod.js +1 -1
  86. package/dist/lang/pt-BR.umd.prod.js +1 -1
  87. package/dist/lang/pt.umd.prod.js +1 -1
  88. package/dist/lang/ro.umd.prod.js +1 -1
  89. package/dist/lang/ru.umd.prod.js +1 -1
  90. package/dist/lang/sk.umd.prod.js +1 -1
  91. package/dist/lang/sl.umd.prod.js +1 -1
  92. package/dist/lang/sm.umd.prod.js +1 -1
  93. package/dist/lang/sr-CYR.umd.prod.js +1 -1
  94. package/dist/lang/sr.umd.prod.js +1 -1
  95. package/dist/lang/sv.umd.prod.js +1 -1
  96. package/dist/lang/ta.umd.prod.js +1 -1
  97. package/dist/lang/th.umd.prod.js +1 -1
  98. package/dist/lang/tr.umd.prod.js +1 -1
  99. package/dist/lang/ug.umd.prod.js +1 -1
  100. package/dist/lang/uk.umd.prod.js +1 -1
  101. package/dist/lang/uz-Cyrl.umd.prod.js +1 -1
  102. package/dist/lang/uz-Latn.umd.prod.js +1 -1
  103. package/dist/lang/vi.umd.prod.js +1 -1
  104. package/dist/lang/zh-CN.umd.prod.js +1 -1
  105. package/dist/lang/zh-TW.umd.prod.js +1 -1
  106. package/dist/quasar.cjs.prod.js +2 -2
  107. package/dist/quasar.esm.js +90 -102
  108. package/dist/quasar.esm.prod.js +2 -2
  109. package/dist/quasar.sass +1 -1
  110. package/dist/quasar.umd.js +90 -102
  111. package/dist/quasar.umd.prod.js +2 -2
  112. package/dist/web-types/web-types.json +1 -1
  113. package/package.json +2 -2
  114. package/src/components/ajax-bar/QAjaxBar.js +12 -2
  115. package/src/components/btn-dropdown/QBtnDropdown.js +4 -4
  116. package/src/components/expansion-item/QExpansionItem.js +4 -3
  117. package/src/components/fab/QFab.js +4 -4
  118. package/src/components/icon/QIcon.js +3 -3
  119. package/src/components/infinite-scroll/QInfiniteScroll.js +1 -1
  120. package/src/components/menu/__tests__/QMenu.cy.js +24 -0
  121. package/src/components/tabs/use-tab.js +1 -1
  122. package/src/composables/private/use-field.js +13 -30
  123. package/src/composables/private/use-id.js +34 -0
  124. package/src/composables/private/use-validate.js +16 -29
  125. package/src/plugins/Dark.js +3 -27
  126. package/src/utils/copy-to-clipboard.js +0 -1
  127. package/src/utils/get-css-var.js +0 -1
  128. package/src/utils/is.js +0 -1
  129. package/src/utils/private/define-reactive-plugin.js +0 -1
  130. package/src/utils/private/global-config.js +0 -1
  131. package/src/utils/private/touch.js +0 -1
  132. package/src/utils/private/vm.js +0 -1
  133. package/src/utils/run-sequential-promises.js +0 -1
@@ -2,7 +2,7 @@
2
2
  "$schema": "",
3
3
  "framework": "vue",
4
4
  "name": "quasar",
5
- "version": "2.14.2",
5
+ "version": "2.14.3",
6
6
  "contributions": {
7
7
  "html": {
8
8
  "types-syntax": "typescript",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quasar",
3
- "version": "2.14.2",
3
+ "version": "2.14.3",
4
4
  "description": "Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time",
5
5
  "main": "dist/quasar.cjs.prod.js",
6
6
  "module": "dist/quasar.esm.prod.js",
@@ -105,7 +105,7 @@
105
105
  "table": "^6.8.1",
106
106
  "typescript": "^4.9.5",
107
107
  "uglify-es": "^3.3.9",
108
- "vue": "^3.3.4",
108
+ "vue": "^3.4.15",
109
109
  "vue-router": "^4.2.1",
110
110
  "yargs": "^17.7.2"
111
111
  },
@@ -184,13 +184,23 @@ export default createComponent({
184
184
 
185
185
  progress.value = 0
186
186
 
187
+ /**
188
+ * We're trying to avoid side effects if start() is called inside a watchEffect()
189
+ * so we're accessing the _value property directly (under the covers implementation detail of ref())
190
+ *
191
+ * Otherwise, any refs() accessed here would be marked as deps for the watchEffect()
192
+ * -- and we are changing them below, which would cause an infinite loop
193
+ */
194
+
187
195
  timer = setTimeout(() => {
188
196
  timer = null
189
197
  animate.value = true
190
198
  newSpeed > 0 && planNextStep()
191
- }, onScreen.value === true ? 500 : 1)
199
+ // eslint-disable-next-line vue/no-ref-as-operand
200
+ }, onScreen._value === true ? 500 : 1)
192
201
 
193
- if (onScreen.value !== true) {
202
+ // eslint-disable-next-line vue/no-ref-as-operand
203
+ if (onScreen._value !== true) {
194
204
  onScreen.value = true
195
205
  animate.value = false
196
206
  }
@@ -6,11 +6,11 @@ import QBtnGroup from '../btn-group/QBtnGroup.js'
6
6
  import QMenu from '../menu/QMenu.js'
7
7
 
8
8
  import { getBtnDesignAttr, useBtnProps } from '../btn/use-btn.js'
9
+ import useId from '../../composables/private/use-id.js'
9
10
  import { useTransitionProps } from '../../composables/private/use-transition.js'
10
11
 
11
12
  import { createComponent } from '../../utils/private/create.js'
12
13
  import { stop } from '../../utils/event.js'
13
- import uid from '../../utils/uid.js'
14
14
  import { hSlot } from '../../utils/private/render.js'
15
15
 
16
16
  const btnPropsList = Object.keys(useBtnProps)
@@ -70,13 +70,13 @@ export default createComponent({
70
70
 
71
71
  const showing = ref(props.modelValue)
72
72
  const menuRef = ref(null)
73
- const targetUid = uid()
73
+ const targetUid = useId()
74
74
 
75
75
  const ariaAttrs = computed(() => {
76
76
  const acc = {
77
77
  'aria-expanded': showing.value === true ? 'true' : 'false',
78
78
  'aria-haspopup': 'true',
79
- 'aria-controls': targetUid,
79
+ 'aria-controls': targetUid.value,
80
80
  'aria-label': props.toggleAriaLabel || proxy.$q.lang.label[ showing.value === true ? 'collapse' : 'expand' ](props.label)
81
81
  }
82
82
 
@@ -170,7 +170,7 @@ export default createComponent({
170
170
  props.disableDropdown !== true && Arrow.push(
171
171
  h(QMenu, {
172
172
  ref: menuRef,
173
- id: targetUid,
173
+ id: targetUid.value,
174
174
  class: props.contentClass,
175
175
  style: props.contentStyle,
176
176
  cover: props.cover,
@@ -8,6 +8,7 @@ import QSlideTransition from '../slide-transition/QSlideTransition.js'
8
8
  import QSeparator from '../separator/QSeparator.js'
9
9
 
10
10
  import useDark, { useDarkProps } from '../../composables/private/use-dark.js'
11
+ import useId from '../../composables/private/use-id.js'
11
12
  import { useRouterLinkProps } from '../../composables/private/use-router-link.js'
12
13
  import useModelToggle, { useModelToggleProps, useModelToggleEmits } from '../../composables/private/use-model-toggle.js'
13
14
 
@@ -75,7 +76,7 @@ export default createComponent({
75
76
  )
76
77
 
77
78
  const blurTargetRef = ref(null)
78
- const targetUid = uid()
79
+ const targetUid = useId()
79
80
 
80
81
  const { show, hide, toggle } = useModelToggle({ showing })
81
82
 
@@ -143,7 +144,7 @@ export default createComponent({
143
144
  return {
144
145
  role: 'button',
145
146
  'aria-expanded': showing.value === true ? 'true' : 'false',
146
- 'aria-controls': targetUid,
147
+ 'aria-controls': targetUid.value,
147
148
  'aria-label': toggleAriaLabel
148
149
  }
149
150
  })
@@ -320,7 +321,7 @@ export default createComponent({
320
321
  key: 'e-content',
321
322
  class: 'q-expansion-item__content relative-position',
322
323
  style: contentStyle.value,
323
- id: targetUid
324
+ id: targetUid.value
324
325
  }, hSlot(slots.default)),
325
326
  [ [
326
327
  vShow,
@@ -4,12 +4,12 @@ import QBtn from '../btn/QBtn.js'
4
4
  import QIcon from '../icon/QIcon.js'
5
5
 
6
6
  import useFab, { useFabProps } from './use-fab.js'
7
+ import useId from '../../composables/private/use-id.js'
7
8
  import useModelToggle, { useModelToggleProps, useModelToggleEmits } from '../../composables/private/use-model-toggle.js'
8
9
 
9
10
  import { createComponent } from '../../utils/private/create.js'
10
11
  import { hSlot, hMergeSlot } from '../../utils/private/render.js'
11
12
  import { fabKey } from '../../utils/private/symbols.js'
12
- import uid from '../../utils/uid.js'
13
13
 
14
14
  const directions = [ 'up', 'right', 'down', 'left' ]
15
15
  const alignValues = [ 'left', 'center', 'right' ]
@@ -49,7 +49,7 @@ export default createComponent({
49
49
  setup (props, { slots }) {
50
50
  const triggerRef = ref(null)
51
51
  const showing = ref(props.modelValue === true)
52
- const targetUid = uid()
52
+ const targetUid = useId()
53
53
 
54
54
  const { proxy: { $q } } = getCurrentInstance()
55
55
  const { formClass, labelProps } = useFab(props, showing)
@@ -77,7 +77,7 @@ export default createComponent({
77
77
 
78
78
  const actionAttrs = computed(() => {
79
79
  const attrs = {
80
- id: targetUid,
80
+ id: targetUid.value,
81
81
  role: 'menu'
82
82
  }
83
83
 
@@ -149,7 +149,7 @@ export default createComponent({
149
149
  fab: true,
150
150
  'aria-expanded': showing.value === true ? 'true' : 'false',
151
151
  'aria-haspopup': 'true',
152
- 'aria-controls': targetUid,
152
+ 'aria-controls': targetUid.value,
153
153
  onClick: toggle
154
154
  }, getTriggerContent),
155
155
 
@@ -194,13 +194,13 @@ export default createComponent({
194
194
  }
195
195
 
196
196
  if (type.value.img === true) {
197
- return h('span', data, hMergeSlot(slots.default, [
197
+ return h(props.tag, data, hMergeSlot(slots.default, [
198
198
  h('img', { src: type.value.src })
199
199
  ]))
200
200
  }
201
201
 
202
202
  if (type.value.svg === true) {
203
- return h('span', data, hMergeSlot(slots.default, [
203
+ return h(props.tag, data, hMergeSlot(slots.default, [
204
204
  h('svg', {
205
205
  viewBox: type.value.viewBox || '0 0 24 24'
206
206
  }, type.value.nodes)
@@ -208,7 +208,7 @@ export default createComponent({
208
208
  }
209
209
 
210
210
  if (type.value.svguse === true) {
211
- return h('span', data, hMergeSlot(slots.default, [
211
+ return h(props.tag, data, hMergeSlot(slots.default, [
212
212
  h('svg', {
213
213
  viewBox: type.value.viewBox
214
214
  }, [
@@ -236,7 +236,7 @@ export default createComponent({
236
236
  const vm = getCurrentInstance()
237
237
  Object.assign(vm.proxy, {
238
238
  poll: () => { poll !== void 0 && poll() },
239
- trigger, stop, reset, resume, setIndex
239
+ trigger, stop, reset, resume, setIndex, updateScrollTarget
240
240
  })
241
241
 
242
242
  return () => {
@@ -271,8 +271,11 @@ describe('Menu API', () => {
271
271
  })
272
272
  cy.dataCy('wrapper')
273
273
  .click()
274
+
274
275
  cy.dataCy('menu')
275
276
  .checkVerticalPosition('wrapper', 'center', 'center')
277
+
278
+ cy.dataCy('menu')
276
279
  .checkHorizontalPosition('wrapper', 'middle', 'middle')
277
280
  })
278
281
 
@@ -285,8 +288,11 @@ describe('Menu API', () => {
285
288
  })
286
289
  cy.dataCy('other-target')
287
290
  .click()
291
+
288
292
  cy.dataCy('menu')
289
293
  .checkVerticalPosition('other-target', 'center', 'center')
294
+
295
+ cy.dataCy('menu')
290
296
  .checkHorizontalPosition('other-target', 'middle', 'middle')
291
297
  })
292
298
 
@@ -300,8 +306,11 @@ describe('Menu API', () => {
300
306
  })
301
307
  cy.dataCy('other-target')
302
308
  .click()
309
+
303
310
  cy.dataCy('menu')
304
311
  .checkVerticalPosition('other-target', 'center', 'center')
312
+
313
+ cy.dataCy('menu')
305
314
  .checkHorizontalPosition('other-target', 'middle', 'middle')
306
315
  })
307
316
  })
@@ -312,8 +321,11 @@ describe('Menu API', () => {
312
321
 
313
322
  cy.dataCy('wrapper')
314
323
  .click()
324
+
315
325
  cy.dataCy('menu')
316
326
  .checkVerticalPosition('wrapper', 'bottom', 'top')
327
+
328
+ cy.dataCy('menu')
317
329
  .checkHorizontalPosition('wrapper', 'left', 'left')
318
330
  })
319
331
 
@@ -335,8 +347,11 @@ describe('Menu API', () => {
335
347
 
336
348
  cy.dataCy('wrapper')
337
349
  .click()
350
+
338
351
  cy.dataCy('menu')
339
352
  .checkVerticalPosition('wrapper', vA, vS)
353
+
354
+ cy.dataCy('menu')
340
355
  .checkHorizontalPosition('wrapper', hA, hS)
341
356
  })
342
357
  })
@@ -535,12 +550,17 @@ describe('Menu API', () => {
535
550
  cy.dataCy('menu')
536
551
  .should('exist')
537
552
  .checkVerticalPosition('wrapper', 'bottom', 'bottom')
553
+
554
+ cy.dataCy('menu')
538
555
  .checkHorizontalPosition('wrapper', 'left', 'left')
556
+
557
+ cy.dataCy('menu')
539
558
  .then(($el) => {
540
559
  const rect = $el[ 0 ].getBoundingClientRect()
541
560
  bottom = rect.bottom
542
561
  left = rect.left
543
562
  })
563
+
544
564
  cy.dataCy('div')
545
565
  .then(($el) => {
546
566
  $el[ 0 ].style.height = '100px'
@@ -550,12 +570,16 @@ describe('Menu API', () => {
550
570
  expect(rect.bottom).to.equal(bottom - 100)
551
571
  expect(rect.left).to.equal(left)
552
572
  })
573
+
553
574
  cy.dataCy('wrapper')
554
575
  .then(() => {
555
576
  Cypress.vueWrapper.vm.updatePosition()
556
577
  })
578
+
557
579
  cy.dataCy('menu')
558
580
  .checkVerticalPosition('wrapper', 'bottom', 'bottom')
581
+
582
+ cy.dataCy('menu')
559
583
  .checkHorizontalPosition('wrapper', 'left', 'left')
560
584
  })
561
585
  })
@@ -140,7 +140,7 @@ export default function (props, slots, emit, routeData) {
140
140
  if (
141
141
  hardError === void 0 && (
142
142
  softError === void 0
143
- || softError.message.startsWith('Avoided redundant navigation') === true
143
+ || (softError.message !== void 0 && softError.message.startsWith('Avoided redundant navigation') === true)
144
144
  )
145
145
  ) {
146
146
  $tabs.updateModel({ name: props.name })
@@ -1,25 +1,17 @@
1
1
  import { h, ref, computed, watch, Transition, nextTick, onActivated, onDeactivated, onBeforeUnmount, onMounted, getCurrentInstance } from 'vue'
2
2
 
3
- import { isRuntimeSsrPreHydration } from '../../plugins/Platform.js'
4
-
5
3
  import QIcon from '../../components/icon/QIcon.js'
6
4
  import QSpinner from '../../components/spinner/QSpinner.js'
7
5
 
8
6
  import useDark, { useDarkProps } from '../../composables/private/use-dark.js'
7
+ import useId, { getId } from './use-id.js'
9
8
  import useValidate, { useValidateProps } from './use-validate.js'
10
9
  import useSplitAttrs from './use-split-attrs.js'
11
10
 
12
11
  import { hSlot } from '../../utils/private/render.js'
13
- import uid from '../../utils/uid.js'
14
12
  import { prevent, stopAndPrevent } from '../../utils/event.js'
15
13
  import { addFocusFn, removeFocusFn } from '../../utils/private/focus-manager.js'
16
14
 
17
- function getTargetUid (val, requiredForAttr) {
18
- return val === void 0
19
- ? (requiredForAttr === true ? `f_${ uid() }` : void 0)
20
- : val
21
- }
22
-
23
15
  export function fieldValueIsFilled (val) {
24
16
  return val !== void 0
25
17
  && val !== null
@@ -80,6 +72,7 @@ export function useFieldState ({ requiredForAttr = true, tagProp } = {}) {
80
72
  const { props, attrs, proxy, vnode } = getCurrentInstance()
81
73
 
82
74
  const isDark = useDark(props, proxy.$q)
75
+ const targetUid = useId(props.for, requiredForAttr)
83
76
 
84
77
  return {
85
78
  requiredForAttr,
@@ -98,9 +91,7 @@ export function useFieldState ({ requiredForAttr = true, tagProp } = {}) {
98
91
  hasPopupOpen: false,
99
92
 
100
93
  splitAttrs: useSplitAttrs(attrs, vnode),
101
- targetUid: ref(
102
- getTargetUid(props.for, requiredForAttr)
103
- ),
94
+ targetUid,
104
95
 
105
96
  rootRef: ref(null),
106
97
  targetRef: ref(null),
@@ -252,8 +243,10 @@ export default function (state) {
252
243
  }))
253
244
 
254
245
  const attributes = computed(() => {
255
- const acc = {
256
- for: state.targetUid.value
246
+ const acc = {}
247
+
248
+ if (state.targetUid.value) {
249
+ acc.for = state.targetUid.value
257
250
  }
258
251
 
259
252
  if (props.disable === true) {
@@ -266,7 +259,7 @@ export default function (state) {
266
259
  watch(() => props.for, val => {
267
260
  // don't transform targetUid into a computed
268
261
  // prop as it will break SSR
269
- state.targetUid.value = getTargetUid(val, state.requiredForAttr)
262
+ state.targetUid.value = getId(val, state.requiredForAttr)
270
263
  })
271
264
 
272
265
  function focusHandler () {
@@ -342,7 +335,7 @@ export default function (state) {
342
335
  document.activeElement.blur()
343
336
  }
344
337
 
345
- if (props.type === 'file') { // TODO vue3
338
+ if (props.type === 'file') {
346
339
  // do not let focus be triggered
347
340
  // as it will make the native file dialog
348
341
  // appear for another selection
@@ -353,11 +346,9 @@ export default function (state) {
353
346
  emit('clear', props.modelValue)
354
347
 
355
348
  nextTick(() => {
349
+ const isDirty = isDirtyModel.value
356
350
  resetValidation()
357
-
358
- if ($q.platform.is.mobile !== true) {
359
- isDirtyModel.value = false
360
- }
351
+ isDirtyModel.value = isDirty
361
352
  })
362
353
  }
363
354
 
@@ -550,16 +541,8 @@ export default function (state) {
550
541
  shouldActivate === true && props.autofocus === true && proxy.focus()
551
542
  })
552
543
 
553
- onMounted(() => {
554
- if (
555
- isRuntimeSsrPreHydration.value === true
556
- && state.requiredForAttr === true
557
- && props.for === void 0
558
- ) {
559
- state.targetUid.value = `f_${ uid() }` // getTargetUid(void 0, true)
560
- }
561
-
562
- props.autofocus === true && proxy.focus()
544
+ props.autofocus === true && onMounted(() => {
545
+ proxy.focus()
563
546
  })
564
547
 
565
548
  onBeforeUnmount(() => {
@@ -0,0 +1,34 @@
1
+ import { ref, onMounted } from 'vue'
2
+
3
+ import uid from '../../utils/uid.js'
4
+
5
+ import { isRuntimeSsrPreHydration } from '../../plugins/Platform.js'
6
+
7
+ export function getId (val, requiredId) {
8
+ return val === void 0
9
+ ? (requiredId === true ? `f_${ uid() }` : void 0)
10
+ : val
11
+ }
12
+
13
+ /**
14
+ * Returns an "id" which is a ref() that can be used as a unique identifier.
15
+ * On SSR, it takes care of generating the id on the client side (only) to
16
+ * avoid hydration errors.
17
+ */
18
+ export default function (initialId, requiredId = true) {
19
+ if (isRuntimeSsrPreHydration.value === true) {
20
+ const id = ref(initialId)
21
+
22
+ if (requiredId === true && initialId === void 0) {
23
+ onMounted(() => {
24
+ id.value = `f_${ uid() }` // getId(void 0, true)
25
+ })
26
+ }
27
+
28
+ return id
29
+ }
30
+
31
+ return ref(
32
+ getId(initialId, requiredId)
33
+ )
34
+ }
@@ -31,7 +31,7 @@ export default function (focused, innerLoading) {
31
31
 
32
32
  const innerError = ref(false)
33
33
  const innerErrorMessage = ref(null)
34
- const isDirtyModel = ref(null)
34
+ const isDirtyModel = ref(false)
35
35
 
36
36
  useFormChild({ validate, resetValidation })
37
37
 
@@ -74,18 +74,20 @@ export default function (focused, innerLoading) {
74
74
  }
75
75
  })
76
76
 
77
+ function onRulesChange () {
78
+ if (
79
+ props.lazyRules !== 'ondemand'
80
+ && canDebounceValidate.value === true
81
+ && isDirtyModel.value === true
82
+ ) {
83
+ debouncedValidate()
84
+ }
85
+ }
86
+
77
87
  watch(() => props.reactiveRules, val => {
78
88
  if (val === true) {
79
89
  if (unwatchRules === void 0) {
80
- unwatchRules = watch(() => props.rules, () => {
81
- if (
82
- canDebounceValidate.value === true
83
- && isDirtyModel.value === true
84
- && props.lazyRules !== 'ondemand'
85
- ) {
86
- debouncedValidate()
87
- }
88
- }, { immediate: true })
90
+ unwatchRules = watch(() => props.rules, onRulesChange, { immediate: true, deep: true })
89
91
  }
90
92
  }
91
93
  else if (unwatchRules !== void 0) {
@@ -94,30 +96,15 @@ export default function (focused, innerLoading) {
94
96
  }
95
97
  }, { immediate: true })
96
98
 
97
- watch(() => props.lazyRules, val => {
98
- if (
99
- val === false
100
- && canDebounceValidate.value === true
101
- && isDirtyModel.value === true
102
- ) {
103
- debouncedValidate()
104
- }
105
- })
99
+ watch(() => props.lazyRules, onRulesChange)
106
100
 
107
101
  watch(focused, val => {
108
102
  if (val === true) {
109
- if (isDirtyModel.value === null) {
110
- isDirtyModel.value = props.lazyRules === true
111
- }
103
+ isDirtyModel.value = true
112
104
  }
113
105
  else if (
114
106
  canDebounceValidate.value === true
115
- && (
116
- // props.lazyRules can also be 'ondemand',
117
- // hence the following form:
118
- props.lazyRules === false
119
- || (props.lazyRules === true && isDirtyModel.value === true)
120
- )
107
+ && props.lazyRules !== 'ondemand'
121
108
  ) {
122
109
  debouncedValidate()
123
110
  }
@@ -126,7 +113,7 @@ export default function (focused, innerLoading) {
126
113
  function resetValidation () {
127
114
  validateIndex++
128
115
  innerLoading.value = false
129
- isDirtyModel.value = null
116
+ isDirtyModel.value = false
130
117
  innerError.value = false
131
118
  innerErrorMessage.value = null
132
119
  debouncedValidate.cancel()
@@ -1,5 +1,4 @@
1
1
  import defineReactivePlugin from '../utils/private/define-reactive-plugin.js'
2
- import { isRuntimeSsrPreHydration } from './Platform.js'
3
2
 
4
3
  const Plugin = defineReactivePlugin({
5
4
  isActive: false,
@@ -38,7 +37,7 @@ const Plugin = defineReactivePlugin({
38
37
  }
39
38
  },
40
39
 
41
- install ({ $q, onSSRHydrated, ssrContext }) {
40
+ install ({ $q, ssrContext }) {
42
41
  const { dark } = $q.config
43
42
 
44
43
  if (__QUASAR_SSR_SERVER__) {
@@ -66,31 +65,8 @@ const Plugin = defineReactivePlugin({
66
65
 
67
66
  $q.dark = this
68
67
 
69
- if (this.__installed === true && dark === void 0) {
70
- return
71
- }
72
-
73
- this.isActive = dark === true
74
-
75
- const initialVal = dark !== void 0 ? dark : false
76
-
77
- if (isRuntimeSsrPreHydration.value === true) {
78
- const ssrSet = val => {
79
- this.__fromSSR = val
80
- }
81
-
82
- const originalSet = this.set
83
-
84
- this.set = ssrSet
85
- ssrSet(initialVal)
86
-
87
- onSSRHydrated.push(() => {
88
- this.set = originalSet
89
- this.set(this.__fromSSR)
90
- })
91
- }
92
- else {
93
- this.set(initialVal)
68
+ if (this.__installed !== true) {
69
+ this.set(dark !== void 0 ? dark : false)
94
70
  }
95
71
  }
96
72
  })
@@ -1,4 +1,3 @@
1
-
2
1
  import { addFocusout, removeFocusout } from './private/focusout.js'
3
2
 
4
3
  function fallback (text) {
@@ -1,4 +1,3 @@
1
-
2
1
  export default function getCssVar (propName, element = document.body) {
3
2
  if (typeof propName !== 'string') {
4
3
  throw new TypeError('Expected a string as propName')
package/src/utils/is.js CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  export function isDeepEqual (a, b) {
3
2
  if (a === b) {
4
3
  return true
@@ -1,4 +1,3 @@
1
-
2
1
  import { reactive } from 'vue'
3
2
  import { injectProp } from './inject-obj-prop.js'
4
3
 
@@ -1,4 +1,3 @@
1
-
2
1
  export const globalConfig = {}
3
2
  export let globalConfigIsFrozen = false
4
3
 
@@ -1,4 +1,3 @@
1
-
2
1
  const modifiersAll = {
3
2
  left: true,
4
3
  right: true,
@@ -1,4 +1,3 @@
1
-
2
1
  // copied to docs too
3
2
  export function getParentProxy (proxy) {
4
3
  if (Object(proxy.$parent) === proxy.$parent) {
@@ -1,4 +1,3 @@
1
-
2
1
  function parsePromises (sequentialPromises) {
3
2
  const isList = Array.isArray(sequentialPromises)
4
3