@tremolo-ui/react 0.0.9 → 0.0.11
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/cjs/index.js +434 -271
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/AnimationCanvas/index.d.ts +9 -4
- package/dist/cjs/types/components/AnimationCanvas/index.d.ts.map +1 -1
- package/dist/cjs/types/components/AnimationKnob/index.d.ts +2 -0
- package/dist/cjs/types/components/AnimationKnob/index.d.ts.map +1 -1
- package/dist/cjs/types/components/DragObserver/index.d.ts +3 -1
- package/dist/cjs/types/components/DragObserver/index.d.ts.map +1 -1
- package/dist/cjs/types/components/Knob/index.d.ts +2 -0
- package/dist/cjs/types/components/Knob/index.d.ts.map +1 -1
- package/dist/cjs/types/components/NumberInput/DecrementStepper.d.ts +7 -0
- package/dist/cjs/types/components/NumberInput/DecrementStepper.d.ts.map +1 -0
- package/dist/cjs/types/components/NumberInput/IncrementStepper.d.ts +7 -0
- package/dist/cjs/types/components/NumberInput/IncrementStepper.d.ts.map +1 -0
- package/dist/cjs/types/components/NumberInput/Stepper.d.ts +8 -0
- package/dist/cjs/types/components/NumberInput/Stepper.d.ts.map +1 -0
- package/dist/cjs/types/components/NumberInput/context.d.ts +27 -0
- package/dist/cjs/types/components/NumberInput/context.d.ts.map +1 -0
- package/dist/cjs/types/components/NumberInput/index.d.ts +31 -16
- package/dist/cjs/types/components/NumberInput/index.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/BlackKey.d.ts +1 -0
- package/dist/cjs/types/components/Piano/BlackKey.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/KeyLabel.d.ts +2 -0
- package/dist/cjs/types/components/Piano/KeyLabel.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/WhiteKey.d.ts +2 -0
- package/dist/cjs/types/components/Piano/WhiteKey.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/index.d.ts +6 -4
- package/dist/cjs/types/components/Piano/index.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/key.d.ts +8 -2
- package/dist/cjs/types/components/Piano/key.d.ts.map +1 -1
- package/dist/cjs/types/components/Piano/keyboardShortcuts.d.ts +2 -0
- package/dist/cjs/types/components/Piano/keyboardShortcuts.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/Scale.d.ts +2 -0
- package/dist/cjs/types/components/Slider/Scale.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/ScaleOption.d.ts +2 -0
- package/dist/cjs/types/components/Slider/ScaleOption.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/Thumb.d.ts +4 -0
- package/dist/cjs/types/components/Slider/Thumb.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/Track.d.ts +4 -1
- package/dist/cjs/types/components/Slider/Track.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/context.d.ts +7 -12
- package/dist/cjs/types/components/Slider/context.d.ts.map +1 -1
- package/dist/cjs/types/components/Slider/index.d.ts +8 -5
- package/dist/cjs/types/components/Slider/index.d.ts.map +1 -1
- package/dist/cjs/types/components/WheelObserver/index.d.ts +1 -0
- package/dist/cjs/types/components/WheelObserver/index.d.ts.map +1 -1
- package/dist/cjs/types/components/XYPad/Area.d.ts +2 -0
- package/dist/cjs/types/components/XYPad/Area.d.ts.map +1 -1
- package/dist/cjs/types/components/XYPad/Thumb.d.ts +3 -0
- package/dist/cjs/types/components/XYPad/Thumb.d.ts.map +1 -1
- package/dist/cjs/types/components/XYPad/index.d.ts +4 -0
- package/dist/cjs/types/components/XYPad/index.d.ts.map +1 -1
- package/dist/cjs/types/hooks/useAnimationFrame.d.ts +3 -0
- package/dist/cjs/types/hooks/useAnimationFrame.d.ts.map +1 -0
- package/dist/cjs/types/hooks/useDrag.d.ts +15 -0
- package/dist/cjs/types/hooks/useDrag.d.ts.map +1 -0
- package/dist/cjs/types/hooks/useRefCallbackEvent.d.ts +1 -4
- package/dist/cjs/types/hooks/useRefCallbackEvent.d.ts.map +1 -1
- package/dist/esm/index.js +432 -262
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/AnimationCanvas/index.d.ts +9 -4
- package/dist/esm/types/components/AnimationCanvas/index.d.ts.map +1 -1
- package/dist/esm/types/components/AnimationKnob/index.d.ts +2 -0
- package/dist/esm/types/components/AnimationKnob/index.d.ts.map +1 -1
- package/dist/esm/types/components/DragObserver/index.d.ts +3 -1
- package/dist/esm/types/components/DragObserver/index.d.ts.map +1 -1
- package/dist/esm/types/components/Knob/index.d.ts +2 -0
- package/dist/esm/types/components/Knob/index.d.ts.map +1 -1
- package/dist/esm/types/components/NumberInput/DecrementStepper.d.ts +7 -0
- package/dist/esm/types/components/NumberInput/DecrementStepper.d.ts.map +1 -0
- package/dist/esm/types/components/NumberInput/IncrementStepper.d.ts +7 -0
- package/dist/esm/types/components/NumberInput/IncrementStepper.d.ts.map +1 -0
- package/dist/esm/types/components/NumberInput/Stepper.d.ts +8 -0
- package/dist/esm/types/components/NumberInput/Stepper.d.ts.map +1 -0
- package/dist/esm/types/components/NumberInput/context.d.ts +27 -0
- package/dist/esm/types/components/NumberInput/context.d.ts.map +1 -0
- package/dist/esm/types/components/NumberInput/index.d.ts +31 -16
- package/dist/esm/types/components/NumberInput/index.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/BlackKey.d.ts +1 -0
- package/dist/esm/types/components/Piano/BlackKey.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/KeyLabel.d.ts +2 -0
- package/dist/esm/types/components/Piano/KeyLabel.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/WhiteKey.d.ts +2 -0
- package/dist/esm/types/components/Piano/WhiteKey.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/index.d.ts +6 -4
- package/dist/esm/types/components/Piano/index.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/key.d.ts +8 -2
- package/dist/esm/types/components/Piano/key.d.ts.map +1 -1
- package/dist/esm/types/components/Piano/keyboardShortcuts.d.ts +2 -0
- package/dist/esm/types/components/Piano/keyboardShortcuts.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/Scale.d.ts +2 -0
- package/dist/esm/types/components/Slider/Scale.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/ScaleOption.d.ts +2 -0
- package/dist/esm/types/components/Slider/ScaleOption.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/Thumb.d.ts +4 -0
- package/dist/esm/types/components/Slider/Thumb.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/Track.d.ts +4 -1
- package/dist/esm/types/components/Slider/Track.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/context.d.ts +7 -12
- package/dist/esm/types/components/Slider/context.d.ts.map +1 -1
- package/dist/esm/types/components/Slider/index.d.ts +8 -5
- package/dist/esm/types/components/Slider/index.d.ts.map +1 -1
- package/dist/esm/types/components/WheelObserver/index.d.ts +1 -0
- package/dist/esm/types/components/WheelObserver/index.d.ts.map +1 -1
- package/dist/esm/types/components/XYPad/Area.d.ts +2 -0
- package/dist/esm/types/components/XYPad/Area.d.ts.map +1 -1
- package/dist/esm/types/components/XYPad/Thumb.d.ts +3 -0
- package/dist/esm/types/components/XYPad/Thumb.d.ts.map +1 -1
- package/dist/esm/types/components/XYPad/index.d.ts +4 -0
- package/dist/esm/types/components/XYPad/index.d.ts.map +1 -1
- package/dist/esm/types/hooks/useAnimationFrame.d.ts +3 -0
- package/dist/esm/types/hooks/useAnimationFrame.d.ts.map +1 -0
- package/dist/esm/types/hooks/useDrag.d.ts +15 -0
- package/dist/esm/types/hooks/useDrag.d.ts.map +1 -0
- package/dist/esm/types/hooks/useRefCallbackEvent.d.ts +1 -4
- package/dist/esm/types/hooks/useRefCallbackEvent.d.ts.map +1 -1
- package/dist/styles/index.css +110 -14
- package/package.json +41 -37
- package/src/components/AnimationCanvas/index.tsx +14 -5
- package/src/components/AnimationKnob/index.tsx +24 -42
- package/src/components/DragObserver/index.tsx +14 -52
- package/src/components/Knob/index.tsx +23 -40
- package/src/components/NumberInput/DecrementStepper.tsx +52 -0
- package/src/components/NumberInput/IncrementStepper.tsx +52 -0
- package/src/components/NumberInput/Stepper.tsx +25 -0
- package/src/components/NumberInput/context.tsx +150 -0
- package/src/components/NumberInput/index.css +102 -14
- package/src/components/NumberInput/index.tsx +164 -55
- package/src/components/Piano/BlackKey.tsx +13 -10
- package/src/components/Piano/KeyLabel.tsx +2 -0
- package/src/components/Piano/WhiteKey.tsx +14 -10
- package/src/components/Piano/index.tsx +14 -12
- package/src/components/Piano/key.ts +8 -2
- package/src/components/Piano/keyboardShortcuts.ts +2 -0
- package/src/components/Slider/Scale.tsx +8 -6
- package/src/components/Slider/ScaleOption.tsx +8 -6
- package/src/components/Slider/Thumb.tsx +9 -3
- package/src/components/Slider/Track.tsx +25 -15
- package/src/components/Slider/context.tsx +50 -51
- package/src/components/Slider/index.css +8 -0
- package/src/components/Slider/index.tsx +20 -10
- package/src/components/WheelObserver/index.tsx +1 -0
- package/src/components/XYPad/Area.tsx +2 -0
- package/src/components/XYPad/Thumb.tsx +3 -0
- package/src/components/XYPad/index.tsx +6 -2
- package/src/hooks/useAnimationFrame.ts +18 -0
- package/src/hooks/useDrag.ts +92 -0
- package/src/hooks/useRefCallbackEvent.ts +4 -7
|
@@ -7,8 +7,9 @@ import {
|
|
|
7
7
|
useRef,
|
|
8
8
|
} from 'react'
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { useSliderContext } from './context'
|
|
11
11
|
|
|
12
|
+
/** @category Slider */
|
|
12
13
|
export interface SliderThumbProps {
|
|
13
14
|
size?: number | string
|
|
14
15
|
width?: number | string
|
|
@@ -22,13 +23,16 @@ export interface SliderThumbProps {
|
|
|
22
23
|
__percent?: number
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
/** @category Slider */
|
|
25
27
|
export interface SliderThumbMethods {
|
|
26
28
|
focus: () => void
|
|
27
29
|
blur: () => void
|
|
28
30
|
}
|
|
29
31
|
|
|
32
|
+
/** @category Slider */
|
|
30
33
|
export const defaultThumbSize = 22
|
|
31
34
|
|
|
35
|
+
/** @category Slider */
|
|
32
36
|
export const SliderThumb = forwardRef<SliderThumbMethods, SliderThumbProps>(
|
|
33
37
|
(
|
|
34
38
|
{
|
|
@@ -43,8 +47,9 @@ export const SliderThumb = forwardRef<SliderThumbMethods, SliderThumbProps>(
|
|
|
43
47
|
ref,
|
|
44
48
|
) => {
|
|
45
49
|
const wrapperRef = useRef<HTMLDivElement>(null)
|
|
46
|
-
const vertical =
|
|
47
|
-
const disabled =
|
|
50
|
+
const vertical = useSliderContext((s) => s.vertical)
|
|
51
|
+
const disabled = useSliderContext((s) => s.disabled)
|
|
52
|
+
const readonly = useSliderContext((s) => s.readonly)
|
|
48
53
|
|
|
49
54
|
useImperativeHandle(ref, () => {
|
|
50
55
|
return {
|
|
@@ -75,6 +80,7 @@ export const SliderThumb = forwardRef<SliderThumbMethods, SliderThumbProps>(
|
|
|
75
80
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
|
76
81
|
tabIndex={0}
|
|
77
82
|
aria-disabled={disabled}
|
|
83
|
+
aria-readonly={readonly}
|
|
78
84
|
style={{
|
|
79
85
|
width: size ?? width,
|
|
80
86
|
height: size ?? height,
|
|
@@ -3,11 +3,12 @@ import { CSSProperties, ReactElement } from 'react'
|
|
|
3
3
|
|
|
4
4
|
import { styleHelper, xor } from '@tremolo-ui/functions'
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { useSliderContext } from './context'
|
|
7
7
|
|
|
8
8
|
export const defaultLength = 140
|
|
9
9
|
export const defaultThickness = 10
|
|
10
10
|
|
|
11
|
+
/** @category Slider */
|
|
11
12
|
export interface SliderTrackProps {
|
|
12
13
|
length?: number | string
|
|
13
14
|
thickness?: number | string
|
|
@@ -15,6 +16,8 @@ export interface SliderTrackProps {
|
|
|
15
16
|
active?: string
|
|
16
17
|
inactive?: string
|
|
17
18
|
|
|
19
|
+
defaultStyle?: boolean
|
|
20
|
+
|
|
18
21
|
className?: string
|
|
19
22
|
style?: CSSProperties
|
|
20
23
|
children?: ReactElement
|
|
@@ -25,6 +28,7 @@ export interface SliderTrackProps {
|
|
|
25
28
|
__percent?: number
|
|
26
29
|
}
|
|
27
30
|
|
|
31
|
+
/** @category Slider */
|
|
28
32
|
export function SliderTrack({
|
|
29
33
|
length = defaultLength,
|
|
30
34
|
thickness = defaultThickness,
|
|
@@ -33,12 +37,13 @@ export function SliderTrack({
|
|
|
33
37
|
children,
|
|
34
38
|
className,
|
|
35
39
|
style,
|
|
40
|
+
defaultStyle = true,
|
|
36
41
|
__thumb,
|
|
37
|
-
__percent,
|
|
42
|
+
__percent = 0,
|
|
38
43
|
}: SliderTrackProps) {
|
|
39
|
-
const vertical =
|
|
40
|
-
const reverse =
|
|
41
|
-
const disabled =
|
|
44
|
+
const vertical = useSliderContext((s) => s.vertical)
|
|
45
|
+
const reverse = useSliderContext((s) => s.reverse)
|
|
46
|
+
const disabled = useSliderContext((s) => s.disabled)
|
|
42
47
|
|
|
43
48
|
const direction = vertical ? 'bottom' : 'right'
|
|
44
49
|
const colors = {
|
|
@@ -50,16 +55,21 @@ export function SliderTrack({
|
|
|
50
55
|
<div
|
|
51
56
|
className={clsx('tremolo-slider-track', className)}
|
|
52
57
|
aria-disabled={disabled}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
?
|
|
57
|
-
:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
data-vertical={vertical}
|
|
59
|
+
style={
|
|
60
|
+
!defaultStyle
|
|
61
|
+
? style
|
|
62
|
+
: {
|
|
63
|
+
...colors,
|
|
64
|
+
background: xor(vertical, reverse)
|
|
65
|
+
? `linear-gradient(to ${direction}, var(--inactive, #eee) ${__percent}%, var(--active, #7998ec) ${__percent}%)`
|
|
66
|
+
: `linear-gradient(to ${direction}, var(--active, #7998ec) ${__percent}%, var(--inactive, #eee) ${__percent}%)`,
|
|
67
|
+
borderRadius: styleHelper(thickness!, '/', 2),
|
|
68
|
+
width: !vertical ? length : thickness,
|
|
69
|
+
height: vertical ? length : thickness,
|
|
70
|
+
...style,
|
|
71
|
+
}
|
|
72
|
+
}
|
|
63
73
|
>
|
|
64
74
|
{children}
|
|
65
75
|
{__thumb}
|
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
import { createContext,
|
|
1
|
+
import { createContext, useContext, useEffect, useRef } from 'react'
|
|
2
|
+
import { createStore, useStore } from 'zustand'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const maxContext = createContext(0)
|
|
5
|
-
const stepContext = createContext(0)
|
|
6
|
-
const skewContext = createContext(0)
|
|
7
|
-
const verticalContext = createContext(false)
|
|
8
|
-
const reverseContext = createContext(false)
|
|
9
|
-
const disabledContext = createContext(false)
|
|
10
|
-
|
|
11
|
-
interface Props {
|
|
4
|
+
type State = {
|
|
12
5
|
min: number
|
|
13
6
|
max: number
|
|
14
7
|
step: number
|
|
@@ -16,51 +9,57 @@ interface Props {
|
|
|
16
9
|
vertical: boolean
|
|
17
10
|
reverse: boolean
|
|
18
11
|
disabled: boolean
|
|
19
|
-
|
|
12
|
+
readonly: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type SliderStore = ReturnType<typeof createSliderStore>
|
|
16
|
+
|
|
17
|
+
const createSliderStore = (initProps?: Partial<State>) => {
|
|
18
|
+
const DEFAULT_PROPS: State = {
|
|
19
|
+
min: 0,
|
|
20
|
+
max: 0,
|
|
21
|
+
step: 0,
|
|
22
|
+
skew: 0,
|
|
23
|
+
vertical: false,
|
|
24
|
+
reverse: false,
|
|
25
|
+
disabled: false,
|
|
26
|
+
readonly: false,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return createStore<State>()(() => ({
|
|
30
|
+
...DEFAULT_PROPS,
|
|
31
|
+
...initProps,
|
|
32
|
+
}))
|
|
20
33
|
}
|
|
21
34
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
const SliderContext = createContext<SliderStore | null>(null)
|
|
36
|
+
|
|
37
|
+
type SliderProviderProps = React.PropsWithChildren<Partial<State>>
|
|
38
|
+
|
|
39
|
+
export function SliderProvider({ children, ...props }: SliderProviderProps) {
|
|
40
|
+
const storeRef = useRef<SliderStore>(null)
|
|
41
|
+
if (!storeRef.current) {
|
|
42
|
+
storeRef.current = createSliderStore(props)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (storeRef.current) {
|
|
47
|
+
storeRef.current.setState(props)
|
|
48
|
+
} else {
|
|
49
|
+
storeRef.current = createSliderStore(props)
|
|
50
|
+
}
|
|
51
|
+
}, [props])
|
|
39
52
|
|
|
40
53
|
return (
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<skewContext.Provider value={skew}>
|
|
45
|
-
<verticalContext.Provider value={vertical}>
|
|
46
|
-
<reverseContext.Provider value={reverse}>
|
|
47
|
-
<disabledContext.Provider value={disabled}>
|
|
48
|
-
{children}
|
|
49
|
-
</disabledContext.Provider>
|
|
50
|
-
</reverseContext.Provider>
|
|
51
|
-
</verticalContext.Provider>
|
|
52
|
-
</skewContext.Provider>
|
|
53
|
-
</stepContext.Provider>
|
|
54
|
-
</maxContext.Provider>
|
|
55
|
-
</minContext.Provider>
|
|
54
|
+
<SliderContext.Provider value={storeRef.current}>
|
|
55
|
+
{children}
|
|
56
|
+
</SliderContext.Provider>
|
|
56
57
|
)
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
export
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
export const useReverse = () => useContext(reverseContext)
|
|
66
|
-
export const useDisabled = () => useContext(disabledContext)
|
|
60
|
+
/** @category Slider */
|
|
61
|
+
export function useSliderContext<T>(selector: (state: State) => T): T {
|
|
62
|
+
const store = useContext(SliderContext)
|
|
63
|
+
if (!store) throw new Error('Missing SliderContext.Provider in the tree')
|
|
64
|
+
return useStore(store, selector)
|
|
65
|
+
}
|
|
@@ -25,11 +25,12 @@ import { useEventListener } from '../../hooks/useEventListener'
|
|
|
25
25
|
import { useRefCallbackEvent } from '../../hooks/useRefCallbackEvent'
|
|
26
26
|
import { addNoSelect, removeNoSelect } from '../_util'
|
|
27
27
|
|
|
28
|
-
import {
|
|
28
|
+
import { SliderProvider } from './context'
|
|
29
29
|
import { Scale } from './Scale'
|
|
30
30
|
import { SliderThumb, SliderThumbMethods, SliderThumbProps } from './Thumb'
|
|
31
31
|
import { SliderTrack, SliderTrackProps } from './Track'
|
|
32
32
|
|
|
33
|
+
/** @category Slider */
|
|
33
34
|
export interface SliderProps {
|
|
34
35
|
// required
|
|
35
36
|
value: number
|
|
@@ -67,6 +68,7 @@ export interface SliderProps {
|
|
|
67
68
|
// ReactElement<typeof SliderThumb, typeof SliderTrack>[]
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
/** @category Slider */
|
|
70
72
|
export interface SliderMethods {
|
|
71
73
|
focus: () => void
|
|
72
74
|
blur: () => void
|
|
@@ -77,6 +79,7 @@ type Props = SliderProps &
|
|
|
77
79
|
|
|
78
80
|
/**
|
|
79
81
|
* Customizable slider
|
|
82
|
+
* @category Slider
|
|
80
83
|
*/
|
|
81
84
|
export const Slider = forwardRef<SliderMethods, Props>(
|
|
82
85
|
(
|
|
@@ -229,11 +232,11 @@ export const Slider = forwardRef<SliderMethods, Props>(
|
|
|
229
232
|
[wheel, value, min, max, skew, step],
|
|
230
233
|
)
|
|
231
234
|
|
|
232
|
-
useEventListener(window, 'mousemove', (event) => {
|
|
235
|
+
useEventListener(globalThis.window, 'mousemove', (event) => {
|
|
233
236
|
handleValue(event)
|
|
234
237
|
})
|
|
235
238
|
|
|
236
|
-
useEventListener(window, 'mouseup', () => {
|
|
239
|
+
useEventListener(globalThis.window, 'mouseup', () => {
|
|
237
240
|
thumbDragged.current = false
|
|
238
241
|
if (bodyNoSelect) removeNoSelect()
|
|
239
242
|
})
|
|
@@ -250,7 +253,7 @@ export const Slider = forwardRef<SliderMethods, Props>(
|
|
|
250
253
|
}, [])
|
|
251
254
|
|
|
252
255
|
return (
|
|
253
|
-
<
|
|
256
|
+
<SliderProvider
|
|
254
257
|
min={min}
|
|
255
258
|
max={max}
|
|
256
259
|
step={step}
|
|
@@ -258,6 +261,7 @@ export const Slider = forwardRef<SliderMethods, Props>(
|
|
|
258
261
|
vertical={vertical}
|
|
259
262
|
reverse={reverse}
|
|
260
263
|
disabled={disabled}
|
|
264
|
+
readonly={readonly}
|
|
261
265
|
>
|
|
262
266
|
<div
|
|
263
267
|
className={clsx('tremolo-slider', className)}
|
|
@@ -290,6 +294,8 @@ export const Slider = forwardRef<SliderMethods, Props>(
|
|
|
290
294
|
style={{
|
|
291
295
|
display: 'flex',
|
|
292
296
|
flexDirection: vertical ? 'row' : 'column',
|
|
297
|
+
width: !vertical ? '100%' : undefined,
|
|
298
|
+
height: vertical ? '100%' : undefined,
|
|
293
299
|
}}
|
|
294
300
|
>
|
|
295
301
|
<div className="tremolo-slider-track-wrapper" ref={trackElementRef}>
|
|
@@ -308,13 +314,17 @@ export const Slider = forwardRef<SliderMethods, Props>(
|
|
|
308
314
|
{scaleComponent}
|
|
309
315
|
</div>
|
|
310
316
|
</div>
|
|
311
|
-
</
|
|
317
|
+
</SliderProvider>
|
|
312
318
|
)
|
|
313
319
|
},
|
|
314
320
|
)
|
|
315
321
|
|
|
316
|
-
export
|
|
317
|
-
export
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
322
|
+
export { useSliderContext } from './context'
|
|
323
|
+
export {
|
|
324
|
+
SliderThumb,
|
|
325
|
+
type SliderThumbMethods,
|
|
326
|
+
type SliderThumbProps,
|
|
327
|
+
} from './Thumb'
|
|
328
|
+
export { SliderTrack, type SliderTrackProps } from './Track'
|
|
329
|
+
export { Scale, type ScaleProps } from './Scale'
|
|
330
|
+
export { ScaleOption, type ScaleOptionProps } from './ScaleOption'
|
|
@@ -25,6 +25,7 @@ interface Props<T extends ElementType> {
|
|
|
25
25
|
onWheel?: (event: WheelEvent) => void
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/** @category WheelObserver */
|
|
28
29
|
export function WheelObserver<T extends ElementType = 'div'>(
|
|
29
30
|
props: Props<T> & Omit<ComponentPropsWithoutRef<T>, keyof Props<T>>,
|
|
30
31
|
) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import clsx from 'clsx'
|
|
2
2
|
import { CSSProperties, ReactElement } from 'react'
|
|
3
3
|
|
|
4
|
+
/** @category XYPad */
|
|
4
5
|
export interface AreaProps {
|
|
5
6
|
width?: number | string
|
|
6
7
|
height?: number | string
|
|
@@ -13,6 +14,7 @@ export interface AreaProps {
|
|
|
13
14
|
__thumb?: ReactElement
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
/** @category XYPad */
|
|
16
18
|
export function XYPadArea({
|
|
17
19
|
width = 120,
|
|
18
20
|
height = 120,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
useRef,
|
|
9
9
|
} from 'react'
|
|
10
10
|
|
|
11
|
+
/** @category XYPad */
|
|
11
12
|
export interface ThumbProps {
|
|
12
13
|
size?: number | string
|
|
13
14
|
width?: number | string
|
|
@@ -24,6 +25,7 @@ export interface ThumbProps {
|
|
|
24
25
|
__css?: CSSProperties
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
/** @category XYPad */
|
|
27
29
|
export interface XYPadThumbMethods {
|
|
28
30
|
focus: () => void
|
|
29
31
|
blur: () => void
|
|
@@ -32,6 +34,7 @@ export interface XYPadThumbMethods {
|
|
|
32
34
|
type Props = ThumbProps &
|
|
33
35
|
Omit<ComponentPropsWithoutRef<'div'>, keyof ThumbProps>
|
|
34
36
|
|
|
37
|
+
/** @category XYPad */
|
|
35
38
|
export const XYPadThumb = forwardRef<XYPadThumbMethods, Props>(
|
|
36
39
|
(
|
|
37
40
|
{
|
|
@@ -26,6 +26,7 @@ import { addNoSelect, removeNoSelect } from '../_util'
|
|
|
26
26
|
import { XYPadArea, AreaProps } from './Area'
|
|
27
27
|
import { XYPadThumb, XYPadThumbMethods, ThumbProps } from './Thumb'
|
|
28
28
|
|
|
29
|
+
/** @category XYPad */
|
|
29
30
|
export interface ValueOptions {
|
|
30
31
|
// required
|
|
31
32
|
value: number
|
|
@@ -46,6 +47,7 @@ export interface ValueOptions {
|
|
|
46
47
|
keyboard?: InputEventOption | null
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
/** @category XYPad */
|
|
49
51
|
export interface XYPadProps {
|
|
50
52
|
x: ValueOptions
|
|
51
53
|
y: ValueOptions
|
|
@@ -58,6 +60,7 @@ export interface XYPadProps {
|
|
|
58
60
|
children?: ReactElement | ReactElement[]
|
|
59
61
|
}
|
|
60
62
|
|
|
63
|
+
/** @category XYPad */
|
|
61
64
|
export interface XYPadMethods {
|
|
62
65
|
focus: () => void
|
|
63
66
|
blur: () => void
|
|
@@ -76,6 +79,7 @@ type Props = XYPadProps &
|
|
|
76
79
|
|
|
77
80
|
/**
|
|
78
81
|
* Simple XYPad
|
|
82
|
+
* @category XYPad
|
|
79
83
|
*/
|
|
80
84
|
export const XYPad = forwardRef<XYPadMethods, Props>(
|
|
81
85
|
(
|
|
@@ -246,11 +250,11 @@ export const XYPad = forwardRef<XYPadMethods, Props>(
|
|
|
246
250
|
[x, y],
|
|
247
251
|
)
|
|
248
252
|
|
|
249
|
-
useEventListener(window, 'mousemove', (event) => {
|
|
253
|
+
useEventListener(globalThis.window, 'mousemove', (event) => {
|
|
250
254
|
handleValue(event)
|
|
251
255
|
})
|
|
252
256
|
|
|
253
|
-
useEventListener(window, 'mouseup', () => {
|
|
257
|
+
useEventListener(globalThis.window, 'mouseup', () => {
|
|
254
258
|
thumbDragged.current = false
|
|
255
259
|
if (bodyNoSelect) removeNoSelect()
|
|
256
260
|
})
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { DependencyList, useCallback, useEffect, useRef } from 'react'
|
|
2
|
+
|
|
3
|
+
export const useAnimationFrame = (
|
|
4
|
+
callback = () => {},
|
|
5
|
+
deps: DependencyList = [],
|
|
6
|
+
) => {
|
|
7
|
+
const reqIdRef = useRef(-1)
|
|
8
|
+
const loop = useCallback(() => {
|
|
9
|
+
reqIdRef.current = requestAnimationFrame(loop)
|
|
10
|
+
callback()
|
|
11
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
12
|
+
}, [callback, ...deps])
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
reqIdRef.current = requestAnimationFrame(loop)
|
|
16
|
+
return () => cancelAnimationFrame(reqIdRef.current)
|
|
17
|
+
}, [loop])
|
|
18
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { useRef, useCallback } from 'react'
|
|
2
|
+
|
|
3
|
+
import { useEventListener } from './useEventListener'
|
|
4
|
+
import { useRefCallbackEvent } from './useRefCallbackEvent'
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
threshold?: number
|
|
8
|
+
|
|
9
|
+
onDrag: (x: number, y: number, deltaX: number, deltaY: number) => void
|
|
10
|
+
onDragStart?: () => void
|
|
11
|
+
onDragEnd?: () => void
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @returns [refCallback, pointerDownHandler]
|
|
16
|
+
*/
|
|
17
|
+
export function useDrag<T extends Element>({
|
|
18
|
+
threshold = 1,
|
|
19
|
+
onDrag,
|
|
20
|
+
onDragStart,
|
|
21
|
+
onDragEnd,
|
|
22
|
+
}: Props): [
|
|
23
|
+
(div: EventTarget | null) => void,
|
|
24
|
+
(event: React.PointerEvent<T>) => void,
|
|
25
|
+
] {
|
|
26
|
+
const dragOffsetX = useRef<number | undefined>(undefined)
|
|
27
|
+
const dragOffsetY = useRef<number | undefined>(undefined)
|
|
28
|
+
const dragStartX = useRef(0)
|
|
29
|
+
const dragStartY = useRef(0)
|
|
30
|
+
|
|
31
|
+
const handleDrag = useCallback(
|
|
32
|
+
(
|
|
33
|
+
event: MouseEvent | React.MouseEvent<T, MouseEvent> | TouchEvent,
|
|
34
|
+
first = false,
|
|
35
|
+
) => {
|
|
36
|
+
const isTouch = event instanceof TouchEvent
|
|
37
|
+
if (isTouch && event.cancelable) event.preventDefault()
|
|
38
|
+
const screenX = isTouch ? event.touches[0].screenX : event.screenX
|
|
39
|
+
const screenY = isTouch ? event.touches[0].screenY : event.screenY
|
|
40
|
+
let deltaX = 0
|
|
41
|
+
let deltaY = 0
|
|
42
|
+
if (first) {
|
|
43
|
+
dragStartX.current = screenX
|
|
44
|
+
dragStartY.current = screenY
|
|
45
|
+
}
|
|
46
|
+
if (dragOffsetX.current) {
|
|
47
|
+
deltaX = screenX - dragOffsetX.current
|
|
48
|
+
dragOffsetX.current = screenX
|
|
49
|
+
}
|
|
50
|
+
if (dragOffsetY.current) {
|
|
51
|
+
deltaY = screenY - dragOffsetY.current
|
|
52
|
+
dragOffsetY.current = screenY
|
|
53
|
+
}
|
|
54
|
+
if (Math.abs(deltaX) < threshold && Math.abs(deltaY) < threshold) return
|
|
55
|
+
if (onDrag)
|
|
56
|
+
onDrag(
|
|
57
|
+
screenX - dragStartX.current,
|
|
58
|
+
screenY - dragStartY.current,
|
|
59
|
+
deltaX,
|
|
60
|
+
deltaY,
|
|
61
|
+
)
|
|
62
|
+
},
|
|
63
|
+
[threshold, onDrag],
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
const refHandler = useRefCallbackEvent(
|
|
67
|
+
'touchmove',
|
|
68
|
+
handleDrag,
|
|
69
|
+
{ passive: false },
|
|
70
|
+
[onDrag],
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
const pointerDownHandler = useCallback(
|
|
74
|
+
(event: React.PointerEvent<T>) => {
|
|
75
|
+
dragOffsetX.current = event.screenX
|
|
76
|
+
dragOffsetY.current = event.screenY
|
|
77
|
+
handleDrag(event, true)
|
|
78
|
+
onDragStart?.()
|
|
79
|
+
},
|
|
80
|
+
[handleDrag, onDragStart],
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
useEventListener(globalThis.window, 'mousemove', handleDrag)
|
|
84
|
+
|
|
85
|
+
useEventListener(globalThis.window, 'pointerup', () => {
|
|
86
|
+
dragOffsetX.current = undefined
|
|
87
|
+
dragOffsetY.current = undefined
|
|
88
|
+
onDragEnd?.()
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
return [refHandler, pointerDownHandler]
|
|
92
|
+
}
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
import { useMemo } from 'react'
|
|
2
2
|
|
|
3
|
-
type Options = boolean | AddEventListenerOptions
|
|
4
|
-
type CallbackFunc = (div: EventTarget | null) => void
|
|
5
|
-
|
|
6
3
|
export function useRefCallbackEvent<K extends keyof DocumentEventMap>(
|
|
7
4
|
event: K,
|
|
8
5
|
handler: (event: DocumentEventMap[K]) => void,
|
|
9
|
-
options?:
|
|
6
|
+
options?: boolean | AddEventListenerOptions,
|
|
10
7
|
deps?: React.DependencyList,
|
|
11
|
-
):
|
|
8
|
+
): (div: EventTarget | null) => void
|
|
12
9
|
export function useRefCallbackEvent(
|
|
13
10
|
event: string,
|
|
14
11
|
handler: (event: Event) => void,
|
|
15
|
-
options?:
|
|
12
|
+
options?: boolean | AddEventListenerOptions,
|
|
16
13
|
deps: React.DependencyList = [],
|
|
17
|
-
):
|
|
14
|
+
): (div: EventTarget | null) => void {
|
|
18
15
|
return useMemo(() => {
|
|
19
16
|
let cleanup: (() => void) | undefined
|
|
20
17
|
return (node: EventTarget | null) => {
|