quasar 2.18.2 → 2.18.4

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 (130) hide show
  1. package/dist/api/QField.json +1 -1
  2. package/dist/api/QFile.json +1 -1
  3. package/dist/api/QInput.json +1 -1
  4. package/dist/api/QSelect.json +1 -1
  5. package/dist/icon-set/bootstrap-icons.umd.prod.js +1 -1
  6. package/dist/icon-set/eva-icons.umd.prod.js +1 -1
  7. package/dist/icon-set/fontawesome-v5-pro.umd.prod.js +1 -1
  8. package/dist/icon-set/fontawesome-v5.umd.prod.js +1 -1
  9. package/dist/icon-set/fontawesome-v6-pro.umd.prod.js +1 -1
  10. package/dist/icon-set/fontawesome-v6.umd.prod.js +1 -1
  11. package/dist/icon-set/ionicons-v4.umd.prod.js +1 -1
  12. package/dist/icon-set/line-awesome.umd.prod.js +1 -1
  13. package/dist/icon-set/material-icons-outlined.umd.prod.js +1 -1
  14. package/dist/icon-set/material-icons-round.umd.prod.js +1 -1
  15. package/dist/icon-set/material-icons-sharp.umd.prod.js +1 -1
  16. package/dist/icon-set/material-icons.umd.prod.js +1 -1
  17. package/dist/icon-set/material-symbols-outlined.umd.prod.js +1 -1
  18. package/dist/icon-set/material-symbols-rounded.umd.prod.js +1 -1
  19. package/dist/icon-set/material-symbols-sharp.umd.prod.js +1 -1
  20. package/dist/icon-set/mdi-v3.umd.prod.js +1 -1
  21. package/dist/icon-set/mdi-v4.umd.prod.js +1 -1
  22. package/dist/icon-set/mdi-v5.umd.prod.js +1 -1
  23. package/dist/icon-set/mdi-v6.umd.prod.js +1 -1
  24. package/dist/icon-set/mdi-v7.umd.prod.js +1 -1
  25. package/dist/icon-set/svg-bootstrap-icons.umd.prod.js +1 -1
  26. package/dist/icon-set/svg-eva-icons.umd.prod.js +1 -1
  27. package/dist/icon-set/svg-fontawesome-v5.umd.prod.js +1 -1
  28. package/dist/icon-set/svg-fontawesome-v6.umd.prod.js +1 -1
  29. package/dist/icon-set/svg-ionicons-v4.umd.prod.js +1 -1
  30. package/dist/icon-set/svg-ionicons-v5.umd.prod.js +1 -1
  31. package/dist/icon-set/svg-ionicons-v6.umd.prod.js +1 -1
  32. package/dist/icon-set/svg-line-awesome.umd.prod.js +1 -1
  33. package/dist/icon-set/svg-material-icons-outlined.umd.prod.js +1 -1
  34. package/dist/icon-set/svg-material-icons-round.umd.prod.js +1 -1
  35. package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +1 -1
  36. package/dist/icon-set/svg-material-icons.umd.prod.js +1 -1
  37. package/dist/icon-set/svg-material-symbols-outlined.umd.prod.js +1 -1
  38. package/dist/icon-set/svg-material-symbols-rounded.umd.prod.js +1 -1
  39. package/dist/icon-set/svg-material-symbols-sharp.umd.prod.js +1 -1
  40. package/dist/icon-set/svg-mdi-v6.umd.prod.js +1 -1
  41. package/dist/icon-set/svg-mdi-v7.umd.prod.js +1 -1
  42. package/dist/icon-set/svg-themify.umd.prod.js +1 -1
  43. package/dist/icon-set/themify.umd.prod.js +1 -1
  44. package/dist/lang/ar-TN.umd.prod.js +1 -1
  45. package/dist/lang/ar.umd.prod.js +1 -1
  46. package/dist/lang/az-Latn.umd.prod.js +1 -1
  47. package/dist/lang/bg.umd.prod.js +1 -1
  48. package/dist/lang/bn.umd.prod.js +1 -1
  49. package/dist/lang/bs-BA.umd.prod.js +1 -1
  50. package/dist/lang/ca.umd.prod.js +1 -1
  51. package/dist/lang/cs.umd.prod.js +1 -1
  52. package/dist/lang/da.umd.prod.js +1 -1
  53. package/dist/lang/de-CH.umd.prod.js +1 -1
  54. package/dist/lang/de-DE.umd.prod.js +1 -1
  55. package/dist/lang/de.umd.prod.js +1 -1
  56. package/dist/lang/el.umd.prod.js +1 -1
  57. package/dist/lang/en-GB.umd.prod.js +1 -1
  58. package/dist/lang/en-US.umd.prod.js +1 -1
  59. package/dist/lang/eo.umd.prod.js +1 -1
  60. package/dist/lang/es.umd.prod.js +1 -1
  61. package/dist/lang/et.umd.prod.js +1 -1
  62. package/dist/lang/eu.umd.prod.js +1 -1
  63. package/dist/lang/fa-IR.umd.prod.js +1 -1
  64. package/dist/lang/fa.umd.prod.js +1 -1
  65. package/dist/lang/fi.umd.prod.js +1 -1
  66. package/dist/lang/fr.umd.prod.js +1 -1
  67. package/dist/lang/gn.umd.prod.js +1 -1
  68. package/dist/lang/he.umd.prod.js +1 -1
  69. package/dist/lang/hi.umd.prod.js +1 -1
  70. package/dist/lang/hr.umd.prod.js +1 -1
  71. package/dist/lang/hu.umd.prod.js +1 -1
  72. package/dist/lang/id.umd.prod.js +1 -1
  73. package/dist/lang/is.umd.prod.js +1 -1
  74. package/dist/lang/it.umd.prod.js +1 -1
  75. package/dist/lang/ja.umd.prod.js +1 -1
  76. package/dist/lang/kk.umd.prod.js +1 -1
  77. package/dist/lang/km.umd.prod.js +1 -1
  78. package/dist/lang/ko-KR.umd.prod.js +1 -1
  79. package/dist/lang/kur-CKB.umd.prod.js +1 -1
  80. package/dist/lang/lt.umd.prod.js +1 -1
  81. package/dist/lang/lu.umd.prod.js +1 -1
  82. package/dist/lang/lv.umd.prod.js +1 -1
  83. package/dist/lang/mk.umd.prod.js +1 -1
  84. package/dist/lang/ml.umd.prod.js +1 -1
  85. package/dist/lang/mm.umd.prod.js +1 -1
  86. package/dist/lang/ms-MY.umd.prod.js +1 -1
  87. package/dist/lang/ms.umd.prod.js +1 -1
  88. package/dist/lang/my.umd.prod.js +1 -1
  89. package/dist/lang/nb-NO.umd.prod.js +1 -1
  90. package/dist/lang/nl.umd.prod.js +1 -1
  91. package/dist/lang/pl.umd.prod.js +1 -1
  92. package/dist/lang/pt-BR.umd.prod.js +1 -1
  93. package/dist/lang/pt.umd.prod.js +1 -1
  94. package/dist/lang/ro.umd.prod.js +1 -1
  95. package/dist/lang/ru.umd.prod.js +1 -1
  96. package/dist/lang/sk.umd.prod.js +1 -1
  97. package/dist/lang/sl.umd.prod.js +1 -1
  98. package/dist/lang/sm.umd.prod.js +1 -1
  99. package/dist/lang/sq.umd.prod.js +1 -1
  100. package/dist/lang/sr-CYR.umd.prod.js +1 -1
  101. package/dist/lang/sr.umd.prod.js +1 -1
  102. package/dist/lang/sv.umd.prod.js +1 -1
  103. package/dist/lang/ta.umd.prod.js +1 -1
  104. package/dist/lang/th.umd.prod.js +1 -1
  105. package/dist/lang/tl.umd.prod.js +1 -1
  106. package/dist/lang/tr.umd.prod.js +1 -1
  107. package/dist/lang/ug.umd.prod.js +1 -1
  108. package/dist/lang/uk.umd.prod.js +1 -1
  109. package/dist/lang/ur-PK.umd.prod.js +1 -1
  110. package/dist/lang/uz-Cyrl.umd.prod.js +2 -2
  111. package/dist/lang/uz-Latn.umd.prod.js +2 -2
  112. package/dist/lang/vi.umd.prod.js +1 -1
  113. package/dist/lang/zh-CN.umd.prod.js +1 -1
  114. package/dist/lang/zh-TW.umd.prod.js +1 -1
  115. package/dist/quasar.client.js +400 -365
  116. package/dist/quasar.sass +1 -1
  117. package/dist/quasar.server.prod.cjs +25 -25
  118. package/dist/quasar.server.prod.js +25 -25
  119. package/dist/quasar.umd.js +52 -17
  120. package/dist/quasar.umd.prod.js +26 -26
  121. package/dist/types/index.d.ts +26 -0
  122. package/dist/vetur/quasar-attributes.json +1 -1
  123. package/dist/vetur/quasar-tags.json +1 -1
  124. package/dist/web-types/web-types.json +1 -1
  125. package/lang/uz-Cyrl.js +9 -4
  126. package/lang/uz-Latn.js +9 -4
  127. package/package.json +3 -3
  128. package/src/components/input/use-mask.js +58 -17
  129. package/src/components/input/use-mask.json +55 -4
  130. package/src/composables/private.use-validate/use-validate.json +6 -6
package/lang/uz-Cyrl.js CHANGED
@@ -41,10 +41,15 @@ export default {
41
41
  noData: 'Маълумот топилмади',
42
42
  noResults: 'Қидирув бўйича маълумотлар топилмади',
43
43
  loading: 'Юкланмоқда...',
44
- selectedRecords: (rows) =>
45
- (rows === 1
46
- ? '1 та маълумот танланди.'
47
- : (rows === 0 ? 'Хеч қандай' : rows) + ' маълумотла танланмади.'),
44
+ selectedRecords: (rows) => {
45
+ if (rows === 0) {
46
+ return 'Хеч қандай маълумотлар танланмади.'
47
+ }
48
+ if (rows === 1) {
49
+ return '1 та маълумот танланди.'
50
+ }
51
+ return rows + ' та маълумотлар танланди.'
52
+ },
48
53
  recordsPerPage: 'Сахифадаги қаторлар:',
49
54
  allRows: 'Барчаси',
50
55
  pagination: (start, end, total) => start + '-' + end + ' жами ' + total,
package/lang/uz-Latn.js CHANGED
@@ -45,10 +45,15 @@ export default {
45
45
  noData: 'Ma\'lumotlar topilmadi',
46
46
  noResults: 'Qidiruv bo\'yicha ma\'lumotlar topilmadi',
47
47
  loading: 'Yuklanmoqda...',
48
- selectedRecords: (rows) =>
49
- (rows === 1
50
- ? '1 ta malumot tanlandi.'
51
- : (rows === 0 ? 'Hech qanday' : rows) + ' ma\'lumotlar tanlanmadi.'),
48
+ selectedRecords: (rows) => {
49
+ if (rows === 0) {
50
+ return 'Hech qanday ma\'lumotlar tanlanmadi.'
51
+ }
52
+ if (rows === 1) {
53
+ return '1 ta ma\'lumot tanlandi.'
54
+ }
55
+ return rows + ' ta ma\'lumotlar tanlandi.'
56
+ },
52
57
  recordsPerPage: 'Saxifadagi qatorlar:',
53
58
  allRows: 'Barchasi',
54
59
  pagination: (start, end, total) => start + '-' + end + ' jami ' + total,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quasar",
3
- "version": "2.18.2",
3
+ "version": "2.18.4",
4
4
  "description": "Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time",
5
5
  "type": "module",
6
6
  "module": "dist/quasar.client.js",
@@ -76,8 +76,8 @@
76
76
  "tinyglobby": "^0.2.10",
77
77
  "typescript": "^5.6.2",
78
78
  "vue": "^3.5.5",
79
- "@quasar/extras": "1.17.0",
80
- "eslint-config-quasar": "0.0.3"
79
+ "eslint-config-quasar": "0.0.3",
80
+ "@quasar/extras": "1.17.0"
81
81
  },
82
82
  "vetur": {
83
83
  "tags": "dist/vetur/quasar-tags.json",
@@ -1,4 +1,4 @@
1
- import { ref, watch, nextTick } from 'vue'
1
+ import { ref, computed, watch, nextTick } from 'vue'
2
2
 
3
3
  import { shouldIgnoreKey } from '../../utils/private.keyboard/key-composition.js'
4
4
 
@@ -12,7 +12,7 @@ const NAMED_MASKS = {
12
12
  card: '#### #### #### ####'
13
13
  }
14
14
 
15
- const TOKENS = {
15
+ const { tokenMap: DEFAULT_TOKEN_MAP, tokenKeys: DEFAULT_TOKEN_MAP_KEYS } = getTokenMap({
16
16
  '#': { pattern: '[\\d]', negate: '[^\\d]' },
17
17
 
18
18
  S: { pattern: '[a-zA-Z]', negate: '[^a-zA-Z]' },
@@ -23,29 +23,62 @@ const TOKENS = {
23
23
 
24
24
  X: { pattern: '[0-9a-zA-Z]', negate: '[^0-9a-zA-Z]', transform: v => v.toLocaleUpperCase() },
25
25
  x: { pattern: '[0-9a-zA-Z]', negate: '[^0-9a-zA-Z]', transform: v => v.toLocaleLowerCase() }
26
- }
27
-
28
- const KEYS = Object.keys(TOKENS)
29
- KEYS.forEach(key => {
30
- TOKENS[ key ].regex = new RegExp(TOKENS[ key ].pattern)
31
26
  })
32
27
 
33
- const
34
- tokenRegexMask = new RegExp('\\\\([^.*+?^${}()|([\\]])|([.*+?^${}()|[\\]])|([' + KEYS.join('') + '])|(.)', 'g'),
35
- escRegex = /[.*+?^${}()|[\]\\]/g
28
+ function getTokenMap (tokens) {
29
+ const tokenKeys = Object.keys(tokens)
30
+ const tokenMap = {}
31
+
32
+ tokenKeys.forEach(key => {
33
+ const entry = tokens[ key ]
34
+ tokenMap[ key ] = {
35
+ ...entry,
36
+ regex: new RegExp(entry.pattern)
37
+ }
38
+ })
36
39
 
40
+ return { tokenMap, tokenKeys }
41
+ }
42
+
43
+ function getTokenRegexMask (keys) {
44
+ return new RegExp('\\\\([^.*+?^${}()|([\\]])|([.*+?^${}()|[\\]])|([' + keys.join('') + '])|(.)', 'g')
45
+ }
46
+
47
+ const escRegex = /[.*+?^${}()|[\]\\]/g
48
+ const DEFAULT_TOKEN_REGEX_MASK = getTokenRegexMask(DEFAULT_TOKEN_MAP_KEYS)
37
49
  const MARKER = String.fromCharCode(1)
38
50
 
39
51
  export const useMaskProps = {
40
52
  mask: String,
41
53
  reverseFillMask: Boolean,
42
54
  fillMask: [ Boolean, String ],
43
- unmaskedValue: Boolean
55
+ unmaskedValue: Boolean,
56
+ maskTokens: Object
44
57
  }
45
58
 
46
59
  export default function (props, emit, emitValue, inputRef) {
47
60
  let maskMarked, maskReplaced, computedMask, computedUnmask, pastedTextStart, selectionAnchor
48
61
 
62
+ const tokens = computed(() => {
63
+ if (props.maskTokens === void 0 || props.maskTokens === null) {
64
+ return {
65
+ tokenMap: DEFAULT_TOKEN_MAP,
66
+ tokenRegexMask: DEFAULT_TOKEN_REGEX_MASK
67
+ }
68
+ }
69
+
70
+ const { tokenMap: customTokens } = getTokenMap(props.maskTokens)
71
+ const tokenMap = {
72
+ ...DEFAULT_TOKEN_MAP,
73
+ ...customTokens
74
+ }
75
+
76
+ return {
77
+ tokenMap,
78
+ tokenRegexMask: getTokenRegexMask(Object.keys(tokenMap))
79
+ }
80
+ })
81
+
49
82
  const hasMask = ref(null)
50
83
  const innerValue = ref(getInitialMaskedValue())
51
84
 
@@ -137,9 +170,9 @@ export default function (props, emit, emitValue, inputRef) {
137
170
  unmaskChar = '',
138
171
  negateChar = ''
139
172
 
140
- localComputedMask.replace(tokenRegexMask, (_, char1, esc, token, char2) => {
173
+ localComputedMask.replace(tokens.value.tokenRegexMask, (_, char1, esc, token, char2) => {
141
174
  if (token !== void 0) {
142
- const c = TOKENS[ token ]
175
+ const c = tokens.value.tokenMap[ token ]
143
176
  mask.push(c)
144
177
  negateChar = c.negate
145
178
  if (firstMatch === true) {
@@ -226,7 +259,7 @@ export default function (props, emit, emitValue, inputRef) {
226
259
  updateMaskInternalsFlag === true && updateMaskInternals()
227
260
 
228
261
  const
229
- preMasked = maskValue(unmasked),
262
+ preMasked = maskValue(unmasked, updateMaskInternalsFlag),
230
263
  masked = props.fillMask !== false
231
264
  ? fillWithMask(preMasked)
232
265
  : preMasked,
@@ -481,11 +514,11 @@ export default function (props, emit, emitValue, inputRef) {
481
514
  }
482
515
  }
483
516
 
484
- function maskValue (val) {
517
+ function maskValue (val, updateMaskInternalsFlag) {
485
518
  if (val === void 0 || val === null || val === '') { return '' }
486
519
 
487
520
  if (props.reverseFillMask === true) {
488
- return maskValueReverse(val)
521
+ return maskValueReverse(val, updateMaskInternalsFlag)
489
522
  }
490
523
 
491
524
  const mask = computedMask
@@ -499,6 +532,10 @@ export default function (props, emit, emitValue, inputRef) {
499
532
 
500
533
  if (typeof maskDef === 'string') {
501
534
  output += maskDef
535
+
536
+ if (updateMaskInternalsFlag === true && valChar === maskDef) {
537
+ valIndex++
538
+ }
502
539
  }
503
540
  else if (valChar !== void 0 && maskDef.regex.test(valChar)) {
504
541
  output += maskDef.transform !== void 0
@@ -514,7 +551,7 @@ export default function (props, emit, emitValue, inputRef) {
514
551
  return output
515
552
  }
516
553
 
517
- function maskValueReverse (val) {
554
+ function maskValueReverse (val, updateMaskInternalsFlag) {
518
555
  const
519
556
  mask = computedMask,
520
557
  firstTokenIndex = maskMarked.indexOf(MARKER)
@@ -528,6 +565,10 @@ export default function (props, emit, emitValue, inputRef) {
528
565
 
529
566
  if (typeof maskDef === 'string') {
530
567
  output = maskDef + output
568
+
569
+ if (updateMaskInternalsFlag === true && valChar === maskDef) {
570
+ valIndex--
571
+ }
531
572
  }
532
573
  else if (valChar !== void 0 && maskDef.regex.test(valChar)) {
533
574
  do {
@@ -6,26 +6,77 @@
6
6
  "examples": [
7
7
  "'###-##'", "'date'", "'datetime'", "'time'", "'fulltime'", "'phone'", "'card'"
8
8
  ],
9
- "category": "behavior"
9
+ "category": "mask"
10
10
  },
11
11
 
12
12
  "fill-mask": {
13
13
  "type": [ "Boolean", "String" ],
14
14
  "desc": "Fills string with specified characters (or underscore if value is not string) to fill mask's length",
15
15
  "examples": [ "true", "'0'", "'_'" ],
16
- "category": "behavior"
16
+ "category": "mask"
17
17
  },
18
18
 
19
19
  "reverse-fill-mask": {
20
20
  "type": "Boolean",
21
21
  "desc": "Fills string from the right side of the mask",
22
- "category": "behavior"
22
+ "category": "mask"
23
23
  },
24
24
 
25
25
  "unmasked-value": {
26
26
  "type": "Boolean",
27
27
  "desc": "Model will be unmasked (won't contain tokens/separation characters)",
28
- "category": "behavior"
28
+ "category": "mask"
29
+ },
30
+
31
+ "mask-tokens": {
32
+ "type": "Object",
33
+ "desc": "Object of custom mask tokens to be added on top of the default ones; Can also override any of the default ones",
34
+ "definition": {
35
+ "...tokenCharacter": {
36
+ "type": "Object",
37
+ "desc": "The definition for the current custom mask token",
38
+ "required": true,
39
+ "definition": {
40
+ "pattern": {
41
+ "type": "String",
42
+ "required": true,
43
+ "desc": "A string representing a regular expression to match against a single character",
44
+ "examples": [ "'[0-9]'", "'[a-zA-Z]'" ]
45
+ },
46
+ "negate": {
47
+ "type": "String",
48
+ "required": true,
49
+ "desc": "A string representing a regular expression to NOT match against a single character",
50
+ "examples": [ "'[^0-9]'", "'[^a-zA-Z]'" ]
51
+ },
52
+ "transform": {
53
+ "type": "Function",
54
+ "required": false,
55
+ "desc": "A function that takes the character as argument and returns the transformed character",
56
+ "examples": [ "v => v.toLocaleUpperCase()" ],
57
+ "params": {
58
+ "char": {
59
+ "type": "String",
60
+ "required": true,
61
+ "desc": "The character being transformed",
62
+ "examples": [ "'a'", "'1'" ]
63
+ }
64
+ },
65
+ "returns": {
66
+ "type": "String",
67
+ "desc": "The transformed character"
68
+ }
69
+ }
70
+ },
71
+ "examples": [
72
+ "{ pattern: '[0-4a-eA-E]', negate: '[^0-4a-eA-E]', transform: v => v.toLocaleUpperCase() }",
73
+ "{ pattern: '[5-8]', negate: '[^5-8]' }"
74
+ ]
75
+ }
76
+ },
77
+ "examples": [ "{ C: { pattern: '[0-4a-eA-E]', negate: '[^0-4a-eA-E]', transform: v => v.toLocaleUpperCase() } }" ],
78
+ "category": "mask",
79
+ "addedIn": "v2.18.4"
29
80
  }
30
81
  }
31
82
  }
@@ -10,20 +10,20 @@
10
10
  "type": [ "Boolean", "null" ],
11
11
  "default": "null",
12
12
  "desc": "Does field have validation errors?",
13
- "category": "behavior"
13
+ "category": "validation"
14
14
  },
15
15
 
16
16
  "error-message": {
17
17
  "type": "String",
18
18
  "desc": "Validation error message (gets displayed only if 'error' is set to 'true')",
19
19
  "examples": [ "'Username must have at least 5 characters'" ],
20
- "category": "content"
20
+ "category": "validation"
21
21
  },
22
22
 
23
23
  "no-error-icon": {
24
24
  "type": "Boolean",
25
25
  "desc": "Hide error icon when there is an error",
26
- "category": "content"
26
+ "category": "validation"
27
27
  },
28
28
 
29
29
  "rules": {
@@ -35,13 +35,13 @@
35
35
  "[ 'fulltime' ]",
36
36
  "[ (val, rules) => rules.email(val) || 'Please enter a valid email address' ]"
37
37
  ],
38
- "category": "behavior"
38
+ "category": "validation"
39
39
  },
40
40
 
41
41
  "reactive-rules": {
42
42
  "type": "Boolean",
43
43
  "desc": "By default a change in the rules does not trigger a new validation until the model changes; If set to true then a change in the rules will trigger a validation; Has a performance penalty, so use it only when you really need it",
44
- "category": "behavior"
44
+ "category": "validation"
45
45
  },
46
46
 
47
47
  "lazy-rules": {
@@ -49,7 +49,7 @@
49
49
  "desc": "If set to boolean true then it checks validation status against the 'rules' only after field loses focus for first time; If set to 'ondemand' then it will trigger only when component's validate() method is manually called or when the wrapper QForm submits itself",
50
50
  "default": "false",
51
51
  "values": [ "true", "false", "'ondemand'" ],
52
- "category": "behavior"
52
+ "category": "validation"
53
53
  }
54
54
  },
55
55