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.
- package/dist/api/BottomSheet.json +1 -1
- package/dist/api/Loading.json +2 -6
- package/dist/api/Notify.json +5 -5
- package/dist/api/QAvatar.json +1 -1
- package/dist/api/QBreadcrumbsEl.json +32 -11
- package/dist/api/QBtn.json +32 -16
- package/dist/api/QBtnDropdown.json +33 -17
- package/dist/api/QBtnToggle.json +4 -1
- package/dist/api/QCarousel.json +4 -4
- package/dist/api/QChatMessage.json +4 -12
- package/dist/api/QChip.json +4 -4
- package/dist/api/QExpansionItem.json +34 -13
- package/dist/api/QFab.json +32 -2
- package/dist/api/QFabAction.json +9 -1
- package/dist/api/QField.json +1 -0
- package/dist/api/QFile.json +1 -0
- package/dist/api/QInput.json +1 -0
- package/dist/api/QItem.json +31 -10
- package/dist/api/QLinearProgress.json +1 -1
- package/dist/api/QOptionGroup.json +74 -4
- package/dist/api/QPagination.json +4 -4
- package/dist/api/QPullToRefresh.json +1 -1
- package/dist/api/QRange.json +592 -107
- package/dist/api/QRating.json +3 -3
- package/dist/api/QRouteTab.json +32 -12
- package/dist/api/QSelect.json +4 -7
- package/dist/api/QSlider.json +504 -39
- package/dist/api/QStep.json +4 -4
- package/dist/api/QStepper.json +4 -4
- package/dist/api/QTab.json +1 -1
- package/dist/api/QTable.json +4 -4
- package/dist/api/QTimelineEntry.json +1 -1
- package/dist/api/QToggle.json +1 -1
- package/dist/api/QTree.json +1 -1
- package/dist/api/QUploader.json +16 -2
- package/dist/api/QVideo.json +11 -1
- package/dist/icon-set/bootstrap-icons.umd.prod.js +1 -1
- package/dist/icon-set/eva-icons.umd.prod.js +1 -1
- package/dist/icon-set/fontawesome-v5-pro.umd.prod.js +1 -1
- package/dist/icon-set/fontawesome-v5.umd.prod.js +1 -1
- package/dist/icon-set/ionicons-v4.umd.prod.js +1 -1
- package/dist/icon-set/line-awesome.umd.prod.js +1 -1
- package/dist/icon-set/material-icons-outlined.umd.prod.js +1 -1
- package/dist/icon-set/material-icons-round.umd.prod.js +1 -1
- package/dist/icon-set/material-icons-sharp.umd.prod.js +1 -1
- package/dist/icon-set/material-icons.umd.prod.js +1 -1
- package/dist/icon-set/mdi-v3.umd.prod.js +1 -1
- package/dist/icon-set/mdi-v4.umd.prod.js +1 -1
- package/dist/icon-set/mdi-v5.umd.prod.js +1 -1
- package/dist/icon-set/mdi-v6.umd.prod.js +1 -1
- package/dist/icon-set/svg-bootstrap-icons.umd.prod.js +1 -1
- package/dist/icon-set/svg-eva-icons.umd.prod.js +1 -1
- package/dist/icon-set/svg-fontawesome-v5.umd.prod.js +1 -1
- package/dist/icon-set/svg-ionicons-v4.umd.prod.js +1 -1
- package/dist/icon-set/svg-ionicons-v5.umd.prod.js +1 -1
- package/dist/icon-set/svg-ionicons-v6.umd.prod.js +1 -1
- package/dist/icon-set/svg-line-awesome.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-icons-outlined.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-icons-round.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-icons.umd.prod.js +1 -1
- package/dist/icon-set/svg-mdi-v4.umd.prod.js +1 -1
- package/dist/icon-set/svg-mdi-v5.umd.prod.js +1 -1
- package/dist/icon-set/svg-mdi-v6.umd.prod.js +1 -1
- package/dist/icon-set/svg-themify.umd.prod.js +1 -1
- package/dist/icon-set/themify.umd.prod.js +1 -1
- package/dist/lang/ar.umd.prod.js +1 -1
- package/dist/lang/az-Latn.umd.prod.js +1 -1
- package/dist/lang/bg.umd.prod.js +1 -1
- package/dist/lang/bn.umd.prod.js +1 -1
- package/dist/lang/ca.umd.prod.js +1 -1
- package/dist/lang/cs.umd.prod.js +1 -1
- package/dist/lang/da.umd.prod.js +1 -1
- package/dist/lang/de.umd.prod.js +1 -1
- package/dist/lang/el.umd.prod.js +1 -1
- package/dist/lang/en-GB.umd.prod.js +1 -1
- package/dist/lang/en-US.umd.prod.js +1 -1
- package/dist/lang/eo.umd.prod.js +1 -1
- package/dist/lang/es.umd.prod.js +1 -1
- package/dist/lang/et.umd.prod.js +1 -1
- package/dist/lang/fa-IR.umd.prod.js +1 -1
- package/dist/lang/fa.umd.prod.js +1 -1
- package/dist/lang/fi.umd.prod.js +1 -1
- package/dist/lang/fr.umd.prod.js +1 -1
- package/dist/lang/gn.umd.prod.js +1 -1
- package/dist/lang/he.umd.prod.js +1 -1
- package/dist/lang/hr.umd.prod.js +1 -1
- package/dist/lang/hu.umd.prod.js +1 -1
- package/dist/lang/id.umd.prod.js +1 -1
- package/dist/lang/is.umd.prod.js +1 -1
- package/dist/lang/it.umd.prod.js +1 -1
- package/dist/lang/ja.umd.prod.js +1 -1
- package/dist/lang/km.umd.prod.js +1 -1
- package/dist/lang/ko-KR.umd.prod.js +1 -1
- package/dist/lang/kur-CKB.umd.prod.js +1 -1
- package/dist/lang/lt.umd.prod.js +1 -1
- package/dist/lang/lu.umd.prod.js +1 -1
- package/dist/lang/lv.umd.prod.js +1 -1
- package/dist/lang/ml.umd.prod.js +1 -1
- package/dist/lang/ms.umd.prod.js +1 -1
- package/dist/lang/nb-NO.umd.prod.js +1 -1
- package/dist/lang/nl.umd.prod.js +1 -1
- package/dist/lang/pl.umd.prod.js +1 -1
- package/dist/lang/pt-BR.umd.prod.js +1 -1
- package/dist/lang/pt.umd.prod.js +1 -1
- package/dist/lang/ro.umd.prod.js +1 -1
- package/dist/lang/ru.umd.prod.js +1 -1
- package/dist/lang/sk.umd.prod.js +1 -1
- package/dist/lang/sl.umd.prod.js +1 -1
- package/dist/lang/sr-CYR.umd.prod.js +1 -1
- package/dist/lang/sr.umd.prod.js +1 -1
- package/dist/lang/sv.umd.prod.js +1 -1
- package/dist/lang/ta.umd.prod.js +1 -1
- package/dist/lang/th.umd.prod.js +1 -1
- package/dist/lang/tr.umd.prod.js +1 -1
- package/dist/lang/ug.umd.prod.js +1 -1
- package/dist/lang/uk.umd.prod.js +1 -1
- package/dist/lang/vi.umd.prod.js +1 -1
- package/dist/lang/zh-CN.umd.prod.js +1 -1
- package/dist/lang/zh-TW.umd.prod.js +1 -1
- package/dist/quasar.cjs.prod.js +2 -2
- package/dist/quasar.css +277 -196
- package/dist/quasar.esm.prod.js +2 -2
- package/dist/quasar.prod.css +1 -1
- package/dist/quasar.rtl.css +344 -275
- package/dist/quasar.rtl.prod.css +1 -1
- package/dist/quasar.sass +243 -189
- package/dist/quasar.umd.js +16670 -16294
- package/dist/quasar.umd.prod.js +2 -2
- package/dist/ssr-directives/Morph.js +1 -1
- package/dist/transforms/loader-asset-urls.json +20 -0
- package/dist/types/api/slider.d.ts +46 -0
- package/dist/types/api/validation.d.ts +4 -0
- package/dist/types/api.d.ts +2 -0
- package/dist/types/composables.d.ts +3 -3
- package/dist/types/index.d.ts +599 -121
- package/dist/types/utils/date.d.ts +2 -1
- package/dist/vetur/quasar-attributes.json +254 -82
- package/dist/vetur/quasar-tags.json +61 -18
- package/dist/web-types/web-types.json +635 -197
- package/package.json +1 -1
- package/src/api.extends.json +1 -2
- package/src/components/breadcrumbs/QBreadcrumbs.js +7 -2
- package/src/components/breadcrumbs/QBreadcrumbs.sass +0 -3
- package/src/components/breadcrumbs/QBreadcrumbsEl.js +14 -8
- package/src/components/btn/QBtn.js +5 -5
- package/src/components/btn/use-btn.js +21 -21
- package/src/components/btn/use-btn.json +22 -13
- package/src/components/btn-toggle/QBtnToggle.json +3 -0
- package/src/components/checkbox/use-checkbox.js +1 -1
- package/src/components/color/QColor.js +32 -26
- package/src/components/color/QColor.sass +10 -23
- package/src/components/date/QDate.sass +2 -0
- package/src/components/dialog/QDialog.js +7 -5
- package/src/components/drawer/QDrawer.js +18 -15
- package/src/components/editor/QEditor.js +1 -1
- package/src/components/editor/QEditor.sass +10 -1
- package/src/components/expansion-item/QExpansionItem.js +4 -1
- package/src/components/fab/QFab.js +18 -12
- package/src/components/fab/QFab.json +33 -0
- package/src/components/fab/QFab.sass +1 -1
- package/src/components/fab/QFabAction.js +14 -7
- package/src/components/fab/QFabAction.json +10 -0
- package/src/components/file/QFile.js +12 -5
- package/src/components/file/QFile.sass +4 -2
- package/src/components/footer/QFooter.js +1 -1
- package/src/components/header/QHeader.js +1 -1
- package/src/components/icon/QIcon.js +1 -1
- package/src/components/infinite-scroll/QInfiniteScroll.js +4 -5
- package/src/components/item/QItem.js +2 -3
- package/src/components/linear-progress/QLinearProgress.json +1 -1
- package/src/components/menu/QMenu.js +6 -2
- package/src/components/option-group/QOptionGroup.js +3 -0
- package/src/components/option-group/QOptionGroup.json +48 -2
- package/src/components/parallax/QParallax.js +4 -2
- package/src/components/popup-edit/QPopupEdit.js +2 -5
- package/src/components/radio/QRadio.js +2 -7
- package/src/components/range/QRange.js +132 -273
- package/src/components/range/QRange.json +11 -121
- package/src/components/rating/QRating.json +3 -3
- package/src/components/resize-observer/QResizeObserver.js +11 -10
- package/src/components/scroll-area/QScrollArea.js +8 -2
- package/src/components/scroll-observer/QScrollObserver.js +2 -0
- package/src/components/select/QSelect.js +4 -1
- package/src/components/slider/QSlider.js +61 -137
- package/src/components/slider/QSlider.json +1 -121
- package/src/components/slider/QSlider.sass +203 -138
- package/src/components/slider/use-slider.js +454 -107
- package/src/components/slider/use-slider.json +546 -0
- package/src/components/stepper/QStepper.js +3 -3
- package/src/components/stepper/QStepper.sass +24 -26
- package/src/components/table/QTable.js +26 -46
- package/src/components/tabs/QRouteTab.js +1 -2
- package/src/components/tabs/QRouteTab.json +0 -7
- package/src/components/tabs/QTabs.js +91 -24
- package/src/components/tabs/use-tab.js +26 -13
- package/src/components/tooltip/QTooltip.js +1 -2
- package/src/components/tree/QTree.js +14 -12
- package/src/components/uploader/QUploader.json +14 -2
- package/src/components/uploader/uploader-core.js +16 -9
- package/src/components/video/QVideo.js +4 -1
- package/src/components/video/QVideo.json +12 -1
- package/src/components/virtual-scroll/QVirtualScroll.sass +1 -0
- package/src/components/virtual-scroll/use-virtual-scroll.js +30 -17
- package/src/composables/private/use-field.js +18 -20
- package/src/composables/private/use-file.js +20 -5
- package/src/composables/private/use-form.js +2 -3
- package/src/composables/private/use-fullscreen.js +15 -4
- package/src/composables/private/use-model-toggle.js +1 -1
- package/src/composables/private/use-portal.js +9 -7
- package/src/composables/private/use-router-link.js +44 -23
- package/src/composables/private/use-router-link.json +26 -10
- package/src/composables/private/use-split-attrs.js +4 -4
- package/src/composables/private/use-tick.js +7 -14
- package/src/composables/private/use-validate.js +21 -15
- package/src/composables/private/use-validate.json +1 -0
- package/src/css/core/helpers.sass +3 -0
- package/src/css/core/positioning.sass +5 -0
- package/src/css/variables.sass +4 -6
- package/src/directives/ScrollFire.js +1 -0
- package/src/icon-set.js +2 -4
- package/src/plugins/AppFullscreen.js +70 -53
- package/src/plugins/AppVisibility.js +2 -3
- package/src/plugins/BottomSheet.js +3 -5
- package/src/plugins/Dialog.js +3 -5
- package/src/plugins/LoadingBar.js +17 -18
- package/src/plugins/Notify.js +296 -295
- package/src/plugins/Platform.js +14 -14
- package/src/utils/clone.js +53 -4
- package/src/utils/date.js +4 -4
- package/src/utils/dom.js +2 -2
- package/src/utils/open-url.js +2 -2
- package/src/utils/patterns.js +1 -0
- package/src/utils/private/define-reactive-plugin.js +10 -8
- package/src/utils/private/focus-manager.js +8 -10
- package/src/utils/private/global-dialog.js +6 -8
- package/src/utils/private/inject-obj-prop.js +13 -0
- 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
|
-
|
|
62
|
+
markerLabels: [ Boolean, Array, Object, Function ],
|
|
63
|
+
switchMarkerLabelsSide: Boolean,
|
|
66
64
|
|
|
67
|
-
|
|
68
|
-
|
|
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
|
|
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
|
-
+ (
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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 (
|
|
123
|
-
const size = 100 * markerStep.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
|
-
|
|
333
|
+
function getMarkerList (def) {
|
|
334
|
+
if (def === false) { return null }
|
|
136
335
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
: isReversed.value === true ? 'right' : 'left'
|
|
141
|
-
))
|
|
336
|
+
if (def === true) {
|
|
337
|
+
return markerTicks.value.map(defaultMarkerConvertFn)
|
|
338
|
+
}
|
|
142
339
|
|
|
143
|
-
|
|
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
|
-
|
|
347
|
+
const filterFn = ({ value }) => value >= props.min && value <= props.max
|
|
146
348
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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
|
-
|
|
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
|
-
|
|
306
|
-
|
|
649
|
+
getContent,
|
|
650
|
+
getThumbRenderFn,
|
|
651
|
+
convertRatioToModel,
|
|
652
|
+
convertModelToRatio,
|
|
653
|
+
getDraggingRatio
|
|
307
654
|
}
|
|
308
655
|
}
|
|
309
656
|
}
|