@tremolo-ui/react 0.6.0 → 0.7.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 +252 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +550 -133
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +550 -133
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +218 -39
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/components/DropZone/index.tsx +100 -0
- package/src/components/FileInput/Trigger.tsx +39 -0
- package/src/components/FileInput/context.tsx +24 -0
- package/src/components/FileInput/index.tsx +144 -0
- package/src/components/Knob/index.tsx +8 -5
- package/src/components/NumberInput/DecrementStepper.tsx +2 -13
- package/src/components/NumberInput/IncrementStepper.tsx +2 -14
- package/src/components/NumberInput/InputField.tsx +5 -11
- package/src/components/NumberInput/Stepper.tsx +4 -19
- package/src/components/NumberInput/StepperButton.tsx +13 -8
- package/src/components/NumberInput/context.tsx +6 -7
- package/src/components/NumberInput/index.tsx +4 -13
- package/src/components/Piano/index.tsx +10 -13
- package/src/components/PointsEditor/Background.tsx +2 -8
- package/src/components/PointsEditor/Container.tsx +2 -8
- package/src/components/PointsEditor/Point.tsx +7 -5
- package/src/components/PointsEditor/SelectionBox.tsx +2 -8
- package/src/components/PointsEditor/context.tsx +6 -6
- package/src/components/PointsEditor/index.tsx +9 -11
- package/src/components/Slider/Marks.tsx +6 -9
- package/src/components/Slider/MarksOption.tsx +7 -2
- package/src/components/Slider/Thumb.tsx +9 -15
- package/src/components/Slider/Track.tsx +6 -13
- package/src/components/Slider/index.tsx +5 -12
- package/src/components/Slider/type.ts +4 -2
- package/src/components/XYPad/Area.tsx +5 -10
- package/src/components/XYPad/Thumb.tsx +5 -11
- package/src/components/XYPad/index.tsx +3 -5
- package/src/components/_util/VisuallyHiddenRangeInput.tsx +3 -15
- package/src/components/_util/decimal-digits.ts +23 -0
- package/src/components/_util/visually-hidden.ts +25 -0
- package/src/css-variables.ts +23 -0
- package/src/hooks/_internal/useCheckSteps.ts +2 -3
- package/src/hooks/useDrag.ts +13 -4
- package/src/hooks/useDragValue.ts +17 -2
- package/src/hooks/useDropZone.ts +78 -0
- package/src/hooks/useWheel.ts +4 -1
- package/src/index.ts +12 -9
- package/src/input-event.ts +2 -2
|
@@ -51,9 +51,19 @@ export interface UseDragValueOptions {
|
|
|
51
51
|
*/
|
|
52
52
|
sensitivity?: (state: DragState) => number
|
|
53
53
|
|
|
54
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* Move the value on pointerdown, before the pointer has moved at all. With
|
|
56
|
+
* `baseElementRef` that makes a press jump the value to where it landed.
|
|
57
|
+
*
|
|
58
|
+
* @see DragValueOptions.updateOnPointerDown
|
|
59
|
+
*/
|
|
55
60
|
updateOnPointerDown?: boolean
|
|
56
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* Pixels the pointer has to travel before the drag counts as one. The
|
|
63
|
+
* default is 0, so the value follows the very first move.
|
|
64
|
+
*
|
|
65
|
+
* @default 0
|
|
66
|
+
*/
|
|
57
67
|
threshold?: number
|
|
58
68
|
/** CSS cursor to show while dragging. Applied to the element itself. */
|
|
59
69
|
cursor?: string
|
|
@@ -75,11 +85,16 @@ export interface UseDragValueOptions {
|
|
|
75
85
|
shouldStart?: (event: PointerEvent) => boolean
|
|
76
86
|
|
|
77
87
|
/**
|
|
88
|
+
* Called with the new value whenever the drag moves it. The hook holds no
|
|
89
|
+
* value of its own, so this is where it is stored.
|
|
90
|
+
*
|
|
78
91
|
* @param state the whole drag, for anything the value leaves out — the
|
|
79
92
|
* pointer event and its modifier keys, most of all.
|
|
80
93
|
*/
|
|
81
94
|
onChange?: (value: XY<number>, state: DragState) => void
|
|
95
|
+
/** Called once the drag starts, with the value it starts from. */
|
|
82
96
|
onDragStart?: (value: XY<number>, state: DragState) => void
|
|
97
|
+
/** Called when the pointer is released, with the value it ends on. */
|
|
83
98
|
onDragEnd?: (value: XY<number>, state: DragState) => void
|
|
84
99
|
}
|
|
85
100
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
createDropZone,
|
|
5
|
+
type DropZoneInstance,
|
|
6
|
+
type DropZoneOptions,
|
|
7
|
+
} from '@tremolo-ui/dom'
|
|
8
|
+
|
|
9
|
+
import { useCallbackRef } from './_internal/useCallbackRef'
|
|
10
|
+
|
|
11
|
+
// `onStateChange` is left out: what it reports comes back from the hook as
|
|
12
|
+
// `over` and `invalid`, which is what a component renders from.
|
|
13
|
+
export interface UseDropZoneOptions extends Omit<
|
|
14
|
+
DropZoneOptions,
|
|
15
|
+
'onStateChange'
|
|
16
|
+
> {}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Take files dropped onto an element.
|
|
20
|
+
*
|
|
21
|
+
* Any element can become a drop target this way — a waveform display, a track
|
|
22
|
+
* lane, a canvas — without wrapping it in anything.
|
|
23
|
+
*
|
|
24
|
+
* @returns a ref callback for the element, and whether a drag is over it
|
|
25
|
+
*/
|
|
26
|
+
export function useDropZone<T extends Element>({
|
|
27
|
+
accept,
|
|
28
|
+
multiple,
|
|
29
|
+
disabled,
|
|
30
|
+
onDrop,
|
|
31
|
+
onReject,
|
|
32
|
+
}: UseDropZoneOptions = {}): {
|
|
33
|
+
refCallback: (node: T | null) => void
|
|
34
|
+
over: boolean
|
|
35
|
+
invalid: boolean
|
|
36
|
+
} {
|
|
37
|
+
const dropHandler = useCallbackRef(onDrop)
|
|
38
|
+
const rejectHandler = useCallbackRef(onReject)
|
|
39
|
+
|
|
40
|
+
const [state, setState] = useState({ over: false, invalid: false })
|
|
41
|
+
|
|
42
|
+
// See useDrag for why the node is held in state.
|
|
43
|
+
const [node, setNode] = useState<T | null>(null)
|
|
44
|
+
|
|
45
|
+
const instanceRef = useRef<DropZoneInstance | null>(null)
|
|
46
|
+
|
|
47
|
+
// Read when the instance is created. The effect below keeps it current, and
|
|
48
|
+
// runs right after, so a stale setting is replaced within the same commit.
|
|
49
|
+
const latest = useRef({ accept, multiple, disabled })
|
|
50
|
+
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
if (!node) return
|
|
53
|
+
|
|
54
|
+
const instance = createDropZone(node, {
|
|
55
|
+
...latest.current,
|
|
56
|
+
onDrop: (files, event) => dropHandler(files, event),
|
|
57
|
+
onReject: (files, event) => rejectHandler(files, event),
|
|
58
|
+
onStateChange: (next) => setState(next),
|
|
59
|
+
})
|
|
60
|
+
instanceRef.current = instance
|
|
61
|
+
|
|
62
|
+
return () => {
|
|
63
|
+
instanceRef.current = null
|
|
64
|
+
instance.destroy()
|
|
65
|
+
// The listeners are gone, so no `dragleave` is coming to clear this.
|
|
66
|
+
setState({ over: false, invalid: false })
|
|
67
|
+
}
|
|
68
|
+
}, [node, dropHandler, rejectHandler])
|
|
69
|
+
|
|
70
|
+
// Runs after every render: the settings come from props and are cheap to
|
|
71
|
+
// push, and updating in place leaves a drag in progress untouched.
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
latest.current = { accept, multiple, disabled }
|
|
74
|
+
instanceRef.current?.update({ accept, multiple, disabled })
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
return { refCallback: setNode, over: state.over, invalid: state.invalid }
|
|
78
|
+
}
|
package/src/hooks/useWheel.ts
CHANGED
|
@@ -4,7 +4,10 @@ import { createWheel, type WheelOptions } from '@tremolo-ui/dom'
|
|
|
4
4
|
|
|
5
5
|
import { useCallbackRef } from './_internal/useCallbackRef'
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
// `onWheel` is left out: `createWheel` takes it so that `update()` can replace
|
|
8
|
+
// the callback, but this hook takes the handler as its first argument and the
|
|
9
|
+
// option would be silently ignored.
|
|
10
|
+
export interface UseWheelOptions extends Omit<WheelOptions, 'onWheel'> {
|
|
8
11
|
/**
|
|
9
12
|
* Listen on this element rather than on the one the returned ref callback is
|
|
10
13
|
* attached to, and ignore that callback.
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,14 @@ export {
|
|
|
7
7
|
type DrawFunction,
|
|
8
8
|
type InitFunction,
|
|
9
9
|
} from './components/AnimationCanvas'
|
|
10
|
+
export { DropZone, type DropZoneProps } from './components/DropZone'
|
|
11
|
+
export {
|
|
12
|
+
FileInput,
|
|
13
|
+
useFileInputContext,
|
|
14
|
+
type FileInputContextValue,
|
|
15
|
+
type FileInputProps,
|
|
16
|
+
type FileInputTriggerProps,
|
|
17
|
+
} from './components/FileInput'
|
|
10
18
|
export {
|
|
11
19
|
Knob,
|
|
12
20
|
useKnobContext,
|
|
@@ -22,10 +30,6 @@ export {
|
|
|
22
30
|
type NumberInputContextValue,
|
|
23
31
|
type NumberInputProps,
|
|
24
32
|
type NumberInputMethods,
|
|
25
|
-
type NumberInputInputFieldProps,
|
|
26
|
-
type NumberInputStepperProps,
|
|
27
|
-
type NumberInputIncrementStepperProps,
|
|
28
|
-
type NumberInputDecrementStepperProps,
|
|
29
33
|
} from './components/NumberInput'
|
|
30
34
|
export {
|
|
31
35
|
Piano,
|
|
@@ -34,7 +38,6 @@ export {
|
|
|
34
38
|
type PianoMethods,
|
|
35
39
|
type KeyState,
|
|
36
40
|
type KeyAttributes,
|
|
37
|
-
type CSSVariables,
|
|
38
41
|
type KeyboardShortcuts,
|
|
39
42
|
} from './components/Piano'
|
|
40
43
|
export {
|
|
@@ -43,9 +46,6 @@ export {
|
|
|
43
46
|
clampPoint,
|
|
44
47
|
type PointsEditorProps,
|
|
45
48
|
type PointsEditorContextValue,
|
|
46
|
-
type PointsEditorBackgroundProps,
|
|
47
|
-
type PointsEditorContainerProps,
|
|
48
|
-
type PointsEditorSelectionBoxProps,
|
|
49
49
|
type PointsEditorPointProps,
|
|
50
50
|
type PointBaseType,
|
|
51
51
|
} from './components/PointsEditor'
|
|
@@ -75,10 +75,13 @@ export {
|
|
|
75
75
|
type XYInput,
|
|
76
76
|
} from './components/XYPad'
|
|
77
77
|
|
|
78
|
+
export { type CSSVariables } from './css-variables'
|
|
79
|
+
|
|
78
80
|
// hooks
|
|
79
81
|
export { useAnimationFrame } from './hooks/useAnimationFrame'
|
|
80
|
-
export { useDrag } from './hooks/useDrag'
|
|
82
|
+
export { useDrag, type UseDragOptions } from './hooks/useDrag'
|
|
81
83
|
export { useDragValue, type UseDragValueOptions } from './hooks/useDragValue'
|
|
84
|
+
export { useDropZone, type UseDropZoneOptions } from './hooks/useDropZone'
|
|
82
85
|
export { useEventListener } from './hooks/useEventListener'
|
|
83
86
|
export { useInterval } from './hooks/useInterval'
|
|
84
87
|
export { useLongPress } from './hooks/useLongPress'
|
package/src/input-event.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type InputEventOption, type ModifierValue } from '@tremolo-ui/dom'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The keyboard amount used by Knob, NumberInput, Slider, and XYPad by default:
|
|
@@ -7,7 +7,7 @@ import type { InputEventOption, ModifierValue } from '@tremolo-ui/functions'
|
|
|
7
7
|
* `useCheckSteps` warns about.
|
|
8
8
|
*
|
|
9
9
|
* A modifier entry is not snapped to `step`, which is what lets the finer
|
|
10
|
-
* amount move at all — see `applyDelta` in `@tremolo-ui/
|
|
10
|
+
* amount move at all — see `applyDelta` in `@tremolo-ui/dom`.
|
|
11
11
|
*/
|
|
12
12
|
export const DEFAULT_KEYBOARD_OPTIONS: ModifierValue<InputEventOption> = {
|
|
13
13
|
default: ['raw', 1],
|