@tremolo-ui/react 0.1.3 → 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 CHANGED
@@ -26,8 +26,6 @@ const react = __toESM(require("react"));
26
26
  const react_jsx_runtime = __toESM(require("react/jsx-runtime"));
27
27
  const __tremolo_ui_functions = __toESM(require("@tremolo-ui/functions"));
28
28
  const zustand = __toESM(require("zustand"));
29
- const __tremolo_ui_functions_NumberInput = __toESM(require("@tremolo-ui/functions/NumberInput"));
30
- const __tremolo_ui_functions_Slider = __toESM(require("@tremolo-ui/functions/Slider"));
31
29
 
32
30
  //#region src/components/AnimationCanvas/canvas.ts
33
31
  const drawingState = [
@@ -50,9 +48,6 @@ const drawingState = [
50
48
  "direction",
51
49
  "imageSmoothingEnabled"
52
50
  ];
53
-
54
- //#endregion
55
- //#region src/components/AnimationCanvas/index.tsx
56
51
  function setDprConfig(canvas, context, width, height, dpr) {
57
52
  canvas.width = width * dpr;
58
53
  canvas.height = height * dpr;
@@ -61,7 +56,10 @@ function setDprConfig(canvas, context, width, height, dpr) {
61
56
  canvas.style.width = `${width}px`;
62
57
  canvas.style.height = `${height}px`;
63
58
  }
64
- function AnimationCanvas({ options, init, draw, width = 100, height = 100, relativeSize, reduceFlickering = true, className, onContextMenu = (event) => event.preventDefault(),...props }) {
59
+
60
+ //#endregion
61
+ //#region src/components/AnimationCanvas/index.tsx
62
+ function AnimationCanvas({ draw, init, animate = true, options, width: _width = 100, height: _height = 100, relativeSize, reduceFlickering = true, className, onContextMenu = (event) => event.preventDefault(),...props }) {
65
63
  const canvasRef = (0, react.useRef)(null);
66
64
  const memoCanvasRef = (0, react.useRef)(null);
67
65
  const reqIdRef = (0, react.useRef)(-1);
@@ -69,27 +67,40 @@ function AnimationCanvas({ options, init, draw, width = 100, height = 100, relat
69
67
  const heightRef = (0, react.useRef)(0);
70
68
  const deltaMemoRef = (0, react.useRef)(-1);
71
69
  const startTimeRef = (0, react.useRef)(-1);
72
- const loop = (0, react.useCallback)((context, width$1, height$1, count) => {
70
+ const loop = (0, react.useCallback)((context, width, height, count) => {
73
71
  const now = performance.now();
74
72
  const deltaTime = now - deltaMemoRef.current;
75
73
  const elapsedTime = now - startTimeRef.current;
76
74
  deltaMemoRef.current = now;
77
- reqIdRef.current = requestAnimationFrame(() => loop(context, width$1, height$1, count + 1));
75
+ if (animate) reqIdRef.current = requestAnimationFrame(() => loop(context, width, height, count + 1));
78
76
  draw(context, {
79
- width: width$1.current,
80
- height: height$1.current,
77
+ width: width.current,
78
+ height: height.current,
81
79
  count: count + 1,
82
80
  deltaTime,
83
81
  elapsedTime,
84
82
  fps: 1e3 / deltaTime
85
83
  });
86
- }, [draw]);
84
+ }, [draw, animate]);
87
85
  (0, react.useEffect)(() => {
88
86
  if (!canvasRef.current) return;
89
87
  const canvas = canvasRef.current;
90
88
  const context = canvas.getContext("2d", options);
91
89
  if (!context) throw new Error("Cannot get canvas context.");
92
90
  const dpr = globalThis.devicePixelRatio;
91
+ const firstRendering = (width, height) => {
92
+ setDprConfig(canvas, context, width, height, dpr);
93
+ widthRef.current = width;
94
+ heightRef.current = height;
95
+ if (init) init(context, {
96
+ width,
97
+ height
98
+ });
99
+ const now = performance.now();
100
+ deltaMemoRef.current = now;
101
+ startTimeRef.current = now;
102
+ loop(context, widthRef, heightRef, -1);
103
+ };
93
104
  if (relativeSize) {
94
105
  const parent = canvas.parentElement;
95
106
  if (!parent) throw new Error("Canvas doesn't have a parent element.");
@@ -97,52 +108,37 @@ function AnimationCanvas({ options, init, draw, width = 100, height = 100, relat
97
108
  const memoContext = memoCanvas?.getContext("2d", options);
98
109
  const ro = new ResizeObserver((entries) => {
99
110
  for (const entry of entries) {
111
+ const w = entry.contentRect.width;
112
+ const h = entry.contentRect.height;
100
113
  const contextMemo = {};
101
- for (const prop of drawingState) contextMemo[prop] = context[prop];
102
- const w$1 = entry.contentRect.width;
103
- const h$1 = entry.contentRect.height;
104
114
  if (reduceFlickering && memoCanvas && memoContext) {
105
- memoCanvas.width = w$1 * dpr;
106
- memoCanvas.height = h$1 * dpr;
115
+ for (const prop of drawingState) contextMemo[prop] = context[prop];
116
+ memoCanvas.width = w * dpr;
117
+ memoCanvas.height = h * dpr;
107
118
  memoContext.scale(1 / dpr, 1 / dpr);
108
119
  if (canvas.width > 0 && canvas.height > 0) memoContext.drawImage(canvas, 0, 0);
109
120
  }
110
- setDprConfig(canvas, context, w$1, h$1, dpr);
111
- widthRef.current = w$1;
112
- heightRef.current = h$1;
113
- for (const prop of drawingState) context[prop] = contextMemo[prop];
114
- if (reduceFlickering && memoContext && memoCanvas && memoCanvas.width > 0 && memoCanvas.height > 0) context.drawImage(memoContext.canvas, 0, 0);
121
+ setDprConfig(canvas, context, w, h, dpr);
122
+ widthRef.current = w;
123
+ heightRef.current = h;
124
+ if (reduceFlickering && memoContext && memoCanvas && memoCanvas.width > 0 && memoCanvas.height > 0) {
125
+ for (const prop of drawingState) context[prop] = contextMemo[prop];
126
+ context.drawImage(memoContext.canvas, 0, 0);
127
+ }
128
+ if (!animate) loop(context, widthRef, heightRef, -1);
115
129
  }
116
130
  });
117
131
  ro.observe(parent);
118
- const w = parent.clientWidth;
119
- const h = parent.clientHeight;
120
- setDprConfig(canvas, context, w, h, dpr);
121
- if (init) init(context, {
122
- width: widthRef.current,
123
- height: heightRef.current
124
- });
125
- const now = performance.now();
126
- deltaMemoRef.current = now;
127
- startTimeRef.current = now;
128
- loop(context, widthRef, heightRef, -1);
132
+ const width = parent.clientWidth;
133
+ const height = parent.clientHeight;
134
+ firstRendering(width, height);
129
135
  return () => {
130
136
  if (reqIdRef.current) cancelAnimationFrame(reqIdRef.current);
131
137
  ro.disconnect();
132
138
  };
133
139
  } else {
134
- const rect = canvas.getBoundingClientRect();
135
- setDprConfig(canvas, context, rect.width, rect.height, dpr);
136
- widthRef.current = rect.width;
137
- heightRef.current = rect.height;
138
- if (init) init(context, {
139
- width: widthRef.current,
140
- height: heightRef.current
141
- });
142
- const now = performance.now();
143
- deltaMemoRef.current = now;
144
- startTimeRef.current = now;
145
- loop(context, widthRef, heightRef, -1);
140
+ const { width, height } = canvas.getBoundingClientRect();
141
+ firstRendering(width, height);
146
142
  return () => {
147
143
  if (reqIdRef.current) cancelAnimationFrame(reqIdRef.current);
148
144
  };
@@ -152,12 +148,13 @@ function AnimationCanvas({ options, init, draw, width = 100, height = 100, relat
152
148
  init,
153
149
  options,
154
150
  reduceFlickering,
155
- relativeSize
151
+ relativeSize,
152
+ animate
156
153
  ]);
157
154
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
158
155
  className: (0, clsx.default)("tremolo-animation-canvas", className),
159
- width: relativeSize ? 0 : width,
160
- height: relativeSize ? 0 : height,
156
+ width: relativeSize ? 0 : _width,
157
+ height: relativeSize ? 0 : _height,
161
158
  ref: canvasRef,
162
159
  onContextMenu,
163
160
  ...props
@@ -637,6 +634,47 @@ const Knob = (0, react.forwardRef)(({ value, min, max, step = 1, skew = 1, defau
637
634
  });
638
635
  });
639
636
 
637
+ //#endregion
638
+ //#region src/components/NumberInput/type.ts
639
+ function selectUnit(units, value) {
640
+ let i = 0;
641
+ for (; i < units.length; i++) if (Math.abs(units[i][1]) > Math.abs(value)) break;
642
+ return units[Math.max(0, i - 1)];
643
+ }
644
+ function parseValue(inputString, units, digit) {
645
+ const str = inputString.trim();
646
+ if (!units || typeof units == "string") {
647
+ const m$1 = str.match(/-?\d+(\.\d+)?/);
648
+ let v = Number(m$1?.[0] ?? "0");
649
+ v = isNaN(v) ? 0 : v;
650
+ return {
651
+ rawValue: v,
652
+ formatValue: (digit != void 0 ? v.toFixed(digit) : v) + (units ?? ""),
653
+ unit: units ?? ""
654
+ };
655
+ }
656
+ const unitList = units.map(([u, _s]) => u);
657
+ const scaleList = units.map(([_u, s]) => s);
658
+ let rawValue$5 = 0;
659
+ let unit = unitList[0];
660
+ let formatValue = (digit != void 0 ? rawValue$5.toFixed(digit) : rawValue$5) + unit;
661
+ const m = str.match(/^(-?\d+(\.\d+)?)\s*(\w*)$/);
662
+ if (m) {
663
+ rawValue$5 = Number(m[1]) || 0;
664
+ const uIndex = unitList.indexOf(m[3]);
665
+ rawValue$5 *= uIndex != -1 ? scaleList[uIndex] : 1;
666
+ const [u, scale] = selectUnit(units, rawValue$5);
667
+ const v = rawValue$5 / scale;
668
+ formatValue = (digit != void 0 ? v.toFixed(digit) : v) + u;
669
+ unit = u;
670
+ }
671
+ return {
672
+ rawValue: rawValue$5,
673
+ formatValue,
674
+ unit
675
+ };
676
+ }
677
+
640
678
  //#endregion
641
679
  //#region src/components/NumberInput/context.tsx
642
680
  function safeClamp(value, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) {
@@ -656,14 +694,14 @@ const createNumberInputStore = (initProps) => {
656
694
  return (0, zustand.createStore)()((set) => ({
657
695
  ...DEFAULT_PROPS,
658
696
  ...initProps,
659
- value: (0, __tremolo_ui_functions_NumberInput.parseValue)(String(initProps?.value || ""), initProps?.units, initProps?.digit).formatValue,
660
- valueAsNumber: (0, __tremolo_ui_functions_NumberInput.parseValue)(String(initProps?.value || ""), initProps?.units, initProps?.digit).rawValue,
697
+ value: parseValue(String(initProps?.value || ""), initProps?.units, initProps?.digit).formatValue,
698
+ valueAsNumber: parseValue(String(initProps?.value || ""), initProps?.units, initProps?.digit).rawValue,
661
699
  increment: () => set((state) => {
662
700
  if (state.readonly) return {};
663
- const current = (0, __tremolo_ui_functions_NumberInput.parseValue)(state.value, state.units, state.digit).rawValue;
701
+ const current = parseValue(state.value, state.units, state.digit).rawValue;
664
702
  let next = current + (state.step ?? 1);
665
703
  if (state.keepWithinRange) next = safeClamp(next, state.min, state.max);
666
- const v = (0, __tremolo_ui_functions_NumberInput.parseValue)(String(next), state.units, state.digit).formatValue;
704
+ const v = parseValue(String(next), state.units, state.digit).formatValue;
667
705
  state?.onChange?.(next, v);
668
706
  return {
669
707
  value: v,
@@ -672,10 +710,10 @@ const createNumberInputStore = (initProps) => {
672
710
  }),
673
711
  decrement: () => set((state) => {
674
712
  if (state.readonly) return {};
675
- const current = (0, __tremolo_ui_functions_NumberInput.parseValue)(state.value, state.units, state.digit).rawValue;
713
+ const current = parseValue(state.value, state.units, state.digit).rawValue;
676
714
  let next = current - (state.step ?? 1);
677
715
  if (state.keepWithinRange) next = safeClamp(next, state.min, state.max);
678
- const v = (0, __tremolo_ui_functions_NumberInput.parseValue)(String(next), state.units, state.digit).formatValue;
716
+ const v = parseValue(String(next), state.units, state.digit).formatValue;
679
717
  state?.onChange?.(next, v);
680
718
  return {
681
719
  value: v,
@@ -687,7 +725,7 @@ const createNumberInputStore = (initProps) => {
687
725
  const v = value ?? "";
688
726
  return {
689
727
  value: v,
690
- valueAsNumber: (0, __tremolo_ui_functions_NumberInput.parseValue)(v, state.units, state.digit).rawValue
728
+ valueAsNumber: parseValue(v, state.units, state.digit).rawValue
691
729
  };
692
730
  })
693
731
  }));
@@ -698,7 +736,7 @@ function NumberInputProvider({ children,...props }) {
698
736
  if (!storeRef.current) storeRef.current = createNumberInputStore(props);
699
737
  (0, react.useEffect)(() => {
700
738
  if (storeRef.current) {
701
- const parsed = (0, __tremolo_ui_functions_NumberInput.parseValue)(String(props?.value || ""), props?.units, props?.digit);
739
+ const parsed = parseValue(String(props?.value || ""), props?.units, props?.digit);
702
740
  storeRef.current.setState({
703
741
  ...props,
704
742
  value: parsed.formatValue,
@@ -764,7 +802,7 @@ const InternalInput = (0, react.forwardRef)(({ disabled, readonly, selectWithFoc
764
802
  if (!["ArrowUp", "ArrowDown"].includes(key)) return;
765
803
  event.preventDefault();
766
804
  const x = key == "ArrowUp" ? keyboard[1] : -keyboard[1];
767
- const parsed = (0, __tremolo_ui_functions_NumberInput.parseValue)(String(updateValueByEvent(keyboard[0], x)));
805
+ const parsed = parseValue(String(updateValueByEvent(keyboard[0], x)));
768
806
  onChange?.(parsed.rawValue, parsed.formatValue);
769
807
  }, [
770
808
  keyboard,
@@ -777,7 +815,7 @@ const InternalInput = (0, react.forwardRef)(({ disabled, readonly, selectWithFoc
777
815
  event.preventDefault();
778
816
  if (!onChange || event.deltaY == 0) return;
779
817
  const x = Math.sign(event.deltaY) * -wheel[1];
780
- const parsed = (0, __tremolo_ui_functions_NumberInput.parseValue)(String(updateValueByEvent(wheel[0], x)));
818
+ const parsed = parseValue(String(updateValueByEvent(wheel[0], x)));
781
819
  onChange?.(parsed.rawValue, parsed.formatValue);
782
820
  }, { passive: false }, [
783
821
  wheel,
@@ -815,7 +853,7 @@ const InternalInput = (0, react.forwardRef)(({ disabled, readonly, selectWithFoc
815
853
  const v = event.currentTarget.value;
816
854
  const cursorPos = event.target.selectionStart;
817
855
  change(v);
818
- const valueAsNumber$1 = (0, __tremolo_ui_functions_NumberInput.parseValue)(v, units, digit).rawValue;
856
+ const valueAsNumber$1 = parseValue(v, units, digit).rawValue;
819
857
  onChange?.(valueAsNumber$1, v);
820
858
  if (cursorPos) {
821
859
  event.target.selectionStart = cursorPos;
@@ -825,16 +863,16 @@ const InternalInput = (0, react.forwardRef)(({ disabled, readonly, selectWithFoc
825
863
  onFocus: (event) => {
826
864
  setEditing(true);
827
865
  const v = event.currentTarget.value;
828
- const parsed = (0, __tremolo_ui_functions_NumberInput.parseValue)(v, units, digit);
866
+ const parsed = parseValue(v, units, digit);
829
867
  if (selectWithFocus == "all") event.currentTarget.setSelectionRange(0, v.length);
830
868
  else if (selectWithFocus == "number") event.currentTarget.setSelectionRange(0, parsed.formatValue.length - parsed.unit.length);
831
869
  onFocus?.(parsed.rawValue, parsed.formatValue, event);
832
870
  },
833
871
  onBlur: (event) => {
834
872
  setEditing(false);
835
- let v = (0, __tremolo_ui_functions_NumberInput.parseValue)(event.currentTarget.value, units, digit).rawValue;
873
+ let v = parseValue(event.currentTarget.value, units, digit).rawValue;
836
874
  if (clampValueOnBlur) v = safeClamp(v, min, max);
837
- const parsed = (0, __tremolo_ui_functions_NumberInput.parseValue)(String(v), units, digit);
875
+ const parsed = parseValue(String(v), units, digit);
838
876
  change(parsed.formatValue);
839
877
  if (clampValueOnBlur) onChange?.(parsed.rawValue, parsed.formatValue);
840
878
  onBlur?.(parsed.rawValue, parsed.formatValue, event);
@@ -1484,6 +1522,22 @@ function ScaleOption({ value, type = "mark-number", label, thickness = 1, length
1484
1522
  });
1485
1523
  }
1486
1524
 
1525
+ //#endregion
1526
+ //#region src/components/Slider/type.ts
1527
+ function generateOptionsList(options, min, max, step) {
1528
+ const optionsList = [];
1529
+ const per = options[0] == "step" ? step : options[0];
1530
+ const count = Math.floor(max / per) - Math.ceil(min / per) + 1;
1531
+ for (let i = 0; i < count; i++) {
1532
+ const value = (0, __tremolo_ui_functions.toFixed)(per * (Math.ceil(min / per) + i), (0, __tremolo_ui_functions.decimalPart)(per)?.length);
1533
+ optionsList.push({
1534
+ value,
1535
+ type: options[1]
1536
+ });
1537
+ }
1538
+ return optionsList;
1539
+ }
1540
+
1487
1541
  //#endregion
1488
1542
  //#region src/components/Slider/Scale.tsx
1489
1543
  /** @category Slider */
@@ -1493,7 +1547,7 @@ function Scale({ gap = 6, options, children, className, style,...props }) {
1493
1547
  const step = useSliderContext((s) => s.step);
1494
1548
  const vertical = useSliderContext((s) => s.vertical);
1495
1549
  const reverse = useSliderContext((s) => s.reverse);
1496
- const optionsList = options ? (0, __tremolo_ui_functions_Slider.generateOptionsList)(options, min, max, step) : [];
1550
+ const optionsList = options ? generateOptionsList(options, min, max, step) : [];
1497
1551
  if ((0, __tremolo_ui_functions.xor)(vertical, reverse)) optionsList.reverse();
1498
1552
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1499
1553
  className: (0, clsx.default)("tremolo-slider-scale", className),