Skip to content

Commit 75ae39a

Browse files
committed
feat(range): content inset support and active handle in useRangeEditor
1 parent 4916efd commit 75ae39a

2 files changed

Lines changed: 56 additions & 4 deletions

File tree

src/composables/useRangeEditor.test.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ interface HarnessOptions {
5050
valueMax?: number
5151
showMidpoint?: boolean
5252
track?: HTMLElement | null
53+
contentInsetX?: number
5354
}
5455

5556
interface Harness {
@@ -72,6 +73,7 @@ const mountRangeEditor = (opts: HarnessOptions = {}): Harness => {
7273
const valueMin = ref(opts.valueMin ?? 0)
7374
const valueMax = ref(opts.valueMax ?? 100)
7475
const showMidpoint = ref(opts.showMidpoint ?? true)
76+
const contentInsetX = ref(opts.contentInsetX ?? 0)
7577

7678
let api: ReturnType<typeof useRangeEditor> | undefined
7779
const TestComponent = defineComponent({
@@ -81,7 +83,8 @@ const mountRangeEditor = (opts: HarnessOptions = {}): Harness => {
8183
modelValue,
8284
valueMin,
8385
valueMax,
84-
showMidpoint
86+
showMidpoint,
87+
contentInsetX
8588
})
8689
return () => null
8790
}
@@ -323,4 +326,44 @@ describe('useRangeEditor', () => {
323326
expect.arrayContaining(['pointermove', 'pointerup', 'lostpointercapture'])
324327
)
325328
})
329+
330+
it('maps pointer at content inset to valueMin when contentInsetX is set', () => {
331+
harness = mountRangeEditor({
332+
initial: { min: 20, max: 80, midpoint: 0.5 },
333+
valueMin: 0,
334+
valueMax: 100,
335+
showMidpoint: false,
336+
contentInsetX: 16
337+
})
338+
339+
harness.api.startDrag(
340+
'min',
341+
createPointerEvent('pointerdown', { clientX: 16 })
342+
)
343+
harness.trackRef.value!.dispatchEvent(
344+
createPointerEvent('pointermove', { clientX: 16 })
345+
)
346+
347+
expect(harness.modelValue.value.min).toBe(0)
348+
})
349+
350+
it('maps pointer at right content inset to valueMax when contentInsetX is set', () => {
351+
harness = mountRangeEditor({
352+
initial: { min: 0, max: 80, midpoint: 0.5 },
353+
valueMin: 0,
354+
valueMax: 100,
355+
showMidpoint: false,
356+
contentInsetX: 16
357+
})
358+
359+
harness.api.startDrag(
360+
'max',
361+
createPointerEvent('pointerdown', { clientX: 184 })
362+
)
363+
harness.trackRef.value!.dispatchEvent(
364+
createPointerEvent('pointermove', { clientX: 184 })
365+
)
366+
367+
expect(harness.modelValue.value.max).toBe(100)
368+
})
326369
})

src/composables/useRangeEditor.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@ interface UseRangeEditorOptions {
1414
valueMin: Ref<number>
1515
valueMax: Ref<number>
1616
showMidpoint: Ref<boolean>
17+
contentInsetX?: Ref<number>
1718
}
1819

1920
export function useRangeEditor({
2021
trackRef,
2122
modelValue,
2223
valueMin,
2324
valueMax,
24-
showMidpoint
25+
showMidpoint,
26+
contentInsetX
2527
}: UseRangeEditorOptions) {
2628
const activeHandle = ref<HandleType | null>(null)
2729
let cleanupDrag: (() => void) | null = null
@@ -30,7 +32,13 @@ export function useRangeEditor({
3032
const el = trackRef.value
3133
if (!el) return valueMin.value
3234
const rect = el.getBoundingClientRect()
33-
const normalized = clamp((e.clientX - rect.left) / rect.width, 0, 1)
35+
const inset = contentInsetX?.value ?? 0
36+
const contentWidth = Math.max(rect.width - 2 * inset, 1)
37+
const normalized = clamp(
38+
(e.clientX - rect.left - inset) / contentWidth,
39+
0,
40+
1
41+
)
3442
return denormalize(normalized, valueMin.value, valueMax.value)
3543
}
3644

@@ -108,6 +116,7 @@ export function useRangeEditor({
108116

109117
return {
110118
handleTrackPointerDown,
111-
startDrag
119+
startDrag,
120+
activeHandle
112121
}
113122
}

0 commit comments

Comments
 (0)