@tremolo-ui/vue 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +865 -611
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +954 -189
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +954 -189
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +339 -128
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/components/AnimationCanvas/AnimationCanvas.ts +27 -30
- package/src/components/AnimationCanvas/index.ts +1 -5
- package/src/components/DropZone/DropZone.ts +19 -9
- package/src/components/DropZone/index.ts +1 -1
- package/src/components/FileInput/FileInput.ts +28 -14
- package/src/components/FileInput/index.ts +1 -1
- package/src/components/Knob/Knob.ts +107 -57
- package/src/components/Knob/KnobThumb.ts +32 -22
- package/src/components/Knob/index.ts +2 -2
- package/src/components/NumberInput/NumberInput.ts +136 -53
- package/src/components/NumberInput/NumberInputField.ts +5 -2
- package/src/components/NumberInput/NumberInputStepper.ts +25 -4
- package/src/components/NumberInput/context.ts +12 -0
- package/src/components/NumberInput/index.ts +1 -1
- package/src/components/NumberInput/stepper-button.ts +8 -1
- package/src/components/Piano/Piano.ts +51 -43
- package/src/components/Piano/index.ts +6 -1
- package/src/components/PointsEditor/PointsEditor.ts +43 -35
- package/src/components/PointsEditor/PointsEditorContainer.ts +2 -6
- package/src/components/PointsEditor/PointsEditorPoint.ts +82 -42
- package/src/components/PointsEditor/context.ts +1 -1
- package/src/components/PointsEditor/index.ts +5 -2
- package/src/components/Slider/Slider.ts +92 -49
- package/src/components/Slider/SliderMarks.ts +28 -14
- package/src/components/Slider/SliderMarksOption.ts +54 -33
- package/src/components/Slider/SliderThumb.ts +26 -8
- package/src/components/Slider/SliderTrack.ts +31 -16
- package/src/components/Slider/context.ts +1 -1
- package/src/components/Slider/index.ts +8 -5
- package/src/components/XYPad/XYPad.ts +94 -56
- package/src/components/XYPad/XYPadThumb.ts +21 -14
- package/src/components/XYPad/index.ts +2 -2
- package/src/components/_util/change-gesture.ts +44 -0
- package/src/components/_util/useCheckSteps.ts +1 -1
- package/src/components/_util/visually-hidden-range-input.ts +1 -1
- package/src/composables/useInstance.ts +1 -1
- package/src/composables/useWheel.ts +5 -2
- package/src/index.ts +21 -4
|
@@ -1,27 +1,33 @@
|
|
|
1
1
|
import {
|
|
2
|
+
type ComponentObjectPropsOptions,
|
|
2
3
|
computed,
|
|
3
4
|
defineComponent,
|
|
5
|
+
type ExtractPublicPropTypes,
|
|
4
6
|
h,
|
|
5
7
|
mergeProps,
|
|
8
|
+
type PropType,
|
|
6
9
|
ref,
|
|
7
10
|
useId,
|
|
8
11
|
watch,
|
|
9
|
-
type PropType,
|
|
10
12
|
} from 'vue'
|
|
11
13
|
|
|
12
14
|
import {
|
|
13
|
-
arrowKeyMove,
|
|
14
|
-
clampPoint,
|
|
15
15
|
createDragValue,
|
|
16
16
|
elementMapping,
|
|
17
|
-
POINT_AXIS,
|
|
18
|
-
selectModifier,
|
|
19
17
|
type InputEventOption,
|
|
20
18
|
type ModifierValue,
|
|
19
|
+
type ChangeSource,
|
|
21
20
|
type PointPosition,
|
|
22
21
|
type PointsEditorPoint as PointRegistration,
|
|
23
22
|
} from '@tremolo-ui/dom'
|
|
23
|
+
import {
|
|
24
|
+
arrowKeyMove,
|
|
25
|
+
clampPoint,
|
|
26
|
+
POINT_AXIS,
|
|
27
|
+
selectModifier,
|
|
28
|
+
} from '@tremolo-ui/dom/internal'
|
|
24
29
|
|
|
30
|
+
import { useChangeGesture } from '../_util/change-gesture'
|
|
25
31
|
import { checkPlacement } from '../_util/placement'
|
|
26
32
|
import { visuallyHiddenRangeInput } from '../_util/visually-hidden-range-input'
|
|
27
33
|
|
|
@@ -32,44 +38,65 @@ type PerAxis = string | Partial<Record<'x' | 'y', string>>
|
|
|
32
38
|
const perAxis = (setting: PerAxis | undefined, axis: 'x' | 'y') =>
|
|
33
39
|
typeof setting === 'string' ? setting : setting?.[axis]
|
|
34
40
|
|
|
41
|
+
const pointsEditorPointProps = {
|
|
42
|
+
/** Where the point is, with `y` growing downwards. Bind it with `v-model`. */
|
|
43
|
+
modelValue: { type: Object as PropType<PointPosition>, required: true },
|
|
44
|
+
/** How the selection refers to this point. One is generated when left out. */
|
|
45
|
+
id: String,
|
|
46
|
+
/** The lowest position the point can take, per axis. */
|
|
47
|
+
min: Object as PropType<Partial<PointPosition>>,
|
|
48
|
+
/** The highest position the point can take, per axis. */
|
|
49
|
+
max: Object as PropType<Partial<PointPosition>>,
|
|
50
|
+
/** Sets `--color`, for the theme to colour the point with. */
|
|
51
|
+
color: String,
|
|
52
|
+
/** Overrides the `disabled` of `PointsEditor`. */
|
|
53
|
+
disabled: { type: Boolean, default: undefined },
|
|
54
|
+
/** Overrides the `readonly` of `PointsEditor`. */
|
|
55
|
+
readonly: { type: Boolean, default: undefined },
|
|
56
|
+
/**
|
|
57
|
+
* How long after the last wheel notch or arrow key a change counts as over,
|
|
58
|
+
* in milliseconds, for `change-end`.
|
|
59
|
+
* @default 500
|
|
60
|
+
*/
|
|
61
|
+
changeEndDelay: { type: Number, default: 500 },
|
|
62
|
+
/** Overrides the `wheel` of `PointsEditor`; `null` turns it off. */
|
|
63
|
+
wheel: {
|
|
64
|
+
type: [Array, Object] as PropType<ModifierValue<InputEventOption> | null>,
|
|
65
|
+
default: undefined,
|
|
66
|
+
},
|
|
67
|
+
/** Overrides the `keyboard` of `PointsEditor`; `null` turns it off. */
|
|
68
|
+
keyboard: {
|
|
69
|
+
type: [Array, Object] as PropType<ModifierValue<InputEventOption> | null>,
|
|
70
|
+
default: undefined,
|
|
71
|
+
},
|
|
72
|
+
/** The accessible name of each axis, or one for both. */
|
|
73
|
+
ariaLabel: [String, Object] as PropType<PerAxis>,
|
|
74
|
+
/** What the value of each axis means, or one for both. */
|
|
75
|
+
ariaValuetext: [String, Object] as PropType<PerAxis>,
|
|
76
|
+
} satisfies ComponentObjectPropsOptions
|
|
77
|
+
|
|
78
|
+
export type PointsEditorPointProps = ExtractPublicPropTypes<
|
|
79
|
+
typeof pointsEditorPointProps
|
|
80
|
+
>
|
|
81
|
+
|
|
35
82
|
/** One point, bound with `v-model` as `{ x, y }` from 0 to 1. */
|
|
36
83
|
export const PointsEditorPoint = /* @__PURE__ */ defineComponent({
|
|
37
84
|
name: 'PointsEditorPoint',
|
|
38
85
|
inheritAttrs: false,
|
|
39
|
-
props:
|
|
40
|
-
/** Where the point is, with `y` growing downwards. Bind it with `v-model`. */
|
|
41
|
-
modelValue: { type: Object as PropType<PointPosition>, required: true },
|
|
42
|
-
/** How the selection refers to this point. One is generated when left out. */
|
|
43
|
-
id: String,
|
|
44
|
-
/** The lowest position the point can take, per axis. */
|
|
45
|
-
min: Object as PropType<Partial<PointPosition>>,
|
|
46
|
-
/** The highest position the point can take, per axis. */
|
|
47
|
-
max: Object as PropType<Partial<PointPosition>>,
|
|
48
|
-
/** Sets `--color`, for the theme to colour the point with. */
|
|
49
|
-
color: String,
|
|
50
|
-
/** Overrides the `disabled` of `PointsEditor`. */
|
|
51
|
-
disabled: { type: Boolean, default: undefined },
|
|
52
|
-
/** Overrides the `readonly` of `PointsEditor`. */
|
|
53
|
-
readonly: { type: Boolean, default: undefined },
|
|
54
|
-
/** Overrides the `wheel` of `PointsEditor`; `null` turns it off. */
|
|
55
|
-
wheel: {
|
|
56
|
-
type: [Array, Object] as PropType<ModifierValue<InputEventOption> | null>,
|
|
57
|
-
default: undefined,
|
|
58
|
-
},
|
|
59
|
-
/** Overrides the `keyboard` of `PointsEditor`; `null` turns it off. */
|
|
60
|
-
keyboard: {
|
|
61
|
-
type: [Array, Object] as PropType<ModifierValue<InputEventOption> | null>,
|
|
62
|
-
default: undefined,
|
|
63
|
-
},
|
|
64
|
-
/** The accessible name of each axis, or one for both. */
|
|
65
|
-
ariaLabel: [String, Object] as PropType<PerAxis>,
|
|
66
|
-
/** What the value of each axis means, or one for both. */
|
|
67
|
-
ariaValuetext: [String, Object] as PropType<PerAxis>,
|
|
68
|
-
},
|
|
86
|
+
props: pointsEditorPointProps,
|
|
69
87
|
emits: {
|
|
70
88
|
'update:modelValue': (value: PointPosition) => typeof value === 'object',
|
|
71
|
-
|
|
72
|
-
|
|
89
|
+
/**
|
|
90
|
+
* A change of this point started — a drag on it, the first wheel notch or
|
|
91
|
+
* arrow key while it has the focus — with where it is and what the change
|
|
92
|
+
* is made with. The points that move along with a selection report
|
|
93
|
+
* through `update:modelValue` only.
|
|
94
|
+
*/
|
|
95
|
+
changeStart: (value: PointPosition, _source: ChangeSource) =>
|
|
96
|
+
typeof value === 'object',
|
|
97
|
+
/** The change ended, with where the point is. */
|
|
98
|
+
changeEnd: (value: PointPosition, _source: ChangeSource) =>
|
|
99
|
+
typeof value === 'object',
|
|
73
100
|
},
|
|
74
101
|
setup(props, { slots, attrs, emit }) {
|
|
75
102
|
const points = usePointsEditorContext()
|
|
@@ -90,6 +117,14 @@ export const PointsEditorPoint = /* @__PURE__ */ defineComponent({
|
|
|
90
117
|
clampPoint(props.modelValue, props.min, props.max),
|
|
91
118
|
)
|
|
92
119
|
|
|
120
|
+
const gesture = useChangeGesture({
|
|
121
|
+
value: () => current.value,
|
|
122
|
+
inactive: () => inactive.value,
|
|
123
|
+
endDelay: () => props.changeEndDelay,
|
|
124
|
+
onStart: (value, source) => emit('changeStart', value, source),
|
|
125
|
+
onEnd: (value, source) => emit('changeEnd', value, source),
|
|
126
|
+
})
|
|
127
|
+
|
|
93
128
|
const el = ref<HTMLDivElement | null>(null)
|
|
94
129
|
const x = ref<HTMLInputElement | null>(null)
|
|
95
130
|
const dragging = ref(false)
|
|
@@ -101,9 +136,13 @@ export const PointsEditorPoint = /* @__PURE__ */ defineComponent({
|
|
|
101
136
|
min: props.min,
|
|
102
137
|
max: props.max,
|
|
103
138
|
readonly: inactive.value,
|
|
104
|
-
onChange: (next) =>
|
|
139
|
+
onChange: (next) => {
|
|
140
|
+
gesture.changed(next)
|
|
141
|
+
emit('update:modelValue', next)
|
|
142
|
+
},
|
|
105
143
|
element: el.value,
|
|
106
144
|
wheel: wheel.value,
|
|
145
|
+
beforeWheel: () => gesture.pulse('wheel'),
|
|
107
146
|
})
|
|
108
147
|
watch(
|
|
109
148
|
id,
|
|
@@ -125,7 +164,7 @@ export const PointsEditorPoint = /* @__PURE__ */ defineComponent({
|
|
|
125
164
|
sensitivity: (state) =>
|
|
126
165
|
selectModifier(points.dragSensitivity, state.event).value,
|
|
127
166
|
}),
|
|
128
|
-
cursor: inactive.value ? undefined : points.
|
|
167
|
+
cursor: inactive.value ? undefined : points.dragCursor,
|
|
129
168
|
shouldStart: () => !disabled.value,
|
|
130
169
|
// A move rather than a position: the point keeps the offset it was
|
|
131
170
|
// grabbed at, and everything else selected moves with it.
|
|
@@ -142,16 +181,16 @@ export const PointsEditorPoint = /* @__PURE__ */ defineComponent({
|
|
|
142
181
|
origin = { x: px, y: py }
|
|
143
182
|
dragging.value = true
|
|
144
183
|
x.value?.focus()
|
|
145
|
-
if (!inactive.value)
|
|
184
|
+
if (!inactive.value) gesture.hold('pointer')
|
|
146
185
|
},
|
|
147
186
|
onDragEnd: () => {
|
|
148
187
|
origin = null
|
|
149
188
|
dragging.value = false
|
|
150
|
-
|
|
189
|
+
gesture.end()
|
|
151
190
|
},
|
|
152
191
|
})
|
|
153
192
|
const stop = watch(
|
|
154
|
-
() => (inactive.value ? undefined : points.
|
|
193
|
+
() => (inactive.value ? undefined : points.dragCursor),
|
|
155
194
|
(cursor) => drag.update({ cursor }),
|
|
156
195
|
)
|
|
157
196
|
onCleanup(() => {
|
|
@@ -234,6 +273,7 @@ export const PointsEditorPoint = /* @__PURE__ */ defineComponent({
|
|
|
234
273
|
if (!move) return
|
|
235
274
|
event.preventDefault()
|
|
236
275
|
if (inactive.value || !keyboard.value) return
|
|
276
|
+
gesture.pulse('keyboard')
|
|
237
277
|
points.editor.nudgePoint(
|
|
238
278
|
id.value,
|
|
239
279
|
move.axis === 0 ? 'x' : 'y',
|
|
@@ -16,7 +16,7 @@ export interface PointsEditorContextValue {
|
|
|
16
16
|
readonly wheel: ModifierValue<InputEventOption> | null
|
|
17
17
|
readonly keyboard: ModifierValue<InputEventOption> | null
|
|
18
18
|
readonly dragSensitivity: ModifierValue<number>
|
|
19
|
-
readonly
|
|
19
|
+
readonly dragCursor: string
|
|
20
20
|
readonly selectable: boolean
|
|
21
21
|
/** Ids of the selected points. Always empty while `selectable` is off. */
|
|
22
22
|
readonly selection: readonly string[]
|
|
@@ -2,8 +2,11 @@ export {
|
|
|
2
2
|
usePointsEditorContext,
|
|
3
3
|
type PointsEditorContextValue,
|
|
4
4
|
} from './context'
|
|
5
|
-
export { PointsEditor } from './PointsEditor'
|
|
5
|
+
export { PointsEditor, type PointsEditorProps } from './PointsEditor'
|
|
6
6
|
export { PointsEditorBackground } from './PointsEditorBackground'
|
|
7
7
|
export { PointsEditorContainer } from './PointsEditorContainer'
|
|
8
|
-
export {
|
|
8
|
+
export {
|
|
9
|
+
PointsEditorPoint,
|
|
10
|
+
type PointsEditorPointProps,
|
|
11
|
+
} from './PointsEditorPoint'
|
|
9
12
|
export { PointsEditorSelectionBox } from './PointsEditorSelectionBox'
|
|
@@ -1,58 +1,92 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type ComponentObjectPropsOptions,
|
|
3
|
+
computed,
|
|
4
|
+
defineComponent,
|
|
5
|
+
type ExtractPublicPropTypes,
|
|
6
|
+
h,
|
|
7
|
+
type PropType,
|
|
8
|
+
provide,
|
|
9
|
+
ref,
|
|
10
|
+
} from 'vue'
|
|
2
11
|
|
|
3
12
|
import {
|
|
4
|
-
applyDelta,
|
|
5
|
-
arrowKeyDirection,
|
|
6
13
|
elementMapping,
|
|
7
|
-
selectModifier,
|
|
8
14
|
valuePercent,
|
|
9
|
-
wheelDirection,
|
|
10
15
|
type AxisOptions,
|
|
16
|
+
type ChangeSource,
|
|
11
17
|
type XY,
|
|
12
18
|
} from '@tremolo-ui/dom'
|
|
19
|
+
import {
|
|
20
|
+
applyDelta,
|
|
21
|
+
arrowKeyDirection,
|
|
22
|
+
selectModifier,
|
|
23
|
+
wheelDirection,
|
|
24
|
+
} from '@tremolo-ui/dom/internal'
|
|
13
25
|
import { linearScale, type Scale } from '@tremolo-ui/functions'
|
|
14
26
|
|
|
15
27
|
import { useDragValue } from '../../composables/useDragValue'
|
|
16
28
|
import { useWheel } from '../../composables/useWheel'
|
|
29
|
+
import { useChangeGesture } from '../_util/change-gesture'
|
|
17
30
|
import { dragSensitivityProp, keyboardProp, wheelProp } from '../_util/props'
|
|
18
31
|
import { useCheckSteps } from '../_util/useCheckSteps'
|
|
19
32
|
|
|
20
33
|
import { SliderKey } from './context'
|
|
21
34
|
|
|
35
|
+
const sliderProps = {
|
|
36
|
+
/** The current value. Bind it with `v-model`. */
|
|
37
|
+
modelValue: { type: Number, required: true },
|
|
38
|
+
/** The value at the start of the travel. */
|
|
39
|
+
min: { type: Number, required: true },
|
|
40
|
+
/** The value at the end of the travel. */
|
|
41
|
+
max: { type: Number, required: true },
|
|
42
|
+
/** Granularity of the value. @default 1 */
|
|
43
|
+
step: { type: Number, default: 1 },
|
|
44
|
+
/** How the value is distributed across the travel. @default linearScale */
|
|
45
|
+
scale: { type: Object as PropType<Scale>, default: () => linearScale },
|
|
46
|
+
/**
|
|
47
|
+
* Which way the slider runs. A vertical slider grows upwards.
|
|
48
|
+
* @default 'horizontal'
|
|
49
|
+
*/
|
|
50
|
+
orientation: {
|
|
51
|
+
type: String as PropType<'horizontal' | 'vertical'>,
|
|
52
|
+
default: 'horizontal',
|
|
53
|
+
},
|
|
54
|
+
/** Grow the value the other way. */
|
|
55
|
+
reverse: Boolean,
|
|
56
|
+
/** The cursor to show while dragging. @default 'pointer' */
|
|
57
|
+
dragCursor: { type: String, default: 'pointer' },
|
|
58
|
+
wheel: wheelProp,
|
|
59
|
+
keyboard: keyboardProp,
|
|
60
|
+
dragSensitivity: dragSensitivityProp,
|
|
61
|
+
/** Make the slider unchangeable and remove it from the tab order. */
|
|
62
|
+
disabled: Boolean,
|
|
63
|
+
/** Make the value unchangeable. */
|
|
64
|
+
readonly: Boolean,
|
|
65
|
+
/**
|
|
66
|
+
* How long after the last wheel notch or arrow key a change counts as over,
|
|
67
|
+
* in milliseconds, for `change-end`.
|
|
68
|
+
* @default 500
|
|
69
|
+
*/
|
|
70
|
+
changeEndDelay: { type: Number, default: 500 },
|
|
71
|
+
} satisfies ComponentObjectPropsOptions
|
|
72
|
+
|
|
73
|
+
export type SliderProps = ExtractPublicPropTypes<typeof sliderProps>
|
|
74
|
+
|
|
22
75
|
/** Customizable slider. Bind the value with `v-model`. */
|
|
23
76
|
export const Slider = /* @__PURE__ */ defineComponent({
|
|
24
77
|
name: 'Slider',
|
|
25
|
-
props:
|
|
26
|
-
/** The current value. Bind it with `v-model`. */
|
|
27
|
-
modelValue: { type: Number, required: true },
|
|
28
|
-
/** The value at the start of the travel. */
|
|
29
|
-
min: { type: Number, required: true },
|
|
30
|
-
/** The value at the end of the travel. */
|
|
31
|
-
max: { type: Number, required: true },
|
|
32
|
-
/** Granularity of the value. @default 1 */
|
|
33
|
-
step: { type: Number, default: 1 },
|
|
34
|
-
/** How the value is distributed across the travel. @default linearScale */
|
|
35
|
-
scale: { type: Object as PropType<Scale>, default: () => linearScale },
|
|
36
|
-
/** Run the slider vertically, with the value growing upwards. */
|
|
37
|
-
vertical: Boolean,
|
|
38
|
-
/** Grow the value the other way. */
|
|
39
|
-
reverse: Boolean,
|
|
40
|
-
/** The cursor to show while dragging. @default { cursor: 'pointer' } */
|
|
41
|
-
externalStyles: Object as PropType<{ cursor?: string }>,
|
|
42
|
-
wheel: wheelProp,
|
|
43
|
-
keyboard: keyboardProp,
|
|
44
|
-
dragSensitivity: dragSensitivityProp,
|
|
45
|
-
/** Make the slider unchangeable and remove it from the tab order. */
|
|
46
|
-
disabled: Boolean,
|
|
47
|
-
/** Make the value unchangeable. */
|
|
48
|
-
readonly: Boolean,
|
|
49
|
-
},
|
|
78
|
+
props: sliderProps,
|
|
50
79
|
emits: {
|
|
51
80
|
'update:modelValue': (value: number) => typeof value === 'number',
|
|
52
|
-
/**
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
81
|
+
/**
|
|
82
|
+
* A change of the value started, with the value before it and what it is
|
|
83
|
+
* made with.
|
|
84
|
+
*/
|
|
85
|
+
changeStart: (value: number, _source: ChangeSource) =>
|
|
86
|
+
typeof value === 'number',
|
|
87
|
+
/** The change ended, with the value it ended on. */
|
|
88
|
+
changeEnd: (value: number, _source: ChangeSource) =>
|
|
89
|
+
typeof value === 'number',
|
|
56
90
|
},
|
|
57
91
|
setup(props, { slots, emit, expose }) {
|
|
58
92
|
const root = ref<HTMLDivElement | null>(null)
|
|
@@ -62,7 +96,8 @@ export const Slider = /* @__PURE__ */ defineComponent({
|
|
|
62
96
|
const inactive = computed(() => props.disabled || props.readonly)
|
|
63
97
|
// Measured from the left or the top, as CSS places things: vertical and
|
|
64
98
|
// reverse each flip it, and together they cancel out.
|
|
65
|
-
const
|
|
99
|
+
const vertical = computed(() => props.orientation === 'vertical')
|
|
100
|
+
const displayReversed = computed(() => vertical.value !== props.reverse)
|
|
66
101
|
const percent = computed(() =>
|
|
67
102
|
valuePercent(
|
|
68
103
|
props.modelValue,
|
|
@@ -85,7 +120,17 @@ export const Slider = /* @__PURE__ */ defineComponent({
|
|
|
85
120
|
wheel: props.wheel,
|
|
86
121
|
}))
|
|
87
122
|
|
|
88
|
-
const
|
|
123
|
+
const gesture = useChangeGesture({
|
|
124
|
+
value: () => props.modelValue,
|
|
125
|
+
inactive: () => inactive.value,
|
|
126
|
+
endDelay: () => props.changeEndDelay,
|
|
127
|
+
onStart: (value, source) => emit('changeStart', value, source),
|
|
128
|
+
onEnd: (value, source) => emit('changeEnd', value, source),
|
|
129
|
+
})
|
|
130
|
+
const change = (next: number) => {
|
|
131
|
+
gesture.changed(next)
|
|
132
|
+
emit('update:modelValue', next)
|
|
133
|
+
}
|
|
89
134
|
|
|
90
135
|
provide(SliderKey, {
|
|
91
136
|
get value() {
|
|
@@ -103,8 +148,8 @@ export const Slider = /* @__PURE__ */ defineComponent({
|
|
|
103
148
|
get scale() {
|
|
104
149
|
return props.scale
|
|
105
150
|
},
|
|
106
|
-
get
|
|
107
|
-
return props.
|
|
151
|
+
get orientation() {
|
|
152
|
+
return props.orientation
|
|
108
153
|
},
|
|
109
154
|
get reverse() {
|
|
110
155
|
return props.reverse
|
|
@@ -127,7 +172,7 @@ export const Slider = /* @__PURE__ */ defineComponent({
|
|
|
127
172
|
},
|
|
128
173
|
})
|
|
129
174
|
|
|
130
|
-
const valueOf = (v: XY<number>) => v[
|
|
175
|
+
const valueOf = (v: XY<number>) => v[vertical.value ? 1 : 0]
|
|
131
176
|
|
|
132
177
|
useDragValue(root, () => ({
|
|
133
178
|
axis: axis.value,
|
|
@@ -135,22 +180,18 @@ export const Slider = /* @__PURE__ */ defineComponent({
|
|
|
135
180
|
sensitivity: (state) =>
|
|
136
181
|
selectModifier(props.dragSensitivity, state.event).value,
|
|
137
182
|
}),
|
|
138
|
-
cursor: inactive.value
|
|
139
|
-
? undefined
|
|
140
|
-
: (props.externalStyles?.cursor ?? 'pointer'),
|
|
183
|
+
cursor: inactive.value ? undefined : props.dragCursor,
|
|
141
184
|
shouldStart: () => !inactive.value,
|
|
142
185
|
updateOnPointerDown: true,
|
|
143
186
|
onChange: (v) => {
|
|
144
187
|
if (!inactive.value) change(valueOf(v))
|
|
145
188
|
},
|
|
146
|
-
onDragStart: (
|
|
189
|
+
onDragStart: () => {
|
|
147
190
|
if (inactive.value) return
|
|
191
|
+
gesture.hold('pointer')
|
|
148
192
|
thumb?.focus()
|
|
149
|
-
emit('dragStart', valueOf(v))
|
|
150
|
-
},
|
|
151
|
-
onDragEnd: (v) => {
|
|
152
|
-
if (!inactive.value) emit('dragEnd', valueOf(v))
|
|
153
193
|
},
|
|
194
|
+
onDragEnd: () => gesture.end(),
|
|
154
195
|
}))
|
|
155
196
|
|
|
156
197
|
useWheel(
|
|
@@ -159,9 +200,10 @@ export const Slider = /* @__PURE__ */ defineComponent({
|
|
|
159
200
|
if (!props.wheel || inactive.value) return
|
|
160
201
|
// A notch the slider does not read — a sideways scroll on a vertical
|
|
161
202
|
// slider — is left to the page rather than swallowed.
|
|
162
|
-
const direction = wheelDirection(event, { horizontal: !
|
|
203
|
+
const direction = wheelDirection(event, { horizontal: !vertical.value })
|
|
163
204
|
if (direction === null) return
|
|
164
205
|
event.preventDefault()
|
|
206
|
+
gesture.pulse('wheel')
|
|
165
207
|
change(
|
|
166
208
|
applyDelta(
|
|
167
209
|
props.modelValue,
|
|
@@ -195,7 +237,7 @@ export const Slider = /* @__PURE__ */ defineComponent({
|
|
|
195
237
|
ref: root,
|
|
196
238
|
role: 'group',
|
|
197
239
|
tabindex: -1,
|
|
198
|
-
'data-orientation': props.
|
|
240
|
+
'data-orientation': props.orientation,
|
|
199
241
|
'data-disabled': props.disabled ? '' : undefined,
|
|
200
242
|
'data-readonly': props.readonly ? '' : undefined,
|
|
201
243
|
onKeydown: (event: KeyboardEvent) => {
|
|
@@ -203,6 +245,7 @@ export const Slider = /* @__PURE__ */ defineComponent({
|
|
|
203
245
|
if (direction === null) return
|
|
204
246
|
event.preventDefault()
|
|
205
247
|
if (!props.keyboard || inactive.value) return
|
|
248
|
+
gesture.pulse('keyboard')
|
|
206
249
|
change(
|
|
207
250
|
applyDelta(
|
|
208
251
|
props.modelValue,
|
|
@@ -1,25 +1,37 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type ComponentObjectPropsOptions,
|
|
3
|
+
computed,
|
|
4
|
+
defineComponent,
|
|
5
|
+
type ExtractPublicPropTypes,
|
|
6
|
+
h,
|
|
7
|
+
type PropType,
|
|
8
|
+
} from 'vue'
|
|
2
9
|
|
|
3
|
-
import {
|
|
10
|
+
import { type MarksOptions } from '@tremolo-ui/dom'
|
|
11
|
+
import { cssLength, sliderMarks } from '@tremolo-ui/dom/internal'
|
|
4
12
|
|
|
5
13
|
import { providePlacement } from '../_util/placement'
|
|
6
14
|
|
|
7
15
|
import { useSliderContext } from './context'
|
|
8
16
|
import { SliderMarksOption } from './SliderMarksOption'
|
|
9
17
|
|
|
18
|
+
const sliderMarksProps = {
|
|
19
|
+
/** Space between the marks and the track. Sets `--gap`. */
|
|
20
|
+
gap: [Number, String],
|
|
21
|
+
/**
|
|
22
|
+
* Build the marks instead of writing `SliderMarksOption` out: a number
|
|
23
|
+
* puts one every that many, `'step'` one every `step`. The default slot
|
|
24
|
+
* is ignored while it is set.
|
|
25
|
+
*/
|
|
26
|
+
options: [String, Number, Object] as PropType<MarksOptions>,
|
|
27
|
+
} satisfies ComponentObjectPropsOptions
|
|
28
|
+
|
|
29
|
+
export type SliderMarksProps = ExtractPublicPropTypes<typeof sliderMarksProps>
|
|
30
|
+
|
|
10
31
|
/** The marks along the slider: written out as options, or built from `options`. */
|
|
11
32
|
export const SliderMarks = /* @__PURE__ */ defineComponent({
|
|
12
33
|
name: 'SliderMarks',
|
|
13
|
-
props:
|
|
14
|
-
/** Space between the marks and the track. Sets `--gap`. */
|
|
15
|
-
gap: [Number, String],
|
|
16
|
-
/**
|
|
17
|
-
* Build the marks instead of writing `SliderMarksOption` out: a number
|
|
18
|
-
* puts one every that many, `'step'` one every `step`. The default slot
|
|
19
|
-
* is ignored while it is set.
|
|
20
|
-
*/
|
|
21
|
-
options: [String, Number, Object] as PropType<MarksOptions>,
|
|
22
|
-
},
|
|
34
|
+
props: sliderMarksProps,
|
|
23
35
|
setup(props, { slots }) {
|
|
24
36
|
const slider = useSliderContext()
|
|
25
37
|
providePlacement('SliderMarks')
|
|
@@ -32,14 +44,16 @@ export const SliderMarks = /* @__PURE__ */ defineComponent({
|
|
|
32
44
|
slider.step,
|
|
33
45
|
)
|
|
34
46
|
// In the order they are on screen.
|
|
35
|
-
return slider.vertical !== slider.reverse
|
|
47
|
+
return (slider.orientation === 'vertical') !== slider.reverse
|
|
48
|
+
? list.reverse()
|
|
49
|
+
: list
|
|
36
50
|
})
|
|
37
51
|
// Each option inside is placed against this box.
|
|
38
52
|
return () =>
|
|
39
53
|
h(
|
|
40
54
|
'div',
|
|
41
55
|
{
|
|
42
|
-
'data-orientation': slider.
|
|
56
|
+
'data-orientation': slider.orientation,
|
|
43
57
|
style: { '--gap': cssLength(props.gap), position: 'relative' },
|
|
44
58
|
},
|
|
45
59
|
props.options !== undefined
|
|
@@ -1,38 +1,52 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type ComponentObjectPropsOptions,
|
|
3
|
+
computed,
|
|
4
|
+
defineComponent,
|
|
5
|
+
type ExtractPublicPropTypes,
|
|
6
|
+
h,
|
|
7
|
+
type PropType,
|
|
8
|
+
} from 'vue'
|
|
2
9
|
|
|
3
|
-
import {
|
|
10
|
+
import { valuePercent } from '@tremolo-ui/dom'
|
|
11
|
+
import { cssLength } from '@tremolo-ui/dom/internal'
|
|
4
12
|
|
|
5
13
|
import { checkPlacement } from '../_util/placement'
|
|
6
14
|
|
|
7
15
|
import { useSliderContext } from './context'
|
|
8
16
|
|
|
17
|
+
const sliderMarksOptionProps = {
|
|
18
|
+
/** Where the mark sits, on the same scale as the thumb. */
|
|
19
|
+
value: { type: Number, required: true },
|
|
20
|
+
/** Draw the mark itself. @default true */
|
|
21
|
+
mark: { type: Boolean, default: true },
|
|
22
|
+
/**
|
|
23
|
+
* Text shown next to the mark. Leave it out to show the value; `null`
|
|
24
|
+
* leaves the label out.
|
|
25
|
+
*/
|
|
26
|
+
label: {
|
|
27
|
+
type: [Number, String, null] as PropType<number | string | null>,
|
|
28
|
+
default: undefined,
|
|
29
|
+
},
|
|
30
|
+
/** Thickness of the mark. Sets `--thickness`. */
|
|
31
|
+
thickness: [Number, String],
|
|
32
|
+
/** Length of the mark. Sets `--length`. */
|
|
33
|
+
length: [Number, String],
|
|
34
|
+
/** Space between the mark and the label. Sets `--gap`. */
|
|
35
|
+
gap: [Number, String],
|
|
36
|
+
/** Classes for the mark and the label inside the option. */
|
|
37
|
+
classes: Object as PropType<{ mark?: string; label?: string }>,
|
|
38
|
+
/** Styles for the mark and the label inside the option. */
|
|
39
|
+
styles: Object as PropType<{ mark?: string; label?: string }>,
|
|
40
|
+
} satisfies ComponentObjectPropsOptions
|
|
41
|
+
|
|
42
|
+
export type SliderMarksOptionProps = ExtractPublicPropTypes<
|
|
43
|
+
typeof sliderMarksOptionProps
|
|
44
|
+
>
|
|
45
|
+
|
|
9
46
|
/** One mark along the slider, and its label. */
|
|
10
47
|
export const SliderMarksOption = /* @__PURE__ */ defineComponent({
|
|
11
48
|
name: 'SliderMarksOption',
|
|
12
|
-
props:
|
|
13
|
-
/** Where the mark sits, on the same scale as the thumb. */
|
|
14
|
-
value: { type: Number, required: true },
|
|
15
|
-
/** Draw the mark itself. @default true */
|
|
16
|
-
mark: { type: Boolean, default: true },
|
|
17
|
-
/**
|
|
18
|
-
* Text shown next to the mark. Leave it out to show the value; `null`
|
|
19
|
-
* leaves the label out.
|
|
20
|
-
*/
|
|
21
|
-
label: {
|
|
22
|
-
type: [Number, String, null] as PropType<number | string | null>,
|
|
23
|
-
default: undefined,
|
|
24
|
-
},
|
|
25
|
-
/** Thickness of the mark. Sets `--thickness`. */
|
|
26
|
-
thickness: [Number, String],
|
|
27
|
-
/** Length of the mark. Sets `--length`. */
|
|
28
|
-
length: [Number, String],
|
|
29
|
-
/** Space between the mark and the label. Sets `--gap`. */
|
|
30
|
-
gap: [Number, String],
|
|
31
|
-
/** Classes for the mark and the label inside the option. */
|
|
32
|
-
classes: Object as PropType<{ mark?: string; label?: string }>,
|
|
33
|
-
/** Styles for the mark and the label inside the option. */
|
|
34
|
-
styles: Object as PropType<{ mark?: string; label?: string }>,
|
|
35
|
-
},
|
|
49
|
+
props: sliderMarksOptionProps,
|
|
36
50
|
setup(props) {
|
|
37
51
|
const slider = useSliderContext()
|
|
38
52
|
checkPlacement('SliderMarksOption', 'SliderMarks')
|
|
@@ -41,11 +55,11 @@ export const SliderMarksOption = /* @__PURE__ */ defineComponent({
|
|
|
41
55
|
valuePercent(
|
|
42
56
|
props.value,
|
|
43
57
|
{ min: slider.min, max: slider.max, scale: slider.scale },
|
|
44
|
-
slider.vertical !== slider.reverse,
|
|
58
|
+
(slider.orientation === 'vertical') !== slider.reverse,
|
|
45
59
|
),
|
|
46
60
|
)
|
|
47
61
|
return () => {
|
|
48
|
-
const orientation = slider.
|
|
62
|
+
const orientation = slider.orientation
|
|
49
63
|
return h(
|
|
50
64
|
'div',
|
|
51
65
|
{
|
|
@@ -55,12 +69,19 @@ export const SliderMarksOption = /* @__PURE__ */ defineComponent({
|
|
|
55
69
|
'--length': cssLength(props.length),
|
|
56
70
|
'--gap': cssLength(props.gap),
|
|
57
71
|
position: 'absolute',
|
|
58
|
-
translate:
|
|
59
|
-
|
|
60
|
-
|
|
72
|
+
translate:
|
|
73
|
+
slider.orientation === 'vertical'
|
|
74
|
+
? 'var(--translate, 0 -50%)'
|
|
75
|
+
: 'var(--translate, -50% 0)',
|
|
61
76
|
zIndex: 10,
|
|
62
|
-
left:
|
|
63
|
-
|
|
77
|
+
left:
|
|
78
|
+
slider.orientation === 'vertical'
|
|
79
|
+
? undefined
|
|
80
|
+
: `${percent.value}%`,
|
|
81
|
+
top:
|
|
82
|
+
slider.orientation === 'vertical'
|
|
83
|
+
? `${percent.value}%`
|
|
84
|
+
: undefined,
|
|
64
85
|
},
|
|
65
86
|
},
|
|
66
87
|
[
|