quasar 2.1.9 → 2.2.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 (127) hide show
  1. package/dist/api/QCarousel.json +19 -5
  2. package/dist/api/QColor.json +6 -0
  3. package/dist/api/QInnerLoading.json +32 -0
  4. package/dist/api/QOptionGroup.json +22 -0
  5. package/dist/api/QSkeleton.json +14 -0
  6. package/dist/api/QStepper.json +16 -2
  7. package/dist/api/QTabPanels.json +16 -2
  8. package/dist/icon-set/bootstrap-icons.umd.prod.js +1 -1
  9. package/dist/icon-set/eva-icons.umd.prod.js +1 -1
  10. package/dist/icon-set/fontawesome-v5-pro.umd.prod.js +1 -1
  11. package/dist/icon-set/fontawesome-v5.umd.prod.js +1 -1
  12. package/dist/icon-set/ionicons-v4.umd.prod.js +1 -1
  13. package/dist/icon-set/line-awesome.umd.prod.js +1 -1
  14. package/dist/icon-set/material-icons-outlined.umd.prod.js +1 -1
  15. package/dist/icon-set/material-icons-round.umd.prod.js +1 -1
  16. package/dist/icon-set/material-icons-sharp.umd.prod.js +1 -1
  17. package/dist/icon-set/material-icons.umd.prod.js +1 -1
  18. package/dist/icon-set/mdi-v3.umd.prod.js +1 -1
  19. package/dist/icon-set/mdi-v4.umd.prod.js +1 -1
  20. package/dist/icon-set/mdi-v5.umd.prod.js +1 -1
  21. package/dist/icon-set/mdi-v6.umd.prod.js +1 -1
  22. package/dist/icon-set/svg-bootstrap-icons.umd.prod.js +1 -1
  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-ionicons-v4.umd.prod.js +1 -1
  26. package/dist/icon-set/svg-ionicons-v5.umd.prod.js +1 -1
  27. package/dist/icon-set/svg-line-awesome.umd.prod.js +1 -1
  28. package/dist/icon-set/svg-material-icons-outlined.umd.prod.js +1 -1
  29. package/dist/icon-set/svg-material-icons-round.umd.prod.js +1 -1
  30. package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +1 -1
  31. package/dist/icon-set/svg-material-icons.umd.prod.js +1 -1
  32. package/dist/icon-set/svg-mdi-v4.umd.prod.js +1 -1
  33. package/dist/icon-set/svg-mdi-v5.umd.prod.js +1 -1
  34. package/dist/icon-set/svg-mdi-v6.umd.prod.js +1 -1
  35. package/dist/icon-set/svg-themify.umd.prod.js +1 -1
  36. package/dist/icon-set/themify.umd.prod.js +1 -1
  37. package/dist/lang/ar.umd.prod.js +1 -1
  38. package/dist/lang/az-Latn.umd.prod.js +1 -1
  39. package/dist/lang/bg.umd.prod.js +1 -1
  40. package/dist/lang/bn.umd.prod.js +1 -1
  41. package/dist/lang/ca.umd.prod.js +1 -1
  42. package/dist/lang/cs.umd.prod.js +1 -1
  43. package/dist/lang/da.umd.prod.js +1 -1
  44. package/dist/lang/de.umd.prod.js +1 -1
  45. package/dist/lang/el.umd.prod.js +1 -1
  46. package/dist/lang/en-GB.umd.prod.js +1 -1
  47. package/dist/lang/en-US.umd.prod.js +1 -1
  48. package/dist/lang/eo.umd.prod.js +1 -1
  49. package/dist/lang/es.umd.prod.js +1 -1
  50. package/dist/lang/et.umd.prod.js +1 -1
  51. package/dist/lang/fa-IR.umd.prod.js +1 -1
  52. package/dist/lang/fa.umd.prod.js +1 -1
  53. package/dist/lang/fi.umd.prod.js +1 -1
  54. package/dist/lang/fr.umd.prod.js +1 -1
  55. package/dist/lang/gn.umd.prod.js +1 -1
  56. package/dist/lang/he.umd.prod.js +1 -1
  57. package/dist/lang/hr.umd.prod.js +1 -1
  58. package/dist/lang/hu.umd.prod.js +1 -1
  59. package/dist/lang/id.umd.prod.js +1 -1
  60. package/dist/lang/is.umd.prod.js +1 -1
  61. package/dist/lang/it.umd.prod.js +1 -1
  62. package/dist/lang/ja.umd.prod.js +1 -1
  63. package/dist/lang/km.umd.prod.js +1 -1
  64. package/dist/lang/ko-KR.umd.prod.js +1 -1
  65. package/dist/lang/kur-CKB.umd.prod.js +1 -1
  66. package/dist/lang/lt.umd.prod.js +6 -0
  67. package/dist/lang/lu.umd.prod.js +1 -1
  68. package/dist/lang/lv.umd.prod.js +1 -1
  69. package/dist/lang/ml.umd.prod.js +1 -1
  70. package/dist/lang/ms.umd.prod.js +1 -1
  71. package/dist/lang/nb-NO.umd.prod.js +1 -1
  72. package/dist/lang/nl.umd.prod.js +1 -1
  73. package/dist/lang/pl.umd.prod.js +1 -1
  74. package/dist/lang/pt-BR.umd.prod.js +1 -1
  75. package/dist/lang/pt.umd.prod.js +1 -1
  76. package/dist/lang/ro.umd.prod.js +1 -1
  77. package/dist/lang/ru.umd.prod.js +1 -1
  78. package/dist/lang/sk.umd.prod.js +1 -1
  79. package/dist/lang/sl.umd.prod.js +1 -1
  80. package/dist/lang/sr-CYR.umd.prod.js +1 -1
  81. package/dist/lang/sr.umd.prod.js +1 -1
  82. package/dist/lang/sv.umd.prod.js +1 -1
  83. package/dist/lang/ta.umd.prod.js +1 -1
  84. package/dist/lang/th.umd.prod.js +1 -1
  85. package/dist/lang/tr.umd.prod.js +1 -1
  86. package/dist/lang/ug.umd.prod.js +2 -2
  87. package/dist/lang/uk.umd.prod.js +1 -1
  88. package/dist/lang/vi.umd.prod.js +1 -1
  89. package/dist/lang/zh-CN.umd.prod.js +1 -1
  90. package/dist/lang/zh-TW.umd.prod.js +1 -1
  91. package/dist/quasar.cjs.prod.js +2 -2
  92. package/dist/quasar.css +24 -17
  93. package/dist/quasar.esm.prod.js +2 -2
  94. package/dist/quasar.prod.css +1 -1
  95. package/dist/quasar.rtl.css +29 -22
  96. package/dist/quasar.rtl.prod.css +1 -1
  97. package/dist/quasar.sass +24 -16
  98. package/dist/quasar.umd.js +236 -143
  99. package/dist/quasar.umd.prod.js +2 -2
  100. package/dist/ssr-directives/Morph.js +1 -1
  101. package/dist/types/index.d.ts +57 -4
  102. package/dist/vetur/quasar-attributes.json +33 -1
  103. package/dist/vetur/quasar-tags.json +9 -1
  104. package/dist/web-types/web-types.json +93 -5
  105. package/lang/index.json +4 -0
  106. package/lang/lt.js +103 -0
  107. package/lang/ug.js +42 -42
  108. package/package.json +1 -1
  109. package/src/components/carousel/QCarousel.js +8 -1
  110. package/src/components/carousel/QCarousel.json +9 -1
  111. package/src/components/color/QColor.js +73 -61
  112. package/src/components/color/QColor.json +7 -0
  113. package/src/components/color/QColor.sass +5 -1
  114. package/src/components/dialog/QDialog.js +6 -0
  115. package/src/components/inner-loading/QInnerLoading.js +31 -7
  116. package/src/components/inner-loading/QInnerLoading.json +29 -0
  117. package/src/components/inner-loading/QInnerLoading.sass +4 -0
  118. package/src/components/option-group/QOptionGroup.js +29 -19
  119. package/src/components/option-group/QOptionGroup.json +26 -0
  120. package/src/components/rating/QRating.js +59 -39
  121. package/src/components/rating/QRating.sass +8 -6
  122. package/src/components/skeleton/QSkeleton.js +15 -5
  123. package/src/components/skeleton/QSkeleton.json +9 -0
  124. package/src/components/skeleton/QSkeleton.sass +7 -6
  125. package/src/composables/private/use-panel.js +13 -8
  126. package/src/composables/private/use-panel.json +11 -2
  127. package/src/css/core/transitions.sass +4 -4
@@ -40,7 +40,7 @@
40
40
 
41
41
  "autoplay": {
42
42
  "type": [ "Number", "Boolean" ],
43
- "desc": "Jump to next slide at fixed time intervals (in milliseconds); 'false' disables autoplay, 'true' enables it for 5000ms intervals",
43
+ "desc": "Jump to next slide (if 'true' or val > 0) or previous slide (if val < 0) at fixed time intervals (in milliseconds); 'false' disables autoplay, 'true' enables it for 5000ms intervals",
44
44
  "default": false,
45
45
  "examples": [
46
46
  ":autoplay=\"2500\"",
@@ -92,6 +92,14 @@
92
92
  "type": "Boolean",
93
93
  "desc": "Show thumbnails",
94
94
  "category": "content"
95
+ },
96
+
97
+ "transition-prev": {
98
+ "default": "fade"
99
+ },
100
+
101
+ "transition-next": {
102
+ "default": "fade"
95
103
  }
96
104
  },
97
105
 
@@ -60,6 +60,7 @@ export default defineComponent({
60
60
  palette: Array,
61
61
 
62
62
  noHeader: Boolean,
63
+ noHeaderTabs: Boolean,
63
64
  noFooter: Boolean,
64
65
 
65
66
  square: Boolean,
@@ -145,7 +146,7 @@ export default defineComponent({
145
146
  ? true
146
147
  : luminosity(model.value) > 0.4
147
148
 
148
- return 'q-color-picker__header-content absolute-full'
149
+ return 'q-color-picker__header-content'
149
150
  + ` q-color-picker__header-content--${ light ? 'light' : 'dark' }`
150
151
  })
151
152
 
@@ -496,6 +497,63 @@ export default defineComponent({
496
497
  }
497
498
 
498
499
  function getHeader () {
500
+ const child = []
501
+
502
+ props.noHeaderTabs !== true && child.push(
503
+ h(QTabs, {
504
+ class: 'q-color-picker__header-tabs',
505
+ modelValue: topView.value,
506
+ dense: true,
507
+ align: 'justify',
508
+ ...getCache('topVTab', {
509
+ 'onUpdate:modelValue': val => { topView.value = val }
510
+ })
511
+ }, () => [
512
+ h(QTab, {
513
+ label: 'HEX' + (hasAlpha.value === true ? 'A' : ''),
514
+ name: 'hex',
515
+ ripple: false
516
+ }),
517
+
518
+ h(QTab, {
519
+ label: 'RGB' + (hasAlpha.value === true ? 'A' : ''),
520
+ name: 'rgb',
521
+ ripple: false
522
+ })
523
+ ])
524
+ )
525
+
526
+ child.push(
527
+ h('div', {
528
+ class: 'q-color-picker__header-banner row flex-center no-wrap'
529
+ }, [
530
+ h('input', {
531
+ class: 'fit',
532
+ value: model.value[ topView.value ],
533
+ ...(editable.value !== true
534
+ ? { readonly: true }
535
+ : {}
536
+ ),
537
+ ...getCache('topIn', {
538
+ onInput: evt => {
539
+ updateErrorIcon(onEditorChange(evt) === true)
540
+ },
541
+ onChange: stop,
542
+ onBlur: evt => {
543
+ onEditorChange(evt, true) === true && proxy.$forceUpdate()
544
+ updateErrorIcon(false)
545
+ }
546
+ })
547
+ }),
548
+
549
+ h(QIcon, {
550
+ ref: errorIconRef,
551
+ class: 'q-color-picker__error-icon absolute no-pointer-events',
552
+ name: $q.iconSet.type.negative
553
+ })
554
+ ])
555
+ )
556
+
499
557
  return h('div', {
500
558
  class: 'q-color-picker__header relative-position overflow-hidden'
501
559
  }, [
@@ -504,57 +562,7 @@ export default defineComponent({
504
562
  h('div', {
505
563
  class: headerClass.value,
506
564
  style: currentBgColor.value
507
- }, [
508
- h(QTabs, {
509
- modelValue: topView.value,
510
- dense: true,
511
- align: 'justify',
512
- ...getCache('topVTab', {
513
- 'onUpdate:modelValue': val => { topView.value = val }
514
- })
515
- }, () => [
516
- h(QTab, {
517
- label: 'HEX' + (hasAlpha.value === true ? 'A' : ''),
518
- name: 'hex',
519
- ripple: false
520
- }),
521
-
522
- h(QTab, {
523
- label: 'RGB' + (hasAlpha.value === true ? 'A' : ''),
524
- name: 'rgb',
525
- ripple: false
526
- })
527
- ]),
528
-
529
- h('div', {
530
- class: 'q-color-picker__header-banner row flex-center no-wrap'
531
- }, [
532
- h('input', {
533
- class: 'fit',
534
- value: model.value[ topView.value ],
535
- ...(editable.value !== true
536
- ? { readonly: true }
537
- : {}
538
- ),
539
- ...getCache('topIn', {
540
- onInput: evt => {
541
- updateErrorIcon(onEditorChange(evt) === true)
542
- },
543
- onChange: stop,
544
- onBlur: evt => {
545
- onEditorChange(evt, true) === true && proxy.$forceUpdate()
546
- updateErrorIcon(false)
547
- }
548
- })
549
- }),
550
-
551
- h(QIcon, {
552
- ref: errorIconRef,
553
- class: 'q-color-picker__error-icon absolute no-pointer-events',
554
- name: $q.iconSet.type.negative
555
- })
556
- ])
557
- ])
565
+ }, child)
558
566
  ])
559
567
  }
560
568
 
@@ -790,19 +798,23 @@ export default defineComponent({
790
798
  }
791
799
 
792
800
  function getPaletteTab () {
801
+ const fn = color => h('div', {
802
+ class: 'q-color-picker__cube col-auto',
803
+ style: { backgroundColor: color },
804
+ ...(
805
+ editable.value === true
806
+ ? getCache('palette#' + color, {
807
+ onClick: () => { onPalettePick(color) }
808
+ })
809
+ : {}
810
+ )
811
+ })
812
+
793
813
  return [
794
814
  h('div', {
795
815
  class: 'row items-center q-color-picker__palette-rows'
796
816
  + (editable.value === true ? ' q-color-picker__palette-rows--editable' : '')
797
- }, computedPalette.value.map(color => h('div', {
798
- class: 'q-color-picker__cube col-auto',
799
- style: { backgroundColor: color },
800
- ...(editable.value === true ? getCache('palette#' + color, {
801
- onClick: () => {
802
- onPalettePick(color)
803
- }
804
- }) : {})
805
- })))
817
+ }, computedPalette.value.map(fn))
806
818
  ]
807
819
  }
808
820
 
@@ -64,6 +64,13 @@
64
64
  "category": "content"
65
65
  },
66
66
 
67
+ "no-header-tabs": {
68
+ "type": "Boolean",
69
+ "desc": "Do not render header tabs (only the input)",
70
+ "category": "content",
71
+ "addedIn": "v2.2"
72
+ },
73
+
67
74
  "no-footer": {
68
75
  "type": "Boolean",
69
76
  "desc": "Do not render footer; Useful when you want a specific view ('default-view' prop) and don't want the user to be able to switch it",
@@ -16,7 +16,11 @@
16
16
  border: 1px solid $separator-color
17
17
 
18
18
  &__header
19
- height: 68px
19
+
20
+ &-tabs
21
+ height: 32px
22
+ &-banner
23
+ height: 36px
20
24
 
21
25
  input
22
26
  line-height: 24px
@@ -135,6 +135,10 @@ export default defineComponent({
135
135
  : transitionShow.value
136
136
  ))
137
137
 
138
+ const transitionStyle = computed(
139
+ () => `--q-transition-duration: ${ props.transitionDuration }ms`
140
+ )
141
+
138
142
  const useBackdrop = computed(() => showing.value === true && props.seamless !== true)
139
143
 
140
144
  const onEvents = computed(() => (
@@ -375,6 +379,7 @@ export default defineComponent({
375
379
  useBackdrop.value === true
376
380
  ? h('div', {
377
381
  class: 'q-dialog__backdrop fixed-full',
382
+ style: transitionStyle.value,
378
383
  'aria-hidden': 'true',
379
384
  onMousedown: onBackdropClick
380
385
  })
@@ -389,6 +394,7 @@ export default defineComponent({
389
394
  ? h('div', {
390
395
  ref: innerRef,
391
396
  class: classes.value,
397
+ style: transitionStyle.value,
392
398
  tabindex: -1,
393
399
  ...onEvents.value
394
400
  }, hSlot(slots.default))
@@ -18,7 +18,11 @@ export default defineComponent({
18
18
  size: {
19
19
  type: [ String, Number ],
20
20
  default: 42
21
- }
21
+ },
22
+
23
+ label: String,
24
+ labelClass: String,
25
+ labelStyle: [ String, Array, Object ]
22
26
  },
23
27
 
24
28
  setup (props, { slots }) {
@@ -32,6 +36,31 @@ export default defineComponent({
32
36
  + (isDark.value === true ? ' q-inner-loading--dark' : '')
33
37
  )
34
38
 
39
+ const labelClass = computed(() =>
40
+ 'q-inner-loading__label'
41
+ + (props.labelClass !== void 0 ? ` ${ props.labelClass}` : '')
42
+ )
43
+
44
+ function getInner () {
45
+ const child = [
46
+ h(QSpinner, {
47
+ size: props.size,
48
+ color: props.color
49
+ })
50
+ ]
51
+
52
+ if (props.label !== void 0) {
53
+ child.push(
54
+ h('div', {
55
+ class: labelClass.value,
56
+ style: props.labelStyle
57
+ }, [ props.label ])
58
+ )
59
+ }
60
+
61
+ return child
62
+ }
63
+
35
64
  function getContent () {
36
65
  return props.showing === true
37
66
  ? h(
@@ -39,12 +68,7 @@ export default defineComponent({
39
68
  { class: classes.value, style: transitionStyle.value },
40
69
  slots.default !== void 0
41
70
  ? slots.default()
42
- : [
43
- h(QSpinner, {
44
- size: props.size,
45
- color: props.color
46
- })
47
- ]
71
+ : getInner()
48
72
  )
49
73
  : null
50
74
  }
@@ -22,6 +22,35 @@
22
22
  "default": "42px"
23
23
  },
24
24
 
25
+ "label": {
26
+ "type": "String",
27
+ "desc": "Add a label; Gets overriden when using the default slot",
28
+ "examples": [ "Please wait..." ],
29
+ "category": "label",
30
+ "addedIn": "v2.2"
31
+ },
32
+
33
+ "label-class": {
34
+ "type": "String",
35
+ "desc": "Add CSS class(es) to the label; Works along the 'label' prop only",
36
+ "examples": [
37
+ "text-red q-mt-xl"
38
+ ],
39
+ "category": "label",
40
+ "addedIn": "v2.2"
41
+ },
42
+
43
+ "label-style": {
44
+ "type": [ "Array", "String", "Object" ],
45
+ "desc": "Apply custom style to the label; Works along the 'label' prop only",
46
+ "examples": [
47
+ "font-size: 28px",
48
+ ":label-style=\"{ color: '#ff0000' }\""
49
+ ],
50
+ "category": "label",
51
+ "addedIn": "v2.2"
52
+ },
53
+
25
54
  "dark": {
26
55
  "extends": "dark"
27
56
  }
@@ -1,4 +1,8 @@
1
1
  .q-inner-loading
2
2
  background: $light-dimmed-background
3
+
3
4
  &--dark
4
5
  background: $dimmed-background
6
+
7
+ &__label
8
+ margin-top: 8px
@@ -48,7 +48,7 @@ export default defineComponent({
48
48
 
49
49
  emits: [ 'update:modelValue' ],
50
50
 
51
- setup (props, { emit }) {
51
+ setup (props, { emit, slots }) {
52
52
  const { proxy: { $q } } = getCurrentInstance()
53
53
 
54
54
  const arrayModel = Array.isArray(props.modelValue)
@@ -92,23 +92,33 @@ export default defineComponent({
92
92
  return () => h('div', {
93
93
  class: classes.value,
94
94
  ...attrs.value
95
- }, props.options.map(opt => h('div', [
96
- h(component.value, {
97
- modelValue: props.modelValue,
98
- val: opt.value,
99
- name: opt.name === void 0 ? props.name : opt.name,
100
- disable: props.disable || opt.disable,
101
- label: opt.label,
102
- leftLabel: opt.leftLabel === void 0 ? props.leftLabel : opt.leftLabel,
103
- color: opt.color === void 0 ? props.color : opt.color,
104
- checkedIcon: opt.checkedIcon,
105
- uncheckedIcon: opt.uncheckedIcon,
106
- dark: opt.dark || isDark.value,
107
- size: opt.size === void 0 ? props.size : opt.size,
108
- dense: props.dense,
109
- keepColor: opt.keepColor === void 0 ? props.keepColor : opt.keepColor,
110
- 'onUpdate:modelValue': onUpdateModelValue
111
- })
112
- ])))
95
+ }, props.options.map((opt, i) => {
96
+ const child = slots[ 'label-' + i ] !== void 0
97
+ ? () => slots[ 'label-' + i ](opt)
98
+ : (
99
+ slots.label !== void 0
100
+ ? () => slots.label(opt)
101
+ : void 0
102
+ )
103
+
104
+ return h('div', [
105
+ h(component.value, {
106
+ modelValue: props.modelValue,
107
+ val: opt.value,
108
+ name: opt.name === void 0 ? props.name : opt.name,
109
+ disable: props.disable || opt.disable,
110
+ label: child === void 0 ? opt.label : null,
111
+ leftLabel: opt.leftLabel === void 0 ? props.leftLabel : opt.leftLabel,
112
+ color: opt.color === void 0 ? props.color : opt.color,
113
+ checkedIcon: opt.checkedIcon,
114
+ uncheckedIcon: opt.uncheckedIcon,
115
+ dark: opt.dark || isDark.value,
116
+ size: opt.size === void 0 ? props.size : opt.size,
117
+ dense: props.dense,
118
+ keepColor: opt.keepColor === void 0 ? props.keepColor : opt.keepColor,
119
+ 'onUpdate:modelValue': onUpdateModelValue
120
+ }, child)
121
+ ])
122
+ }))
113
123
  }
114
124
  })
@@ -72,6 +72,32 @@
72
72
  }
73
73
  },
74
74
 
75
+ "slots": {
76
+ "label": {
77
+ "desc": "Generic slot for all labels",
78
+ "scope": {
79
+ "opt": {
80
+ "type": "Object",
81
+ "desc": "The corresponding option entry from the 'options' prop",
82
+ "__exemption": [ "examples" ]
83
+ }
84
+ },
85
+ "addedIn": "v2.2"
86
+ },
87
+
88
+ "label-[name]": {
89
+ "desc": "Slot to define the specific label for the option at '[name]' where name is a 0-based index; Overrides the generic 'label' slot if used",
90
+ "scope": {
91
+ "...opt": {
92
+ "type": "Object",
93
+ "desc": "The corresponding option entry from the 'options' prop",
94
+ "__exemption": [ "examples" ]
95
+ }
96
+ },
97
+ "addedIn": "v2.2"
98
+ }
99
+ },
100
+
75
101
  "events": {
76
102
  "update:model-value": {
77
103
  "extends": "update:model-value"
@@ -4,6 +4,7 @@ import QIcon from '../icon/QIcon.js'
4
4
 
5
5
  import { stopAndPrevent } from '../../utils/event.js'
6
6
  import { between } from '../../utils/format.js'
7
+ import { hMergeSlot } from '../../utils/private/render.js'
7
8
 
8
9
  import useSize, { useSizeProps } from '../../composables/private/use-size.js'
9
10
  import { useFormProps, useFormAttrs, useFormInject } from '../../composables/private/use-form.js'
@@ -94,6 +95,51 @@ export default defineComponent({
94
95
  }
95
96
  })
96
97
 
98
+ const stars = computed(() => {
99
+ const
100
+ acc = [],
101
+ icons = iconData.value,
102
+ ceil = Math.ceil(props.modelValue)
103
+
104
+ const halfIndex = props.iconHalf === void 0 || ceil === props.modelValue
105
+ ? -1
106
+ : ceil
107
+
108
+ for (let i = 1; i <= props.max; i++) {
109
+ const
110
+ active = (mouseModel.value === 0 && props.modelValue >= i) || (mouseModel.value > 0 && mouseModel.value >= i),
111
+ half = halfIndex === i && mouseModel.value < i,
112
+ exSelected = mouseModel.value > 0 && (half === true ? ceil : props.modelValue) >= i && mouseModel.value < i,
113
+ color = half === true
114
+ ? (i <= icons.halfColorLen ? props.colorHalf[ i - 1 ] : icons.halfColor)
115
+ : (
116
+ icons.selColor !== void 0 && active === true
117
+ ? (i <= icons.selColorLen ? props.colorSelected[ i - 1 ] : icons.selColor)
118
+ : (i <= icons.colorLen ? props.color[ i - 1 ] : icons.color)
119
+ )
120
+
121
+ acc.push({
122
+ name: (
123
+ half === true
124
+ ? (i <= icons.halfIconLen ? props.iconHalf[ i - 1 ] : icons.halfIcon)
125
+ : (
126
+ icons.selIcon !== void 0 && (active === true || exSelected === true)
127
+ ? (i <= icons.selIconLen ? props.iconSelected[ i - 1 ] : icons.selIcon)
128
+ : (i <= icons.iconLen ? props.icon[ i - 1 ] : icons.icon)
129
+ )
130
+ ) || $q.iconSet.rating.icon,
131
+
132
+ classes: 'q-rating__icon'
133
+ + (active === true || half === true ? ' q-rating__icon--active' : '')
134
+ + (exSelected === true ? ' q-rating__icon--exselected' : '')
135
+ + (mouseModel.value === i ? ' q-rating__icon--hovered' : '')
136
+ + (color !== void 0 ? ` text-${ color }` : '')
137
+ })
138
+ }
139
+
140
+ return acc
141
+ })
142
+
97
143
  const attributes = computed(() => {
98
144
  if (props.disable === true) {
99
145
  return { 'aria-disabled': 'true' }
@@ -103,6 +149,8 @@ export default defineComponent({
103
149
  }
104
150
  })
105
151
 
152
+ const tabindex = computed(() => (editable.value === true ? 0 : null))
153
+
106
154
  function set (value) {
107
155
  if (editable.value === true) {
108
156
  const
@@ -150,57 +198,29 @@ export default defineComponent({
150
198
  })
151
199
 
152
200
  return () => {
153
- const
154
- child = [],
155
- tabindex = editable.value === true ? 0 : null,
156
- icons = iconData.value,
157
- ceil = Math.ceil(props.modelValue)
201
+ const child = []
158
202
 
159
- const halfIndex = props.iconHalf === void 0 || ceil === props.modelValue
160
- ? -1
161
- : ceil
162
-
163
- for (let i = 1; i <= props.max; i++) {
164
- const
165
- active = (mouseModel.value === 0 && props.modelValue >= i) || (mouseModel.value > 0 && mouseModel.value >= i),
166
- half = halfIndex === i && mouseModel.value < i,
167
- exSelected = mouseModel.value > 0 && (half === true ? ceil : props.modelValue) >= i && mouseModel.value < i,
168
- name = half === true
169
- ? (i <= icons.halfIconLen ? props.iconHalf[ i - 1 ] : icons.halfIcon)
170
- : (
171
- icons.selIcon !== void 0 && (active === true || exSelected === true)
172
- ? (i <= icons.selIconLen ? props.iconSelected[ i - 1 ] : icons.selIcon)
173
- : (i <= icons.iconLen ? props.icon[ i - 1 ] : icons.icon)
174
- ),
175
- color = half === true
176
- ? (i <= icons.halfColorLen ? props.colorHalf[ i - 1 ] : icons.halfColor)
177
- : (
178
- icons.selColor !== void 0 && active === true
179
- ? (i <= icons.selColorLen ? props.colorSelected[ i - 1 ] : icons.selColor)
180
- : (i <= icons.colorLen ? props.color[ i - 1 ] : icons.color)
181
- ),
182
- classes = 'q-rating__icon'
183
- + (active === true || half === true ? ' q-rating__icon--active' : '')
184
- + (exSelected === true ? ' q-rating__icon--exselected' : '')
185
- + (mouseModel.value === i ? ' q-rating__icon--hovered' : '')
186
- + (color !== void 0 ? ` text-${ color }` : '')
203
+ stars.value.forEach(({ classes, name }, index) => {
204
+ const i = index + 1
187
205
 
188
206
  child.push(
189
- h(QIcon, {
207
+ h('div', {
190
208
  key: i,
191
209
  ref: vm => { iconRefs[ `rt${ i }` ] = vm },
192
- class: classes,
193
- name: name || $q.iconSet.rating.icon,
194
- tabindex,
210
+ class: 'q-rating__icon-container flex flex-center',
211
+ tabindex: tabindex.value,
195
212
  onClick () { set(i) },
196
213
  onMouseover () { setHoverValue(i) },
197
214
  onMouseout: resetMouseModel,
198
215
  onFocus () { setHoverValue(i) },
199
216
  onBlur: resetMouseModel,
200
217
  onKeyup (e) { onKeyup(e, i) }
201
- }, slots[ `tip-${ i }` ])
218
+ }, hMergeSlot(
219
+ slots[ `tip-${ i }` ],
220
+ [ h(QIcon, { class: classes, name }) ]
221
+ ))
202
222
  )
203
- }
223
+ })
204
224
 
205
225
  if (props.name !== void 0 && props.disable !== true) {
206
226
  injectFormInput(child, 'push')
@@ -2,6 +2,13 @@
2
2
  color: $rating-grade-color
3
3
  vertical-align: middle
4
4
 
5
+ &__icon-container
6
+ height: 1em
7
+ outline: 0
8
+
9
+ & + &
10
+ margin-left: 2px
11
+
5
12
  &__icon
6
13
  color: currentColor
7
14
  text-shadow: $rating-shadow
@@ -17,13 +24,8 @@
17
24
  &--exselected
18
25
  opacity: .7
19
26
 
20
- & + &
21
- margin-left: 2px
22
-
23
27
  &--no-dimming .q-rating__icon
24
28
  opacity: 1
25
29
 
26
- &--editable .q-icon
30
+ &--editable .q-rating__icon-container
27
31
  cursor: pointer
28
- &--non-editable span, .q-icon
29
- outline: 0
@@ -38,6 +38,10 @@ export default defineComponent({
38
38
  validator: v => skeletonAnimations.includes(v),
39
39
  default: 'wave'
40
40
  },
41
+ animationSpeed: {
42
+ type: [ String, Number ],
43
+ default: 1500
44
+ },
41
45
 
42
46
  square: Boolean,
43
47
  bordered: Boolean,
@@ -51,11 +55,17 @@ export default defineComponent({
51
55
  const vm = getCurrentInstance()
52
56
  const isDark = useDark(props, vm.proxy.$q)
53
57
 
54
- const style = computed(() => (
55
- props.size !== void 0
56
- ? { width: props.size, height: props.size }
57
- : { width: props.width, height: props.height }
58
- ))
58
+ const style = computed(() => {
59
+ const size = props.size !== void 0
60
+ ? [ props.size, props.size ]
61
+ : [ props.width, props.height ]
62
+
63
+ return {
64
+ '--q-skeleton-speed': `${ props.animationSpeed }ms`,
65
+ width: size[ 0 ],
66
+ height: size[ 1 ]
67
+ }
68
+ })
59
69
 
60
70
  const classes = computed(() =>
61
71
  `q-skeleton q-skeleton--${ isDark.value === true ? 'dark' : 'light' } q-skeleton--type-${ props.type }`
@@ -32,6 +32,15 @@
32
32
  "category": "style"
33
33
  },
34
34
 
35
+ "animation-speed": {
36
+ "type": [ "String", "Number" ],
37
+ "desc": "Animation speed (in milliseconds, without unit)",
38
+ "default": 300,
39
+ "examples": [ 500, "1200" ],
40
+ "category": "style",
41
+ "addedIn": "v2.2"
42
+ },
43
+
35
44
  "square": {
36
45
  "extends": "square"
37
46
  },