@tremolo-ui/react 0.1.6 → 0.2.1

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.
Files changed (68) hide show
  1. package/dist/index.cjs +1329 -1152
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.css +238 -183
  4. package/dist/index.d.cts +367 -366
  5. package/dist/index.d.cts.map +1 -1
  6. package/dist/index.d.ts +367 -366
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1313 -1125
  9. package/dist/index.js.map +1 -1
  10. package/package.json +17 -19
  11. package/src/components/AnimationCanvas/index.tsx +0 -7
  12. package/src/components/DragObserver/index.tsx +9 -7
  13. package/src/components/Knob/ActiveLine.tsx +29 -0
  14. package/src/components/Knob/InactiveLine.tsx +53 -0
  15. package/src/components/Knob/SVGRoot.tsx +39 -0
  16. package/src/components/Knob/Thumb.tsx +64 -0
  17. package/src/components/Knob/context.tsx +120 -0
  18. package/src/components/Knob/index.css +25 -27
  19. package/src/components/Knob/index.tsx +110 -164
  20. package/src/components/NumberInput/DecrementStepper.tsx +0 -2
  21. package/src/components/NumberInput/IncrementStepper.tsx +0 -2
  22. package/src/components/NumberInput/InternalInput.tsx +3 -1
  23. package/src/components/NumberInput/Stepper.tsx +0 -2
  24. package/src/components/NumberInput/context.tsx +0 -1
  25. package/src/components/NumberInput/index.css +31 -15
  26. package/src/components/NumberInput/index.tsx +21 -14
  27. package/src/components/Piano/KeyLabel.tsx +0 -2
  28. package/src/components/Piano/context.tsx +0 -2
  29. package/src/components/Piano/index.css +7 -14
  30. package/src/components/Piano/index.tsx +14 -15
  31. package/src/components/Piano/key.tsx +0 -10
  32. package/src/components/Piano/keyboardShortcuts.ts +0 -2
  33. package/src/components/PointsEditor/Background.tsx +17 -0
  34. package/src/components/PointsEditor/Container.tsx +26 -0
  35. package/src/components/PointsEditor/Point.tsx +137 -0
  36. package/src/components/PointsEditor/context.tsx +91 -0
  37. package/src/components/PointsEditor/index.css +30 -0
  38. package/src/components/PointsEditor/index.tsx +129 -0
  39. package/src/components/Slider/Scale.tsx +0 -2
  40. package/src/components/Slider/ScaleOption.tsx +0 -2
  41. package/src/components/Slider/Thumb.tsx +1 -5
  42. package/src/components/Slider/Track.tsx +1 -3
  43. package/src/components/Slider/context.tsx +0 -1
  44. package/src/components/Slider/index.css +33 -8
  45. package/src/components/Slider/index.tsx +61 -33
  46. package/src/components/WheelObserver/index.tsx +17 -19
  47. package/src/components/XYPad/Area.tsx +4 -5
  48. package/src/components/XYPad/Thumb.tsx +8 -7
  49. package/src/components/XYPad/index.css +18 -4
  50. package/src/components/XYPad/index.tsx +71 -38
  51. package/src/components/_util/composeRefs.tsx +63 -0
  52. package/src/components/_util/index.ts +23 -6
  53. package/src/components/_util/type.ts +1 -0
  54. package/src/hooks/useAnimationFrame.ts +0 -3
  55. package/src/hooks/useCallbackRef.ts +2 -2
  56. package/src/hooks/useDrag.ts +12 -11
  57. package/src/hooks/useDragWithElement.ts +12 -17
  58. package/src/hooks/useEventListener.ts +6 -9
  59. package/src/hooks/useInterval.ts +0 -3
  60. package/src/hooks/useLongPress.ts +0 -3
  61. package/src/hooks/useMIDIAccess.ts +0 -1
  62. package/src/hooks/useMIDIInput.ts +0 -1
  63. package/src/hooks/useMIDIMessage.ts +0 -1
  64. package/src/hooks/usePianoDrag.ts +75 -0
  65. package/src/index.ts +21 -30
  66. package/src/styles/global.css +16 -4
  67. package/dist/index.css.map +0 -1
  68. package/src/components/AnimationKnob/index.tsx +0 -314
@@ -9,7 +9,7 @@
9
9
  .tremolo-piano-white-key {
10
10
  --bg: oklch(100% 0 0);
11
11
  --color: oklch(0% 0 0);
12
- --active-bg: oklch(90% 0 0);
12
+ --active-bg: oklch(92% 0 0);
13
13
  --active-color: oklch(0% 0 0);
14
14
 
15
15
  box-sizing: border-box;
@@ -34,9 +34,9 @@
34
34
 
35
35
  .tremolo-piano-black-key {
36
36
  --color: oklch(100% 0 0);
37
- --bg: oklch(32.109% 0.00004 271.152);
37
+ --bg: oklch(32% 0 0);
38
38
  --active-color: oklch(100% 0 0);
39
- --active-bg: oklch(47.836% 0.00005 271.152);
39
+ --active-bg: oklch(44% 0 0);
40
40
 
41
41
  box-sizing: border-box;
42
42
  position: absolute;
@@ -82,16 +82,9 @@
82
82
 
83
83
  :where(.dark, [data-theme='dark']) {
84
84
  .tremolo-piano-white-key {
85
- --bg: oklch(48.193% 0.00005 271.152);
86
- --color: oklch(100% 0 0);
87
- --active-bg: oklch(52.78% 0.00006 271.152);
88
- --active-color: oklch(100% 0 0);
89
- }
90
-
91
- .tremolo-piano-black-key {
92
- --color: oklch(100% 0 0);
93
- --bg: oklch(32.109% 0 0);
94
- --active-color: oklch(100% 0 0);
95
- --active-bg: oklch(38.666% 0.00004 271.152);
85
+ --bg: oklch(80% 0 0);
86
+ --color: oklch(0% 0 0);
87
+ --active-bg: oklch(72% 0 0);
88
+ --active-color: oklch(0% 0 0);
96
89
  }
97
90
  }
@@ -23,8 +23,8 @@ import {
23
23
  noteKeys,
24
24
  } from '@tremolo-ui/functions'
25
25
 
26
- import { useDragWithElement } from '../../hooks/useDragWithElement'
27
26
  import { useEventListener } from '../../hooks/useEventListener'
27
+ import { usePianoDrag } from '../../hooks/usePianoDrag'
28
28
 
29
29
  import { NoteRange, PianoProvider } from './context'
30
30
  import {
@@ -35,10 +35,10 @@ import {
35
35
  WhiteKey,
36
36
  } from './key'
37
37
  import { KeyboardShortcuts } from './keyboardShortcuts'
38
+ import { KeyLabel } from './KeyLabel'
38
39
 
39
40
  /**
40
41
  * [noteRange.first, noteRange.first + 1 ..., noteRange.last]
41
- * @category Piano
42
42
  */
43
43
  export function getNoteRangeArray(noteRange: NoteRange) {
44
44
  return Array.from(
@@ -47,7 +47,6 @@ export function getNoteRangeArray(noteRange: NoteRange) {
47
47
  )
48
48
  }
49
49
 
50
- /** @category Piano */
51
50
  export interface PianoProps {
52
51
  noteRange: NoteRange
53
52
 
@@ -73,9 +72,6 @@ export interface PianoProps {
73
72
 
74
73
  const blackPerWhiteWidth = defaultBlackKeyWidth / defaultWhiteKeyWidth // 0.65
75
74
 
76
- /**
77
- * @category Piano
78
- */
79
75
  export interface PianoMethods {
80
76
  playNote: (note: number, velocity?: number) => void
81
77
  stopNote: (note: number) => void
@@ -84,11 +80,7 @@ export interface PianoMethods {
84
80
  type Props = PianoProps &
85
81
  Omit<ComponentPropsWithoutRef<'div'>, keyof PianoProps>
86
82
 
87
- /**
88
- * Customizable piano component.
89
- * @category Piano
90
- */
91
- export const Piano = forwardRef<PianoMethods, Props>(
83
+ const Root = forwardRef<PianoMethods, Props>(
92
84
  (
93
85
  {
94
86
  noteRange,
@@ -243,10 +235,12 @@ export const Piano = forwardRef<PianoMethods, Props>(
243
235
  }
244
236
  }, [fill, _whiteNoteWidth, whiteNoteCount])
245
237
 
246
- const [touchMoveRefCallback, pointerDownHandler] =
247
- useDragWithElement<HTMLDivElement>({
238
+ // FIXME
239
+ const { refHandler: touchMoveRefCallback, pointerDownHandler } =
240
+ usePianoDrag<HTMLDivElement>({
248
241
  baseElementRef: pianoRef,
249
242
  onDrag: onDrag,
243
+ // onDragStart: onDrag,
250
244
  onDragEnd: onDragEnd,
251
245
  })
252
246
 
@@ -345,6 +339,11 @@ export const Piano = forwardRef<PianoMethods, Props>(
345
339
  },
346
340
  )
347
341
 
342
+ /**
343
+ * Customizable piano component.
344
+ */
345
+ export const Piano = { Root, WhiteKey, BlackKey, KeyLabel }
346
+
348
347
  export { type KeyboardShortcuts, SHORTCUTS } from './keyboardShortcuts'
349
- export { WhiteKey, BlackKey, type KeyProps, type KeyMethods } from './key'
350
- export { KeyLabel, type KeyLabelProps } from './KeyLabel'
348
+ export { type KeyProps, type KeyMethods } from './key'
349
+ export { type KeyLabelProps } from './KeyLabel'
@@ -11,9 +11,6 @@ import React, {
11
11
  import { usePianoContext } from './context'
12
12
  import { KeyLabel, KeyLabelProps } from './KeyLabel'
13
13
 
14
- /**
15
- * @category Piano
16
- */
17
14
  export interface KeyProps {
18
15
  noteNumber: number
19
16
 
@@ -36,9 +33,6 @@ export interface KeyProps {
36
33
  __width?: number
37
34
  }
38
35
 
39
- /**
40
- * @category Piano
41
- */
42
36
  export interface KeyMethods {
43
37
  play: (velocity?: number) => void
44
38
  stop: () => void
@@ -48,9 +42,7 @@ export interface KeyMethods {
48
42
  type Props = KeyProps & Omit<ComponentPropsWithoutRef<'div'>, keyof KeyProps>
49
43
  type ImplProps = Props & { keyType: 'black' | 'white' }
50
44
 
51
- /** @category Piano */
52
45
  export const defaultWhiteKeyWidth = 40
53
- /** @category Piano */
54
46
  export const defaultBlackKeyWidth = 26
55
47
 
56
48
  const KeyImpl = forwardRef<KeyMethods, ImplProps>(
@@ -166,7 +158,6 @@ const KeyImpl = forwardRef<KeyMethods, ImplProps>(
166
158
  },
167
159
  )
168
160
 
169
- /** @category Piano */
170
161
  export const WhiteKey = forwardRef<KeyMethods, Props>(
171
162
  (
172
163
  {
@@ -190,7 +181,6 @@ export const WhiteKey = forwardRef<KeyMethods, Props>(
190
181
  },
191
182
  )
192
183
 
193
- /** @category Piano */
194
184
  export const BlackKey = forwardRef<KeyMethods, Props>(
195
185
  (
196
186
  {
@@ -1,4 +1,3 @@
1
- /** @category Piano */
2
1
  export type KeyboardShortcuts = {
3
2
  keys: string[]
4
3
  // TODO
@@ -7,7 +6,6 @@ export type KeyboardShortcuts = {
7
6
  }
8
7
  }
9
8
 
10
- /** @category Piano */
11
9
  export const SHORTCUTS = {
12
10
  HOME_ROW: {
13
11
  keys: [
@@ -0,0 +1,17 @@
1
+ import clsx from 'clsx'
2
+ import { ComponentPropsWithoutRef } from 'react'
3
+
4
+ export function Background({
5
+ className,
6
+ children,
7
+ ...props
8
+ }: ComponentPropsWithoutRef<'div'>) {
9
+ return (
10
+ <div
11
+ className={clsx('tremolo-points-editor-background', className)}
12
+ {...props}
13
+ >
14
+ {children}
15
+ </div>
16
+ )
17
+ }
@@ -0,0 +1,26 @@
1
+ import clsx from 'clsx'
2
+ import { ComponentPropsWithoutRef, useRef } from 'react'
3
+
4
+ import { usePointsEditorContext } from './context'
5
+
6
+ export function Container({
7
+ className,
8
+ children,
9
+ ...props
10
+ }: ComponentPropsWithoutRef<'div'>) {
11
+ const containerElementRef = useRef<HTMLDivElement>(null)
12
+ const setContainerElementRef = usePointsEditorContext(
13
+ (s) => s.setContainerElementRef,
14
+ )
15
+ setContainerElementRef(containerElementRef)
16
+
17
+ return (
18
+ <div
19
+ ref={containerElementRef}
20
+ className={clsx('tremolo-points-editor-container', className)}
21
+ {...props}
22
+ >
23
+ {children}
24
+ </div>
25
+ )
26
+ }
@@ -0,0 +1,137 @@
1
+ import clsx from 'clsx'
2
+ import { ComponentPropsWithoutRef } from 'react'
3
+
4
+ import { clamp } from '@tremolo-ui/functions'
5
+
6
+ import { useDragWithElement } from '../../hooks/useDragWithElement'
7
+ import {
8
+ addUserSelectNone,
9
+ removeUserSelectNone,
10
+ resetCursorStyle,
11
+ setCursorStyle,
12
+ } from '../_util'
13
+
14
+ import { usePointsEditorContext } from './context'
15
+
16
+ export type PointBaseType = { x: number; y: number }
17
+
18
+ export function clampPoint(
19
+ point: PointBaseType,
20
+ min?: Partial<PointBaseType>,
21
+ max?: Partial<PointBaseType>,
22
+ ) {
23
+ const { x, y } = point
24
+ const newX = clamp(x, min?.x ?? 0, max?.x ?? 1)
25
+ const newY = clamp(y, min?.y ?? 0, max?.y ?? 1)
26
+ return { x: newX, y: newY }
27
+ }
28
+
29
+ export interface PointProps<T extends PointBaseType> {
30
+ value: T
31
+ min?: Partial<PointBaseType>
32
+ max?: Partial<PointBaseType>
33
+
34
+ size?: number | string
35
+ width?: number | string
36
+ height?: number | string
37
+ color?: string
38
+
39
+ disabled?: boolean
40
+ readonly?: boolean
41
+
42
+ onChange?: (value: PointBaseType) => void
43
+ onDragStart?: (value: PointBaseType) => void
44
+ onDragEnd?: (value: PointBaseType) => void
45
+ }
46
+
47
+ export function Point<T extends PointBaseType>({
48
+ value,
49
+ min,
50
+ max,
51
+ size,
52
+ width = 16,
53
+ height = 16,
54
+ color,
55
+
56
+ disabled,
57
+ readonly,
58
+
59
+ onChange,
60
+ onDragStart,
61
+ onDragEnd,
62
+
63
+ className,
64
+ style,
65
+ onPointerDown,
66
+ ...props
67
+ }: PointProps<T> & Omit<ComponentPropsWithoutRef<'div'>, keyof PointProps<T>>) {
68
+ const containerElementRef = usePointsEditorContext(
69
+ (s) => s.containerElementRef,
70
+ )
71
+ const externalStyles = usePointsEditorContext((s) => s.externalStyles)
72
+ const __disabled = usePointsEditorContext((s) => s.disabled)
73
+ const __readonly = usePointsEditorContext((s) => s.readonly)
74
+
75
+ // console.log(value.x, value.y)
76
+
77
+ // Piano: 値が更新されることで、イベントハンドラがリセットされる
78
+
79
+ const {
80
+ refHandler: touchMoveRefCallback,
81
+ pointerDownHandler,
82
+ dragging,
83
+ } = useDragWithElement<HTMLDivElement>({
84
+ baseElementRef: containerElementRef,
85
+ onDrag: (x, y) => {
86
+ if (readonly) return
87
+
88
+ onChange?.(clampPoint({ x, y }, min, max))
89
+ },
90
+ onDragStart: (x, y) => {
91
+ if (readonly) return
92
+ if (externalStyles.userSelectNone) addUserSelectNone()
93
+ if (externalStyles.cursor) setCursorStyle(externalStyles.cursor)
94
+
95
+ onDragStart?.(clampPoint({ x, y }, min, max))
96
+ },
97
+ onDragEnd: (x, y) => {
98
+ if (readonly) return
99
+ if (externalStyles.userSelectNone) removeUserSelectNone()
100
+ if (externalStyles.cursor) resetCursorStyle()
101
+
102
+ onDragEnd?.(clampPoint({ x, y }, min, max))
103
+ },
104
+ })
105
+
106
+ const colors: Record<string, string | undefined> = {
107
+ '--color': color,
108
+ }
109
+
110
+ return (
111
+ <div
112
+ ref={(div) => {
113
+ // wheelRefCallback(div)
114
+ touchMoveRefCallback(div)
115
+ }}
116
+ className={clsx('tremolo-points-editor-point', className)}
117
+ // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
118
+ tabIndex={0}
119
+ aria-disabled={disabled != undefined ? disabled : __disabled}
120
+ aria-readonly={readonly != undefined ? readonly : __readonly}
121
+ data-dragging={dragging}
122
+ style={{
123
+ ...colors,
124
+ width: size ?? width,
125
+ height: size ?? height,
126
+ left: `${value.x * 100}%`,
127
+ top: `${value.y * 100}%`,
128
+ ...style,
129
+ }}
130
+ onPointerDown={(event) => {
131
+ pointerDownHandler(event)
132
+ onPointerDown?.(event)
133
+ }}
134
+ {...props}
135
+ />
136
+ )
137
+ }
@@ -0,0 +1,91 @@
1
+ import {
2
+ createContext,
3
+ createRef,
4
+ RefObject,
5
+ useContext,
6
+ useEffect,
7
+ useRef,
8
+ } from 'react'
9
+ import { createStore, useStore } from 'zustand'
10
+
11
+ import { Cursor } from '../_util'
12
+
13
+ type State = {
14
+ containerElementRef: RefObject<HTMLDivElement | null>
15
+ disabled: boolean
16
+ readonly: boolean
17
+ externalStyles: {
18
+ userSelectNone?: boolean
19
+ cursor?: Cursor
20
+ }
21
+ }
22
+
23
+ type Action = {
24
+ setContainerElementRef: (
25
+ containerElementRef: RefObject<HTMLDivElement | null>,
26
+ ) => void
27
+ }
28
+
29
+ type PointsEditorStore = ReturnType<typeof createPointsEditorStore>
30
+
31
+ const createPointsEditorStore = (initProps: Partial<State & Action>) => {
32
+ // const noteRange = initProps.noteRange || { first: 0, last: 127 }
33
+ const DEFAULT_PROPS: State = {
34
+ containerElementRef: createRef(),
35
+ disabled: false,
36
+ readonly: false,
37
+ externalStyles: {
38
+ userSelectNone: true,
39
+ cursor: 'grabbing',
40
+ },
41
+ }
42
+
43
+ return createStore<State & Action>()((set) => ({
44
+ ...DEFAULT_PROPS,
45
+ ...initProps,
46
+ setContainerElementRef: (containerElementRef) => {
47
+ set(() => ({
48
+ containerElementRef,
49
+ }))
50
+ },
51
+ }))
52
+ }
53
+
54
+ const PointsEditorContext = createContext<PointsEditorStore | null>(null)
55
+
56
+ type PointsEditorProviderProps = React.PropsWithChildren<
57
+ Partial<State & Action>
58
+ >
59
+
60
+ export function PointsEditorProvider({
61
+ children,
62
+ ...props
63
+ }: PointsEditorProviderProps) {
64
+ const storeRef = useRef<PointsEditorStore>(null)
65
+ if (!storeRef.current) {
66
+ storeRef.current = createPointsEditorStore(props)
67
+ }
68
+
69
+ useEffect(() => {
70
+ if (storeRef.current) {
71
+ storeRef.current.setState(props)
72
+ } else {
73
+ storeRef.current = createPointsEditorStore(props)
74
+ }
75
+ }, [props])
76
+
77
+ return (
78
+ <PointsEditorContext.Provider value={storeRef.current}>
79
+ {children}
80
+ </PointsEditorContext.Provider>
81
+ )
82
+ }
83
+
84
+ export function usePointsEditorContext<T>(
85
+ selector: (state: State & Action) => T,
86
+ ): T {
87
+ const store = useContext(PointsEditorContext)
88
+ if (!store)
89
+ throw new Error('Missing PointsEditorContext.Provider in the tree')
90
+ return useStore(store, selector)
91
+ }
@@ -0,0 +1,30 @@
1
+ .tremolo-points-editor {
2
+ position: relative;
3
+ }
4
+
5
+ .tremolo-points-editor-background {
6
+ position: absolute;
7
+ inset: 0;
8
+ z-index: 0;
9
+ }
10
+
11
+ .tremolo-points-editor-container {
12
+ position: absolute;
13
+ inset: 0;
14
+ z-index: 10;
15
+ }
16
+
17
+ .tremolo-points-editor-point {
18
+ --color: oklch(59.5% 0.17548 266.373);
19
+
20
+ position: absolute;
21
+ border-radius: 50%;
22
+ outline: none;
23
+ cursor: grab;
24
+ background-color: var(--color);
25
+ translate: -50% -50%;
26
+
27
+ &[data-dragging='true'] {
28
+ cursor: inherit;
29
+ }
30
+ }
@@ -0,0 +1,129 @@
1
+ import clsx from 'clsx'
2
+ import { ComponentPropsWithoutRef, forwardRef } from 'react'
3
+
4
+ import { InputEventOption } from '@tremolo-ui/functions'
5
+
6
+ import { Cursor } from '../_util'
7
+
8
+ import { Background } from './Background'
9
+ import { Container } from './Container'
10
+ import { PointsEditorProvider } from './context'
11
+ import { Point, PointBaseType } from './Point'
12
+
13
+ /*
14
+ TODO:
15
+
16
+ - 複数選択
17
+ - modifier
18
+ */
19
+
20
+ /*
21
+ import { useState } from 'react'
22
+
23
+ export default function App() {
24
+ const [points, setPoints] = useState(initialPoints)
25
+
26
+ return (
27
+ <PointsEditor.Root
28
+ onDoubleClick={({ x, y }, _e) => {
29
+ const newPoints = [...points, { x, y }]
30
+ setPoints(newPoints)
31
+ }}
32
+ >
33
+ {points.map((point) => (
34
+ <PointsEditor.Point key={`${point.x}, ${point.y}`} value={point} />
35
+ ))}
36
+ </PointsEditor.Root>
37
+ )
38
+ }
39
+ */
40
+
41
+ const defaultExternalStyles: PointsEditorProps['externalStyles'] = {
42
+ userSelectNone: true,
43
+ cursor: 'grabbing',
44
+ }
45
+
46
+ export interface PointsEditorProps {
47
+ width?: number | string
48
+ height?: number | string
49
+
50
+ // TODO
51
+ grid?: number | PointBaseType
52
+ // modifier?:
53
+
54
+ disabled?: boolean
55
+ readonly?: boolean
56
+
57
+ externalStyles?: {
58
+ userSelectNone?: boolean
59
+ cursor?: Cursor
60
+ }
61
+
62
+ // TODO
63
+ /**
64
+ * wheel control option
65
+ * If null, no event will be triggered
66
+ */
67
+ wheel?: InputEventOption | null
68
+ /**
69
+ * keyboard control option
70
+ * If null, no event will be triggered
71
+ */
72
+ keyboard?: InputEventOption | null
73
+ }
74
+
75
+ type Props = PointsEditorProps &
76
+ Omit<ComponentPropsWithoutRef<'div'>, keyof PointsEditorProps>
77
+
78
+ const Root = forwardRef<HTMLDivElement, Props>(
79
+ (
80
+ {
81
+ width = 200,
82
+ height = 100,
83
+ disabled = false,
84
+ readonly = false,
85
+ externalStyles: _externalStyles,
86
+ style,
87
+ className,
88
+ children,
89
+ ...props
90
+ },
91
+ forwardedRef,
92
+ ) => {
93
+ const externalStyles = { ...defaultExternalStyles, ..._externalStyles }
94
+
95
+ return (
96
+ <PointsEditorProvider
97
+ disabled={disabled}
98
+ readonly={readonly}
99
+ externalStyles={externalStyles}
100
+ >
101
+ <div
102
+ ref={forwardedRef}
103
+ className={clsx('tremolo-points-editor', className)}
104
+ style={{
105
+ width,
106
+ height,
107
+ ...style,
108
+ }}
109
+ {...props}
110
+ >
111
+ {children}
112
+ </div>
113
+ </PointsEditorProvider>
114
+ )
115
+ },
116
+ )
117
+
118
+ /**
119
+ * Multiple Point Controller
120
+ */
121
+ export const PointsEditor = {
122
+ Root,
123
+ Background,
124
+ Container,
125
+ Point,
126
+ }
127
+
128
+ export { usePointsEditorContext } from './context'
129
+ export { clampPoint, type PointBaseType, type PointProps } from './Point'
@@ -7,14 +7,12 @@ import { useSliderContext } from './context'
7
7
  import { ScaleOption } from './ScaleOption'
8
8
  import { generateOptionsList, ScaleOptions } from './type'
9
9
 
10
- /** @category Slider */
11
10
  export interface ScaleProps {
12
11
  gap?: number | string
13
12
  options?: ScaleOptions
14
13
  children?: ReactNode
15
14
  }
16
15
 
17
- /** @category Slider */
18
16
  export function Scale({
19
17
  gap = 6,
20
18
  options,
@@ -6,7 +6,6 @@ import { toFixed, xor, normalizeValue } from '@tremolo-ui/functions'
6
6
  import { useSliderContext } from './context'
7
7
  import { ScaleType } from './type'
8
8
 
9
- /** @category Slider */
10
9
  export interface ScaleOptionProps {
11
10
  // required
12
11
  value: number
@@ -32,7 +31,6 @@ export interface ScaleOptionProps {
32
31
  }
33
32
  }
34
33
 
35
- /** @category Slider */
36
34
  export function ScaleOption({
37
35
  value,
38
36
  type = 'mark-number',
@@ -9,7 +9,6 @@ import {
9
9
 
10
10
  import { useSliderContext } from './context'
11
11
 
12
- /** @category Slider */
13
12
  export interface SliderThumbProps {
14
13
  size?: number | string
15
14
  width?: number | string
@@ -25,17 +24,14 @@ export interface SliderThumbProps {
25
24
  __percent?: number
26
25
  }
27
26
 
28
- /** @category Slider */
29
27
  export interface SliderThumbMethods {
30
28
  focus: () => void
31
29
  blur: () => void
32
30
  }
33
31
 
34
- /** @category Slider */
35
32
  export const defaultThumbSize = 22
36
33
 
37
- /** @category Slider */
38
- export const SliderThumb = forwardRef<SliderThumbMethods, SliderThumbProps>(
34
+ export const Thumb = forwardRef<SliderThumbMethods, SliderThumbProps>(
39
35
  (
40
36
  {
41
37
  size,
@@ -8,7 +8,6 @@ import { useSliderContext } from './context'
8
8
  export const defaultLength = 140
9
9
  export const defaultThickness = 10
10
10
 
11
- /** @category Slider */
12
11
  export interface SliderTrackProps {
13
12
  length?: number | string
14
13
  thickness?: number | string
@@ -28,8 +27,7 @@ export interface SliderTrackProps {
28
27
  __percent?: number
29
28
  }
30
29
 
31
- /** @category Slider */
32
- export function SliderTrack({
30
+ export function Track({
33
31
  length = defaultLength,
34
32
  thickness = defaultThickness,
35
33
  active,
@@ -57,7 +57,6 @@ export function SliderProvider({ children, ...props }: SliderProviderProps) {
57
57
  )
58
58
  }
59
59
 
60
- /** @category Slider */
61
60
  export function useSliderContext<T>(selector: (state: State) => T): T {
62
61
  const store = useContext(SliderContext)
63
62
  if (!store) throw new Error('Missing SliderContext.Provider in the tree')