@v-c/slider 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Handles/Handle.cjs +195 -1
- package/dist/Handles/Handle.d.ts +17 -5
- package/dist/Handles/Handle.js +191 -202
- package/dist/Handles/index.cjs +108 -1
- package/dist/Handles/index.d.ts +20 -4
- package/dist/Handles/index.js +105 -116
- package/dist/Marks/Mark.cjs +51 -1
- package/dist/Marks/Mark.d.ts +2 -2
- package/dist/Marks/Mark.js +48 -39
- package/dist/Marks/index.cjs +39 -1
- package/dist/Marks/index.d.ts +2 -2
- package/dist/Marks/index.js +36 -32
- package/dist/Slider.cjs +569 -1
- package/dist/Slider.d.ts +60 -263
- package/dist/Slider.js +563 -352
- package/dist/Steps/Dot.cjs +52 -1
- package/dist/Steps/Dot.d.ts +2 -2
- package/dist/Steps/Dot.js +49 -38
- package/dist/Steps/index.cjs +64 -1
- package/dist/Steps/index.d.ts +2 -2
- package/dist/Steps/index.js +61 -41
- package/dist/Tracks/Track.cjs +74 -1
- package/dist/Tracks/Track.js +70 -81
- package/dist/Tracks/index.cjs +70 -1
- package/dist/Tracks/index.js +66 -82
- package/dist/_virtual/rolldown_runtime.cjs +21 -0
- package/dist/context.cjs +39 -1
- package/dist/context.d.ts +13 -7
- package/dist/context.js +29 -24
- package/dist/hooks/useDrag.cjs +160 -1
- package/dist/hooks/useDrag.d.ts +2 -2
- package/dist/hooks/useDrag.js +155 -86
- package/dist/hooks/useOffset.cjs +124 -1
- package/dist/hooks/useOffset.d.ts +2 -1
- package/dist/hooks/useOffset.js +122 -97
- package/dist/hooks/useRange.cjs +21 -1
- package/dist/hooks/useRange.js +18 -9
- package/dist/index.cjs +6 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -4
- package/dist/interface.cjs +0 -1
- package/dist/interface.js +0 -1
- package/dist/util.cjs +32 -1
- package/dist/util.js +27 -26
- package/package.json +18 -10
- package/docs/TooltipSlider.tsx +0 -94
- package/docs/assets/anim.less +0 -63
- package/docs/assets/bootstrap.less +0 -163
- package/docs/assets/index.less +0 -337
- package/docs/debug.vue +0 -60
- package/docs/editable.vue +0 -59
- package/docs/handle.vue +0 -45
- package/docs/marks.vue +0 -94
- package/docs/multiple.vue +0 -54
- package/docs/range.vue +0 -211
- package/docs/slider.stories.vue +0 -45
- package/docs/sliderDemo.vue +0 -267
- package/docs/vertical.vue +0 -122
- package/src/Handles/Handle.tsx +0 -223
- package/src/Handles/index.tsx +0 -124
- package/src/Marks/Mark.tsx +0 -40
- package/src/Marks/index.tsx +0 -40
- package/src/Slider.tsx +0 -593
- package/src/Steps/Dot.tsx +0 -40
- package/src/Steps/index.tsx +0 -54
- package/src/Tracks/Track.tsx +0 -89
- package/src/Tracks/index.tsx +0 -92
- package/src/context.ts +0 -65
- package/src/hooks/useDrag.ts +0 -243
- package/src/hooks/useOffset.ts +0 -264
- package/src/hooks/useRange.ts +0 -24
- package/src/index.ts +0 -8
- package/src/interface.ts +0 -17
- package/src/util.ts +0 -41
- package/vite.config.ts +0 -18
- package/vitest.config.ts +0 -11
package/src/Slider.tsx
DELETED
|
@@ -1,593 +0,0 @@
|
|
|
1
|
-
import type { ComputedRef, CSSProperties, ExtractPropTypes, PropType, Ref, SlotsType } from 'vue'
|
|
2
|
-
import type { HandlesRef } from './Handles'
|
|
3
|
-
import type {
|
|
4
|
-
AriaValueFormat,
|
|
5
|
-
Direction,
|
|
6
|
-
OnStartMove,
|
|
7
|
-
SliderClassNames,
|
|
8
|
-
SliderStyles,
|
|
9
|
-
} from './interface'
|
|
10
|
-
import type { InternalMarkObj, MarkObj } from './Marks'
|
|
11
|
-
import isEqual from '@v-c/util/dist/isEqual'
|
|
12
|
-
import warning from '@v-c/util/dist/warning'
|
|
13
|
-
import cls from 'classnames'
|
|
14
|
-
import { computed, defineComponent, isVNode, ref, shallowRef, watch, watchEffect } from 'vue'
|
|
15
|
-
import { useProviderSliderContext } from './context'
|
|
16
|
-
import Handles from './Handles'
|
|
17
|
-
import useDrag from './hooks/useDrag'
|
|
18
|
-
import useOffset from './hooks/useOffset'
|
|
19
|
-
import useRange from './hooks/useRange'
|
|
20
|
-
import Marks from './Marks'
|
|
21
|
-
import Steps from './Steps'
|
|
22
|
-
import Tracks from './Tracks'
|
|
23
|
-
|
|
24
|
-
export interface RangeConfig {
|
|
25
|
-
editable?: boolean
|
|
26
|
-
draggableTrack?: boolean
|
|
27
|
-
/** Set min count when `editable` */
|
|
28
|
-
minCount?: number
|
|
29
|
-
/** Set max count when `editable` */
|
|
30
|
-
maxCount?: number
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
type ValueType = number | number[]
|
|
34
|
-
|
|
35
|
-
function sliderProps() {
|
|
36
|
-
return {
|
|
37
|
-
prefixCls: { type: String, default: 'vc-slider' },
|
|
38
|
-
className: String,
|
|
39
|
-
classNames: Object as PropType<SliderClassNames>,
|
|
40
|
-
styles: Object as PropType<SliderStyles>,
|
|
41
|
-
id: String,
|
|
42
|
-
disabled: { type: Boolean, default: false },
|
|
43
|
-
keyboard: { type: Boolean, default: true },
|
|
44
|
-
autoFocus: Boolean,
|
|
45
|
-
min: { type: Number, default: 0 },
|
|
46
|
-
max: { type: Number, default: 100 },
|
|
47
|
-
step: { type: Number, default: 1 },
|
|
48
|
-
value: [Number, Array] as PropType<ValueType>,
|
|
49
|
-
defaultValue: [Number, Array] as PropType<ValueType>,
|
|
50
|
-
range: [Boolean, Object] as PropType<boolean | RangeConfig>,
|
|
51
|
-
count: Number,
|
|
52
|
-
allowCross: { type: Boolean, default: true },
|
|
53
|
-
pushable: { type: [Boolean, Number], default: false },
|
|
54
|
-
reverse: Boolean,
|
|
55
|
-
vertical: Boolean,
|
|
56
|
-
included: { type: Boolean, default: true },
|
|
57
|
-
startPoint: Number,
|
|
58
|
-
trackStyle: [Object, Array] as PropType<Record<string, any> | Record<string, any>[]>,
|
|
59
|
-
handleStyle: [Object, Array] as PropType<Record<string, any> | Record<string, any>[]>,
|
|
60
|
-
railStyle: Object as PropType<Record<string, any>>,
|
|
61
|
-
dotStyle: [Object, Function] as PropType<Record<string, any> | ((dotValue: number) => Record<string, any>)>,
|
|
62
|
-
activeDotStyle: [Object, Function] as PropType<Record<string, any> | ((dotValue: number) => Record<string, any>)>,
|
|
63
|
-
marks: Object as PropType<Record<string | number, any | MarkObj>>,
|
|
64
|
-
dots: Boolean,
|
|
65
|
-
handleRender: Function,
|
|
66
|
-
activeHandleRender: Function,
|
|
67
|
-
track: { type: Boolean, default: true },
|
|
68
|
-
tabIndex: { type: [Number, Array] as PropType<ValueType>, default: 0 },
|
|
69
|
-
ariaLabelForHandle: [String, Array] as PropType<string | string[]>,
|
|
70
|
-
ariaLabelledByForHandle: [String, Array] as PropType<string | string[]>,
|
|
71
|
-
ariaRequired: Boolean,
|
|
72
|
-
ariaValueTextFormatterForHandle: [Function, Array] as PropType<AriaValueFormat | AriaValueFormat[]>,
|
|
73
|
-
onFocus: Function as PropType<(e: FocusEvent) => void>,
|
|
74
|
-
onBlur: Function as PropType<(e: FocusEvent) => void>,
|
|
75
|
-
onChange: Function as PropType<(value: ValueType) => void>,
|
|
76
|
-
/** @deprecated It's always better to use `onChange` instead */
|
|
77
|
-
onBeforeChange: Function as PropType<(value: ValueType) => void>,
|
|
78
|
-
/** @deprecated Use `onChangeComplete` instead */
|
|
79
|
-
onAfterChange: Function as PropType<(value: ValueType) => void>,
|
|
80
|
-
onChangeComplete: Function as PropType<(value: ValueType) => void>,
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
export type SliderProps = Partial<ExtractPropTypes<ReturnType<typeof sliderProps>>>
|
|
84
|
-
|
|
85
|
-
export interface SliderRef {
|
|
86
|
-
focus: () => void
|
|
87
|
-
blur: () => void
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export default defineComponent({
|
|
91
|
-
name: 'Slider',
|
|
92
|
-
props: {
|
|
93
|
-
...sliderProps(),
|
|
94
|
-
},
|
|
95
|
-
emits: ['focus', 'blur', 'change', 'beforeChange', 'afterChange', 'changeComplete'],
|
|
96
|
-
slots: Object as SlotsType<{
|
|
97
|
-
mark: ({ point: number, label: unknown }) => any
|
|
98
|
-
}>,
|
|
99
|
-
setup(props, { attrs, emit, expose, slots }) {
|
|
100
|
-
const handlesRef = ref<HandlesRef>()
|
|
101
|
-
const containerRef = ref<HTMLDivElement>()
|
|
102
|
-
|
|
103
|
-
const direction = shallowRef<Direction>('ltr')
|
|
104
|
-
watch([() => props.reverse, () => props.vertical], ([newReverse, newVertical]) => {
|
|
105
|
-
if (newVertical) {
|
|
106
|
-
direction.value = newReverse ? 'ttb' : 'btt'
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
direction.value = newReverse ? 'rtl' : 'ltr'
|
|
110
|
-
}
|
|
111
|
-
}, { immediate: true })
|
|
112
|
-
|
|
113
|
-
const mergedMin = shallowRef(0)
|
|
114
|
-
const mergedMax = shallowRef(100)
|
|
115
|
-
const mergedStep = shallowRef(1)
|
|
116
|
-
const markList = ref<InternalMarkObj[]>([])
|
|
117
|
-
|
|
118
|
-
const mergedValue = ref<ValueType>(props.defaultValue! || props.value!)
|
|
119
|
-
const rawValues = ref<number[] | ComputedRef<number[]>>([])
|
|
120
|
-
const getRange = ref()
|
|
121
|
-
const getOffset = ref()
|
|
122
|
-
|
|
123
|
-
watchEffect(() => {
|
|
124
|
-
const {
|
|
125
|
-
range,
|
|
126
|
-
min,
|
|
127
|
-
max,
|
|
128
|
-
step,
|
|
129
|
-
pushable,
|
|
130
|
-
marks,
|
|
131
|
-
allowCross,
|
|
132
|
-
value,
|
|
133
|
-
count,
|
|
134
|
-
} = props
|
|
135
|
-
// ============================ Range =============================
|
|
136
|
-
const [rangeEnabled, rangeEditable, rangeDraggableTrack, minCount, maxCount] = useRange(range)
|
|
137
|
-
getRange.value = {
|
|
138
|
-
rangeEnabled,
|
|
139
|
-
rangeEditable,
|
|
140
|
-
rangeDraggableTrack,
|
|
141
|
-
minCount,
|
|
142
|
-
maxCount,
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
mergedMin.value = isFinite(min) ? min : 0
|
|
146
|
-
mergedMax.value = isFinite(max) ? max : 100
|
|
147
|
-
|
|
148
|
-
// ============================= Step =============================
|
|
149
|
-
mergedStep.value = step !== null && step <= 0 ? 1 : step
|
|
150
|
-
|
|
151
|
-
// ============================= Push =============================
|
|
152
|
-
const mergedPush = computed(() => {
|
|
153
|
-
if (typeof pushable === 'boolean') {
|
|
154
|
-
return pushable ? mergedStep.value : false
|
|
155
|
-
}
|
|
156
|
-
return pushable >= 0 ? pushable : false
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
// ============================ Marks =============================
|
|
160
|
-
markList.value = Object.keys(marks || {})
|
|
161
|
-
.map<InternalMarkObj>((key) => {
|
|
162
|
-
const mark = marks?.[key]
|
|
163
|
-
const markObj: InternalMarkObj = {
|
|
164
|
-
value: Number(key),
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
if (
|
|
168
|
-
mark
|
|
169
|
-
&& typeof mark === 'object'
|
|
170
|
-
&& !isVNode(mark)
|
|
171
|
-
&& ('label' in mark || 'style' in mark)
|
|
172
|
-
) {
|
|
173
|
-
markObj.style = mark.style
|
|
174
|
-
markObj.label = mark.label
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
markObj.label = mark
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return markObj
|
|
181
|
-
})
|
|
182
|
-
.filter(({ label }) => label || typeof label === 'number')
|
|
183
|
-
.sort((a, b) => a.value - b.value)
|
|
184
|
-
|
|
185
|
-
// ============================ Format ============================
|
|
186
|
-
const [formatValue, offsetValues] = useOffset(
|
|
187
|
-
mergedMin.value,
|
|
188
|
-
mergedMax.value,
|
|
189
|
-
mergedStep.value,
|
|
190
|
-
markList.value,
|
|
191
|
-
allowCross,
|
|
192
|
-
mergedPush.value,
|
|
193
|
-
)
|
|
194
|
-
getOffset.value = {
|
|
195
|
-
formatValue,
|
|
196
|
-
offsetValues,
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// ============================ Values ============================
|
|
200
|
-
if (value !== undefined) {
|
|
201
|
-
mergedValue.value = value
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const getRawValues = computed(() => {
|
|
205
|
-
const valueList
|
|
206
|
-
= mergedValue.value === null || mergedValue.value === undefined
|
|
207
|
-
? []
|
|
208
|
-
: Array.isArray(mergedValue.value)
|
|
209
|
-
? mergedValue.value
|
|
210
|
-
: [mergedValue.value]
|
|
211
|
-
|
|
212
|
-
const [val0 = mergedMin.value] = valueList
|
|
213
|
-
let returnValues = mergedValue.value === null ? [] : [val0]
|
|
214
|
-
|
|
215
|
-
// Format as range
|
|
216
|
-
if (rangeEnabled) {
|
|
217
|
-
returnValues = [...valueList]
|
|
218
|
-
|
|
219
|
-
// When count provided or value is `undefined`, we fill values
|
|
220
|
-
if (count || mergedValue.value === undefined) {
|
|
221
|
-
const pointCount = count! >= 0 ? count! + 1 : 2
|
|
222
|
-
returnValues = returnValues.slice(0, pointCount)
|
|
223
|
-
|
|
224
|
-
// Fill with count
|
|
225
|
-
while (returnValues.length < pointCount) {
|
|
226
|
-
returnValues.push(returnValues[returnValues.length - 1] ?? mergedMin.value)
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
returnValues.sort((a, b) => a - b)
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Align in range
|
|
233
|
-
returnValues.forEach((val, index) => {
|
|
234
|
-
returnValues[index] = formatValue(val)
|
|
235
|
-
})
|
|
236
|
-
|
|
237
|
-
return returnValues
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
rawValues.value = getRawValues.value
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
// =========================== onChange ===========================
|
|
244
|
-
const getTriggerValue = (triggerValues: number[]) => {
|
|
245
|
-
return getRange.value.rangeEnabled ? triggerValues : triggerValues[0]
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const triggerChange = (nextValues: number[]) => {
|
|
249
|
-
// Order first
|
|
250
|
-
const cloneNextValues = [...nextValues].sort((a, b) => a - b)
|
|
251
|
-
|
|
252
|
-
// Trigger event if needed
|
|
253
|
-
if (!isEqual(cloneNextValues, rawValues.value, true)) {
|
|
254
|
-
emit('change', getTriggerValue(cloneNextValues))
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// We set this later since it will re-render component immediately
|
|
258
|
-
mergedValue.value = cloneNextValues
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
const finishChange = (draggingDelete?: boolean) => {
|
|
262
|
-
// Trigger from `useDrag` will tell if it's a delete action
|
|
263
|
-
if (draggingDelete) {
|
|
264
|
-
handlesRef.value?.hideHelp()
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const finishValue = getTriggerValue(rawValues.value)
|
|
268
|
-
if (props.onAfterChange) {
|
|
269
|
-
emit('afterChange', finishValue)
|
|
270
|
-
warning(
|
|
271
|
-
false,
|
|
272
|
-
'[vc-slider] `onAfterChange` is deprecated. Please use `onChangeComplete` instead.',
|
|
273
|
-
)
|
|
274
|
-
}
|
|
275
|
-
emit('changeComplete', finishValue)
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const onDelete = (index: number) => {
|
|
279
|
-
if (props.disabled || !getRange.value.rangeEditable || rawValues.value.length <= getRange.value.minCount) {
|
|
280
|
-
return
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const cloneNextValues = [...rawValues.value]
|
|
284
|
-
cloneNextValues.splice(index, 1)
|
|
285
|
-
|
|
286
|
-
emit('beforeChange', getTriggerValue(cloneNextValues))
|
|
287
|
-
triggerChange(cloneNextValues)
|
|
288
|
-
|
|
289
|
-
const nextFocusIndex = Math.max(0, index - 1)
|
|
290
|
-
handlesRef.value?.hideHelp()
|
|
291
|
-
handlesRef.value?.focus(nextFocusIndex)
|
|
292
|
-
}
|
|
293
|
-
const [draggingIndex, draggingValue, draggingDelete, cacheValues, onStartDrag] = useDrag(
|
|
294
|
-
containerRef as Ref<HTMLDivElement>,
|
|
295
|
-
direction,
|
|
296
|
-
rawValues,
|
|
297
|
-
mergedMin,
|
|
298
|
-
mergedMax,
|
|
299
|
-
getOffset.value.formatValue,
|
|
300
|
-
triggerChange,
|
|
301
|
-
finishChange,
|
|
302
|
-
getOffset.value.offsetValues,
|
|
303
|
-
getRange.value.rangeEditable,
|
|
304
|
-
getRange.value.minCount,
|
|
305
|
-
)
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* When `rangeEditable` will insert a new value in the values array.
|
|
309
|
-
* Else it will replace the value in the values array.
|
|
310
|
-
*/
|
|
311
|
-
const changeToCloseValue = (newValue: number, e?: MouseEvent) => {
|
|
312
|
-
if (!props.disabled) {
|
|
313
|
-
// Create new values
|
|
314
|
-
const cloneNextValues = [...rawValues.value]
|
|
315
|
-
|
|
316
|
-
let valueIndex = 0
|
|
317
|
-
let valueBeforeIndex = 0 // Record the index which value < newValue
|
|
318
|
-
let valueDist = mergedMax.value - mergedMin.value
|
|
319
|
-
|
|
320
|
-
rawValues.value.forEach((val, index) => {
|
|
321
|
-
const dist = Math.abs(newValue - val)
|
|
322
|
-
if (dist <= valueDist) {
|
|
323
|
-
valueDist = dist
|
|
324
|
-
valueIndex = index
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
if (val < newValue) {
|
|
328
|
-
valueBeforeIndex = index
|
|
329
|
-
}
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
let focusIndex = valueIndex
|
|
333
|
-
|
|
334
|
-
if (getRange.value.rangeEditable && valueDist !== 0 && (!getRange.value.maxCount || rawValues.value.length < getRange.value.maxCount)) {
|
|
335
|
-
cloneNextValues.splice(valueBeforeIndex + 1, 0, newValue)
|
|
336
|
-
focusIndex = valueBeforeIndex + 1
|
|
337
|
-
}
|
|
338
|
-
else {
|
|
339
|
-
cloneNextValues[valueIndex] = newValue
|
|
340
|
-
}
|
|
341
|
-
// Fill value to match default 2 (only when `rawValues` is empty)
|
|
342
|
-
if (getRange.value.rangeEnabled && !rawValues.value.length && props.count === undefined) {
|
|
343
|
-
cloneNextValues.push(newValue)
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
const nextValue = getTriggerValue(cloneNextValues)
|
|
347
|
-
emit('beforeChange', nextValue)
|
|
348
|
-
triggerChange(cloneNextValues)
|
|
349
|
-
|
|
350
|
-
if (e) {
|
|
351
|
-
(document.activeElement as HTMLElement)?.blur?.()
|
|
352
|
-
handlesRef.value?.focus(focusIndex)
|
|
353
|
-
onStartDrag(e, focusIndex, cloneNextValues)
|
|
354
|
-
}
|
|
355
|
-
else {
|
|
356
|
-
if (props.onAfterChange) {
|
|
357
|
-
// https://github.com/ant-design/ant-design/issues/49997
|
|
358
|
-
emit('afterChange', nextValue)
|
|
359
|
-
warning(
|
|
360
|
-
false,
|
|
361
|
-
'[vc-slider] `onAfterChange` is deprecated. Please use `onChangeComplete` instead.',
|
|
362
|
-
)
|
|
363
|
-
}
|
|
364
|
-
emit('changeComplete', nextValue)
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
// ============================ Click =============================
|
|
370
|
-
const onSliderMouseDown = (e: MouseEvent) => {
|
|
371
|
-
e.preventDefault()
|
|
372
|
-
const { width, height, left, top, bottom, right }
|
|
373
|
-
= containerRef.value!.getBoundingClientRect()
|
|
374
|
-
const { clientX, clientY } = e
|
|
375
|
-
|
|
376
|
-
let percent: number
|
|
377
|
-
switch (direction.value) {
|
|
378
|
-
case 'btt':
|
|
379
|
-
percent = (bottom - clientY) / height
|
|
380
|
-
break
|
|
381
|
-
|
|
382
|
-
case 'ttb':
|
|
383
|
-
percent = (clientY - top) / height
|
|
384
|
-
break
|
|
385
|
-
|
|
386
|
-
case 'rtl':
|
|
387
|
-
percent = (right - clientX) / width
|
|
388
|
-
break
|
|
389
|
-
|
|
390
|
-
default:
|
|
391
|
-
percent = (clientX - left) / width
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
const nextValue = mergedMin.value + percent * (mergedMax.value - mergedMin.value)
|
|
395
|
-
changeToCloseValue(getOffset.value.formatValue(nextValue), e)
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// =========================== Keyboard ===========================
|
|
399
|
-
const keyboardValue = ref<number | null>(null)
|
|
400
|
-
|
|
401
|
-
const onHandleOffsetChange = (offset: number | 'min' | 'max', valueIndex: number) => {
|
|
402
|
-
if (!props.disabled) {
|
|
403
|
-
const next = getOffset.value.offsetValues(rawValues.value, offset, valueIndex)
|
|
404
|
-
|
|
405
|
-
emit('beforeChange', getTriggerValue(rawValues.value))
|
|
406
|
-
triggerChange(next.values)
|
|
407
|
-
|
|
408
|
-
keyboardValue.value = next.value
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
watchEffect(() => {
|
|
413
|
-
if (keyboardValue.value !== null) {
|
|
414
|
-
const valueIndex = rawValues.value.indexOf(keyboardValue.value)
|
|
415
|
-
if (valueIndex >= 0) {
|
|
416
|
-
handlesRef.value?.focus(valueIndex)
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
keyboardValue.value = null
|
|
421
|
-
})
|
|
422
|
-
|
|
423
|
-
// ============================= Drag =============================
|
|
424
|
-
const mergedDraggableTrack = computed(() => {
|
|
425
|
-
if (getRange.value.rangeDraggableTrack && mergedStep.value === null) {
|
|
426
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
427
|
-
warning(false, '`draggableTrack` is not supported when `step` is `null`.')
|
|
428
|
-
}
|
|
429
|
-
return false
|
|
430
|
-
}
|
|
431
|
-
return getRange.value.rangeDraggableTrack
|
|
432
|
-
})
|
|
433
|
-
|
|
434
|
-
const onStartMove: OnStartMove = (e, valueIndex) => {
|
|
435
|
-
onStartDrag(e, valueIndex)
|
|
436
|
-
|
|
437
|
-
emit('beforeChange', getTriggerValue(rawValues.value))
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// Auto focus for updated handle
|
|
441
|
-
const dragging = computed(() => draggingIndex.value !== -1)
|
|
442
|
-
watchEffect(() => {
|
|
443
|
-
if (!dragging.value) {
|
|
444
|
-
const valueIndex = rawValues.value.lastIndexOf(draggingValue.value)
|
|
445
|
-
handlesRef.value?.focus(valueIndex)
|
|
446
|
-
}
|
|
447
|
-
})
|
|
448
|
-
|
|
449
|
-
// =========================== Included ===========================
|
|
450
|
-
const sortedCacheValues = computed(
|
|
451
|
-
() => [...cacheValues.value].sort((a, b) => a - b),
|
|
452
|
-
)
|
|
453
|
-
|
|
454
|
-
// Provide a range values with included [min, max]
|
|
455
|
-
// Used for Track, Mark & Dot
|
|
456
|
-
const [includedStart, includedEnd] = computed(() => {
|
|
457
|
-
if (!getRange.value.rangeEnabled) {
|
|
458
|
-
return [mergedMin.value, sortedCacheValues.value[0]]
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
return [sortedCacheValues.value[0], sortedCacheValues.value[sortedCacheValues.value.length - 1]]
|
|
462
|
-
}).value
|
|
463
|
-
|
|
464
|
-
// ============================= Refs =============================
|
|
465
|
-
expose({
|
|
466
|
-
focus: () => {
|
|
467
|
-
handlesRef.value?.focus(0)
|
|
468
|
-
},
|
|
469
|
-
blur: () => {
|
|
470
|
-
const { activeElement } = document
|
|
471
|
-
if (containerRef.value?.contains(activeElement)) {
|
|
472
|
-
(activeElement as HTMLElement)?.blur()
|
|
473
|
-
}
|
|
474
|
-
},
|
|
475
|
-
})
|
|
476
|
-
|
|
477
|
-
// ========================== Auto Focus ==========================
|
|
478
|
-
watchEffect(() => {
|
|
479
|
-
if (props.autoFocus) {
|
|
480
|
-
handlesRef.value?.focus(0)
|
|
481
|
-
}
|
|
482
|
-
})
|
|
483
|
-
// =========================== Context ============================
|
|
484
|
-
const context = computed(() => ({
|
|
485
|
-
min: mergedMin,
|
|
486
|
-
max: mergedMax,
|
|
487
|
-
direction,
|
|
488
|
-
disabled: props.disabled,
|
|
489
|
-
keyboard: props.keyboard,
|
|
490
|
-
step: mergedStep,
|
|
491
|
-
included: props.included,
|
|
492
|
-
includedStart,
|
|
493
|
-
includedEnd,
|
|
494
|
-
range: getRange.value.rangeEnabled,
|
|
495
|
-
tabIndex: props.tabIndex,
|
|
496
|
-
ariaLabelForHandle: props.ariaLabelForHandle,
|
|
497
|
-
ariaLabelledByForHandle: props.ariaLabelledByForHandle,
|
|
498
|
-
ariaRequired: props.ariaRequired,
|
|
499
|
-
ariaValueTextFormatterForHandle: props.ariaValueTextFormatterForHandle,
|
|
500
|
-
styles: props.styles || {},
|
|
501
|
-
classNames: props.classNames || {},
|
|
502
|
-
}))
|
|
503
|
-
useProviderSliderContext(context.value)
|
|
504
|
-
|
|
505
|
-
// ============================ Render ============================
|
|
506
|
-
return () => {
|
|
507
|
-
const {
|
|
508
|
-
prefixCls = 'vc-slider',
|
|
509
|
-
id,
|
|
510
|
-
|
|
511
|
-
// Status
|
|
512
|
-
disabled = false,
|
|
513
|
-
vertical,
|
|
514
|
-
|
|
515
|
-
// Style
|
|
516
|
-
startPoint,
|
|
517
|
-
trackStyle,
|
|
518
|
-
handleStyle,
|
|
519
|
-
railStyle,
|
|
520
|
-
dotStyle,
|
|
521
|
-
activeDotStyle,
|
|
522
|
-
|
|
523
|
-
// Decorations
|
|
524
|
-
dots,
|
|
525
|
-
handleRender,
|
|
526
|
-
activeHandleRender,
|
|
527
|
-
|
|
528
|
-
// Components
|
|
529
|
-
track,
|
|
530
|
-
classNames,
|
|
531
|
-
styles,
|
|
532
|
-
} = props
|
|
533
|
-
return (
|
|
534
|
-
<div
|
|
535
|
-
ref={containerRef}
|
|
536
|
-
class={cls(prefixCls, [attrs.class], {
|
|
537
|
-
[`${prefixCls}-disabled`]: disabled,
|
|
538
|
-
[`${prefixCls}-vertical`]: vertical,
|
|
539
|
-
[`${prefixCls}-horizontal`]: !vertical,
|
|
540
|
-
[`${prefixCls}-with-marks`]: markList.value.length,
|
|
541
|
-
})}
|
|
542
|
-
style={attrs.style as CSSProperties}
|
|
543
|
-
onMousedown={onSliderMouseDown}
|
|
544
|
-
id={id}
|
|
545
|
-
>
|
|
546
|
-
<div
|
|
547
|
-
class={cls(`${prefixCls}-rail`, classNames?.rail)}
|
|
548
|
-
style={{ ...railStyle, ...styles?.rail }}
|
|
549
|
-
/>
|
|
550
|
-
|
|
551
|
-
{track && (
|
|
552
|
-
<Tracks
|
|
553
|
-
prefixCls={prefixCls}
|
|
554
|
-
// 将style换成trackStyle,因为vue通过attrs取style,数组会合并,相同的样式名如backgroundColor后一个会覆盖前面的
|
|
555
|
-
trackStyle={trackStyle}
|
|
556
|
-
values={rawValues.value}
|
|
557
|
-
startPoint={startPoint}
|
|
558
|
-
onStartMove={mergedDraggableTrack.value ? onStartMove : undefined}
|
|
559
|
-
/>
|
|
560
|
-
)}
|
|
561
|
-
|
|
562
|
-
<Steps
|
|
563
|
-
prefixCls={prefixCls}
|
|
564
|
-
marks={markList.value}
|
|
565
|
-
dots={dots}
|
|
566
|
-
style={dotStyle}
|
|
567
|
-
activeStyle={activeDotStyle}
|
|
568
|
-
/>
|
|
569
|
-
|
|
570
|
-
<Handles
|
|
571
|
-
ref={handlesRef}
|
|
572
|
-
prefixCls={prefixCls}
|
|
573
|
-
// 原因如⬆️trackStyle
|
|
574
|
-
handleStyle={handleStyle}
|
|
575
|
-
values={cacheValues.value}
|
|
576
|
-
draggingIndex={draggingIndex.value}
|
|
577
|
-
draggingDelete={draggingDelete.value}
|
|
578
|
-
onStartMove={onStartMove}
|
|
579
|
-
onOffsetChange={onHandleOffsetChange}
|
|
580
|
-
onFocus={(e: FocusEvent) => emit('focus', e)}
|
|
581
|
-
onBlur={(e: FocusEvent) => emit('blur', e)}
|
|
582
|
-
handleRender={handleRender}
|
|
583
|
-
activeHandleRender={activeHandleRender}
|
|
584
|
-
onChangeComplete={finishChange}
|
|
585
|
-
onDelete={getRange.value.rangeEditable ? onDelete : () => {}}
|
|
586
|
-
/>
|
|
587
|
-
|
|
588
|
-
<Marks prefixCls={prefixCls} marks={markList.value} onClick={changeToCloseValue} v-slots={slots} />
|
|
589
|
-
</div>
|
|
590
|
-
)
|
|
591
|
-
}
|
|
592
|
-
},
|
|
593
|
-
})
|
package/src/Steps/Dot.tsx
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { CSSProperties, FunctionalComponent } from 'vue'
|
|
2
|
-
import classNames from 'classnames'
|
|
3
|
-
import { useInjectSlider } from '../context'
|
|
4
|
-
import { getDirectionStyle } from '../util'
|
|
5
|
-
|
|
6
|
-
export interface DotProps {
|
|
7
|
-
prefixCls: string
|
|
8
|
-
value: number
|
|
9
|
-
style?: CSSProperties | ((dotValue: number) => CSSProperties)
|
|
10
|
-
activeStyle?: CSSProperties | ((dotValue: number) => CSSProperties)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const Dot: FunctionalComponent<DotProps> = (props, { attrs }) => {
|
|
14
|
-
const { prefixCls, value, activeStyle } = props
|
|
15
|
-
const { min, max, direction, included, includedStart, includedEnd } = useInjectSlider()
|
|
16
|
-
|
|
17
|
-
const dotClassName = `${prefixCls}-dot`
|
|
18
|
-
const active = included && includedStart <= value && value <= includedEnd
|
|
19
|
-
|
|
20
|
-
// ============================ Offset ============================
|
|
21
|
-
let mergedStyle: CSSProperties = {
|
|
22
|
-
...getDirectionStyle(direction.value, value, min.value, max.value),
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (active) {
|
|
26
|
-
mergedStyle = {
|
|
27
|
-
...mergedStyle,
|
|
28
|
-
...(typeof activeStyle === 'function' ? activeStyle(value) : activeStyle),
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<span
|
|
34
|
-
class={classNames(dotClassName, { [`${dotClassName}-active`]: active })}
|
|
35
|
-
style={{ ...mergedStyle, ...attrs.style as CSSProperties }}
|
|
36
|
-
/>
|
|
37
|
-
)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export default Dot
|
package/src/Steps/index.tsx
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { CSSProperties, FunctionalComponent } from 'vue'
|
|
2
|
-
import type { InternalMarkObj } from '../Marks'
|
|
3
|
-
import { computed } from 'vue'
|
|
4
|
-
import { useInjectSlider } from '../context'
|
|
5
|
-
import Dot from './Dot'
|
|
6
|
-
|
|
7
|
-
export interface StepsProps {
|
|
8
|
-
prefixCls: string
|
|
9
|
-
marks: InternalMarkObj[]
|
|
10
|
-
dots?: boolean
|
|
11
|
-
style?: CSSProperties | ((dotValue: number) => CSSProperties)
|
|
12
|
-
activeStyle?: CSSProperties | ((dotValue: number) => CSSProperties)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const Steps: FunctionalComponent<StepsProps> = (props, { attrs }) => {
|
|
16
|
-
const { prefixCls, marks, dots, activeStyle } = props
|
|
17
|
-
const { min, max, step } = useInjectSlider()
|
|
18
|
-
|
|
19
|
-
const stepDots = computed<number[]>(() => {
|
|
20
|
-
const dotSet = new Set<number>()
|
|
21
|
-
|
|
22
|
-
// Add marks
|
|
23
|
-
marks.forEach((mark) => {
|
|
24
|
-
dotSet.add(mark.value)
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
// Fill dots
|
|
28
|
-
if (dots && step !== null) {
|
|
29
|
-
let current = min.value
|
|
30
|
-
while (current <= max.value) {
|
|
31
|
-
dotSet.add(current)
|
|
32
|
-
current += step.value!
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return Array.from(dotSet)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<div class={`${prefixCls}-step`}>
|
|
41
|
-
{stepDots.value.map(dotValue => (
|
|
42
|
-
<Dot
|
|
43
|
-
prefixCls={prefixCls}
|
|
44
|
-
key={dotValue}
|
|
45
|
-
value={dotValue}
|
|
46
|
-
style={{ ...attrs.style as CSSProperties }}
|
|
47
|
-
activeStyle={activeStyle}
|
|
48
|
-
/>
|
|
49
|
-
))}
|
|
50
|
-
</div>
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export default Steps
|