@tremolo-ui/react 0.0.1 → 0.0.2

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 (64) hide show
  1. package/dist/cjs/index.d.ts +43 -47
  2. package/dist/cjs/index.js +411 -303
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/types/src/components/AnimationCanvas/canvas.d.ts +6 -0
  5. package/dist/cjs/types/src/components/AnimationCanvas/canvas.d.ts.map +1 -0
  6. package/dist/cjs/types/src/components/AnimationCanvas/index.d.ts +20 -0
  7. package/dist/cjs/types/src/components/AnimationCanvas/index.d.ts.map +1 -0
  8. package/dist/cjs/types/src/components/Knob/index.d.ts +23 -10
  9. package/dist/cjs/types/src/components/Knob/index.d.ts.map +1 -1
  10. package/dist/cjs/types/src/components/NumberInput/index.d.ts +47 -0
  11. package/dist/cjs/types/src/components/NumberInput/index.d.ts.map +1 -0
  12. package/dist/cjs/types/src/components/Slider/Thumb.d.ts +11 -0
  13. package/dist/cjs/types/src/components/Slider/Thumb.d.ts.map +1 -0
  14. package/dist/cjs/types/src/components/Slider/Track.d.ts +10 -0
  15. package/dist/cjs/types/src/components/Slider/Track.d.ts.map +1 -0
  16. package/dist/cjs/types/src/components/Slider/index.d.ts +17 -10
  17. package/dist/cjs/types/src/components/Slider/index.d.ts.map +1 -1
  18. package/dist/cjs/types/src/components/Slider/type.d.ts +4 -24
  19. package/dist/cjs/types/src/components/Slider/type.d.ts.map +1 -1
  20. package/dist/cjs/types/src/hooks/useCallbackRef.d.ts.map +1 -1
  21. package/dist/cjs/types/src/hooks/useEventListener.d.ts.map +1 -1
  22. package/dist/cjs/types/src/hooks/useRefCallbackEvent.d.ts +5 -0
  23. package/dist/cjs/types/src/hooks/useRefCallbackEvent.d.ts.map +1 -0
  24. package/dist/cjs/types/src/index.d.ts +2 -2
  25. package/dist/cjs/types/src/index.d.ts.map +1 -1
  26. package/dist/cjs/types/src/math.d.ts.map +1 -1
  27. package/dist/cjs/types/src/system/pseudo.d.ts +14 -0
  28. package/dist/cjs/types/src/system/pseudo.d.ts.map +1 -0
  29. package/dist/cjs/types/src/types.d.ts.map +1 -1
  30. package/dist/cjs/types/src/util.d.ts.map +1 -1
  31. package/dist/esm/index.d.ts +43 -47
  32. package/dist/esm/index.js +378 -268
  33. package/dist/esm/index.js.map +1 -1
  34. package/dist/esm/types/src/components/AnimationCanvas/canvas.d.ts +6 -0
  35. package/dist/esm/types/src/components/AnimationCanvas/canvas.d.ts.map +1 -0
  36. package/dist/esm/types/src/components/AnimationCanvas/index.d.ts +20 -0
  37. package/dist/esm/types/src/components/AnimationCanvas/index.d.ts.map +1 -0
  38. package/dist/esm/types/src/components/Knob/index.d.ts +23 -10
  39. package/dist/esm/types/src/components/Knob/index.d.ts.map +1 -1
  40. package/dist/esm/types/src/components/NumberInput/index.d.ts +47 -0
  41. package/dist/esm/types/src/components/NumberInput/index.d.ts.map +1 -0
  42. package/dist/esm/types/src/components/Slider/Thumb.d.ts +11 -0
  43. package/dist/esm/types/src/components/Slider/Thumb.d.ts.map +1 -0
  44. package/dist/esm/types/src/components/Slider/Track.d.ts +10 -0
  45. package/dist/esm/types/src/components/Slider/Track.d.ts.map +1 -0
  46. package/dist/esm/types/src/components/Slider/index.d.ts +17 -10
  47. package/dist/esm/types/src/components/Slider/index.d.ts.map +1 -1
  48. package/dist/esm/types/src/components/Slider/type.d.ts +4 -24
  49. package/dist/esm/types/src/components/Slider/type.d.ts.map +1 -1
  50. package/dist/esm/types/src/hooks/useCallbackRef.d.ts.map +1 -1
  51. package/dist/esm/types/src/hooks/useEventListener.d.ts.map +1 -1
  52. package/dist/esm/types/src/hooks/useRefCallbackEvent.d.ts +5 -0
  53. package/dist/esm/types/src/hooks/useRefCallbackEvent.d.ts.map +1 -0
  54. package/dist/esm/types/src/index.d.ts +2 -2
  55. package/dist/esm/types/src/index.d.ts.map +1 -1
  56. package/dist/esm/types/src/math.d.ts.map +1 -1
  57. package/dist/esm/types/src/system/pseudo.d.ts +14 -0
  58. package/dist/esm/types/src/system/pseudo.d.ts.map +1 -0
  59. package/dist/esm/types/src/types.d.ts.map +1 -1
  60. package/dist/esm/types/src/util.d.ts.map +1 -1
  61. package/package.json +19 -36
  62. package/LICENSE +0 -21
  63. package/README.md +0 -59
  64. package/dist/tsconfig.tsbuildinfo +0 -1
package/dist/cjs/index.js CHANGED
@@ -1,65 +1,63 @@
1
1
  'use strict';
2
2
 
3
+ var math = require('common/math');
3
4
  var jsxRuntime = require('@emotion/react/jsx-runtime');
4
- var react$1 = require('@emotion/react');
5
- var react = require('react');
5
+ var react = require('@emotion/react');
6
+ var React = require('react');
7
+ var type = require('common/components/Slider/type');
8
+ var util = require('common/util');
6
9
 
7
- function clamp(value, min, max) {
8
- return Math.max(min, Math.min(value, max));
9
- }
10
- function normalizeValue(rawValue, min, max, skew = 1) {
11
- if (min >= max)
12
- throw new RangeError('requirements: min < max');
13
- const v = clamp((rawValue - min) / (max - min), 0, 1);
14
- return Math.pow(v, skew);
15
- }
16
- function rawValue(normalizedValue, min, max, skew = 1) {
17
- if (min >= max)
18
- throw new RangeError('requirements: min < max');
19
- const v = skew == 1
20
- ? clamp(normalizedValue, 0, 1)
21
- : Math.exp(Math.log(clamp(normalizedValue, 0, 1)) / skew);
22
- return min + v * (max - min);
23
- }
24
- function skewWithCenterValue(centerValue, min, max) {
25
- if (!(min <= centerValue && centerValue <= max))
26
- throw new RangeError('requirements: min <= centerValue <= max');
27
- return Math.log(0.5) / Math.log((centerValue - min) / (max - min));
28
- }
29
- function stepValue(value, step) {
30
- var _a;
31
- if (step <= 0)
32
- throw new RangeError('requirements: step > 0');
33
- const quotient = Math.floor(value / step);
34
- const decimalDigits = (_a = decimalPart(step)) === null || _a === void 0 ? void 0 : _a.length;
35
- const v = toFixed(quotient * step, decimalDigits);
36
- const next = toFixed((quotient + 1) * step, decimalDigits);
37
- return Math.abs(value - v) < Math.abs(value - next) ? v : next;
38
- }
39
- function toFixed(x, fractionDigits) {
40
- return Number(x.toFixed(fractionDigits));
41
- }
42
- function decimalPart(x) {
43
- return String(x).split('.')[1];
44
- }
10
+ /******************************************************************************
11
+ Copyright (c) Microsoft Corporation.
12
+
13
+ Permission to use, copy, modify, and/or distribute this software for any
14
+ purpose with or without fee is hereby granted.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
17
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
19
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22
+ PERFORMANCE OF THIS SOFTWARE.
23
+ ***************************************************************************** */
24
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
25
+
26
+
27
+ function __rest(s, e) {
28
+ var t = {};
29
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
30
+ t[p] = s[p];
31
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
32
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
33
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
34
+ t[p[i]] = s[p[i]];
35
+ }
36
+ return t;
37
+ }
38
+
39
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
40
+ var e = new Error(message);
41
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
42
+ };
45
43
 
46
44
  /**
47
45
  * This hook is user-land implementation of the experimental `useEffectEvent` hook.
48
46
  * React docs: https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event
49
47
  */
50
48
  function useCallbackRef(callback, deps = []) {
51
- const callbackRef = react.useRef(() => {
49
+ const callbackRef = React.useRef(() => {
52
50
  throw new Error('Cannot call an event handler while rendering.');
53
51
  });
54
- react.useInsertionEffect(() => {
52
+ React.useInsertionEffect(() => {
55
53
  callbackRef.current = callback;
56
54
  });
57
- return react.useCallback((...args) => { var _a; return (_a = callbackRef.current) === null || _a === void 0 ? void 0 : _a.call(callbackRef, ...args); }, deps);
55
+ return React.useCallback((...args) => { var _a; return (_a = callbackRef.current) === null || _a === void 0 ? void 0 : _a.call(callbackRef, ...args); }, deps);
58
56
  }
59
57
 
60
58
  function useEventListener(target, event, handler, options) {
61
59
  const listener = useCallbackRef(handler);
62
- react.useEffect(() => {
60
+ React.useEffect(() => {
63
61
  const node = typeof target === 'function' ? target() : (target !== null && target !== void 0 ? target : document);
64
62
  if (!handler || !node)
65
63
  return;
@@ -74,238 +72,351 @@ function useEventListener(target, event, handler, options) {
74
72
  };
75
73
  }
76
74
 
77
- function styleHelper(property) {
78
- if (typeof property == 'number') {
79
- return `${property}px`;
80
- }
81
- else {
82
- return property;
83
- }
75
+ function useRefCallbackEvent(event, handler, options, deps = []) {
76
+ return React.useMemo(() => {
77
+ let cleanup;
78
+ return (node) => {
79
+ if (!node) {
80
+ cleanup === null || cleanup === void 0 ? void 0 : cleanup();
81
+ return;
82
+ }
83
+ node.addEventListener(event, handler, options);
84
+ cleanup = () => {
85
+ node.removeEventListener(event, handler, options);
86
+ };
87
+ };
88
+ }, deps);
84
89
  }
85
90
 
86
- function Knob({ value, min, max, step = 1, skew = 1, size = 50, active = '#7998ec', inactive = '#eee', bg = '#ccc', thumb = '#4e76e6', lineWeight = 12, thumbWeight = 4, cursor = 'pointer', style, bodyNoSelect = true, enableWheel, onChange, }) {
91
+ // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save
92
+ const drawingState = [
93
+ 'strokeStyle',
94
+ 'fillStyle',
95
+ 'globalAlpha',
96
+ 'lineWidth',
97
+ 'lineCap',
98
+ 'lineJoin',
99
+ 'miterLimit',
100
+ 'lineDashOffset',
101
+ 'shadowOffsetX',
102
+ 'shadowOffsetY',
103
+ 'shadowBlur',
104
+ 'shadowColor',
105
+ 'globalCompositeOperation',
106
+ 'font',
107
+ 'textAlign',
108
+ 'textBaseline',
109
+ 'direction',
110
+ 'imageSmoothingEnabled',
111
+ ];
112
+
113
+ function setDprConfig(canvas, context, width, height, dpr) {
114
+ canvas.width = width * dpr;
115
+ canvas.height = height * dpr;
116
+ context.scale(dpr, dpr);
117
+ canvas.style.width = `${width}px`;
118
+ canvas.style.height = `${height}px`;
119
+ }
120
+ /**
121
+ * A simple animatable canvas with requestAnimationFrame()
122
+ */
123
+ function AnimationCanvas(_a) {
124
+ var { width = 100, height = 100, style, relativeSize = false, reduceFlickering = true, options, init, draw } = _a, props = __rest(_a, ["width", "height", "style", "relativeSize", "reduceFlickering", "options", "init", "draw"]);
125
+ const canvasRef = React.useRef(null);
126
+ const memoCanvasRef = React.useRef(null);
127
+ const reqIdRef = React.useRef();
128
+ const widthRef = React.useRef(0);
129
+ const heightRef = React.useRef(0);
130
+ const loop = (context, width, height, count) => {
131
+ reqIdRef.current = requestAnimationFrame(() => loop(context, width, height, count + 1));
132
+ draw(context, width, height, count + 1);
133
+ };
134
+ React.useEffect(() => {
135
+ if (!canvasRef.current)
136
+ return;
137
+ const canvas = canvasRef.current;
138
+ const context = canvas.getContext('2d', options);
139
+ if (!context)
140
+ throw new Error('Cannot get canvas context.');
141
+ const dpr = window.devicePixelRatio;
142
+ if (relativeSize) {
143
+ const parent = canvas.parentElement;
144
+ if (!parent)
145
+ throw new Error("Canvas doesn't have a parent element.");
146
+ const memoCanvas = memoCanvasRef.current;
147
+ const memoContext = memoCanvas === null || memoCanvas === void 0 ? void 0 : memoCanvas.getContext('2d', options);
148
+ const resizeObserver = new ResizeObserver(() => {
149
+ console.log('resize');
150
+ // Prevents loss of some context when the canvas is resized
151
+ const contextMemo = {};
152
+ for (const prop of drawingState) {
153
+ contextMemo[prop] = context[prop];
154
+ }
155
+ const w = Math.floor(parent.clientWidth);
156
+ const h = Math.floor(parent.clientHeight);
157
+ if (reduceFlickering && memoCanvas && memoContext) {
158
+ memoCanvas.width = w * dpr;
159
+ memoCanvas.height = h * dpr;
160
+ memoContext.scale(1 / dpr, 1 / dpr);
161
+ memoContext.drawImage(context.canvas, 0, 0);
162
+ }
163
+ setDprConfig(canvas, context, w, h, dpr);
164
+ widthRef.current = w;
165
+ heightRef.current = h;
166
+ for (const prop of drawingState) {
167
+ context[prop] = contextMemo[prop];
168
+ }
169
+ if (reduceFlickering && memoContext) {
170
+ context.drawImage(memoContext.canvas, 0, 0);
171
+ }
172
+ });
173
+ resizeObserver.observe(parent);
174
+ const w = Math.floor(parent.clientWidth);
175
+ const h = Math.floor(parent.clientHeight);
176
+ setDprConfig(canvas, context, w, h, dpr);
177
+ if (init)
178
+ init(context, widthRef, heightRef, 0);
179
+ loop(context, widthRef, heightRef, 0);
180
+ return () => {
181
+ if (reqIdRef.current)
182
+ cancelAnimationFrame(reqIdRef.current);
183
+ resizeObserver.unobserve(parent);
184
+ };
185
+ }
186
+ else {
187
+ const rect = canvas.getBoundingClientRect();
188
+ setDprConfig(canvas, context, rect.width, rect.height, dpr);
189
+ widthRef.current = rect.width;
190
+ heightRef.current = rect.height;
191
+ if (init)
192
+ init(context, widthRef, heightRef, 0);
193
+ loop(context, widthRef, heightRef, 0);
194
+ return () => {
195
+ if (reqIdRef.current)
196
+ cancelAnimationFrame(reqIdRef.current);
197
+ };
198
+ }
199
+ }, [loop]);
200
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("canvas", Object.assign({ width: relativeSize ? 0 : width, height: relativeSize ? 0 : height, css: react.css(style), ref: canvasRef }, props)), relativeSize && reduceFlickering && (jsxRuntime.jsx("canvas", { style: { display: 'none' }, width: relativeSize ? 0 : width, height: relativeSize ? 0 : height, ref: memoCanvasRef }))] }));
201
+ }
202
+
203
+ const defaultOptions = {
204
+ active: '#7998ec',
205
+ inactive: '#eee',
206
+ bg: '#ccc',
207
+ thumb: '#4e76e6',
208
+ lineWeight: 6,
209
+ thumbWeight: 4,
210
+ };
211
+ /**
212
+ * simple rotary Knob.
213
+ */
214
+ function Knob(_a) {
215
+ var { value, min, max, defaultValue = min, startValue = min, step = 1, skew = 1, size, width = 50, height = 50, options = defaultOptions,
216
+ // draw,
217
+ cursor = 'pointer', style, bodyNoSelect = true, enableWheel, enableDoubleClickDefault = true, onChange, _active, _focus, _hover } = _a, props = __rest(_a, ["value", "min", "max", "defaultValue", "startValue", "step", "skew", "size", "width", "height", "options", "cursor", "style", "bodyNoSelect", "enableWheel", "enableDoubleClickDefault", "onChange", "_active", "_focus", "_hover"]);
87
218
  // -- state and ref ---
88
219
  // const [privateValue, setPrivateValue] = useState(value);
89
- const dragOffsetY = react.useRef(undefined);
220
+ const dragOffsetY = React.useRef(undefined);
90
221
  // --- interpret props ---
91
- const percent = normalizeValue(value, min, max, skew);
92
- const handleValue = (event) => {
222
+ const opts = Object.assign(Object.assign({}, defaultOptions), options);
223
+ // const percent = normalizeValue(value, min, max, skew)
224
+ const isRelativeSize = typeof (size !== null && size !== void 0 ? size : width) == 'string';
225
+ const adaptSize = (size) => {
226
+ if (typeof size == 'string') {
227
+ return Number(size.slice(0, -1));
228
+ }
229
+ else {
230
+ return size;
231
+ }
232
+ };
233
+ const handleEvent = (event) => {
234
+ const isTouch = event instanceof TouchEvent;
235
+ if (isTouch && event.cancelable)
236
+ event.preventDefault();
93
237
  if (dragOffsetY.current) {
94
238
  if (bodyNoSelect)
95
239
  document.body.classList.add('no-select');
96
- const delta = dragOffsetY.current - event.screenY;
97
- dragOffsetY.current = event.screenY;
98
- const n = normalizeValue(value, min, max, skew);
99
- const v = rawValue(n + delta / 100, min, max, skew);
100
- const v2 = clamp(stepValue(v, step), min, max);
240
+ const screenY = isTouch ? event.touches[0].screenY : event.screenY;
241
+ const delta = dragOffsetY.current - screenY;
242
+ dragOffsetY.current = screenY;
243
+ const n = math.normalizeValue(value, min, max, skew);
244
+ const v = math.rawValue(n + delta / 100, min, max, skew);
245
+ const v2 = math.clamp(math.stepValue(v, step), min, max);
101
246
  if (onChange)
102
247
  onChange(v2);
103
248
  }
104
249
  };
105
250
  // --- hooks ---
106
- const wrapperRef = react.useMemo(() => {
107
- let cleanup;
108
- return (div) => {
109
- if (!div) {
110
- cleanup === null || cleanup === void 0 ? void 0 : cleanup();
111
- return;
112
- }
113
- const controller = new AbortController();
114
- div.addEventListener('wheel', (event) => {
115
- if (!enableWheel)
116
- return;
117
- event.preventDefault();
118
- const x = event.deltaY > 0 ? -enableWheel[1] : enableWheel[1];
119
- let v;
120
- if (enableWheel[0] == 'normalized') {
121
- const n = normalizeValue(value, min, max, skew);
122
- v = rawValue(n + x, min, max, skew);
123
- }
124
- else {
125
- v = value + x;
126
- }
127
- if (onChange)
128
- onChange(clamp(stepValue(v, step), min, max));
129
- }, {
130
- signal: controller.signal,
131
- passive: false,
132
- });
133
- cleanup = () => {
134
- // console.log("cleanup")
135
- controller.abort();
136
- };
137
- };
138
- }, [value]);
139
- useEventListener(window, 'mousemove', (event) => {
140
- handleValue(event);
141
- });
142
- useEventListener(window, 'mouseup', () => {
251
+ const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
252
+ if (!enableWheel)
253
+ return;
254
+ event.preventDefault();
255
+ const x = event.deltaY > 0 ? -enableWheel[1] : enableWheel[1];
256
+ let v;
257
+ if (enableWheel[0] == 'normalized') {
258
+ const n = math.normalizeValue(value, min, max, skew);
259
+ v = math.rawValue(n + x, min, max, skew);
260
+ }
261
+ else {
262
+ v = value + x;
263
+ }
264
+ if (onChange)
265
+ onChange(math.clamp(math.stepValue(v, step), min, max));
266
+ }, { passive: false }, [enableWheel, value, min, max, skew, step, onChange]);
267
+ const touchMoveRefCallback = useRefCallbackEvent('touchmove', handleEvent, { passive: false }, [value, min, max, skew, step, onChange, bodyNoSelect]);
268
+ useEventListener(window, 'mousemove', handleEvent);
269
+ useEventListener(window, 'pointerup', () => {
143
270
  dragOffsetY.current = undefined;
144
271
  if (bodyNoSelect)
145
272
  document.body.classList.remove('no-select');
146
273
  });
147
- return (jsxRuntime.jsx("div", { className: "tremolo-knob", ref: wrapperRef, onMouseDown: (event) => {
274
+ return (jsxRuntime.jsxs("div", Object.assign({ className: "tremolo-knob", ref: (div) => {
275
+ wheelRefCallback(div);
276
+ touchMoveRefCallback(div);
277
+ }, role: "slider", tabIndex: 0, "aria-valuenow": value, "aria-valuemax": max, "aria-valuemin": min, css: react.css(Object.assign(Object.assign({ display: 'inline-block', width: size !== null && size !== void 0 ? size : width, height: size !== null && size !== void 0 ? size : height, cursor: cursor }, style), { ':active': Object.assign({}, _active), ':focus': Object.assign({}, _focus), ':hover': Object.assign({}, _hover) })), onPointerDown: (event) => {
148
278
  dragOffsetY.current = event.screenY;
149
- handleValue(event);
150
- }, style: Object.assign({ display: 'inline-block', width: size, height: size }, style), children: jsxRuntime.jsx("div", { css: react$1.css({
151
- display: 'inline-block',
152
- width: size,
153
- height: size,
154
- background: `conic-gradient(${active} ${percent * 270}deg, ${inactive} ${percent * 270}deg, ${inactive} ${270}deg, ${bg} 90deg)`,
155
- borderRadius: '50%',
156
- position: 'relative',
157
- cursor: cursor,
158
- rotate: '-135deg',
159
- '&::before': {
160
- display: 'block',
161
- position: 'absolute',
162
- right: 0,
163
- left: 0,
164
- top: 0,
165
- bottom: 0,
166
- margin: 'auto',
167
- content: '""',
168
- width: `calc(${styleHelper(size)} - ${styleHelper(lineWeight)})`,
169
- height: `calc(${styleHelper(size)} - ${styleHelper(lineWeight)})`,
170
- backgroundColor: bg,
171
- borderRadius: '50%',
172
- },
173
- '&::after': {
174
- display: 'block',
175
- position: 'absolute',
176
- top: 0,
177
- bottom: 0,
178
- // left: lineWeight,
179
- margin: 'auto 0',
180
- content: '""',
181
- width: `calc(0.5 * ${styleHelper(size)})`,
182
- height: thumbWeight,
183
- borderRadius: thumbWeight,
184
- backgroundColor: thumb,
185
- rotate: `${90 + percent * 270}deg`,
186
- transformOrigin: '100% 50%',
187
- },
188
- }), children: jsxRuntime.jsx(react$1.Global, { styles: {
279
+ handleEvent(event);
280
+ }, onDoubleClick: () => {
281
+ if (enableDoubleClickDefault && onChange) {
282
+ onChange(defaultValue);
283
+ }
284
+ } }, props, { children: [jsxRuntime.jsx(react.Global, { styles: {
189
285
  '.no-select': {
190
286
  userSelect: 'none',
191
287
  },
192
- } }) }) }));
288
+ } }), jsxRuntime.jsx(AnimationCanvas, { width: adaptSize(size !== null && size !== void 0 ? size : width), height: adaptSize(size !== null && size !== void 0 ? size : height), relativeSize: isRelativeSize,
289
+ // TODO
290
+ // reduceFlickering={false}
291
+ draw: (ctx, _w, _h) => {
292
+ const p = math.normalizeValue(value, min, max, skew);
293
+ const startP = math.normalizeValue(startValue, min, max, skew);
294
+ const w = _w.current, cx = w / 2;
295
+ const h = _h.current, cy = h / 2;
296
+ const r = Math.min(cx, cy);
297
+ // reset
298
+ ctx.clearRect(0, 0, w, h);
299
+ ctx.lineCap = 'butt';
300
+ // bg
301
+ ctx.beginPath();
302
+ ctx.fillStyle = opts.bg;
303
+ ctx.arc(cx, cy, r - 0.5, 0, 2 * Math.PI);
304
+ ctx.fill();
305
+ ctx.lineCap = 'round';
306
+ ctx.lineWidth = opts.lineWeight;
307
+ // inactive rotary
308
+ ctx.beginPath();
309
+ ctx.strokeStyle = opts.inactive;
310
+ ctx.arc(cx, cy, r - 0.5 - opts.lineWeight / 2, math.radian(135), math.radian(45));
311
+ ctx.stroke();
312
+ // active rotary
313
+ ctx.beginPath();
314
+ ctx.strokeStyle = opts.active;
315
+ ctx.arc(cx, cy, r - 0.5 - opts.lineWeight / 2, math.radian(135 + 270 * startP), math.radian(135 + 270 * p), p < startP);
316
+ ctx.stroke();
317
+ // thumb
318
+ ctx.beginPath();
319
+ ctx.moveTo(cx, cy);
320
+ ctx.lineTo(cx +
321
+ Math.cos(math.radian(135 + 270 * p)) *
322
+ (r - 0.5 - opts.thumbWeight / 2), cy +
323
+ Math.sin(math.radian(135 + 270 * p)) *
324
+ (r - 0.5 - opts.thumbWeight / 2));
325
+ ctx.strokeStyle = opts.thumb;
326
+ ctx.lineWidth = opts.thumbWeight;
327
+ ctx.stroke();
328
+ } })] })));
193
329
  }
194
330
 
195
- function isHorizontal(d) {
196
- return d == 'right' || d == 'left';
197
- }
198
- function isVertical(d) {
199
- return d == 'up' || d == 'down';
200
- }
201
- function isReversed(d) {
202
- return d == 'left' || d == 'up';
203
- }
204
- function gradientDirection(d) {
205
- if (d == 'left' || d == 'right')
206
- return d;
207
- if (d == 'up')
208
- return 'top';
209
- if (d == 'down')
210
- return 'bottom';
211
- }
212
- function parseScaleOrderList(scale, min, max, step) {
213
- var _a;
214
- let scalesList = [];
215
- if (!scale) ;
216
- else if (typeof scale[0] == 'object') {
217
- scalesList = scale;
218
- }
219
- else {
220
- const per = scale[0] == 'step' ? step : scale[0];
221
- const count = Math.floor(max / per) - Math.ceil(min / per) + 1;
222
- for (let i = 0; i < count; i++) {
223
- const at = toFixed(per * (Math.ceil(min / per) + i), (_a = decimalPart(per)) === null || _a === void 0 ? void 0 : _a.length);
224
- scalesList.push({ at: at, type: scale[1] });
225
- }
226
- }
227
- return scalesList;
331
+ function SliderThumb({ color, children, style, __css, }) {
332
+ return (jsxRuntime.jsx("div", { className: "tremolo-slider-thumb-wrapper", css: react.css(Object.assign({ width: 'fit-content', height: 'fit-content', position: 'absolute', translate: '-50% -50%', zIndex: 100 }, __css)), children: children ? (children) : (
333
+ // default slider thumb
334
+ jsxRuntime.jsx("div", { className: "tremolo-slider-thumb",
335
+ // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
336
+ tabIndex: 0, css: react.css(Object.assign({ background: color, width: '1.4rem', height: '1.4rem', borderRadius: '50%' }, style)) })) }));
228
337
  }
229
338
 
230
- // interface SliderThumbProps {}
231
- function SliderThumb( /* {}: SliderThumbProps */) {
232
- return jsxRuntime.jsx("div", {});
339
+ function SliderTrack({ children, style, __css, }) {
340
+ return (jsxRuntime.jsx("div", { className: "tremolo-slider-track", css: react.css(Object.assign(Object.assign({}, __css), style)), children: children }));
233
341
  }
234
- function Slider({ value, min, max, step = 1, length = 140, thickness = 10, direction = 'right', skew = 1, scale, scaleOption, color = '#4e76e6', bg = '#eee', cursor = 'pointer', style, bodyNoSelect = true, enableWheel, onChange, children, }) {
235
- var _a, _b;
342
+
343
+ /**
344
+ * Customizable slider
345
+ */
346
+ function Slider(_a) {
347
+ var _b, _c;
348
+ var { value, min, max, step = 1, skew = 1, length = 140, thickness = 10, direction = 'right', scale, scaleOption, color = '#4e76e6', bg = '#eee', className, style, bodyNoSelect = true, enableWheel, onChange, children } = _a; __rest(_a, ["value", "min", "max", "step", "skew", "length", "thickness", "direction", "scale", "scaleOption", "color", "bg", "className", "style", "bodyNoSelect", "enableWheel", "onChange", "children"]);
236
349
  // -- state and ref ---
237
- const baseWrapperElement = react.useRef(null);
238
- // --- interpret props ---
239
- const percent = normalizeValue(value, min, max, skew) * 100;
240
- const percentRev = isReversed(direction) ? 100 - percent : percent;
241
- const scalesList = parseScaleOrderList(scale, min, max, step);
242
- if (isReversed(direction))
350
+ const trackElementRef = React.useRef(null);
351
+ const percent = math.normalizeValue(value, min, max, skew) * 100;
352
+ const percentRev = type.isReversed(direction) ? 100 - percent : percent;
353
+ const scalesList = type.parseScaleOrderList(scale, min, max, step);
354
+ if (type.isReversed(direction))
243
355
  scalesList.reverse();
244
- // let defaultThumb = true
356
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
357
+ let trackProps;
358
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
359
+ let thumbProps;
245
360
  if (children != undefined) {
246
- const childElements = react.Children.toArray(children);
247
- const lastElement = childElements[childElements.length - 1];
248
- if (react.isValidElement(lastElement)) {
249
- // defaultThumb = false
250
- if (lastElement.type == SliderThumb) ;
251
- }
252
- else {
253
- throw new Error('children is an invalid element.');
254
- }
361
+ React.Children.forEach(children, (child) => {
362
+ if (React.isValidElement(child)) {
363
+ if (child.type == SliderThumb) {
364
+ thumbProps = child.props;
365
+ }
366
+ else if (child.type == SliderTrack) {
367
+ trackProps = child.props;
368
+ }
369
+ else {
370
+ throw new Error('only <SliderThumb> or <SliderTrack>');
371
+ }
372
+ }
373
+ else {
374
+ throw new Error('children is an invalid element.');
375
+ }
376
+ });
255
377
  }
256
- const thumbDragged = react.useRef(false);
378
+ const thumbDragged = React.useRef(false);
257
379
  const handleValue = (event) => {
258
- if (baseWrapperElement.current && thumbDragged.current) {
259
- if (bodyNoSelect)
260
- document.body.classList.add('no-select');
261
- const { left: x1, top: y1, right: x2, bottom: y2, } = baseWrapperElement.current.getBoundingClientRect();
262
- const mouseX = event.clientX;
263
- const mouseY = event.clientY;
264
- const n = isHorizontal(direction)
265
- ? normalizeValue(mouseX, x1, x2)
266
- : normalizeValue(mouseY, y1, y2);
267
- const v = rawValue(isReversed(direction) ? 1 - n : n, min, max, skew);
268
- const v2 = clamp(stepValue(v, step), min, max);
269
- if (onChange)
270
- onChange(v2);
271
- }
380
+ if (!trackElementRef.current || !thumbDragged.current)
381
+ return;
382
+ const isTouch = event instanceof TouchEvent;
383
+ if (isTouch && event.cancelable)
384
+ event.preventDefault();
385
+ if (bodyNoSelect)
386
+ document.body.classList.add('no-select');
387
+ const { left: x1, top: y1, right: x2, bottom: y2, } = trackElementRef.current.getBoundingClientRect();
388
+ const mouseX = isTouch ? event.touches[0].clientX : event.clientX;
389
+ const mouseY = isTouch ? event.touches[0].clientY : event.clientY;
390
+ const n = type.isHorizontal(direction)
391
+ ? math.normalizeValue(mouseX, x1, x2)
392
+ : math.normalizeValue(mouseY, y1, y2);
393
+ const v = math.rawValue(type.isReversed(direction) ? 1 - n : n, min, max, skew);
394
+ const v2 = math.clamp(math.stepValue(v, step), min, max);
395
+ if (onChange)
396
+ onChange(v2);
272
397
  };
273
398
  // --- hooks ---
274
- const wrapperRef = react.useMemo(() => {
275
- let cleanup;
276
- return (div) => {
277
- if (!div) {
278
- cleanup === null || cleanup === void 0 ? void 0 : cleanup();
279
- return;
280
- }
281
- const controller = new AbortController();
282
- div.addEventListener('wheel', (event) => {
283
- if (!enableWheel)
284
- return;
285
- event.preventDefault();
286
- let x = event.deltaY > 0 ? enableWheel[1] : -enableWheel[1];
287
- if (isReversed(direction))
288
- x *= -1;
289
- let v;
290
- if (enableWheel[0] == 'normalized') {
291
- const n = normalizeValue(value, min, max, skew);
292
- v = rawValue(n + x, min, max, skew);
293
- }
294
- else {
295
- v = value + x;
296
- }
297
- if (onChange)
298
- onChange(clamp(stepValue(v, step), min, max));
299
- }, {
300
- signal: controller.signal,
301
- passive: false,
302
- });
303
- cleanup = () => {
304
- // console.log("cleanup")
305
- controller.abort();
306
- };
307
- };
308
- }, [value]);
399
+ const touchMoveRefCallback = useRefCallbackEvent('touchmove', handleValue, { passive: false }, [min, max, skew, step, direction, onChange]);
400
+ const wheelRefCallback = useRefCallbackEvent('wheel', (event) => {
401
+ if (!enableWheel)
402
+ return;
403
+ event.preventDefault();
404
+ let x = event.deltaY > 0 ? enableWheel[1] : -enableWheel[1];
405
+ if (type.isReversed(direction) || type.isHorizontal(direction))
406
+ x *= -1;
407
+ let v;
408
+ if (enableWheel[0] == 'normalized') {
409
+ const n = math.normalizeValue(value, min, max, skew);
410
+ v = math.rawValue(n + x, min, max, skew);
411
+ }
412
+ else {
413
+ v = value + x;
414
+ }
415
+ if (onChange)
416
+ onChange(math.clamp(math.stepValue(v, step), min, max));
417
+ }, {
418
+ passive: false,
419
+ }, [enableWheel, value, min, max, skew, step]);
309
420
  useEventListener(window, 'mousemove', (event) => {
310
421
  handleValue(event);
311
422
  });
@@ -314,84 +425,81 @@ function Slider({ value, min, max, step = 1, length = 140, thickness = 10, direc
314
425
  if (bodyNoSelect)
315
426
  document.body.classList.remove('no-select');
316
427
  });
317
- return (jsxRuntime.jsxs("div", { ref: wrapperRef, className: "tremolo-slider", style: {
318
- display: 'inline-block',
319
- boxSizing: 'border-box',
320
- margin: '0.7rem',
321
- padding: 0,
322
- cursor: cursor,
323
- }, onMouseDown: (event) => {
428
+ return (jsxRuntime.jsxs("div", { className: 'tremolo-slider' + (className ? ` ${className}` : ''), ref: (div) => {
429
+ wheelRefCallback(div);
430
+ touchMoveRefCallback(div);
431
+ }, tabIndex: -1, role: "slider", "aria-valuenow": value, "aria-valuemax": max, "aria-valuemin": min, "aria-orientation": type.isHorizontal(direction) ? 'horizontal' : 'vertical', css: react.css(Object.assign({ display: 'inline-block', boxSizing: 'border-box', margin: '0.7rem', padding: 0, cursor: 'pointer' }, style)), onPointerDown: (event) => {
324
432
  thumbDragged.current = true;
325
433
  handleValue(event);
326
- }, children: [jsxRuntime.jsx(react$1.Global, { styles: {
434
+ }, children: [jsxRuntime.jsx(react.Global, { styles: {
327
435
  '.no-select': {
328
436
  userSelect: 'none',
329
437
  },
330
- } }), jsxRuntime.jsxs("div", { style: {
438
+ } }), jsxRuntime.jsxs("div", { css: react.css({
331
439
  display: 'flex',
332
- flexDirection: isHorizontal(direction) ? 'column' : 'row',
333
- }, children: [jsxRuntime.jsx("div", { ref: baseWrapperElement, css: react$1.css(Object.assign({ background: `linear-gradient(to ${gradientDirection(direction)}, ${color} ${percent}%, ${bg} ${percent}%)`, borderRadius: typeof thickness == 'number'
334
- ? thickness / 2
335
- : `calc(${thickness} / 2)`, borderStyle: 'solid', borderColor: '#ccc', borderWidth: 2, width: isHorizontal(direction) ? length : thickness, height: isHorizontal(direction) ? thickness : length, position: 'relative', zIndex: 1 }, style)), children: jsxRuntime.jsx("div", { className: "tremolo-slider-thumb-wrapper", style: {
336
- width: 'fix-content',
337
- height: 'fix-content',
338
- position: 'absolute',
339
- top: isHorizontal(direction) ? '50%' : `${percentRev}%`,
340
- left: isHorizontal(direction) ? `${percentRev}%` : '50%',
341
- translate: '-50% -50%',
342
- zIndex: 100,
343
- }, children: children ? (children) : (jsxRuntime.jsx("div", { className: "tremolo-slider-thumb", style: {
344
- background: color,
345
- width: '1.4rem',
346
- height: '1.4rem',
347
- borderRadius: '50%',
348
- } })) }) }), scale && (jsxRuntime.jsx("div", { className: "tremolo-slider-scale-wrapper", style: Object.assign({ position: 'relative', width: isHorizontal(direction) ? length : undefined, height: isVertical(direction) ? length : undefined, marginLeft: isHorizontal(direction)
440
+ flexDirection: type.isHorizontal(direction) ? 'column' : 'row',
441
+ }), children: [jsxRuntime.jsxs("div", { className: "tremolo-slider-track-wrapper", ref: trackElementRef, css: react.css({ position: 'relative' }), children: [jsxRuntime.jsx(SliderTrack, Object.assign({ __css: {
442
+ background: `linear-gradient(to ${type.gradientDirection(direction)}, ${color} ${percent}%, ${bg} ${percent}%)`,
443
+ borderRadius: util.styleHelper(thickness, '/', 2),
444
+ borderStyle: 'solid',
445
+ borderColor: '#ccc',
446
+ borderWidth: 2,
447
+ width: type.isHorizontal(direction) ? length : thickness,
448
+ height: type.isHorizontal(direction) ? thickness : length,
449
+ zIndex: 1,
450
+ } }, trackProps)), jsxRuntime.jsx(SliderThumb, Object.assign({ color: color, __css: {
451
+ top: type.isHorizontal(direction) ? '50%' : `${percentRev}%`,
452
+ left: type.isHorizontal(direction) ? `${percentRev}%` : '50%',
453
+ } }, thumbProps))] }), scale && (jsxRuntime.jsx("div", { className: "tremolo-slider-scale-wrapper", css: react.css(Object.assign({ position: 'relative', width: type.isHorizontal(direction) ? length : undefined, height: type.isVertical(direction) ? length : undefined, marginLeft: type.isHorizontal(direction)
349
454
  ? 2
350
- : ((_a = scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.gap) !== null && _a !== void 0 ? _a : `calc((1.4rem - ${styleHelper(thickness)}) / 2)`), marginTop: isVertical(direction)
455
+ : ((_b = scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.gap) !== null && _b !== void 0 ? _b : `calc((1.4rem - ${util.styleHelper(thickness)}) / 2)`), marginTop: type.isVertical(direction)
351
456
  ? 2
352
- : ((_b = scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.gap) !== null && _b !== void 0 ? _b : `calc((1.4rem - ${styleHelper(thickness)}) / 2)`) }, scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.style), children: scalesList.map((item, index) => {
353
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
354
- return (jsxRuntime.jsxs("div", { style: {
457
+ : ((_c = scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.gap) !== null && _c !== void 0 ? _c : `calc((1.4rem - ${util.styleHelper(thickness)}) / 2)`) }, scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.style)), children: scalesList.map((item, index) => {
458
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
459
+ return (jsxRuntime.jsxs("div", { css: react.css({
355
460
  display: 'flex',
356
- flexDirection: isHorizontal(direction) ? 'column' : 'row',
461
+ flexDirection: type.isHorizontal(direction) ? 'column' : 'row',
357
462
  justifyContent: 'center',
358
463
  alignItems: 'center',
359
464
  position: 'absolute',
360
- left: isHorizontal(direction)
361
- ? `${isReversed(direction)
362
- ? 100 - normalizeValue(item.at, min, max, skew) * 100
363
- : normalizeValue(item.at, min, max, skew) * 100}%`
465
+ left: type.isHorizontal(direction)
466
+ ? `${type.isReversed(direction)
467
+ ? 100 - math.normalizeValue(item.at, min, max, skew) * 100
468
+ : math.normalizeValue(item.at, min, max, skew) * 100}%`
364
469
  : undefined,
365
- top: isVertical(direction)
366
- ? `${isReversed(direction)
367
- ? 100 - normalizeValue(item.at, min, max, skew) * 100
368
- : normalizeValue(item.at, min, max, skew) * 100}%`
470
+ top: type.isVertical(direction)
471
+ ? `${type.isReversed(direction)
472
+ ? 100 - math.normalizeValue(item.at, min, max, skew) * 100
473
+ : math.normalizeValue(item.at, min, max, skew) * 100}%`
369
474
  : undefined,
370
- translate: isHorizontal(direction) ? '-50% 0' : '0 -50%',
475
+ translate: type.isHorizontal(direction) ? '-50% 0' : '0 -50%',
371
476
  zIndex: 10,
372
- }, children: [item.type != 'number' && (jsxRuntime.jsx("div", { className: "tremolo-slider-scale-mark", style: {
373
- width: isHorizontal(direction)
374
- ? ((_b = (_a = item.style) === null || _a === void 0 ? void 0 : _a.thickness) !== null && _b !== void 0 ? _b : 1)
375
- : ((_d = (_c = item.style) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : '0.5rem'),
376
- height: isVertical(direction)
377
- ? ((_f = (_e = item.style) === null || _e === void 0 ? void 0 : _e.thickness) !== null && _f !== void 0 ? _f : 1)
378
- : ((_h = (_g = item.style) === null || _g === void 0 ? void 0 : _g.length) !== null && _h !== void 0 ? _h : '0.5rem'),
379
- backgroundColor: (_l = (_k = (_j = item.style) === null || _j === void 0 ? void 0 : _j.markColor) !== null && _k !== void 0 ? _k : scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.markColor) !== null && _l !== void 0 ? _l : '#222',
380
- marginBottom: isHorizontal(direction) ? 2 : undefined,
381
- marginRight: isVertical(direction) ? 2 : undefined,
382
- } })), item.type != 'mark' && (jsxRuntime.jsx("div", { className: "tremolo-slider-scale-number", style: {
383
- color: (_o = (_m = item.style) === null || _m === void 0 ? void 0 : _m.labelColor) !== null && _o !== void 0 ? _o : scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.labelColor,
384
- }, children: item.at }))] }, index));
477
+ }), children: [((_b = (_a = item.type) !== null && _a !== void 0 ? _a : scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.defaultType) !== null && _b !== void 0 ? _b : 'mark-number') !=
478
+ 'number' && (jsxRuntime.jsx("div", { className: "tremolo-slider-scale-mark", css: react.css({
479
+ width: type.isHorizontal(direction)
480
+ ? ((_d = (_c = item.style) === null || _c === void 0 ? void 0 : _c.thickness) !== null && _d !== void 0 ? _d : 1)
481
+ : ((_f = (_e = item.style) === null || _e === void 0 ? void 0 : _e.length) !== null && _f !== void 0 ? _f : '0.5rem'),
482
+ height: type.isVertical(direction)
483
+ ? ((_h = (_g = item.style) === null || _g === void 0 ? void 0 : _g.thickness) !== null && _h !== void 0 ? _h : 1)
484
+ : ((_k = (_j = item.style) === null || _j === void 0 ? void 0 : _j.length) !== null && _k !== void 0 ? _k : '0.5rem'),
485
+ backgroundColor: (_o = (_m = (_l = item.style) === null || _l === void 0 ? void 0 : _l.markColor) !== null && _m !== void 0 ? _m : scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.markColor) !== null && _o !== void 0 ? _o : '#222',
486
+ marginBottom: type.isHorizontal(direction) ? 2 : undefined,
487
+ marginRight: type.isVertical(direction) ? 2 : undefined,
488
+ }) })), ((_q = (_p = item.type) !== null && _p !== void 0 ? _p : scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.defaultType) !== null && _q !== void 0 ? _q : 'mark-number') !=
489
+ 'mark' && (jsxRuntime.jsx("div", { className: "tremolo-slider-scale-number", css: react.css({
490
+ color: (_s = (_r = item.style) === null || _r === void 0 ? void 0 : _r.labelColor) !== null && _s !== void 0 ? _s : scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.labelColor,
491
+ width: scaleOption === null || scaleOption === void 0 ? void 0 : scaleOption.labelWidth,
492
+ textAlign: 'right',
493
+ }), children: (_t = item.text) !== null && _t !== void 0 ? _t : item.at }))] }, index));
385
494
  }) }))] })] }));
386
495
  }
387
496
 
388
497
  exports.Knob = Knob;
389
498
  exports.Slider = Slider;
390
- exports.clamp = clamp;
391
- exports.decimalPart = decimalPart;
392
- exports.normalizeValue = normalizeValue;
393
- exports.rawValue = rawValue;
394
- exports.skewWithCenterValue = skewWithCenterValue;
395
- exports.stepValue = stepValue;
396
- exports.toFixed = toFixed;
499
+ Object.keys(math).forEach(function (k) {
500
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
501
+ enumerable: true,
502
+ get: function () { return math[k]; }
503
+ });
504
+ });
397
505
  //# sourceMappingURL=index.js.map