@tremolo-ui/react 0.1.4 → 0.1.5
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 +116 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +27 -16
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +28 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +102 -48
- package/dist/index.js.map +1 -1
- package/package.json +14 -9
- package/src/components/AnimationCanvas/canvas.ts +16 -0
- package/src/components/AnimationCanvas/index.tsx +54 -71
- package/src/components/NumberInput/InternalInput.tsx +1 -1
- package/src/components/NumberInput/context.tsx +2 -1
- package/src/components/NumberInput/index.css +1 -0
- package/src/components/NumberInput/index.tsx +2 -1
- package/src/components/NumberInput/type.ts +58 -0
- package/src/components/Piano/index.tsx +1 -2
- package/src/components/Slider/Scale.tsx +1 -1
- package/src/components/Slider/ScaleOption.tsx +1 -1
- package/src/components/Slider/index.tsx +1 -0
- package/src/components/Slider/type.ts +26 -0
- package/src/index.ts +2 -1
- /package/src/styles/{index.css → global.css} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import clsx from "clsx";
|
|
2
2
|
import React, { createContext, createRef, forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useInsertionEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
-
import { clamp, isBlackKey, isWhiteKey, normalizeValue, noteKey, noteKeys, radian, rawValue, stepValue, styleHelper, toFixed, xor } from "@tremolo-ui/functions";
|
|
4
|
+
import { clamp, decimalPart, isBlackKey, isWhiteKey, normalizeValue, noteKey, noteKeys, radian, rawValue, stepValue, styleHelper, toFixed, xor } from "@tremolo-ui/functions";
|
|
5
5
|
import { createStore, useStore } from "zustand";
|
|
6
|
-
import { parseValue } from "@tremolo-ui/functions/NumberInput";
|
|
7
|
-
import { generateOptionsList } from "@tremolo-ui/functions/Slider";
|
|
8
6
|
|
|
9
7
|
//#region src/components/AnimationCanvas/canvas.ts
|
|
10
8
|
const drawingState = [
|
|
@@ -27,9 +25,6 @@ const drawingState = [
|
|
|
27
25
|
"direction",
|
|
28
26
|
"imageSmoothingEnabled"
|
|
29
27
|
];
|
|
30
|
-
|
|
31
|
-
//#endregion
|
|
32
|
-
//#region src/components/AnimationCanvas/index.tsx
|
|
33
28
|
function setDprConfig(canvas, context, width, height, dpr) {
|
|
34
29
|
canvas.width = width * dpr;
|
|
35
30
|
canvas.height = height * dpr;
|
|
@@ -38,7 +33,10 @@ function setDprConfig(canvas, context, width, height, dpr) {
|
|
|
38
33
|
canvas.style.width = `${width}px`;
|
|
39
34
|
canvas.style.height = `${height}px`;
|
|
40
35
|
}
|
|
41
|
-
|
|
36
|
+
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/components/AnimationCanvas/index.tsx
|
|
39
|
+
function AnimationCanvas({ draw, init, animate = true, options, width: _width = 100, height: _height = 100, relativeSize, reduceFlickering = true, className, onContextMenu = (event) => event.preventDefault(),...props }) {
|
|
42
40
|
const canvasRef = useRef(null);
|
|
43
41
|
const memoCanvasRef = useRef(null);
|
|
44
42
|
const reqIdRef = useRef(-1);
|
|
@@ -46,27 +44,40 @@ function AnimationCanvas({ options, init, draw, width = 100, height = 100, relat
|
|
|
46
44
|
const heightRef = useRef(0);
|
|
47
45
|
const deltaMemoRef = useRef(-1);
|
|
48
46
|
const startTimeRef = useRef(-1);
|
|
49
|
-
const loop = useCallback((context, width
|
|
47
|
+
const loop = useCallback((context, width, height, count) => {
|
|
50
48
|
const now = performance.now();
|
|
51
49
|
const deltaTime = now - deltaMemoRef.current;
|
|
52
50
|
const elapsedTime = now - startTimeRef.current;
|
|
53
51
|
deltaMemoRef.current = now;
|
|
54
|
-
reqIdRef.current = requestAnimationFrame(() => loop(context, width
|
|
52
|
+
if (animate) reqIdRef.current = requestAnimationFrame(() => loop(context, width, height, count + 1));
|
|
55
53
|
draw(context, {
|
|
56
|
-
width: width
|
|
57
|
-
height: height
|
|
54
|
+
width: width.current,
|
|
55
|
+
height: height.current,
|
|
58
56
|
count: count + 1,
|
|
59
57
|
deltaTime,
|
|
60
58
|
elapsedTime,
|
|
61
59
|
fps: 1e3 / deltaTime
|
|
62
60
|
});
|
|
63
|
-
}, [draw]);
|
|
61
|
+
}, [draw, animate]);
|
|
64
62
|
useEffect(() => {
|
|
65
63
|
if (!canvasRef.current) return;
|
|
66
64
|
const canvas = canvasRef.current;
|
|
67
65
|
const context = canvas.getContext("2d", options);
|
|
68
66
|
if (!context) throw new Error("Cannot get canvas context.");
|
|
69
67
|
const dpr = globalThis.devicePixelRatio;
|
|
68
|
+
const firstRendering = (width, height) => {
|
|
69
|
+
setDprConfig(canvas, context, width, height, dpr);
|
|
70
|
+
widthRef.current = width;
|
|
71
|
+
heightRef.current = height;
|
|
72
|
+
if (init) init(context, {
|
|
73
|
+
width,
|
|
74
|
+
height
|
|
75
|
+
});
|
|
76
|
+
const now = performance.now();
|
|
77
|
+
deltaMemoRef.current = now;
|
|
78
|
+
startTimeRef.current = now;
|
|
79
|
+
loop(context, widthRef, heightRef, -1);
|
|
80
|
+
};
|
|
70
81
|
if (relativeSize) {
|
|
71
82
|
const parent = canvas.parentElement;
|
|
72
83
|
if (!parent) throw new Error("Canvas doesn't have a parent element.");
|
|
@@ -74,52 +85,37 @@ function AnimationCanvas({ options, init, draw, width = 100, height = 100, relat
|
|
|
74
85
|
const memoContext = memoCanvas?.getContext("2d", options);
|
|
75
86
|
const ro = new ResizeObserver((entries) => {
|
|
76
87
|
for (const entry of entries) {
|
|
88
|
+
const w = entry.contentRect.width;
|
|
89
|
+
const h = entry.contentRect.height;
|
|
77
90
|
const contextMemo = {};
|
|
78
|
-
for (const prop of drawingState) contextMemo[prop] = context[prop];
|
|
79
|
-
const w$1 = entry.contentRect.width;
|
|
80
|
-
const h$1 = entry.contentRect.height;
|
|
81
91
|
if (reduceFlickering && memoCanvas && memoContext) {
|
|
82
|
-
|
|
83
|
-
memoCanvas.
|
|
92
|
+
for (const prop of drawingState) contextMemo[prop] = context[prop];
|
|
93
|
+
memoCanvas.width = w * dpr;
|
|
94
|
+
memoCanvas.height = h * dpr;
|
|
84
95
|
memoContext.scale(1 / dpr, 1 / dpr);
|
|
85
96
|
if (canvas.width > 0 && canvas.height > 0) memoContext.drawImage(canvas, 0, 0);
|
|
86
97
|
}
|
|
87
|
-
setDprConfig(canvas, context, w
|
|
88
|
-
widthRef.current = w
|
|
89
|
-
heightRef.current = h
|
|
90
|
-
|
|
91
|
-
|
|
98
|
+
setDprConfig(canvas, context, w, h, dpr);
|
|
99
|
+
widthRef.current = w;
|
|
100
|
+
heightRef.current = h;
|
|
101
|
+
if (reduceFlickering && memoContext && memoCanvas && memoCanvas.width > 0 && memoCanvas.height > 0) {
|
|
102
|
+
for (const prop of drawingState) context[prop] = contextMemo[prop];
|
|
103
|
+
context.drawImage(memoContext.canvas, 0, 0);
|
|
104
|
+
}
|
|
105
|
+
if (!animate) loop(context, widthRef, heightRef, -1);
|
|
92
106
|
}
|
|
93
107
|
});
|
|
94
108
|
ro.observe(parent);
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
if (init) init(context, {
|
|
99
|
-
width: widthRef.current,
|
|
100
|
-
height: heightRef.current
|
|
101
|
-
});
|
|
102
|
-
const now = performance.now();
|
|
103
|
-
deltaMemoRef.current = now;
|
|
104
|
-
startTimeRef.current = now;
|
|
105
|
-
loop(context, widthRef, heightRef, -1);
|
|
109
|
+
const width = parent.clientWidth;
|
|
110
|
+
const height = parent.clientHeight;
|
|
111
|
+
firstRendering(width, height);
|
|
106
112
|
return () => {
|
|
107
113
|
if (reqIdRef.current) cancelAnimationFrame(reqIdRef.current);
|
|
108
114
|
ro.disconnect();
|
|
109
115
|
};
|
|
110
116
|
} else {
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
widthRef.current = rect.width;
|
|
114
|
-
heightRef.current = rect.height;
|
|
115
|
-
if (init) init(context, {
|
|
116
|
-
width: widthRef.current,
|
|
117
|
-
height: heightRef.current
|
|
118
|
-
});
|
|
119
|
-
const now = performance.now();
|
|
120
|
-
deltaMemoRef.current = now;
|
|
121
|
-
startTimeRef.current = now;
|
|
122
|
-
loop(context, widthRef, heightRef, -1);
|
|
117
|
+
const { width, height } = canvas.getBoundingClientRect();
|
|
118
|
+
firstRendering(width, height);
|
|
123
119
|
return () => {
|
|
124
120
|
if (reqIdRef.current) cancelAnimationFrame(reqIdRef.current);
|
|
125
121
|
};
|
|
@@ -129,12 +125,13 @@ function AnimationCanvas({ options, init, draw, width = 100, height = 100, relat
|
|
|
129
125
|
init,
|
|
130
126
|
options,
|
|
131
127
|
reduceFlickering,
|
|
132
|
-
relativeSize
|
|
128
|
+
relativeSize,
|
|
129
|
+
animate
|
|
133
130
|
]);
|
|
134
131
|
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("canvas", {
|
|
135
132
|
className: clsx("tremolo-animation-canvas", className),
|
|
136
|
-
width: relativeSize ? 0 :
|
|
137
|
-
height: relativeSize ? 0 :
|
|
133
|
+
width: relativeSize ? 0 : _width,
|
|
134
|
+
height: relativeSize ? 0 : _height,
|
|
138
135
|
ref: canvasRef,
|
|
139
136
|
onContextMenu,
|
|
140
137
|
...props
|
|
@@ -614,6 +611,47 @@ const Knob = forwardRef(({ value, min, max, step = 1, skew = 1, defaultValue = m
|
|
|
614
611
|
});
|
|
615
612
|
});
|
|
616
613
|
|
|
614
|
+
//#endregion
|
|
615
|
+
//#region src/components/NumberInput/type.ts
|
|
616
|
+
function selectUnit(units, value) {
|
|
617
|
+
let i = 0;
|
|
618
|
+
for (; i < units.length; i++) if (Math.abs(units[i][1]) > Math.abs(value)) break;
|
|
619
|
+
return units[Math.max(0, i - 1)];
|
|
620
|
+
}
|
|
621
|
+
function parseValue(inputString, units, digit) {
|
|
622
|
+
const str = inputString.trim();
|
|
623
|
+
if (!units || typeof units == "string") {
|
|
624
|
+
const m$1 = str.match(/-?\d+(\.\d+)?/);
|
|
625
|
+
let v = Number(m$1?.[0] ?? "0");
|
|
626
|
+
v = isNaN(v) ? 0 : v;
|
|
627
|
+
return {
|
|
628
|
+
rawValue: v,
|
|
629
|
+
formatValue: (digit != void 0 ? v.toFixed(digit) : v) + (units ?? ""),
|
|
630
|
+
unit: units ?? ""
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
const unitList = units.map(([u, _s]) => u);
|
|
634
|
+
const scaleList = units.map(([_u, s]) => s);
|
|
635
|
+
let rawValue$1 = 0;
|
|
636
|
+
let unit = unitList[0];
|
|
637
|
+
let formatValue = (digit != void 0 ? rawValue$1.toFixed(digit) : rawValue$1) + unit;
|
|
638
|
+
const m = str.match(/^(-?\d+(\.\d+)?)\s*(\w*)$/);
|
|
639
|
+
if (m) {
|
|
640
|
+
rawValue$1 = Number(m[1]) || 0;
|
|
641
|
+
const uIndex = unitList.indexOf(m[3]);
|
|
642
|
+
rawValue$1 *= uIndex != -1 ? scaleList[uIndex] : 1;
|
|
643
|
+
const [u, scale] = selectUnit(units, rawValue$1);
|
|
644
|
+
const v = rawValue$1 / scale;
|
|
645
|
+
formatValue = (digit != void 0 ? v.toFixed(digit) : v) + u;
|
|
646
|
+
unit = u;
|
|
647
|
+
}
|
|
648
|
+
return {
|
|
649
|
+
rawValue: rawValue$1,
|
|
650
|
+
formatValue,
|
|
651
|
+
unit
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
|
|
617
655
|
//#endregion
|
|
618
656
|
//#region src/components/NumberInput/context.tsx
|
|
619
657
|
function safeClamp(value, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) {
|
|
@@ -1461,6 +1499,22 @@ function ScaleOption({ value, type = "mark-number", label, thickness = 1, length
|
|
|
1461
1499
|
});
|
|
1462
1500
|
}
|
|
1463
1501
|
|
|
1502
|
+
//#endregion
|
|
1503
|
+
//#region src/components/Slider/type.ts
|
|
1504
|
+
function generateOptionsList(options, min, max, step) {
|
|
1505
|
+
const optionsList = [];
|
|
1506
|
+
const per = options[0] == "step" ? step : options[0];
|
|
1507
|
+
const count = Math.floor(max / per) - Math.ceil(min / per) + 1;
|
|
1508
|
+
for (let i = 0; i < count; i++) {
|
|
1509
|
+
const value = toFixed(per * (Math.ceil(min / per) + i), decimalPart(per)?.length);
|
|
1510
|
+
optionsList.push({
|
|
1511
|
+
value,
|
|
1512
|
+
type: options[1]
|
|
1513
|
+
});
|
|
1514
|
+
}
|
|
1515
|
+
return optionsList;
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1464
1518
|
//#endregion
|
|
1465
1519
|
//#region src/components/Slider/Scale.tsx
|
|
1466
1520
|
/** @category Slider */
|