quasar 2.12.7 → 2.13.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 (140) hide show
  1. package/dist/api/QField.json +0 -3
  2. package/dist/api/QSelect.json +1 -1
  3. package/dist/api/QTable.json +54 -1
  4. package/dist/icon-set/bootstrap-icons.umd.prod.js +1 -1
  5. package/dist/icon-set/eva-icons.umd.prod.js +1 -1
  6. package/dist/icon-set/fontawesome-v5-pro.umd.prod.js +1 -1
  7. package/dist/icon-set/fontawesome-v5.umd.prod.js +1 -1
  8. package/dist/icon-set/fontawesome-v6-pro.umd.prod.js +1 -1
  9. package/dist/icon-set/fontawesome-v6.umd.prod.js +1 -1
  10. package/dist/icon-set/ionicons-v4.umd.prod.js +1 -1
  11. package/dist/icon-set/line-awesome.umd.prod.js +1 -1
  12. package/dist/icon-set/material-icons-outlined.umd.prod.js +1 -1
  13. package/dist/icon-set/material-icons-round.umd.prod.js +1 -1
  14. package/dist/icon-set/material-icons-sharp.umd.prod.js +1 -1
  15. package/dist/icon-set/material-icons.umd.prod.js +1 -1
  16. package/dist/icon-set/material-symbols-outlined.umd.prod.js +1 -1
  17. package/dist/icon-set/material-symbols-rounded.umd.prod.js +1 -1
  18. package/dist/icon-set/material-symbols-sharp.umd.prod.js +1 -1
  19. package/dist/icon-set/mdi-v3.umd.prod.js +1 -1
  20. package/dist/icon-set/mdi-v4.umd.prod.js +1 -1
  21. package/dist/icon-set/mdi-v5.umd.prod.js +1 -1
  22. package/dist/icon-set/mdi-v6.umd.prod.js +1 -1
  23. package/dist/icon-set/mdi-v7.umd.prod.js +1 -1
  24. package/dist/icon-set/svg-bootstrap-icons.umd.prod.js +1 -1
  25. package/dist/icon-set/svg-eva-icons.umd.prod.js +1 -1
  26. package/dist/icon-set/svg-fontawesome-v5.umd.prod.js +1 -1
  27. package/dist/icon-set/svg-fontawesome-v6.umd.prod.js +1 -1
  28. package/dist/icon-set/svg-ionicons-v4.umd.prod.js +1 -1
  29. package/dist/icon-set/svg-ionicons-v5.umd.prod.js +1 -1
  30. package/dist/icon-set/svg-ionicons-v6.umd.prod.js +1 -1
  31. package/dist/icon-set/svg-line-awesome.umd.prod.js +1 -1
  32. package/dist/icon-set/svg-material-icons-outlined.umd.prod.js +2 -2
  33. package/dist/icon-set/svg-material-icons-round.umd.prod.js +2 -2
  34. package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +2 -2
  35. package/dist/icon-set/svg-material-icons.umd.prod.js +2 -2
  36. package/dist/icon-set/svg-material-symbols-outlined.umd.prod.js +2 -2
  37. package/dist/icon-set/svg-material-symbols-rounded.umd.prod.js +2 -2
  38. package/dist/icon-set/svg-material-symbols-sharp.umd.prod.js +2 -2
  39. package/dist/icon-set/svg-mdi-v6.umd.prod.js +1 -1
  40. package/dist/icon-set/svg-mdi-v7.umd.prod.js +1 -1
  41. package/dist/icon-set/svg-themify.umd.prod.js +1 -1
  42. package/dist/icon-set/themify.umd.prod.js +1 -1
  43. package/dist/lang/ar-TN.umd.prod.js +1 -1
  44. package/dist/lang/ar.umd.prod.js +1 -1
  45. package/dist/lang/az-Latn.umd.prod.js +1 -1
  46. package/dist/lang/bg.umd.prod.js +1 -1
  47. package/dist/lang/bn.umd.prod.js +1 -1
  48. package/dist/lang/ca.umd.prod.js +1 -1
  49. package/dist/lang/cs.umd.prod.js +1 -1
  50. package/dist/lang/da.umd.prod.js +1 -1
  51. package/dist/lang/de-CH.umd.prod.js +6 -0
  52. package/dist/lang/de-DE.umd.prod.js +6 -0
  53. package/dist/lang/de.umd.prod.js +1 -1
  54. package/dist/lang/el.umd.prod.js +1 -1
  55. package/dist/lang/en-GB.umd.prod.js +1 -1
  56. package/dist/lang/en-US.umd.prod.js +1 -1
  57. package/dist/lang/eo.umd.prod.js +1 -1
  58. package/dist/lang/es.umd.prod.js +1 -1
  59. package/dist/lang/et.umd.prod.js +1 -1
  60. package/dist/lang/eu.umd.prod.js +1 -1
  61. package/dist/lang/fa-IR.umd.prod.js +1 -1
  62. package/dist/lang/fa.umd.prod.js +1 -1
  63. package/dist/lang/fi.umd.prod.js +1 -1
  64. package/dist/lang/fr.umd.prod.js +1 -1
  65. package/dist/lang/gn.umd.prod.js +1 -1
  66. package/dist/lang/he.umd.prod.js +1 -1
  67. package/dist/lang/hi.umd.prod.js +1 -1
  68. package/dist/lang/hr.umd.prod.js +1 -1
  69. package/dist/lang/hu.umd.prod.js +1 -1
  70. package/dist/lang/id.umd.prod.js +1 -1
  71. package/dist/lang/is.umd.prod.js +1 -1
  72. package/dist/lang/it.umd.prod.js +1 -1
  73. package/dist/lang/ja.umd.prod.js +1 -1
  74. package/dist/lang/kk.umd.prod.js +1 -1
  75. package/dist/lang/km.umd.prod.js +1 -1
  76. package/dist/lang/ko-KR.umd.prod.js +1 -1
  77. package/dist/lang/kur-CKB.umd.prod.js +1 -1
  78. package/dist/lang/lt.umd.prod.js +1 -1
  79. package/dist/lang/lu.umd.prod.js +1 -1
  80. package/dist/lang/lv.umd.prod.js +1 -1
  81. package/dist/lang/mk.umd.prod.js +1 -1
  82. package/dist/lang/ml.umd.prod.js +1 -1
  83. package/dist/lang/mm.umd.prod.js +1 -1
  84. package/dist/lang/ms.umd.prod.js +1 -1
  85. package/dist/lang/my.umd.prod.js +1 -1
  86. package/dist/lang/nb-NO.umd.prod.js +1 -1
  87. package/dist/lang/nl.umd.prod.js +1 -1
  88. package/dist/lang/pl.umd.prod.js +1 -1
  89. package/dist/lang/pt-BR.umd.prod.js +1 -1
  90. package/dist/lang/pt.umd.prod.js +1 -1
  91. package/dist/lang/ro.umd.prod.js +1 -1
  92. package/dist/lang/ru.umd.prod.js +1 -1
  93. package/dist/lang/sk.umd.prod.js +1 -1
  94. package/dist/lang/sl.umd.prod.js +1 -1
  95. package/dist/lang/sm.umd.prod.js +1 -1
  96. package/dist/lang/sr-CYR.umd.prod.js +1 -1
  97. package/dist/lang/sr.umd.prod.js +1 -1
  98. package/dist/lang/sv.umd.prod.js +1 -1
  99. package/dist/lang/ta.umd.prod.js +1 -1
  100. package/dist/lang/th.umd.prod.js +1 -1
  101. package/dist/lang/tr.umd.prod.js +1 -1
  102. package/dist/lang/ug.umd.prod.js +1 -1
  103. package/dist/lang/uk.umd.prod.js +1 -1
  104. package/dist/lang/uz-Cyrl.umd.prod.js +1 -1
  105. package/dist/lang/uz-Latn.umd.prod.js +1 -1
  106. package/dist/lang/vi.umd.prod.js +1 -1
  107. package/dist/lang/zh-CN.umd.prod.js +1 -1
  108. package/dist/lang/zh-TW.umd.prod.js +1 -1
  109. package/dist/quasar.addon.prod.css +1 -1
  110. package/dist/quasar.addon.rtl.prod.css +1 -1
  111. package/dist/quasar.cjs.prod.js +2 -2
  112. package/dist/quasar.esm.js +96 -28
  113. package/dist/quasar.esm.prod.js +2 -2
  114. package/dist/quasar.prod.css +1 -1
  115. package/dist/quasar.rtl.prod.css +1 -1
  116. package/dist/quasar.sass +1 -1
  117. package/dist/quasar.umd.js +96 -28
  118. package/dist/quasar.umd.prod.js +2 -2
  119. package/dist/types/index.d.ts +13 -3
  120. package/dist/vetur/quasar-attributes.json +1 -1
  121. package/dist/web-types/web-types.json +2 -6
  122. package/lang/de-CH.js +98 -0
  123. package/lang/de-CH.mjs +93 -0
  124. package/lang/de-DE.js +98 -0
  125. package/lang/de-DE.mjs +93 -0
  126. package/lang/index.json +8 -0
  127. package/package.json +4 -3
  128. package/src/components/field/__tests__/QField.cy.js +156 -0
  129. package/src/components/input/use-mask.js +6 -1
  130. package/src/components/scroll-area/QScrollArea.js +16 -1
  131. package/src/components/select/QSelect.js +42 -17
  132. package/src/components/select/QSelect.json +1 -1
  133. package/src/components/select/__tests__/QSelect.cy.js +2 -1
  134. package/src/components/table/QTable.json +38 -1
  135. package/src/components/table/table-sort.js +5 -0
  136. package/src/components/time/QTime.js +16 -3
  137. package/src/components/tree/QTree.js +8 -3
  138. package/src/composables/private/__tests__/FieldWrapper.vue +17 -2
  139. package/src/composables/private/__tests__/use-field.cy.js +334 -137
  140. package/src/composables/private/__tests__/use-validate.cy.js +162 -15
@@ -304,7 +304,12 @@ export default function (props, emit, emitValue, inputRef) {
304
304
  ? unmaskValue(masked)
305
305
  : masked
306
306
 
307
- String(props.modelValue) !== val && emitValue(val, true)
307
+ if (
308
+ String(props.modelValue) !== val
309
+ && (props.modelValue !== null || val !== '')
310
+ ) {
311
+ emitValue(val, true)
312
+ }
308
313
  }
309
314
 
310
315
  function moveCursorForPaste (inp, start, end) {
@@ -352,11 +352,26 @@ export default createComponent({
352
352
  targetRef.value[ dirProps[ axis ].scroll ] = offset
353
353
  }
354
354
 
355
+ let mouseEventTimer = null
356
+
355
357
  function onMouseenter () {
356
- hover.value = true
358
+ if (mouseEventTimer !== null) {
359
+ clearTimeout(mouseEventTimer)
360
+ }
361
+
362
+ // setTimeout needed for iOS; see ticket #16210
363
+ mouseEventTimer = setTimeout(() => {
364
+ mouseEventTimer = null
365
+ hover.value = true
366
+ }, proxy.$q.platform.is.ios ? 50 : 0)
357
367
  }
358
368
 
359
369
  function onMouseleave () {
370
+ if (mouseEventTimer !== null) {
371
+ clearTimeout(mouseEventTimer)
372
+ mouseEventTimer = null
373
+ }
374
+
360
375
  hover.value = false
361
376
  }
362
377
 
@@ -143,7 +143,8 @@ export default createComponent({
143
143
  const dialogFieldFocused = ref(false)
144
144
  const innerLoadingIndicator = ref(false)
145
145
 
146
- let inputTimer = null, innerValueCache,
146
+ let filterTimer = null, inputValueTimer = null,
147
+ innerValueCache,
147
148
  hasDialog, userInputValue, filterId = null, defaultInputValue,
148
149
  transitionShowComputed, searchBuffer, searchBufferExp
149
150
 
@@ -588,9 +589,11 @@ export default createComponent({
588
589
  scrollTo(index)
589
590
 
590
591
  if (skipInputValue !== true && props.useInput === true && props.fillInput === true) {
591
- setInputValue(index >= 0
592
- ? getOptionLabel.value(props.options[ index ])
593
- : defaultInputValue
592
+ setInputValue(
593
+ index >= 0
594
+ ? getOptionLabel.value(props.options[ index ])
595
+ : defaultInputValue,
596
+ true
594
597
  )
595
598
  }
596
599
  }
@@ -651,9 +654,13 @@ export default createComponent({
651
654
 
652
655
  e.target.value = ''
653
656
 
654
- if (inputTimer !== null) {
655
- clearTimeout(inputTimer)
656
- inputTimer = null
657
+ if (filterTimer !== null) {
658
+ clearTimeout(filterTimer)
659
+ filterTimer = null
660
+ }
661
+ if (inputValueTimer !== null) {
662
+ clearTimeout(inputValueTimer)
663
+ inputValueTimer = null
657
664
  }
658
665
 
659
666
  resetInputValue()
@@ -744,6 +751,10 @@ export default createComponent({
744
751
  // backspace
745
752
  if (
746
753
  e.keyCode === 8
754
+ && (
755
+ props.useChips === true
756
+ || props.clearable === true
757
+ )
747
758
  && props.hideSelected !== true
748
759
  && inputValue.value.length === 0
749
760
  ) {
@@ -838,7 +849,7 @@ export default createComponent({
838
849
  scrollTo(index)
839
850
 
840
851
  if (index >= 0 && props.useInput === true && props.fillInput === true) {
841
- setInputValue(getOptionLabel.value(props.options[ index ]))
852
+ setInputValue(getOptionLabel.value(props.options[ index ]), true)
842
853
  }
843
854
  })
844
855
  }
@@ -1024,9 +1035,13 @@ export default createComponent({
1024
1035
  }
1025
1036
 
1026
1037
  function onInput (e) {
1027
- if (inputTimer !== null) {
1028
- clearTimeout(inputTimer)
1029
- inputTimer = null
1038
+ if (filterTimer !== null) {
1039
+ clearTimeout(filterTimer)
1040
+ filterTimer = null
1041
+ }
1042
+ if (inputValueTimer !== null) {
1043
+ clearTimeout(inputValueTimer)
1044
+ inputValueTimer = null
1030
1045
  }
1031
1046
 
1032
1047
  if (e && e.target && e.target.qComposing === true) {
@@ -1047,17 +1062,26 @@ export default createComponent({
1047
1062
  }
1048
1063
 
1049
1064
  if (props.onFilter !== void 0) {
1050
- inputTimer = setTimeout(() => {
1051
- inputTimer = null
1065
+ filterTimer = setTimeout(() => {
1066
+ filterTimer = null
1052
1067
  filter(inputValue.value)
1053
1068
  }, props.inputDebounce)
1054
1069
  }
1055
1070
  }
1056
1071
 
1057
- function setInputValue (val) {
1072
+ function setInputValue (val, emitImmediately) {
1058
1073
  if (inputValue.value !== val) {
1059
1074
  inputValue.value = val
1060
- emit('inputValue', val)
1075
+
1076
+ if (emitImmediately === true || props.inputDebounce === 0 || props.inputDebounce === '0') {
1077
+ emit('inputValue', val)
1078
+ }
1079
+ else {
1080
+ inputValueTimer = setTimeout(() => {
1081
+ inputValueTimer = null
1082
+ emit('inputValue', val)
1083
+ }, props.inputDebounce)
1084
+ }
1061
1085
  }
1062
1086
  }
1063
1087
 
@@ -1065,7 +1089,7 @@ export default createComponent({
1065
1089
  userInputValue = internal !== true
1066
1090
 
1067
1091
  if (props.useInput === true) {
1068
- setInputValue(val)
1092
+ setInputValue(val, true)
1069
1093
 
1070
1094
  if (noFiltering === true || internal !== true) {
1071
1095
  defaultInputValue = val
@@ -1418,7 +1442,8 @@ export default createComponent({
1418
1442
  updatePreState()
1419
1443
 
1420
1444
  onBeforeUnmount(() => {
1421
- inputTimer !== null && clearTimeout(inputTimer)
1445
+ filterTimer !== null && clearTimeout(filterTimer)
1446
+ inputValueTimer !== null && clearTimeout(inputValueTimer)
1422
1447
  })
1423
1448
 
1424
1449
  // expose public methods
@@ -270,7 +270,7 @@
270
270
 
271
271
  "input-debounce": {
272
272
  "type": [ "Number", "String" ],
273
- "desc": "Debounce the input model update with an amount of milliseconds",
273
+ "desc": "Debounce the input model update with an amount of milliseconds (also affects the 'filter' event, if used)",
274
274
  "default": 500,
275
275
  "category": "content"
276
276
  },
@@ -1258,7 +1258,8 @@ describe('QSelect API', () => {
1258
1258
  props: {
1259
1259
  modelValue: null,
1260
1260
  onInputValue: fn,
1261
- useInput: true
1261
+ useInput: true,
1262
+ inputDebounce: 0
1262
1263
  }
1263
1264
  })
1264
1265
 
@@ -187,7 +187,7 @@
187
187
  },
188
188
  "sort": {
189
189
  "type": "Function",
190
- "desc": "Compare function if you have some custom data or want a specific way to compare two rows",
190
+ "desc": "Compare function if you have some custom data or want a specific way to compare two rows; rows with null/undefined values will get sorted without triggering this method (use 'rawSort' instead if you want to handle those values too)",
191
191
  "examples": ["(a, b, rowA, rowB) => parseInt(a, 10) - parseInt(b, 10)"],
192
192
  "params": {
193
193
  "a": {
@@ -221,6 +221,43 @@
221
221
  "examples": [ "-1", "0", "1" ]
222
222
  }
223
223
  },
224
+ "rawSort": {
225
+ "type": "Function",
226
+ "desc": "Compare function if you have some custom data or want a specific way to compare two rows; includes rows with null/undefined values (use 'sort' instead if you don't want that)",
227
+ "examples": ["(a, b, rowA, rowB) => parseInt(a, 10) - parseInt(b, 10)"],
228
+ "params": {
229
+ "a": {
230
+ "type": "Any",
231
+ "required": true,
232
+ "desc": "Value of the first comparison term",
233
+ "examples": [ 123, "abc" ]
234
+ },
235
+ "b": {
236
+ "type": "Any",
237
+ "required": true,
238
+ "desc": "Value of the second comparison term",
239
+ "examples": [ 123, "abc" ]
240
+ },
241
+ "rowA": {
242
+ "type": "Object",
243
+ "required": true,
244
+ "desc": "Full Row object in which is contained the first term",
245
+ "examples": [ "{ name: 'Potassium', value: 'K' }" ]
246
+ },
247
+ "rowB": {
248
+ "type": "Object",
249
+ "required": true,
250
+ "desc": "Full Row object in which is contained the second term",
251
+ "examples": [ "{ name: 'Fluorine', value: 'F' }" ]
252
+ }
253
+ },
254
+ "returns": {
255
+ "type": "Number",
256
+ "desc": "Comparison result of term 'a' with term 'b'. Less than 0 when 'a' should come first; greater than 0 if 'b' should come first; equal to 0 if their position must not be changed with respect to each other",
257
+ "examples": [ "-1", "0", "1" ]
258
+ },
259
+ "addedIn": "v2.13.0"
260
+ },
224
261
  "sortOrder": {
225
262
  "type": "String",
226
263
  "desc": "Set column sort order: 'ad' (ascending-descending) or 'da' (descending-ascending); Overrides the 'column-sort-order' prop",
@@ -42,6 +42,9 @@ export function useTableSort (props, computedPagination, colList, setPagination)
42
42
  A = val(a),
43
43
  B = val(b)
44
44
 
45
+ if (col.rawSort !== void 0) {
46
+ return col.rawSort(A, B, a, b) * dir
47
+ }
45
48
  if (A === null || A === void 0) {
46
49
  return -1 * dir
47
50
  }
@@ -49,6 +52,8 @@ export function useTableSort (props, computedPagination, colList, setPagination)
49
52
  return 1 * dir
50
53
  }
51
54
  if (col.sort !== void 0) {
55
+ // gets called without rows that have null/undefined as value
56
+ // due to the above two statements
52
57
  return col.sort(A, B, a, b) * dir
53
58
  }
54
59
  if (isNumber(A) === true && isNumber(B) === true) {
@@ -706,23 +706,36 @@ export default createComponent({
706
706
  }
707
707
  }
708
708
 
709
+ function goToViewWhenHasModel (newView) {
710
+ const model = props.modelValue
711
+ if (
712
+ view.value !== newView
713
+ && model !== void 0
714
+ && model !== null
715
+ && model !== ''
716
+ && typeof model !== 'string'
717
+ ) {
718
+ view.value = newView
719
+ }
720
+ }
721
+
709
722
  function verifyAndUpdate () {
710
723
  if (hourInSelection.value !== null && hourInSelection.value(innerModel.value.hour) !== true) {
711
724
  innerModel.value = __splitDate()
712
- view.value = 'hour'
725
+ goToViewWhenHasModel('hour')
713
726
  return
714
727
  }
715
728
 
716
729
  if (minuteInSelection.value !== null && minuteInSelection.value(innerModel.value.minute) !== true) {
717
730
  innerModel.value.minute = null
718
731
  innerModel.value.second = null
719
- view.value = 'minute'
732
+ goToViewWhenHasModel('minute')
720
733
  return
721
734
  }
722
735
 
723
736
  if (props.withSeconds === true && secondInSelection.value !== null && secondInSelection.value(innerModel.value.second) !== true) {
724
737
  innerModel.value.second = null
725
- view.value = 'second'
738
+ goToViewWhenHasModel('second')
726
739
  return
727
740
  }
728
741
 
@@ -523,6 +523,8 @@ export default createComponent({
523
523
  + (m.selected === true ? ' q-tree__node--selected' : '')
524
524
  + (m.disabled === true ? ' q-tree__node--disabled' : ''),
525
525
  tabindex: m.link === true ? 0 : -1,
526
+ ariaExpanded: children.length > 0 ? m.expanded : null,
527
+ role: 'treeitem',
526
528
  onClick: (e) => {
527
529
  onClick(node, m, e)
528
530
  },
@@ -596,7 +598,8 @@ export default createComponent({
596
598
  body,
597
599
  h('div', {
598
600
  class: 'q-tree__children'
599
- + (m.disabled === true ? ' q-tree__node--disabled' : '')
601
+ + (m.disabled === true ? ' q-tree__node--disabled' : ''),
602
+ role: 'group'
600
603
  }, children)
601
604
  ])
602
605
  : null
@@ -614,7 +617,8 @@ export default createComponent({
614
617
  body,
615
618
  h('div', {
616
619
  class: 'q-tree__children'
617
- + (m.disabled === true ? ' q-tree__node--disabled' : '')
620
+ + (m.disabled === true ? ' q-tree__node--disabled' : ''),
621
+ role: 'group'
618
622
  }, children)
619
623
  ]),
620
624
  [ [ vShow, m.expanded ] ]
@@ -708,7 +712,8 @@ export default createComponent({
708
712
 
709
713
  return h(
710
714
  'div', {
711
- class: classes.value
715
+ class: classes.value,
716
+ role: 'tree'
712
717
  },
713
718
  children.length === 0
714
719
  ? (
@@ -1,6 +1,10 @@
1
1
  <template>
2
2
  <div style="margin: 150px auto" class="row justify-center" data-cy="wrapper">
3
- <q-select data-cy="select" class="select-root" ref="compRef" v-bind="$attrs" style="min-width: 300px"></q-select>
3
+ <q-select data-cy="select" class="select-root" ref="compRef" v-bind="$attrs" style="min-width: 300px">
4
+ <template v-for="(_, name) in $slots" #[name]>
5
+ <slot :name="name" />
6
+ </template>
7
+ </q-select>
4
8
  </div>
5
9
  <q-btn class="hidden" data-cy="method-show" @click="show" />
6
10
  <q-btn class="hidden" data-cy="method-hide" @click="hide" />
@@ -32,7 +36,18 @@ export default defineComponent({
32
36
  compRef.value.focus()
33
37
  }
34
38
 
35
- return { compRef, show, hide, toggle, focusMethod }
39
+ function blur () {
40
+ compRef.value.blur()
41
+ }
42
+
43
+ function validate () {
44
+ compRef.value.validate()
45
+ }
46
+
47
+ function resetValidation () {
48
+ compRef.value.resetValidation()
49
+ }
50
+ return { compRef, show, hide, toggle, focusMethod, blur, validate, resetValidation }
36
51
  }
37
52
  })
38
53