quasar 2.14.1 → 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 (144) hide show
  1. package/dist/api/Notify.json +2 -2
  2. package/dist/icon-set/bootstrap-icons.umd.prod.js +1 -1
  3. package/dist/icon-set/eva-icons.umd.prod.js +1 -1
  4. package/dist/icon-set/fontawesome-v5-pro.umd.prod.js +1 -1
  5. package/dist/icon-set/fontawesome-v5.umd.prod.js +1 -1
  6. package/dist/icon-set/fontawesome-v6-pro.umd.prod.js +1 -1
  7. package/dist/icon-set/fontawesome-v6.umd.prod.js +1 -1
  8. package/dist/icon-set/ionicons-v4.umd.prod.js +1 -1
  9. package/dist/icon-set/line-awesome.umd.prod.js +1 -1
  10. package/dist/icon-set/material-icons-outlined.umd.prod.js +1 -1
  11. package/dist/icon-set/material-icons-round.umd.prod.js +1 -1
  12. package/dist/icon-set/material-icons-sharp.umd.prod.js +1 -1
  13. package/dist/icon-set/material-icons.umd.prod.js +1 -1
  14. package/dist/icon-set/material-symbols-outlined.umd.prod.js +1 -1
  15. package/dist/icon-set/material-symbols-rounded.umd.prod.js +1 -1
  16. package/dist/icon-set/material-symbols-sharp.umd.prod.js +1 -1
  17. package/dist/icon-set/mdi-v3.umd.prod.js +1 -1
  18. package/dist/icon-set/mdi-v4.umd.prod.js +1 -1
  19. package/dist/icon-set/mdi-v5.umd.prod.js +1 -1
  20. package/dist/icon-set/mdi-v6.umd.prod.js +1 -1
  21. package/dist/icon-set/mdi-v7.umd.prod.js +1 -1
  22. package/dist/icon-set/svg-bootstrap-icons.umd.prod.js +2 -2
  23. package/dist/icon-set/svg-eva-icons.umd.prod.js +1 -1
  24. package/dist/icon-set/svg-fontawesome-v5.umd.prod.js +1 -1
  25. package/dist/icon-set/svg-fontawesome-v6.umd.prod.js +1 -1
  26. package/dist/icon-set/svg-ionicons-v4.umd.prod.js +1 -1
  27. package/dist/icon-set/svg-ionicons-v5.umd.prod.js +1 -1
  28. package/dist/icon-set/svg-ionicons-v6.umd.prod.js +1 -1
  29. package/dist/icon-set/svg-line-awesome.umd.prod.js +1 -1
  30. package/dist/icon-set/svg-material-icons-outlined.umd.prod.js +1 -1
  31. package/dist/icon-set/svg-material-icons-round.umd.prod.js +1 -1
  32. package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +1 -1
  33. package/dist/icon-set/svg-material-icons.umd.prod.js +1 -1
  34. package/dist/icon-set/svg-material-symbols-outlined.umd.prod.js +1 -1
  35. package/dist/icon-set/svg-material-symbols-rounded.umd.prod.js +1 -1
  36. package/dist/icon-set/svg-material-symbols-sharp.umd.prod.js +1 -1
  37. package/dist/icon-set/svg-mdi-v6.umd.prod.js +1 -1
  38. package/dist/icon-set/svg-mdi-v7.umd.prod.js +1 -1
  39. package/dist/icon-set/svg-themify.umd.prod.js +1 -1
  40. package/dist/icon-set/themify.umd.prod.js +1 -1
  41. package/dist/lang/ar-TN.umd.prod.js +1 -1
  42. package/dist/lang/ar.umd.prod.js +1 -1
  43. package/dist/lang/az-Latn.umd.prod.js +1 -1
  44. package/dist/lang/bg.umd.prod.js +1 -1
  45. package/dist/lang/bn.umd.prod.js +1 -1
  46. package/dist/lang/ca.umd.prod.js +1 -1
  47. package/dist/lang/cs.umd.prod.js +1 -1
  48. package/dist/lang/da.umd.prod.js +1 -1
  49. package/dist/lang/de-CH.umd.prod.js +1 -1
  50. package/dist/lang/de-DE.umd.prod.js +1 -1
  51. package/dist/lang/de.umd.prod.js +1 -1
  52. package/dist/lang/el.umd.prod.js +1 -1
  53. package/dist/lang/en-GB.umd.prod.js +1 -1
  54. package/dist/lang/en-US.umd.prod.js +1 -1
  55. package/dist/lang/eo.umd.prod.js +1 -1
  56. package/dist/lang/es.umd.prod.js +1 -1
  57. package/dist/lang/et.umd.prod.js +1 -1
  58. package/dist/lang/eu.umd.prod.js +1 -1
  59. package/dist/lang/fa-IR.umd.prod.js +1 -1
  60. package/dist/lang/fa.umd.prod.js +1 -1
  61. package/dist/lang/fi.umd.prod.js +1 -1
  62. package/dist/lang/fr.umd.prod.js +1 -1
  63. package/dist/lang/gn.umd.prod.js +1 -1
  64. package/dist/lang/he.umd.prod.js +1 -1
  65. package/dist/lang/hi.umd.prod.js +1 -1
  66. package/dist/lang/hr.umd.prod.js +1 -1
  67. package/dist/lang/hu.umd.prod.js +1 -1
  68. package/dist/lang/id.umd.prod.js +1 -1
  69. package/dist/lang/is.umd.prod.js +1 -1
  70. package/dist/lang/it.umd.prod.js +1 -1
  71. package/dist/lang/ja.umd.prod.js +1 -1
  72. package/dist/lang/kk.umd.prod.js +1 -1
  73. package/dist/lang/km.umd.prod.js +1 -1
  74. package/dist/lang/ko-KR.umd.prod.js +1 -1
  75. package/dist/lang/kur-CKB.umd.prod.js +1 -1
  76. package/dist/lang/lt.umd.prod.js +1 -1
  77. package/dist/lang/lu.umd.prod.js +1 -1
  78. package/dist/lang/lv.umd.prod.js +1 -1
  79. package/dist/lang/mk.umd.prod.js +1 -1
  80. package/dist/lang/ml.umd.prod.js +1 -1
  81. package/dist/lang/mm.umd.prod.js +1 -1
  82. package/dist/lang/ms.umd.prod.js +1 -1
  83. package/dist/lang/my.umd.prod.js +1 -1
  84. package/dist/lang/nb-NO.umd.prod.js +1 -1
  85. package/dist/lang/nl.umd.prod.js +1 -1
  86. package/dist/lang/pl.umd.prod.js +1 -1
  87. package/dist/lang/pt-BR.umd.prod.js +1 -1
  88. package/dist/lang/pt.umd.prod.js +1 -1
  89. package/dist/lang/ro.umd.prod.js +1 -1
  90. package/dist/lang/ru.umd.prod.js +1 -1
  91. package/dist/lang/sk.umd.prod.js +1 -1
  92. package/dist/lang/sl.umd.prod.js +1 -1
  93. package/dist/lang/sm.umd.prod.js +1 -1
  94. package/dist/lang/sr-CYR.umd.prod.js +1 -1
  95. package/dist/lang/sr.umd.prod.js +1 -1
  96. package/dist/lang/sv.umd.prod.js +1 -1
  97. package/dist/lang/ta.umd.prod.js +1 -1
  98. package/dist/lang/th.umd.prod.js +1 -1
  99. package/dist/lang/tr.umd.prod.js +1 -1
  100. package/dist/lang/ug.umd.prod.js +1 -1
  101. package/dist/lang/uk.umd.prod.js +1 -1
  102. package/dist/lang/uz-Cyrl.umd.prod.js +1 -1
  103. package/dist/lang/uz-Latn.umd.prod.js +1 -1
  104. package/dist/lang/vi.umd.prod.js +1 -1
  105. package/dist/lang/zh-CN.umd.prod.js +1 -1
  106. package/dist/lang/zh-TW.umd.prod.js +1 -1
  107. package/dist/quasar.cjs.prod.js +2 -2
  108. package/dist/quasar.esm.js +153 -146
  109. package/dist/quasar.esm.prod.js +2 -2
  110. package/dist/quasar.sass +1 -1
  111. package/dist/quasar.umd.js +153 -146
  112. package/dist/quasar.umd.prod.js +2 -2
  113. package/dist/types/index.d.ts +2 -2
  114. package/dist/web-types/web-types.json +1 -1
  115. package/package.json +2 -2
  116. package/src/components/ajax-bar/QAjaxBar.js +12 -2
  117. package/src/components/btn-dropdown/QBtnDropdown.js +4 -4
  118. package/src/components/color/QColor.js +5 -9
  119. package/src/components/date/QDate.js +1 -1
  120. package/src/components/editor/QEditor.js +1 -1
  121. package/src/components/expansion-item/QExpansionItem.js +4 -3
  122. package/src/components/fab/QFab.js +4 -4
  123. package/src/components/icon/QIcon.js +3 -3
  124. package/src/components/infinite-scroll/QInfiniteScroll.js +1 -1
  125. package/src/components/menu/__tests__/QMenu.cy.js +24 -0
  126. package/src/components/range/QRange.js +8 -8
  127. package/src/components/resize-observer/QResizeObserver.js +3 -3
  128. package/src/components/slider/QSlider.js +2 -2
  129. package/src/components/slider/use-slider.js +14 -8
  130. package/src/components/tabs/use-tab.js +1 -1
  131. package/src/composables/private/use-field.js +13 -33
  132. package/src/composables/private/use-id.js +34 -0
  133. package/src/composables/private/use-validate.js +41 -35
  134. package/src/plugins/Dark.js +3 -27
  135. package/src/plugins/Notify.js +4 -3
  136. package/src/plugins/Notify.json +2 -2
  137. package/src/utils/copy-to-clipboard.js +0 -1
  138. package/src/utils/get-css-var.js +0 -1
  139. package/src/utils/is.js +0 -1
  140. package/src/utils/private/define-reactive-plugin.js +0 -1
  141. package/src/utils/private/global-config.js +0 -1
  142. package/src/utils/private/touch.js +0 -1
  143. package/src/utils/private/vm.js +0 -1
  144. package/src/utils/run-sequential-promises.js +0 -1
@@ -14516,7 +14516,7 @@ export interface QNotifyCreateOptions {
14516
14516
  */
14517
14517
  attrs?: any;
14518
14518
  /**
14519
- * Amount of time to display (in milliseconds)
14519
+ * Amount of time to display (in milliseconds). Set to 0 to never dismiss automatically.
14520
14520
  * Default value: 5000
14521
14521
  */
14522
14522
  timeout?: number;
@@ -15530,7 +15530,7 @@ declare module "./config.d.ts" {
15530
15530
  */
15531
15531
  attrs?: any;
15532
15532
  /**
15533
- * Amount of time to display (in milliseconds)
15533
+ * Amount of time to display (in milliseconds). Set to 0 to never dismiss automatically.
15534
15534
  * Default value: 5000
15535
15535
  */
15536
15536
  timeout?: number;
@@ -2,7 +2,7 @@
2
2
  "$schema": "",
3
3
  "framework": "vue",
4
4
  "name": "quasar",
5
- "version": "2.14.1",
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.1",
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,
@@ -176,15 +176,11 @@ export default createComponent({
176
176
  + (isDark.value === true ? ' q-color-picker--dark q-dark' : '')
177
177
  )
178
178
 
179
- const attributes = computed(() => {
180
- if (props.disable === true) {
181
- return { 'aria-disabled': 'true' }
182
- }
183
- if (props.readonly === true) {
184
- return { 'aria-readonly': 'true' }
185
- }
186
- return {}
187
- })
179
+ const attributes = computed(() => (
180
+ props.disable === true
181
+ ? { 'aria-disabled': 'true' }
182
+ : {}
183
+ ))
188
184
 
189
185
  const spectrumDirective = computed(() => {
190
186
  // if editable.value === true
@@ -694,7 +694,7 @@ export default createComponent({
694
694
  const attributes = computed(() => (
695
695
  props.disable === true
696
696
  ? { 'aria-disabled': 'true' }
697
- : (props.readonly === true ? { 'aria-readonly': 'true' } : {})
697
+ : {}
698
698
  ))
699
699
 
700
700
  watch(() => props.modelValue, v => {
@@ -323,7 +323,7 @@ export default createComponent({
323
323
  const attributes = computed(() => (
324
324
  props.disable === true
325
325
  ? { 'aria-disabled': 'true' }
326
- : (props.readonly === true ? { 'aria-readonly': 'true' } : {})
326
+ : {}
327
327
  ))
328
328
 
329
329
  function onInput () {
@@ -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
  })
@@ -288,15 +288,15 @@ export default createComponent({
288
288
  case dragType.RANGE:
289
289
  const
290
290
  ratioDelta = ratio - dragging.offsetRatio,
291
- minR = between(dragging.ratioMin + ratioDelta, 0, 1 - dragging.rangeRatio),
291
+ minR = between(dragging.ratioMin + ratioDelta, state.innerMinRatio.value, state.innerMaxRatio.value - dragging.rangeRatio),
292
292
  modelDelta = localModel - dragging.offsetModel,
293
- min = between(dragging.valueMin + modelDelta, props.min, props.max - dragging.rangeValue)
293
+ min = between(dragging.valueMin + modelDelta, state.innerMin.value, state.innerMax.value - dragging.rangeValue)
294
294
 
295
295
  pos = {
296
296
  minR,
297
297
  maxR: minR + dragging.rangeRatio,
298
- min: parseFloat(min.toFixed(state.decimals.value)),
299
- max: parseFloat((min + dragging.rangeValue).toFixed(state.decimals.value))
298
+ min: state.roundValueFn.value(min),
299
+ max: state.roundValueFn.value(min + dragging.rangeValue)
300
300
  }
301
301
 
302
302
  state.focus.value = 'both'
@@ -326,7 +326,7 @@ export default createComponent({
326
326
  stopAndPrevent(evt)
327
327
 
328
328
  const
329
- stepVal = ([ 34, 33 ].includes(evt.keyCode) ? 10 : 1) * state.step.value,
329
+ stepVal = ([ 34, 33 ].includes(evt.keyCode) ? 10 : 1) * state.keyStep.value,
330
330
  offset = (
331
331
  ([ 34, 37, 40 ].includes(evt.keyCode) ? -1 : 1)
332
332
  * (state.isReversed.value === true ? -1 : 1)
@@ -336,14 +336,14 @@ export default createComponent({
336
336
  if (state.focus.value === 'both') {
337
337
  const interval = model.value.max - model.value.min
338
338
  const min = between(
339
- parseFloat((model.value.min + offset).toFixed(state.decimals.value)),
339
+ state.roundValueFn.value(model.value.min + offset),
340
340
  state.innerMin.value,
341
341
  state.innerMax.value - interval
342
342
  )
343
343
 
344
344
  model.value = {
345
345
  min,
346
- max: parseFloat((min + interval).toFixed(state.decimals.value))
346
+ max: state.roundValueFn.value(min + interval)
347
347
  }
348
348
  }
349
349
  else if (state.focus.value === false) {
@@ -355,7 +355,7 @@ export default createComponent({
355
355
  model.value = {
356
356
  ...model.value,
357
357
  [ which ]: between(
358
- parseFloat((model.value[ which ] + offset).toFixed(state.decimals.value)),
358
+ state.roundValueFn.value(model.value[ which ] + offset),
359
359
  which === 'min' ? state.innerMin.value : model.value.min,
360
360
  which === 'max' ? state.innerMax.value : model.value.max
361
361
  )
@@ -57,6 +57,9 @@ export default createComponent({
57
57
 
58
58
  const { proxy } = getCurrentInstance()
59
59
 
60
+ // expose public method
61
+ proxy.trigger = trigger
62
+
60
63
  if (hasObserver === true) {
61
64
  let observer
62
65
 
@@ -130,9 +133,6 @@ export default createComponent({
130
133
 
131
134
  onBeforeUnmount(cleanup)
132
135
 
133
- // expose public method
134
- proxy.trigger = trigger
135
-
136
136
  return () => {
137
137
  if (canRender.value === true) {
138
138
  return h('object', {
@@ -133,7 +133,7 @@ export default createComponent({
133
133
  stopAndPrevent(evt)
134
134
 
135
135
  const
136
- stepVal = ([ 34, 33 ].includes(evt.keyCode) ? 10 : 1) * state.step.value,
136
+ stepVal = ([ 34, 33 ].includes(evt.keyCode) ? 10 : 1) * state.keyStep.value,
137
137
  offset = (
138
138
  ([ 34, 37, 40 ].includes(evt.keyCode) ? -1 : 1)
139
139
  * (state.isReversed.value === true ? -1 : 1)
@@ -141,7 +141,7 @@ export default createComponent({
141
141
  )
142
142
 
143
143
  model.value = between(
144
- parseFloat((model.value + offset).toFixed(state.decimals.value)),
144
+ state.roundValueFn.value(model.value + offset),
145
145
  state.innerMin.value,
146
146
  state.innerMax.value
147
147
  )
@@ -129,8 +129,16 @@ export default function ({ updateValue, updatePosition, getDragging, formAttrs }
129
129
  && innerMin.value < innerMax.value
130
130
  ))
131
131
 
132
- const decimals = computed(() => (String(props.step).trim().split('.')[ 1 ] || '').length)
133
- const step = computed(() => (props.step === 0 ? 1 : props.step))
132
+ const roundValueFn = computed(() => {
133
+ if (props.step === 0) {
134
+ return v => v
135
+ }
136
+
137
+ const decimals = (String(props.step).trim().split('.')[ 1 ] || '').length
138
+ return v => parseFloat(v.toFixed(decimals))
139
+ })
140
+
141
+ const keyStep = computed(() => (props.step === 0 ? 1 : props.step))
134
142
  const tabindex = computed(() => (editable.value === true ? props.tabindex || 0 : -1))
135
143
 
136
144
  const trackLen = computed(() => props.max - props.min)
@@ -242,9 +250,7 @@ export default function ({ updateValue, updatePosition, getDragging, formAttrs }
242
250
  model += (Math.abs(modulo) >= step / 2 ? (modulo < 0 ? -1 : 1) * step : 0) - modulo
243
251
  }
244
252
 
245
- if (decimals.value > 0) {
246
- model = parseFloat(model.toFixed(decimals.value))
247
- }
253
+ model = roundValueFn.value(model)
248
254
 
249
255
  return between(model, innerMin.value, innerMax.value)
250
256
  }
@@ -270,7 +276,7 @@ export default function ({ updateValue, updatePosition, getDragging, formAttrs }
270
276
  }
271
277
 
272
278
  const markerStep = computed(() => (
273
- isNumber(props.markers) === true ? props.markers : step.value)
279
+ isNumber(props.markers) === true ? props.markers : keyStep.value)
274
280
  )
275
281
 
276
282
  const markerTicks = computed(() => {
@@ -630,8 +636,8 @@ export default function ({ updateValue, updatePosition, getDragging, formAttrs }
630
636
  tabindex,
631
637
  attributes,
632
638
 
633
- step,
634
- decimals,
639
+ roundValueFn,
640
+ keyStep,
635
641
  trackLen,
636
642
  innerMin,
637
643
  innerMinRatio,
@@ -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,16 +243,15 @@ 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) {
260
253
  acc[ 'aria-disabled' ] = 'true'
261
254
  }
262
- else if (props.readonly === true) {
263
- acc[ 'aria-readonly' ] = 'true'
264
- }
265
255
 
266
256
  return acc
267
257
  })
@@ -269,7 +259,7 @@ export default function (state) {
269
259
  watch(() => props.for, val => {
270
260
  // don't transform targetUid into a computed
271
261
  // prop as it will break SSR
272
- state.targetUid.value = getTargetUid(val, state.requiredForAttr)
262
+ state.targetUid.value = getId(val, state.requiredForAttr)
273
263
  })
274
264
 
275
265
  function focusHandler () {
@@ -345,7 +335,7 @@ export default function (state) {
345
335
  document.activeElement.blur()
346
336
  }
347
337
 
348
- if (props.type === 'file') { // TODO vue3
338
+ if (props.type === 'file') {
349
339
  // do not let focus be triggered
350
340
  // as it will make the native file dialog
351
341
  // appear for another selection
@@ -356,11 +346,9 @@ export default function (state) {
356
346
  emit('clear', props.modelValue)
357
347
 
358
348
  nextTick(() => {
349
+ const isDirty = isDirtyModel.value
359
350
  resetValidation()
360
-
361
- if ($q.platform.is.mobile !== true) {
362
- isDirtyModel.value = false
363
- }
351
+ isDirtyModel.value = isDirty
364
352
  })
365
353
  }
366
354
 
@@ -553,16 +541,8 @@ export default function (state) {
553
541
  shouldActivate === true && props.autofocus === true && proxy.focus()
554
542
  })
555
543
 
556
- onMounted(() => {
557
- if (
558
- isRuntimeSsrPreHydration.value === true
559
- && state.requiredForAttr === true
560
- && props.for === void 0
561
- ) {
562
- state.targetUid.value = `f_${ uid() }` // getTargetUid(void 0, true)
563
- }
564
-
565
- props.autofocus === true && proxy.focus()
544
+ props.autofocus === true && onMounted(() => {
545
+ proxy.focus()
566
546
  })
567
547
 
568
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
+ }