quasar 2.3.4 → 2.4.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 (238) hide show
  1. package/dist/api/BottomSheet.json +1 -1
  2. package/dist/api/Loading.json +2 -6
  3. package/dist/api/Notify.json +5 -5
  4. package/dist/api/QAvatar.json +1 -1
  5. package/dist/api/QBreadcrumbsEl.json +32 -11
  6. package/dist/api/QBtn.json +32 -16
  7. package/dist/api/QBtnDropdown.json +33 -17
  8. package/dist/api/QBtnToggle.json +4 -1
  9. package/dist/api/QCarousel.json +4 -4
  10. package/dist/api/QChatMessage.json +4 -12
  11. package/dist/api/QChip.json +4 -4
  12. package/dist/api/QExpansionItem.json +34 -13
  13. package/dist/api/QFab.json +32 -2
  14. package/dist/api/QFabAction.json +9 -1
  15. package/dist/api/QField.json +1 -0
  16. package/dist/api/QFile.json +1 -0
  17. package/dist/api/QInput.json +1 -0
  18. package/dist/api/QItem.json +31 -10
  19. package/dist/api/QLinearProgress.json +1 -1
  20. package/dist/api/QOptionGroup.json +74 -4
  21. package/dist/api/QPagination.json +4 -4
  22. package/dist/api/QPullToRefresh.json +1 -1
  23. package/dist/api/QRange.json +592 -107
  24. package/dist/api/QRating.json +3 -3
  25. package/dist/api/QRouteTab.json +32 -12
  26. package/dist/api/QSelect.json +4 -7
  27. package/dist/api/QSlider.json +504 -39
  28. package/dist/api/QStep.json +4 -4
  29. package/dist/api/QStepper.json +4 -4
  30. package/dist/api/QTab.json +1 -1
  31. package/dist/api/QTable.json +4 -4
  32. package/dist/api/QTimelineEntry.json +1 -1
  33. package/dist/api/QToggle.json +1 -1
  34. package/dist/api/QTree.json +1 -1
  35. package/dist/api/QUploader.json +16 -2
  36. package/dist/api/QVideo.json +11 -1
  37. package/dist/icon-set/bootstrap-icons.umd.prod.js +1 -1
  38. package/dist/icon-set/eva-icons.umd.prod.js +1 -1
  39. package/dist/icon-set/fontawesome-v5-pro.umd.prod.js +1 -1
  40. package/dist/icon-set/fontawesome-v5.umd.prod.js +1 -1
  41. package/dist/icon-set/ionicons-v4.umd.prod.js +1 -1
  42. package/dist/icon-set/line-awesome.umd.prod.js +1 -1
  43. package/dist/icon-set/material-icons-outlined.umd.prod.js +1 -1
  44. package/dist/icon-set/material-icons-round.umd.prod.js +1 -1
  45. package/dist/icon-set/material-icons-sharp.umd.prod.js +1 -1
  46. package/dist/icon-set/material-icons.umd.prod.js +1 -1
  47. package/dist/icon-set/mdi-v3.umd.prod.js +1 -1
  48. package/dist/icon-set/mdi-v4.umd.prod.js +1 -1
  49. package/dist/icon-set/mdi-v5.umd.prod.js +1 -1
  50. package/dist/icon-set/mdi-v6.umd.prod.js +1 -1
  51. package/dist/icon-set/svg-bootstrap-icons.umd.prod.js +1 -1
  52. package/dist/icon-set/svg-eva-icons.umd.prod.js +1 -1
  53. package/dist/icon-set/svg-fontawesome-v5.umd.prod.js +1 -1
  54. package/dist/icon-set/svg-ionicons-v4.umd.prod.js +1 -1
  55. package/dist/icon-set/svg-ionicons-v5.umd.prod.js +1 -1
  56. package/dist/icon-set/svg-ionicons-v6.umd.prod.js +1 -1
  57. package/dist/icon-set/svg-line-awesome.umd.prod.js +1 -1
  58. package/dist/icon-set/svg-material-icons-outlined.umd.prod.js +1 -1
  59. package/dist/icon-set/svg-material-icons-round.umd.prod.js +1 -1
  60. package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +1 -1
  61. package/dist/icon-set/svg-material-icons.umd.prod.js +1 -1
  62. package/dist/icon-set/svg-mdi-v4.umd.prod.js +1 -1
  63. package/dist/icon-set/svg-mdi-v5.umd.prod.js +1 -1
  64. package/dist/icon-set/svg-mdi-v6.umd.prod.js +1 -1
  65. package/dist/icon-set/svg-themify.umd.prod.js +1 -1
  66. package/dist/icon-set/themify.umd.prod.js +1 -1
  67. package/dist/lang/ar.umd.prod.js +1 -1
  68. package/dist/lang/az-Latn.umd.prod.js +1 -1
  69. package/dist/lang/bg.umd.prod.js +1 -1
  70. package/dist/lang/bn.umd.prod.js +1 -1
  71. package/dist/lang/ca.umd.prod.js +1 -1
  72. package/dist/lang/cs.umd.prod.js +1 -1
  73. package/dist/lang/da.umd.prod.js +1 -1
  74. package/dist/lang/de.umd.prod.js +1 -1
  75. package/dist/lang/el.umd.prod.js +1 -1
  76. package/dist/lang/en-GB.umd.prod.js +1 -1
  77. package/dist/lang/en-US.umd.prod.js +1 -1
  78. package/dist/lang/eo.umd.prod.js +1 -1
  79. package/dist/lang/es.umd.prod.js +1 -1
  80. package/dist/lang/et.umd.prod.js +1 -1
  81. package/dist/lang/fa-IR.umd.prod.js +1 -1
  82. package/dist/lang/fa.umd.prod.js +1 -1
  83. package/dist/lang/fi.umd.prod.js +1 -1
  84. package/dist/lang/fr.umd.prod.js +1 -1
  85. package/dist/lang/gn.umd.prod.js +1 -1
  86. package/dist/lang/he.umd.prod.js +1 -1
  87. package/dist/lang/hr.umd.prod.js +1 -1
  88. package/dist/lang/hu.umd.prod.js +1 -1
  89. package/dist/lang/id.umd.prod.js +1 -1
  90. package/dist/lang/is.umd.prod.js +1 -1
  91. package/dist/lang/it.umd.prod.js +1 -1
  92. package/dist/lang/ja.umd.prod.js +1 -1
  93. package/dist/lang/km.umd.prod.js +1 -1
  94. package/dist/lang/ko-KR.umd.prod.js +1 -1
  95. package/dist/lang/kur-CKB.umd.prod.js +1 -1
  96. package/dist/lang/lt.umd.prod.js +1 -1
  97. package/dist/lang/lu.umd.prod.js +1 -1
  98. package/dist/lang/lv.umd.prod.js +1 -1
  99. package/dist/lang/ml.umd.prod.js +1 -1
  100. package/dist/lang/ms.umd.prod.js +1 -1
  101. package/dist/lang/nb-NO.umd.prod.js +1 -1
  102. package/dist/lang/nl.umd.prod.js +1 -1
  103. package/dist/lang/pl.umd.prod.js +1 -1
  104. package/dist/lang/pt-BR.umd.prod.js +1 -1
  105. package/dist/lang/pt.umd.prod.js +1 -1
  106. package/dist/lang/ro.umd.prod.js +1 -1
  107. package/dist/lang/ru.umd.prod.js +1 -1
  108. package/dist/lang/sk.umd.prod.js +1 -1
  109. package/dist/lang/sl.umd.prod.js +1 -1
  110. package/dist/lang/sr-CYR.umd.prod.js +1 -1
  111. package/dist/lang/sr.umd.prod.js +1 -1
  112. package/dist/lang/sv.umd.prod.js +1 -1
  113. package/dist/lang/ta.umd.prod.js +1 -1
  114. package/dist/lang/th.umd.prod.js +1 -1
  115. package/dist/lang/tr.umd.prod.js +1 -1
  116. package/dist/lang/ug.umd.prod.js +1 -1
  117. package/dist/lang/uk.umd.prod.js +1 -1
  118. package/dist/lang/vi.umd.prod.js +1 -1
  119. package/dist/lang/zh-CN.umd.prod.js +1 -1
  120. package/dist/lang/zh-TW.umd.prod.js +1 -1
  121. package/dist/quasar.cjs.prod.js +2 -2
  122. package/dist/quasar.css +277 -196
  123. package/dist/quasar.esm.prod.js +2 -2
  124. package/dist/quasar.prod.css +1 -1
  125. package/dist/quasar.rtl.css +344 -275
  126. package/dist/quasar.rtl.prod.css +1 -1
  127. package/dist/quasar.sass +243 -189
  128. package/dist/quasar.umd.js +16670 -16294
  129. package/dist/quasar.umd.prod.js +2 -2
  130. package/dist/ssr-directives/Morph.js +1 -1
  131. package/dist/transforms/loader-asset-urls.json +20 -0
  132. package/dist/types/api/slider.d.ts +46 -0
  133. package/dist/types/api/validation.d.ts +4 -0
  134. package/dist/types/api.d.ts +2 -0
  135. package/dist/types/composables.d.ts +3 -3
  136. package/dist/types/index.d.ts +599 -121
  137. package/dist/types/utils/date.d.ts +2 -1
  138. package/dist/vetur/quasar-attributes.json +254 -82
  139. package/dist/vetur/quasar-tags.json +61 -18
  140. package/dist/web-types/web-types.json +635 -197
  141. package/package.json +1 -1
  142. package/src/api.extends.json +1 -2
  143. package/src/components/breadcrumbs/QBreadcrumbs.js +7 -2
  144. package/src/components/breadcrumbs/QBreadcrumbs.sass +0 -3
  145. package/src/components/breadcrumbs/QBreadcrumbsEl.js +14 -8
  146. package/src/components/btn/QBtn.js +5 -5
  147. package/src/components/btn/use-btn.js +21 -21
  148. package/src/components/btn/use-btn.json +22 -13
  149. package/src/components/btn-toggle/QBtnToggle.json +3 -0
  150. package/src/components/checkbox/use-checkbox.js +1 -1
  151. package/src/components/color/QColor.js +32 -26
  152. package/src/components/color/QColor.sass +10 -23
  153. package/src/components/date/QDate.sass +2 -0
  154. package/src/components/dialog/QDialog.js +7 -5
  155. package/src/components/drawer/QDrawer.js +18 -15
  156. package/src/components/editor/QEditor.js +1 -1
  157. package/src/components/editor/QEditor.sass +10 -1
  158. package/src/components/expansion-item/QExpansionItem.js +4 -1
  159. package/src/components/fab/QFab.js +18 -12
  160. package/src/components/fab/QFab.json +33 -0
  161. package/src/components/fab/QFab.sass +1 -1
  162. package/src/components/fab/QFabAction.js +14 -7
  163. package/src/components/fab/QFabAction.json +10 -0
  164. package/src/components/file/QFile.js +12 -5
  165. package/src/components/file/QFile.sass +4 -2
  166. package/src/components/footer/QFooter.js +1 -1
  167. package/src/components/header/QHeader.js +1 -1
  168. package/src/components/icon/QIcon.js +1 -1
  169. package/src/components/infinite-scroll/QInfiniteScroll.js +4 -5
  170. package/src/components/item/QItem.js +2 -3
  171. package/src/components/linear-progress/QLinearProgress.json +1 -1
  172. package/src/components/menu/QMenu.js +6 -2
  173. package/src/components/option-group/QOptionGroup.js +3 -0
  174. package/src/components/option-group/QOptionGroup.json +48 -2
  175. package/src/components/parallax/QParallax.js +4 -2
  176. package/src/components/popup-edit/QPopupEdit.js +2 -5
  177. package/src/components/radio/QRadio.js +2 -7
  178. package/src/components/range/QRange.js +132 -273
  179. package/src/components/range/QRange.json +11 -121
  180. package/src/components/rating/QRating.json +3 -3
  181. package/src/components/resize-observer/QResizeObserver.js +11 -10
  182. package/src/components/scroll-area/QScrollArea.js +8 -2
  183. package/src/components/scroll-observer/QScrollObserver.js +2 -0
  184. package/src/components/select/QSelect.js +4 -1
  185. package/src/components/slider/QSlider.js +61 -137
  186. package/src/components/slider/QSlider.json +1 -121
  187. package/src/components/slider/QSlider.sass +203 -138
  188. package/src/components/slider/use-slider.js +454 -107
  189. package/src/components/slider/use-slider.json +546 -0
  190. package/src/components/stepper/QStepper.js +3 -3
  191. package/src/components/stepper/QStepper.sass +24 -26
  192. package/src/components/table/QTable.js +26 -46
  193. package/src/components/tabs/QRouteTab.js +1 -2
  194. package/src/components/tabs/QRouteTab.json +0 -7
  195. package/src/components/tabs/QTabs.js +91 -24
  196. package/src/components/tabs/use-tab.js +26 -13
  197. package/src/components/tooltip/QTooltip.js +1 -2
  198. package/src/components/tree/QTree.js +14 -12
  199. package/src/components/uploader/QUploader.json +14 -2
  200. package/src/components/uploader/uploader-core.js +16 -9
  201. package/src/components/video/QVideo.js +4 -1
  202. package/src/components/video/QVideo.json +12 -1
  203. package/src/components/virtual-scroll/QVirtualScroll.sass +1 -0
  204. package/src/components/virtual-scroll/use-virtual-scroll.js +30 -17
  205. package/src/composables/private/use-field.js +18 -20
  206. package/src/composables/private/use-file.js +20 -5
  207. package/src/composables/private/use-form.js +2 -3
  208. package/src/composables/private/use-fullscreen.js +15 -4
  209. package/src/composables/private/use-model-toggle.js +1 -1
  210. package/src/composables/private/use-portal.js +9 -7
  211. package/src/composables/private/use-router-link.js +44 -23
  212. package/src/composables/private/use-router-link.json +26 -10
  213. package/src/composables/private/use-split-attrs.js +4 -4
  214. package/src/composables/private/use-tick.js +7 -14
  215. package/src/composables/private/use-validate.js +21 -15
  216. package/src/composables/private/use-validate.json +1 -0
  217. package/src/css/core/helpers.sass +3 -0
  218. package/src/css/core/positioning.sass +5 -0
  219. package/src/css/variables.sass +4 -6
  220. package/src/directives/ScrollFire.js +1 -0
  221. package/src/icon-set.js +2 -4
  222. package/src/plugins/AppFullscreen.js +70 -53
  223. package/src/plugins/AppVisibility.js +2 -3
  224. package/src/plugins/BottomSheet.js +3 -5
  225. package/src/plugins/Dialog.js +3 -5
  226. package/src/plugins/LoadingBar.js +17 -18
  227. package/src/plugins/Notify.js +296 -295
  228. package/src/plugins/Platform.js +14 -14
  229. package/src/utils/clone.js +53 -4
  230. package/src/utils/date.js +4 -4
  231. package/src/utils/dom.js +2 -2
  232. package/src/utils/open-url.js +2 -2
  233. package/src/utils/patterns.js +1 -0
  234. package/src/utils/private/define-reactive-plugin.js +10 -8
  235. package/src/utils/private/focus-manager.js +8 -10
  236. package/src/utils/private/global-dialog.js +6 -8
  237. package/src/utils/private/inject-obj-prop.js +13 -0
  238. package/src/utils/private/is.js +2 -2
@@ -3,41 +3,27 @@ import { h, ref, computed, onBeforeUnmount, getCurrentInstance } from 'vue'
3
3
  import TouchPan from '../../directives/TouchPan.js'
4
4
 
5
5
  import useDark, { useDarkProps } from '../../composables/private/use-dark.js'
6
+ import { useFormProps, useFormInject } from '../../composables/private/use-form.js'
6
7
 
7
8
  import { between } from '../../utils/format.js'
8
9
  import { position } from '../../utils/event.js'
9
10
  import { isNumber } from '../../utils/private/is.js'
11
+ import { hDir } from '../../utils/private/render.js'
12
+
13
+ const markerPrefixClass = 'q-slider__marker-labels'
14
+ const defaultMarkerConvertFn = v => ({ value: v })
15
+ const defaultMarkerLabelRenderFn = ({ marker }) => h('div', {
16
+ key: marker.value,
17
+ style: marker.style,
18
+ class: marker.classes
19
+ }, marker.label)
10
20
 
11
21
  // PGDOWN, LEFT, DOWN, PGUP, RIGHT, UP
12
22
  export const keyCodes = [ 34, 37, 40, 33, 39, 38 ]
13
23
 
14
- export function getRatio (evt, dragging, reverse, vertical) {
15
- const
16
- pos = position(evt),
17
- val = vertical === true
18
- ? between((pos.top - dragging.top) / dragging.height, 0, 1)
19
- : between((pos.left - dragging.left) / dragging.width, 0, 1)
20
-
21
- return reverse === true ? 1.0 - val : val
22
- }
23
-
24
- export function getModel (ratio, min, max, step, decimals) {
25
- let model = min + ratio * (max - min)
26
-
27
- if (step > 0) {
28
- const modulo = (model - min) % step
29
- model += (Math.abs(modulo) >= step / 2 ? (modulo < 0 ? -1 : 1) * step : 0) - modulo
30
- }
31
-
32
- if (decimals > 0) {
33
- model = parseFloat(model.toFixed(decimals))
34
- }
35
-
36
- return between(model, min, max)
37
- }
38
-
39
24
  export const useSliderProps = {
40
25
  ...useDarkProps,
26
+ ...useFormProps,
41
27
 
42
28
  min: {
43
29
  type: Number,
@@ -47,30 +33,58 @@ export const useSliderProps = {
47
33
  type: Number,
48
34
  default: 100
49
35
  },
36
+ innerMin: Number,
37
+ innerMax: Number,
38
+
50
39
  step: {
51
40
  type: Number,
52
41
  default: 1,
53
42
  validator: v => v >= 0
54
43
  },
55
44
 
45
+ snap: Boolean,
46
+
47
+ vertical: Boolean,
48
+ reverse: Boolean,
49
+
50
+ hideSelection: Boolean,
51
+
56
52
  color: String,
53
+ markerLabelsClass: String,
57
54
 
55
+ label: Boolean,
58
56
  labelColor: String,
59
57
  labelTextColor: String,
60
- dense: Boolean,
61
-
62
- label: Boolean,
63
58
  labelAlways: Boolean,
59
+ switchLabelSide: Boolean,
60
+
64
61
  markers: [ Boolean, Number ],
65
- snap: Boolean,
62
+ markerLabels: [ Boolean, Array, Object, Function ],
63
+ switchMarkerLabelsSide: Boolean,
66
64
 
67
- vertical: Boolean,
68
- reverse: Boolean,
65
+ trackImg: String,
66
+ trackColor: String,
67
+ innerTrackImg: String,
68
+ innerTrackColor: String,
69
+ selectionColor: String,
70
+ selectionImg: String,
71
+
72
+ thumbSize: {
73
+ type: String,
74
+ default: '20px'
75
+ },
76
+ trackSize: {
77
+ type: String,
78
+ default: '4px'
79
+ },
69
80
 
70
81
  disable: Boolean,
71
82
  readonly: Boolean,
83
+ dense: Boolean,
84
+
72
85
  tabindex: [ String, Number ],
73
86
 
87
+ thumbColor: String,
74
88
  thumbPath: {
75
89
  type: String,
76
90
  default: 'M 4, 10 a 6,6 0 1,0 12,0 a 6,6 0 1,0 -12,0'
@@ -79,16 +93,19 @@ export const useSliderProps = {
79
93
 
80
94
  export const useSliderEmits = [ 'pan', 'update:modelValue', 'change' ]
81
95
 
82
- export default function ({ updateValue, updatePosition, getDragging }) {
83
- const { props, emit, proxy: { $q } } = getCurrentInstance()
96
+ export default function ({ updateValue, updatePosition, getDragging, formAttrs }) {
97
+ const { props, emit, slots, proxy: { $q } } = getCurrentInstance()
84
98
  const isDark = useDark(props, $q)
85
99
 
100
+ const injectFormInput = useFormInject(formAttrs)
101
+
86
102
  const active = ref(false)
87
103
  const preventFocus = ref(false)
88
104
  const focus = ref(false)
89
105
  const dragging = ref(false)
90
106
 
91
107
  const axis = computed(() => (props.vertical === true ? '--v' : '--h'))
108
+ const labelSide = computed(() => '-' + (props.switchLabelSide === true ? 'switched' : 'standard'))
92
109
 
93
110
  const isReversed = computed(() => (
94
111
  props.vertical === true
@@ -96,12 +113,64 @@ export default function ({ updateValue, updatePosition, getDragging }) {
96
113
  : props.reverse !== ($q.lang.rtl === true)
97
114
  ))
98
115
 
99
- const editable = computed(() => props.disable !== true && props.readonly !== true && props.min < props.max)
116
+ const innerMin = computed(() => (
117
+ isNaN(props.innerMin) === true || props.innerMin < props.min
118
+ ? props.min
119
+ : props.innerMin
120
+ ))
121
+ const innerMax = computed(() => (
122
+ isNaN(props.innerMax) === true || props.innerMax > props.max
123
+ ? props.max
124
+ : props.innerMax
125
+ ))
126
+
127
+ const editable = computed(() => (
128
+ props.disable !== true && props.readonly !== true
129
+ && innerMin.value < innerMax.value
130
+ ))
131
+
132
+ const decimals = computed(() => (String(props.step).trim('0').split('.')[ 1 ] || '').length)
133
+ const step = computed(() => (props.step === 0 ? 1 : props.step))
134
+ const tabindex = computed(() => (editable.value === true ? props.tabindex || 0 : -1))
135
+
136
+ const trackLen = computed(() => props.max - props.min)
137
+ const innerBarLen = computed(() => innerMax.value - innerMin.value)
138
+
139
+ const innerMinRatio = computed(() => convertModelToRatio(innerMin.value))
140
+ const innerMaxRatio = computed(() => convertModelToRatio(innerMax.value))
141
+
142
+ const positionProp = computed(() => (
143
+ props.vertical === true
144
+ ? (isReversed.value === true ? 'bottom' : 'top')
145
+ : (isReversed.value === true ? 'right' : 'left')
146
+ ))
147
+
148
+ const sizeProp = computed(() => (props.vertical === true ? 'height' : 'width'))
149
+ const thicknessProp = computed(() => (props.vertical === true ? 'width' : 'height'))
150
+ const orientation = computed(() => (props.vertical === true ? 'vertical' : 'horizontal'))
151
+
152
+ const attributes = computed(() => {
153
+ const acc = {
154
+ role: 'slider',
155
+ 'aria-valuemin': innerMin.value,
156
+ 'aria-valuemax': innerMax.value,
157
+ 'aria-orientation': orientation.value,
158
+ 'data-step': props.step
159
+ }
160
+
161
+ if (props.disable === true) {
162
+ acc[ 'aria-disabled' ] = 'true'
163
+ }
164
+ else if (props.readonly === true) {
165
+ acc[ 'aria-readonly' ] = 'true'
166
+ }
167
+
168
+ return acc
169
+ })
100
170
 
101
171
  const classes = computed(() =>
102
- `q-slider q-slider${ axis.value } q-slider--${ active.value === true ? '' : 'in' }active`
103
- + (isReversed.value === true ? ' q-slider--reversed' : '')
104
- + (props.color !== void 0 ? ` text-${ props.color }` : '')
172
+ `q-slider q-slider${ axis.value } q-slider--${ active.value === true ? '' : 'in' }active inline no-wrap `
173
+ + (props.vertical === true ? 'row' : 'column')
105
174
  + (props.disable === true ? ' disabled' : ' q-slider--enabled' + (editable.value === true ? ' q-slider--editable' : ''))
106
175
  + (focus.value === 'both' ? ' q-slider--focus' : '')
107
176
  + (props.label || props.labelAlways === true ? ' q-slider--label' : '')
@@ -110,19 +179,148 @@ export default function ({ updateValue, updatePosition, getDragging }) {
110
179
  + (props.dense === true ? ' q-slider--dense q-slider--dense' + axis.value : '')
111
180
  )
112
181
 
113
- const decimals = computed(() => (String(props.step).trim('0').split('.')[ 1 ] || '').length)
114
- const step = computed(() => (props.step === 0 ? 1 : props.step))
115
- const minMaxDiff = computed(() => props.max - props.min)
182
+ function getPositionClass (name) {
183
+ const cls = 'q-slider__' + name
184
+ return `${ cls } ${ cls }${ axis.value } ${ cls }${ axis.value }${ labelSide.value }`
185
+ }
186
+ function getAxisClass (name) {
187
+ const cls = 'q-slider__' + name
188
+ return `${ cls } ${ cls }${ axis.value }`
189
+ }
190
+
191
+ const selectionBarClass = computed(() => {
192
+ const color = props.selectionColor || props.color
193
+ return 'q-slider__selection absolute'
194
+ + (color !== void 0 ? ` text-${ color }` : '')
195
+ })
196
+ const markerClass = computed(() => getAxisClass('markers') + ' absolute overflow-hidden')
197
+ const trackContainerClass = computed(() => getAxisClass('track-container'))
198
+ const pinClass = computed(() => getPositionClass('pin'))
199
+ const labelClass = computed(() => getPositionClass('label'))
200
+ const textContainerClass = computed(() => getPositionClass('text-container'))
201
+ const markerLabelsContainerClass = computed(() =>
202
+ getPositionClass('marker-labels-container')
203
+ + (props.markerLabelsClass !== void 0 ? ` ${ props.markerLabelsClass }` : '')
204
+ )
205
+
206
+ const trackClass = computed(() =>
207
+ 'q-slider__track relative-position no-outline'
208
+ + (props.trackColor !== void 0 ? ` bg-${ props.trackColor }` : '')
209
+ )
210
+ const trackStyle = computed(() => {
211
+ const acc = { [ thicknessProp.value ]: props.trackSize }
212
+ if (props.trackImg !== void 0) {
213
+ acc.backgroundImage = `url(${ props.trackImg }) !important`
214
+ }
215
+ return acc
216
+ })
217
+
218
+ const innerBarClass = computed(() =>
219
+ 'q-slider__inner absolute'
220
+ + (props.innerTrackColor !== void 0 ? ` bg-${ props.innerTrackColor }` : '')
221
+ )
222
+ const innerBarStyle = computed(() => {
223
+ const acc = {
224
+ [ positionProp.value ]: `${ 100 * innerMinRatio.value }%`,
225
+ [ sizeProp.value ]: `${ 100 * (innerMaxRatio.value - innerMinRatio.value) }%`
226
+ }
227
+ if (props.innerTrackImg !== void 0) {
228
+ acc.backgroundImage = `url(${ props.innerTrackImg }) !important`
229
+ }
230
+ return acc
231
+ })
232
+
233
+ function convertRatioToModel (ratio) {
234
+ const { min, max, step } = props
235
+ let model = min + ratio * (max - min)
236
+
237
+ if (step > 0) {
238
+ const modulo = (model - min) % step
239
+ model += (Math.abs(modulo) >= step / 2 ? (modulo < 0 ? -1 : 1) * step : 0) - modulo
240
+ }
241
+
242
+ if (decimals.value > 0) {
243
+ model = parseFloat(model.toFixed(decimals.value))
244
+ }
245
+
246
+ return between(model, innerMin.value, innerMax.value)
247
+ }
248
+
249
+ function convertModelToRatio (model) {
250
+ return trackLen.value === 0
251
+ ? 0
252
+ : (model - props.min) / trackLen.value
253
+ }
254
+
255
+ function getDraggingRatio (evt, dragging) {
256
+ const
257
+ pos = position(evt),
258
+ val = props.vertical === true
259
+ ? between((pos.top - dragging.top) / dragging.height, 0, 1)
260
+ : between((pos.left - dragging.left) / dragging.width, 0, 1)
261
+
262
+ return between(
263
+ isReversed.value === true ? 1.0 - val : val,
264
+ innerMinRatio.value,
265
+ innerMaxRatio.value
266
+ )
267
+ }
116
268
 
117
269
  const markerStep = computed(() => (
118
270
  isNumber(props.markers) === true ? props.markers : step.value)
119
271
  )
120
272
 
273
+ const markerTicks = computed(() => {
274
+ const acc = []
275
+ const step = markerStep.value
276
+ const max = props.max
277
+
278
+ let value = props.min
279
+ do {
280
+ acc.push(value)
281
+ value += step
282
+ } while (value < max)
283
+
284
+ acc.push(max)
285
+ return acc
286
+ })
287
+
288
+ const markerLabelClass = computed(() => {
289
+ const prefix = ` ${ markerPrefixClass }${ axis.value }-`
290
+ return markerPrefixClass
291
+ + `${ prefix }${ props.switchMarkerLabelsSide === true ? 'switched' : 'standard' }`
292
+ + `${ prefix }${ isReversed.value === true ? 'rtl' : 'ltr' }`
293
+ })
294
+
295
+ const markerLabelsList = computed(() => {
296
+ if (props.markerLabels === false) { return null }
297
+
298
+ return getMarkerList(props.markerLabels).map((entry, index) => ({
299
+ index,
300
+ value: entry.value,
301
+ label: entry.label || entry.value,
302
+ classes: markerLabelClass.value
303
+ + (entry.classes !== void 0 ? ' ' + entry.classes : ''),
304
+ style: {
305
+ ...getMarkerLabelStyle(entry.value),
306
+ ...(entry.style || {})
307
+ }
308
+ }))
309
+ })
310
+
311
+ const markerScope = computed(() => ({
312
+ markerList: markerLabelsList.value,
313
+ markerMap: markerLabelsMap.value,
314
+ classes: markerLabelClass.value, // TODO ts definition
315
+ getStyle: getMarkerLabelStyle
316
+ }))
317
+
121
318
  const markerStyle = computed(() => {
122
- if (minMaxDiff.value !== 0) {
123
- const size = 100 * markerStep.value / minMaxDiff.value
319
+ if (innerBarLen.value !== 0) {
320
+ const size = 100 * markerStep.value / innerBarLen.value
124
321
 
125
322
  return {
323
+ ...innerBarStyle.value,
126
324
  backgroundSize: props.vertical === true
127
325
  ? `2px ${ size }%`
128
326
  : `${ size }% 2px`
@@ -132,37 +330,61 @@ export default function ({ updateValue, updatePosition, getDragging }) {
132
330
  return null
133
331
  })
134
332
 
135
- const tabindex = computed(() => (editable.value === true ? props.tabindex || 0 : -1))
333
+ function getMarkerList (def) {
334
+ if (def === false) { return null }
136
335
 
137
- const positionProp = computed(() => (
138
- props.vertical === true
139
- ? (isReversed.value === true ? 'bottom' : 'top')
140
- : isReversed.value === true ? 'right' : 'left'
141
- ))
336
+ if (def === true) {
337
+ return markerTicks.value.map(defaultMarkerConvertFn)
338
+ }
142
339
 
143
- const sizeProp = computed(() => (props.vertical === true ? 'height' : 'width'))
340
+ if (typeof def === 'function') {
341
+ return markerTicks.value.map(value => {
342
+ const item = def(value)
343
+ return Object(item) === item ? { ...item, value } : { value, label: item }
344
+ })
345
+ }
144
346
 
145
- const orientation = computed(() => (props.vertical === true ? 'vertical' : 'horizontal'))
347
+ const filterFn = ({ value }) => value >= props.min && value <= props.max
146
348
 
147
- const attributes = computed(() => {
148
- const acc = {
149
- role: 'slider',
150
- 'aria-valuemin': props.min,
151
- 'aria-valuemax': props.max,
152
- 'aria-orientation': orientation.value,
153
- 'data-step': props.step
349
+ if (Array.isArray(def) === true) {
350
+ return def
351
+ .map(item => (Object(item) === item ? item : { value: item }))
352
+ .filter(filterFn)
154
353
  }
155
354
 
156
- if (props.disable === true) {
157
- acc[ 'aria-disabled' ] = 'true'
158
- }
159
- else if (props.readonly === true) {
160
- acc[ 'aria-readonly' ] = 'true'
161
- }
355
+ return Object.keys(def).map(key => {
356
+ const item = def[ key ]
357
+ const value = Number(key)
358
+ return Object(item) === item ? { ...item, value } : { value, label: item }
359
+ }).filter(filterFn)
360
+ }
361
+
362
+ function getMarkerLabelStyle (val) {
363
+ return { [ positionProp.value ]: `${ 100 * (val - props.min) / trackLen.value }%` }
364
+ }
365
+
366
+ const markerLabelsMap = computed(() => {
367
+ if (props.markerLabels === false) { return null }
162
368
 
369
+ const acc = {}
370
+ markerLabelsList.value.forEach(entry => {
371
+ acc[ entry.value ] = entry
372
+ })
163
373
  return acc
164
374
  })
165
375
 
376
+ function getMarkerLabelsContent () {
377
+ if (slots[ 'marker-label-group' ] !== void 0) {
378
+ return slots[ 'marker-label-group' ](markerScope.value)
379
+ }
380
+
381
+ const fn = slots[ 'marker-label' ] || defaultMarkerLabelRenderFn
382
+ return markerLabelsList.value.map(marker => fn({
383
+ marker,
384
+ ...markerScope.value
385
+ }))
386
+ }
387
+
166
388
  const panDirective = computed(() => {
167
389
  // if editable.value === true
168
390
  return [ [
@@ -179,36 +401,6 @@ export default function ({ updateValue, updatePosition, getDragging }) {
179
401
  ] ]
180
402
  })
181
403
 
182
- function getThumbSvg () {
183
- return h('svg', {
184
- class: 'q-slider__thumb absolute',
185
- viewBox: '0 0 20 20',
186
- width: '20',
187
- height: '20',
188
- 'aria-hidden': 'true'
189
- }, [
190
- h('path', { d: props.thumbPath })
191
- ])
192
- }
193
-
194
- function getPinStyle (percent, ratio) {
195
- if (props.vertical === true) {
196
- return {}
197
- }
198
-
199
- const offset = `${ Math.ceil(20 * Math.abs(0.5 - ratio)) }px`
200
- return {
201
- pin: {
202
- transformOrigin: `${ $q.lang.rtl === true ? offset : `calc(100% - ${ offset })` } 50%`
203
- },
204
-
205
- pinTextContainer: {
206
- [ $q.lang.rtl === true ? 'left' : 'right' ]: `${ percent * 100 }%`,
207
- transform: `translateX(${ Math.ceil(($q.lang.rtl === true ? -1 : 1) * 20 * percent) }px)`
208
- }
209
- }
210
- }
211
-
212
404
  function onPan (event) {
213
405
  if (event.isFinal === true) {
214
406
  if (dragging.value !== void 0) {
@@ -219,6 +411,7 @@ export default function ({ updateValue, updatePosition, getDragging }) {
219
411
  emit('pan', 'end')
220
412
  }
221
413
  active.value = false
414
+ focus.value = false
222
415
  }
223
416
  else if (event.isFirst === true) {
224
417
  dragging.value = getDragging(event.evt)
@@ -249,10 +442,7 @@ export default function ({ updateValue, updatePosition, getDragging }) {
249
442
 
250
443
  function onDeactivate () {
251
444
  preventFocus.value = false
252
-
253
- if (dragging.value === false) {
254
- active.value = false
255
- }
445
+ active.value = false
256
446
 
257
447
  updateValue(true)
258
448
  onBlur()
@@ -271,6 +461,158 @@ export default function ({ updateValue, updatePosition, getDragging }) {
271
461
  }
272
462
  }
273
463
 
464
+ function getTextContainerStyle (ratio) {
465
+ if (props.vertical === true) { return null }
466
+
467
+ const p = $q.lang.rtl !== props.reverse ? 1 - ratio : ratio
468
+ return {
469
+ transform: `translateX(calc(${ 2 * p - 1 } * ${ props.thumbSize } / 2 + ${ 50 - 100 * p }%))`
470
+ }
471
+ }
472
+
473
+ function getThumbRenderFn (thumb) {
474
+ const focusClass = computed(() => (
475
+ preventFocus.value === false && (focus.value === thumb.focusValue || focus.value === 'both')
476
+ ? ' q-slider--focus'
477
+ : ''
478
+ ))
479
+
480
+ const classes = computed(() =>
481
+ `q-slider__thumb q-slider__thumb${ axis.value } q-slider__thumb${ axis.value }-${ isReversed.value === true ? 'rtl' : 'ltr' } absolute non-selectable`
482
+ + focusClass.value
483
+ + (thumb.thumbColor.value !== void 0 ? ` text-${ thumb.thumbColor.value }` : '')
484
+ )
485
+
486
+ const style = computed(() => ({
487
+ width: props.thumbSize,
488
+ height: props.thumbSize,
489
+ [ positionProp.value ]: `${ 100 * thumb.ratio.value }%`,
490
+ zIndex: focus.value === thumb.focusValue ? 2 : void 0
491
+ }))
492
+
493
+ const pinColor = computed(() => (
494
+ thumb.labelColor.value !== void 0
495
+ ? ` text-${ thumb.labelColor.value }`
496
+ : ''
497
+ ))
498
+
499
+ const textContainerStyle = computed(() => getTextContainerStyle(thumb.ratio.value))
500
+
501
+ const textClass = computed(() => (
502
+ 'q-slider__text'
503
+ + (thumb.labelTextColor.value !== void 0 ? ` text-${ thumb.labelTextColor.value }` : '')
504
+ ))
505
+
506
+ return () => {
507
+ const thumbContent = [
508
+ h('svg', {
509
+ class: 'q-slider__thumb-shape absolute-full',
510
+ viewBox: '0 0 20 20',
511
+ 'aria-hidden': 'true'
512
+ }, [
513
+ h('path', { d: props.thumbPath })
514
+ ]),
515
+
516
+ h('div', { class: 'q-slider__focus-ring fit' })
517
+ ]
518
+
519
+ if (props.label === true || props.labelAlways === true) {
520
+ thumbContent.push(
521
+ h('div', {
522
+ class: pinClass.value + ' absolute fit no-pointer-events' + pinColor.value
523
+ }, [
524
+ h('div', {
525
+ class: labelClass.value,
526
+ style: { minWidth: props.thumbSize }
527
+ }, [
528
+ h('div', {
529
+ class: textContainerClass.value,
530
+ style: textContainerStyle.value
531
+ }, [
532
+ h('span', { class: textClass.value }, thumb.label.value)
533
+ ])
534
+ ])
535
+ ])
536
+ )
537
+
538
+ if (props.name !== void 0 && props.disable !== true) {
539
+ injectFormInput(thumbContent, 'push')
540
+ }
541
+ }
542
+
543
+ return h('div', {
544
+ class: classes.value,
545
+ style: style.value,
546
+ ...thumb.getNodeData()
547
+ }, thumbContent)
548
+ }
549
+ }
550
+
551
+ function getContent (selectionBarStyle, trackContainerTabindex, trackContainerEvents, injectThumb) {
552
+ const trackContent = []
553
+
554
+ props.innerTrackColor !== 'transparent' && trackContent.push(
555
+ h('div', {
556
+ key: 'inner',
557
+ class: innerBarClass.value,
558
+ style: innerBarStyle.value
559
+ })
560
+ )
561
+
562
+ props.selectionColor !== 'transparent' && trackContent.push(
563
+ h('div', {
564
+ key: 'selection',
565
+ class: selectionBarClass.value,
566
+ style: selectionBarStyle.value
567
+ })
568
+ )
569
+
570
+ props.markers !== false && trackContent.push(
571
+ h('div', {
572
+ key: 'marker',
573
+ class: markerClass.value,
574
+ style: markerStyle.value
575
+ })
576
+ )
577
+
578
+ injectThumb(trackContent)
579
+
580
+ const content = [
581
+ hDir(
582
+ 'div',
583
+ {
584
+ key: 'trackC',
585
+ class: trackContainerClass.value,
586
+ tabindex: trackContainerTabindex.value,
587
+ ...trackContainerEvents.value
588
+ },
589
+ [
590
+ h('div', {
591
+ class: trackClass.value,
592
+ style: trackStyle.value
593
+ }, trackContent)
594
+ ],
595
+ 'slide',
596
+ editable.value, () => panDirective.value
597
+ )
598
+ ]
599
+
600
+ if (props.markerLabels !== false) {
601
+ const action = props.switchMarkerLabelsSide === true
602
+ ? 'unshift'
603
+ : 'push'
604
+
605
+ content[ action ](
606
+ h('div', {
607
+ key: 'markerL',
608
+ class: markerLabelsContainerClass.value
609
+ }, getMarkerLabelsContent())
610
+ )
611
+ }
612
+
613
+ return content
614
+ }
615
+
274
616
  onBeforeUnmount(() => {
275
617
  document.removeEventListener('mouseup', onDeactivate, true)
276
618
  })
@@ -282,19 +624,21 @@ export default function ({ updateValue, updatePosition, getDragging }) {
282
624
  preventFocus,
283
625
  dragging,
284
626
 
285
- axis,
286
- isReversed,
287
627
  editable,
288
628
  classes,
289
- decimals,
290
- step,
291
- minMaxDiff,
292
- markerStyle,
293
629
  tabindex,
630
+ attributes,
631
+
632
+ step,
633
+ decimals,
634
+ trackLen,
635
+ innerMin,
636
+ innerMinRatio,
637
+ innerMax,
638
+ innerMaxRatio,
294
639
  positionProp,
295
640
  sizeProp,
296
- attributes,
297
- panDirective
641
+ isReversed
298
642
  },
299
643
 
300
644
  methods: {
@@ -302,8 +646,11 @@ export default function ({ updateValue, updatePosition, getDragging }) {
302
646
  onMobileClick,
303
647
  onBlur,
304
648
  onKeyup,
305
- getThumbSvg,
306
- getPinStyle
649
+ getContent,
650
+ getThumbRenderFn,
651
+ convertRatioToModel,
652
+ convertModelToRatio,
653
+ getDraggingRatio
307
654
  }
308
655
  }
309
656
  }