quasar 2.11.7 → 2.11.9

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 (163) hide show
  1. package/dist/api/QCarousel.json +9 -0
  2. package/dist/api/QEditor.json +57 -0
  3. package/dist/api/QTable.json +9 -0
  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 +1 -1
  33. package/dist/icon-set/svg-material-icons-round.umd.prod.js +1 -1
  34. package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +1 -1
  35. package/dist/icon-set/svg-material-icons.umd.prod.js +1 -1
  36. package/dist/icon-set/svg-material-symbols-outlined.umd.prod.js +1 -1
  37. package/dist/icon-set/svg-material-symbols-rounded.umd.prod.js +1 -1
  38. package/dist/icon-set/svg-material-symbols-sharp.umd.prod.js +1 -1
  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.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/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 +2 -2
  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/ml.umd.prod.js +1 -1
  79. package/dist/lang/mm.umd.prod.js +1 -1
  80. package/dist/lang/ms.umd.prod.js +1 -1
  81. package/dist/lang/my.umd.prod.js +1 -1
  82. package/dist/lang/nb-NO.umd.prod.js +1 -1
  83. package/dist/lang/nl.umd.prod.js +1 -1
  84. package/dist/lang/pl.umd.prod.js +1 -1
  85. package/dist/lang/pt-BR.umd.prod.js +1 -1
  86. package/dist/lang/pt.umd.prod.js +1 -1
  87. package/dist/lang/ro.umd.prod.js +1 -1
  88. package/dist/lang/ru.umd.prod.js +1 -1
  89. package/dist/lang/sk.umd.prod.js +1 -1
  90. package/dist/lang/sl.umd.prod.js +1 -1
  91. package/dist/lang/sm.umd.prod.js +1 -1
  92. package/dist/lang/sr-CYR.umd.prod.js +1 -1
  93. package/dist/lang/sr.umd.prod.js +1 -1
  94. package/dist/lang/sv.umd.prod.js +1 -1
  95. package/dist/lang/ta.umd.prod.js +1 -1
  96. package/dist/lang/th.umd.prod.js +1 -1
  97. package/dist/lang/tr.umd.prod.js +1 -1
  98. package/dist/lang/ug.umd.prod.js +1 -1
  99. package/dist/lang/uk.umd.prod.js +1 -1
  100. package/dist/lang/uz-Cyrl.umd.prod.js +1 -1
  101. package/dist/lang/uz-Latn.umd.prod.js +1 -1
  102. package/dist/lang/vi.umd.prod.js +1 -1
  103. package/dist/lang/zh-CN.umd.prod.js +1 -1
  104. package/dist/lang/zh-TW.umd.prod.js +1 -1
  105. package/dist/quasar.cjs.prod.js +2 -2
  106. package/dist/quasar.css +2 -2
  107. package/dist/quasar.esm.js +121 -64
  108. package/dist/quasar.esm.prod.js +2 -2
  109. package/dist/quasar.prod.css +1 -1
  110. package/dist/quasar.rtl.css +2 -2
  111. package/dist/quasar.rtl.prod.css +1 -1
  112. package/dist/quasar.sass +17 -5
  113. package/dist/quasar.umd.js +121 -64
  114. package/dist/quasar.umd.prod.js +2 -2
  115. package/dist/types/index.d.ts +43 -0
  116. package/dist/web-types/web-types.json +102 -1
  117. package/lang/ja.js +1 -1
  118. package/lang/ja.mjs +1 -1
  119. package/package.json +9 -6
  120. package/src/components/avatar/__tests__/{QAvatar.spec.js → QAvatar.cy.js} +7 -8
  121. package/src/components/badge/__tests__/{QBadge.spec.js → QBadge.cy.js} +1 -2
  122. package/src/components/banner/__tests__/{QBanner.spec.js → QBanner.cy.js} +7 -8
  123. package/src/components/bar/__tests__/{QBar.spec.js → QBar.cy.js} +3 -4
  124. package/src/components/breadcrumbs/__tests__/{QBreadcrumbs.spec.js → QBreadcrumbs.cy.js} +8 -9
  125. package/src/components/breadcrumbs/__tests__/{QBreadcrumbsEl.spec.js → QBreadcrumbsEl.cy.js} +5 -6
  126. package/src/components/btn/__tests__/{QBtn.spec.js → QBtn.cy.js} +4 -5
  127. package/src/components/btn/__tests__/{use-btn.spec.js → use-btn.cy.js} +1 -2
  128. package/src/components/chip/__tests__/{QChip.spec.js → QChip.cy.js} +1 -2
  129. package/src/components/editor/QEditor.js +12 -1
  130. package/src/components/editor/QEditor.json +50 -0
  131. package/src/components/editor/editor-utils.js +5 -1
  132. package/src/components/field/QField.sass +16 -4
  133. package/src/components/input/QInput.js +24 -7
  134. package/src/components/input/use-mask.js +74 -50
  135. package/src/components/menu/__tests__/{QMenu.spec.js → QMenu.cy.js} +29 -30
  136. package/src/components/select/QSelect.js +2 -1
  137. package/src/components/select/__tests__/{QSelect.spec.js → QSelect.cy.js} +2 -3
  138. package/src/components/table/QTable.js +1 -1
  139. package/src/components/uploader/__tests__/{QUploader.spec.js → QUploader.cy.js} +1 -2
  140. package/src/composables/private/__tests__/{use-anchor.spec.js → use-anchor.cy.js} +7 -8
  141. package/src/composables/private/__tests__/{use-field.spec.js → use-field.cy.js} +7 -8
  142. package/src/composables/private/__tests__/{use-model-toggle.spec.js → use-model-toggle.cy.js} +17 -18
  143. package/src/composables/private/__tests__/{use-size.spec.js → use-size.cy.js} +4 -5
  144. package/src/composables/private/__tests__/{use-transition.spec.js → use-transition.cy.js} +9 -10
  145. package/src/composables/private/__tests__/{use-validate.spec.js → use-validate.cy.js} +5 -6
  146. package/src/composables/private/use-fullscreen.json +12 -0
  147. /package/src/components/date/__tests__/{QDate.spec.js → QDate.cy.js} +0 -0
  148. /package/src/components/dialog/__tests__/{QDialog.spec.js → QDialog.cy.js} +0 -0
  149. /package/src/components/editor/__tests__/{QEditor.spec.js → QEditor.cy.js} +0 -0
  150. /package/src/components/input/__tests__/{QInput.spec.js → QInput.cy.js} +0 -0
  151. /package/src/components/input/__tests__/{use-mask.spec.js → use-mask.cy.js} +0 -0
  152. /package/src/components/table/__tests__/{QTable.spec.js → QTable.cy.js} +0 -0
  153. /package/src/components/table/__tests__/{QTd.spec.js → QTd.cy.js} +0 -0
  154. /package/src/components/table/__tests__/{QTh.spec.js → QTh.cy.js} +0 -0
  155. /package/src/components/table/__tests__/{QTr.spec.js → QTr.cy.js} +0 -0
  156. /package/src/components/tabs/__tests__/{QRouteTab.spec.js → QRouteTab.cy.js} +0 -0
  157. /package/src/components/tabs/__tests__/{QTab.spec.js → QTab.cy.js} +0 -0
  158. /package/src/components/tabs/__tests__/{QTabs.spec.js → QTabs.cy.js} +0 -0
  159. /package/src/composables/private/__tests__/{use-file.spec.js → use-file.cy.js} +0 -0
  160. /package/src/composables/private/__tests__/{use-form.spec.js → use-form.cy.js} +0 -0
  161. /package/src/composables/private/__tests__/{use-fullscreen.spec.js → use-fullscreen.cy.js} +0 -0
  162. /package/src/composables/private/__tests__/{use-portal.spec.js → use-portal.cy.js} +0 -0
  163. /package/src/composables/private/__tests__/{use-router-link.spec.js → use-router-link.cy.js} +0 -0
@@ -269,6 +269,56 @@
269
269
  "desc": "The pure HTML of the content"
270
270
  }
271
271
  }
272
+ },
273
+
274
+ "dropdown-show": {
275
+ "desc": "Emitted after a dropdown in the toolbar has triggered show()",
276
+ "params": {
277
+ "evt": {
278
+ "extends": "evt"
279
+ }
280
+ },
281
+ "addedIn": "v2.11.8"
282
+ },
283
+
284
+ "dropdown-before-show": {
285
+ "desc": "Emitted when a dropdown in the toolbar triggers show() but before it finishes doing it",
286
+ "params": {
287
+ "evt": {
288
+ "extends": "evt"
289
+ }
290
+ },
291
+ "addedIn": "v2.11.8"
292
+ },
293
+
294
+ "dropdown-hide": {
295
+ "desc": "Emitted after a dropdown in the toolbar has triggered hide()",
296
+ "params": {
297
+ "evt": {
298
+ "extends": "evt"
299
+ }
300
+ },
301
+ "addedIn": "v2.11.8"
302
+ },
303
+
304
+ "dropdown-before-hide": {
305
+ "desc": "Emitted when a dropdown in the toolbar triggers hide() but before it finishes doing it",
306
+ "params": {
307
+ "evt": {
308
+ "extends": "evt"
309
+ }
310
+ },
311
+ "addedIn": "v2.11.8"
312
+ },
313
+
314
+ "link-show": {
315
+ "desc": "Emitted when the toolbar for editing a link is shown",
316
+ "addedIn": "v2.11.9"
317
+ },
318
+
319
+ "link-hide": {
320
+ "desc": "Emitted when the toolbar for editing a link is hidden",
321
+ "addedIn": "v2.11.9"
272
322
  }
273
323
  },
274
324
 
@@ -156,7 +156,11 @@ function getDropdown (eVm, btn) {
156
156
  textColor: highlight && !eVm.props.toolbarPush ? null : eVm.props.toolbarTextColor,
157
157
  label: btn.fixedLabel ? btn.label : label,
158
158
  icon: btn.fixedIcon ? (btn.icon !== null ? btn.icon : void 0) : icon,
159
- contentClass
159
+ contentClass,
160
+ onShow: evt => eVm.emit('dropdownShow', evt),
161
+ onHide: evt => eVm.emit('dropdownHide', evt),
162
+ onBeforeShow: evt => eVm.emit('dropdownBeforeShow', evt),
163
+ onBeforeHide: evt => eVm.emit('dropdownBeforeHide', evt)
160
164
  }, () => Items)
161
165
 
162
166
  return Dropdown
@@ -133,8 +133,14 @@ $field-transition-label-right-up: .324s cubic-bezier(.4,0,.2,1)
133
133
 
134
134
  &:-webkit-autofill + .q-field__label
135
135
  transform: translateY(-40%) scale(.75)
136
- &[type="number"]:invalid + .q-field__label
137
- transform: translateY(-40%) scale(.75)
136
+ &[type="color"],
137
+ &[type="date"],
138
+ &[type="datetime-local"],
139
+ &[type="month"],
140
+ &[type="time"],
141
+ &[type="week"]
142
+ + .q-field__label
143
+ transform: translateY(-40%) scale(.75)
138
144
 
139
145
  &:invalid
140
146
  box-shadow: none
@@ -438,8 +444,14 @@ $field-transition-label-right-up: .324s cubic-bezier(.4,0,.2,1)
438
444
  .q-field__native, .q-field__input
439
445
  &:-webkit-autofill + .q-field__label
440
446
  transform: translateY(-30%) scale(.75)
441
- &[type="number"]:invalid + .q-field__label
442
- transform: translateY(-30%) scale(.75)
447
+ &[type="color"],
448
+ &[type="date"],
449
+ &[type="datetime-local"],
450
+ &[type="month"],
451
+ &[type="time"],
452
+ &[type="week"]
453
+ + .q-field__label
454
+ transform: translateY(-30%) scale(.75)
443
455
 
444
456
  &--borderless, &--standard
445
457
 
@@ -41,7 +41,7 @@ export default createComponent({
41
41
  emits: [
42
42
  ...useFieldEmits,
43
43
  'paste', 'change',
44
- 'keydown', 'animationend'
44
+ 'keydown', 'click', 'animationend'
45
45
  ],
46
46
 
47
47
  setup (props, { emit, attrs }) {
@@ -59,7 +59,8 @@ export default createComponent({
59
59
  hasMask,
60
60
  moveCursorForPaste,
61
61
  updateMaskValue,
62
- onMaskedKeydown
62
+ onMaskedKeydown,
63
+ onMaskedClick
63
64
  } = useMask(props, emit, emitValue, inputRef)
64
65
 
65
66
  const formDomProps = useFileFormDomProps(props, /* type guard */ true)
@@ -96,6 +97,8 @@ export default createComponent({
96
97
 
97
98
  if (hasMask.value === true) {
98
99
  evt.onKeydown = onMaskedKeydown
100
+ // reset selection anchor on pointer selection
101
+ evt.onClick = onMaskedClick
99
102
  }
100
103
 
101
104
  if (props.autogrow === true) {
@@ -305,18 +308,29 @@ export default createComponent({
305
308
  const inp = inputRef.value
306
309
  if (inp !== null) {
307
310
  const parentStyle = inp.parentNode.style
308
- const { overflow } = inp.style
311
+ // chrome does not keep scroll #15498
312
+ const { scrollTop } = inp
313
+ // chrome calculates a smaller scrollHeight when in a .column container
314
+ const { overflowY, maxHeight } = $q.platform.is.firefox === true
315
+ ? {}
316
+ : window.getComputedStyle(inp)
317
+ // on firefox or if overflowY is specified as scroll #14263, #14344
318
+ // we don't touch overflow
319
+ // firefox is not so bad in the end
320
+ const changeOverflow = overflowY !== void 0 && overflowY !== 'scroll'
309
321
 
310
322
  // reset height of textarea to a small size to detect the real height
311
323
  // but keep the total control size the same
312
- // Firefox rulez #14263, #14344
313
- $q.platform.is.firefox !== true && (inp.style.overflow = 'hidden')
324
+ changeOverflow === true && (inp.style.overflowY = 'hidden')
314
325
  parentStyle.marginBottom = (inp.scrollHeight - 1) + 'px'
315
326
  inp.style.height = '1px'
316
327
 
317
328
  inp.style.height = inp.scrollHeight + 'px'
318
- inp.style.overflow = overflow
329
+ // we should allow scrollbars only
330
+ // if there is maxHeight and content is taller than maxHeight
331
+ changeOverflow === true && (inp.style.overflowY = parseInt(maxHeight, 10) < inp.scrollHeight ? 'auto' : 'hidden')
319
332
  parentStyle.marginBottom = ''
333
+ inp.scrollTop = scrollTop
320
334
  }
321
335
  })
322
336
  }
@@ -393,7 +407,10 @@ export default createComponent({
393
407
  hasValue,
394
408
 
395
409
  floatingLabel: computed(() =>
396
- hasValue.value === true
410
+ (
411
+ hasValue.value === true
412
+ && (props.type !== 'number' || isNaN(innerValue.value) === false)
413
+ )
397
414
  || fieldValueIsFilled(props.displayValue)
398
415
  ),
399
416
 
@@ -44,7 +44,7 @@ export const useMaskProps = {
44
44
  }
45
45
 
46
46
  export default function (props, emit, emitValue, inputRef) {
47
- let maskMarked, maskReplaced, computedMask, computedUnmask
47
+ let maskMarked, maskReplaced, computedMask, computedUnmask, pastedTextStart, selectionAnchor
48
48
 
49
49
  const hasMask = ref(null)
50
50
  const innerValue = ref(getInitialMaskedValue())
@@ -246,8 +246,15 @@ export default function (props, emit, emitValue, inputRef) {
246
246
  }
247
247
 
248
248
  if (inputType === 'insertFromPaste' && props.reverseFillMask !== true) {
249
- const cursor = end - 1
250
- moveCursor.right(inp, cursor, cursor)
249
+ const maxEnd = inp.selectionEnd
250
+ let cursor = end - 1
251
+ // each non-marker char means we move once to right
252
+ for (let i = pastedTextStart; i <= cursor && i < maxEnd; i++) {
253
+ if (maskMarked[ i ] !== MARKER) {
254
+ cursor++
255
+ }
256
+ }
257
+ moveCursor.right(inp, cursor)
251
258
 
252
259
  return
253
260
  }
@@ -273,7 +280,7 @@ export default function (props, emit, emitValue, inputRef) {
273
280
  inp.setSelectionRange(cursor, cursor, 'forward')
274
281
  }
275
282
  else {
276
- moveCursor.rightReverse(inp, cursor, cursor)
283
+ moveCursor.rightReverse(inp, cursor)
277
284
  }
278
285
  }
279
286
  else {
@@ -284,11 +291,11 @@ export default function (props, emit, emitValue, inputRef) {
284
291
  else {
285
292
  if (changed === true) {
286
293
  const cursor = Math.max(0, maskMarked.indexOf(MARKER), Math.min(preMasked.length, end) - 1)
287
- moveCursor.right(inp, cursor, cursor)
294
+ moveCursor.right(inp, cursor)
288
295
  }
289
296
  else {
290
297
  const cursor = end - 1
291
- moveCursor.right(inp, cursor, cursor)
298
+ moveCursor.right(inp, cursor)
292
299
  }
293
300
  }
294
301
  })
@@ -304,74 +311,72 @@ export default function (props, emit, emitValue, inputRef) {
304
311
  const preMasked = maskValue(unmaskValue(inp.value))
305
312
 
306
313
  start = Math.max(0, maskMarked.indexOf(MARKER), Math.min(preMasked.length, start))
314
+ pastedTextStart = start
307
315
 
308
316
  inp.setSelectionRange(start, end, 'forward')
309
317
  }
310
318
 
311
319
  const moveCursor = {
312
- left (inp, start, end, selection) {
313
- const noMarkBefore = maskMarked.slice(start - 1).indexOf(MARKER) === -1
314
- let i = Math.max(0, start - 1)
320
+ left (inp, cursor) {
321
+ const noMarkBefore = maskMarked.slice(cursor - 1).indexOf(MARKER) === -1
322
+ let i = Math.max(0, cursor - 1)
315
323
 
316
324
  for (; i >= 0; i--) {
317
325
  if (maskMarked[ i ] === MARKER) {
318
- start = i
319
- noMarkBefore === true && start++
326
+ cursor = i
327
+ noMarkBefore === true && cursor++
320
328
  break
321
329
  }
322
330
  }
323
331
 
324
332
  if (
325
333
  i < 0
326
- && maskMarked[ start ] !== void 0
327
- && maskMarked[ start ] !== MARKER
334
+ && maskMarked[ cursor ] !== void 0
335
+ && maskMarked[ cursor ] !== MARKER
328
336
  ) {
329
- return moveCursor.right(inp, 0, 0)
337
+ return moveCursor.right(inp, 0)
330
338
  }
331
339
 
332
- start >= 0 && inp.setSelectionRange(
333
- start,
334
- selection === true ? end : start, 'backward'
335
- )
340
+ cursor >= 0 && inp.setSelectionRange(cursor, cursor, 'backward')
336
341
  },
337
342
 
338
- right (inp, start, end, selection) {
343
+ right (inp, cursor) {
339
344
  const limit = inp.value.length
340
- let i = Math.min(limit, end + 1)
345
+ let i = Math.min(limit, cursor + 1)
341
346
 
342
347
  for (; i <= limit; i++) {
343
348
  if (maskMarked[ i ] === MARKER) {
344
- end = i
349
+ cursor = i
345
350
  break
346
351
  }
347
352
  else if (maskMarked[ i - 1 ] === MARKER) {
348
- end = i
353
+ cursor = i
349
354
  }
350
355
  }
351
356
 
352
357
  if (
353
358
  i > limit
354
- && maskMarked[ end - 1 ] !== void 0
355
- && maskMarked[ end - 1 ] !== MARKER
359
+ && maskMarked[ cursor - 1 ] !== void 0
360
+ && maskMarked[ cursor - 1 ] !== MARKER
356
361
  ) {
357
- return moveCursor.left(inp, limit, limit)
362
+ return moveCursor.left(inp, limit)
358
363
  }
359
364
 
360
- inp.setSelectionRange(selection ? start : end, end, 'forward')
365
+ inp.setSelectionRange(cursor, cursor, 'forward')
361
366
  },
362
367
 
363
- leftReverse (inp, start, end, selection) {
368
+ leftReverse (inp, cursor) {
364
369
  const
365
370
  localMaskMarked = getPaddedMaskMarked(inp.value.length)
366
- let i = Math.max(0, start - 1)
371
+ let i = Math.max(0, cursor - 1)
367
372
 
368
373
  for (; i >= 0; i--) {
369
374
  if (localMaskMarked[ i - 1 ] === MARKER) {
370
- start = i
375
+ cursor = i
371
376
  break
372
377
  }
373
378
  else if (localMaskMarked[ i ] === MARKER) {
374
- start = i
379
+ cursor = i
375
380
  if (i === 0) {
376
381
  break
377
382
  }
@@ -380,45 +385,48 @@ export default function (props, emit, emitValue, inputRef) {
380
385
 
381
386
  if (
382
387
  i < 0
383
- && localMaskMarked[ start ] !== void 0
384
- && localMaskMarked[ start ] !== MARKER
388
+ && localMaskMarked[ cursor ] !== void 0
389
+ && localMaskMarked[ cursor ] !== MARKER
385
390
  ) {
386
- return moveCursor.rightReverse(inp, 0, 0)
391
+ return moveCursor.rightReverse(inp, 0)
387
392
  }
388
393
 
389
- start >= 0 && inp.setSelectionRange(
390
- start,
391
- selection === true ? end : start, 'backward'
392
- )
394
+ cursor >= 0 && inp.setSelectionRange(cursor, cursor, 'backward')
393
395
  },
394
396
 
395
- rightReverse (inp, start, end, selection) {
397
+ rightReverse (inp, cursor) {
396
398
  const
397
399
  limit = inp.value.length,
398
400
  localMaskMarked = getPaddedMaskMarked(limit),
399
- noMarkBefore = localMaskMarked.slice(0, end + 1).indexOf(MARKER) === -1
400
- let i = Math.min(limit, end + 1)
401
+ noMarkBefore = localMaskMarked.slice(0, cursor + 1).indexOf(MARKER) === -1
402
+ let i = Math.min(limit, cursor + 1)
401
403
 
402
404
  for (; i <= limit; i++) {
403
405
  if (localMaskMarked[ i - 1 ] === MARKER) {
404
- end = i
405
- end > 0 && noMarkBefore === true && end--
406
+ cursor = i
407
+ cursor > 0 && noMarkBefore === true && cursor--
406
408
  break
407
409
  }
408
410
  }
409
411
 
410
412
  if (
411
413
  i > limit
412
- && localMaskMarked[ end - 1 ] !== void 0
413
- && localMaskMarked[ end - 1 ] !== MARKER
414
+ && localMaskMarked[ cursor - 1 ] !== void 0
415
+ && localMaskMarked[ cursor - 1 ] !== MARKER
414
416
  ) {
415
- return moveCursor.leftReverse(inp, limit, limit)
417
+ return moveCursor.leftReverse(inp, limit)
416
418
  }
417
419
 
418
- inp.setSelectionRange(selection === true ? start : end, end, 'forward')
420
+ inp.setSelectionRange(cursor, cursor, 'forward')
419
421
  }
420
422
  }
421
423
 
424
+ function onMaskedClick (e) {
425
+ emit('click', e)
426
+
427
+ selectionAnchor = void 0
428
+ }
429
+
422
430
  function onMaskedKeydown (e) {
423
431
  emit('keydown', e)
424
432
 
@@ -431,25 +439,40 @@ export default function (props, emit, emitValue, inputRef) {
431
439
  start = inp.selectionStart,
432
440
  end = inp.selectionEnd
433
441
 
442
+ if (!e.shiftKey) {
443
+ selectionAnchor = void 0
444
+ }
445
+
434
446
  if (e.keyCode === 37 || e.keyCode === 39) { // Left / Right
447
+ if (e.shiftKey && selectionAnchor === void 0) {
448
+ selectionAnchor = inp.selectionDirection === 'forward' ? start : end
449
+ }
450
+
435
451
  const fn = moveCursor[ (e.keyCode === 39 ? 'right' : 'left') + (props.reverseFillMask === true ? 'Reverse' : '') ]
436
452
 
437
453
  e.preventDefault()
438
- fn(inp, start, end, e.shiftKey)
454
+ fn(inp, selectionAnchor === start ? end : start)
455
+
456
+ if (e.shiftKey) {
457
+ const cursor = inp.selectionStart
458
+ inp.setSelectionRange(Math.min(selectionAnchor, cursor), Math.max(selectionAnchor, cursor), 'forward')
459
+ }
439
460
  }
440
461
  else if (
441
462
  e.keyCode === 8 // Backspace
442
463
  && props.reverseFillMask !== true
443
464
  && start === end
444
465
  ) {
445
- moveCursor.left(inp, start, end, true)
466
+ moveCursor.left(inp, start)
467
+ inp.setSelectionRange(inp.selectionStart, end, 'backward')
446
468
  }
447
469
  else if (
448
470
  e.keyCode === 46 // Delete
449
471
  && props.reverseFillMask === true
450
472
  && start === end
451
473
  ) {
452
- moveCursor.rightReverse(inp, start, end, true)
474
+ moveCursor.rightReverse(inp, end)
475
+ inp.setSelectionRange(start, inp.selectionEnd, 'forward')
453
476
  }
454
477
  }
455
478
 
@@ -540,6 +563,7 @@ export default function (props, emit, emitValue, inputRef) {
540
563
  hasMask,
541
564
  moveCursorForPaste,
542
565
  updateMaskValue,
543
- onMaskedKeydown
566
+ onMaskedKeydown,
567
+ onMaskedClick
544
568
  }
545
569
  }