@cutoff/audio-ui-core 1.0.0-preview.20260123.1125

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 (48) hide show
  1. package/LICENSE.md +690 -0
  2. package/dist/constants/cssVars.d.ts +42 -0
  3. package/dist/constants/cssVars.d.ts.map +1 -0
  4. package/dist/constants/cursors.d.ts +2 -0
  5. package/dist/constants/cursors.d.ts.map +1 -0
  6. package/dist/constants/interaction.d.ts +24 -0
  7. package/dist/constants/interaction.d.ts.map +1 -0
  8. package/dist/constants/styles.d.ts +17 -0
  9. package/dist/constants/styles.d.ts.map +1 -0
  10. package/dist/constants/theme.d.ts +66 -0
  11. package/dist/constants/theme.d.ts.map +1 -0
  12. package/dist/constants/themeDefaults.d.ts +16 -0
  13. package/dist/constants/themeDefaults.d.ts.map +1 -0
  14. package/dist/controller/BooleanInteractionController.d.ts +141 -0
  15. package/dist/controller/BooleanInteractionController.d.ts.map +1 -0
  16. package/dist/controller/ContinuousInteractionController.d.ts +114 -0
  17. package/dist/controller/ContinuousInteractionController.d.ts.map +1 -0
  18. package/dist/controller/DiscreteInteractionController.d.ts +51 -0
  19. package/dist/controller/DiscreteInteractionController.d.ts.map +1 -0
  20. package/dist/controller/NoteInteractionController.d.ts +88 -0
  21. package/dist/controller/NoteInteractionController.d.ts.map +1 -0
  22. package/dist/index.d.ts +21 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +1404 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/model/AudioParameter.d.ts +437 -0
  27. package/dist/model/AudioParameter.d.ts.map +1 -0
  28. package/dist/styles/styles.css +256 -0
  29. package/dist/styles/themes.css +193 -0
  30. package/dist/types.d.ts +18 -0
  31. package/dist/types.d.ts.map +1 -0
  32. package/dist/utils/colorUtils.d.ts +102 -0
  33. package/dist/utils/colorUtils.d.ts.map +1 -0
  34. package/dist/utils/math.d.ts +108 -0
  35. package/dist/utils/math.d.ts.map +1 -0
  36. package/dist/utils/normalizedProps.d.ts +22 -0
  37. package/dist/utils/normalizedProps.d.ts.map +1 -0
  38. package/dist/utils/noteUtils.d.ts +71 -0
  39. package/dist/utils/noteUtils.d.ts.map +1 -0
  40. package/dist/utils/propCompare.d.ts +22 -0
  41. package/dist/utils/propCompare.d.ts.map +1 -0
  42. package/dist/utils/sizing.d.ts +39 -0
  43. package/dist/utils/sizing.d.ts.map +1 -0
  44. package/dist/utils/svg.d.ts +27 -0
  45. package/dist/utils/svg.d.ts.map +1 -0
  46. package/dist/utils/valueFormatters.d.ts +167 -0
  47. package/dist/utils/valueFormatters.d.ts.map +1 -0
  48. package/package.json +48 -0
@@ -0,0 +1,193 @@
1
+ /*
2
+ * Copyright (c) 2026 Tylium.
3
+ * SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-TELF-1.0
4
+ * See LICENSE.md for details.
5
+ */
6
+
7
+ :root {
8
+ /* High-level theming parameters – Change this for global theme customization on default components */
9
+ --audioui-roundness-base: 0.3; /* Normalized 0.0-1.0 */
10
+ --audioui-primary-color: var(--audioui-adaptive-default-color);
11
+
12
+ /* Colors */
13
+
14
+ --audioui-nearwhite: hsl(0, 0%, 96%);
15
+ --audioui-nearblack: hsl(0, 0%, 10%);
16
+
17
+ /* Named color themes */
18
+ --audioui-theme-blue: hsl(204, 88%, 52%);
19
+ --audioui-theme-orange: hsl(29, 100%, 48%);
20
+ --audioui-theme-pink: hsl(332, 92%, 52%);
21
+ --audioui-theme-green: hsl(160, 95%, 44%);
22
+ --audioui-theme-purple: hsl(252, 96%, 54%);
23
+ --audioui-theme-yellow: hsl(50, 100%, 50%);
24
+
25
+ /* Default theme — adaptive: dark ink on light, light ink on dark */
26
+ --audioui-theme-default: var(--audioui-nearblack); /* Light mode: near-black */
27
+ /* CSS variable for adaptive default - resolves correctly on both server and client */
28
+ --audioui-adaptive-default-color: var(--audioui-theme-default);
29
+ --audioui-adaptive-50: color-mix(in srgb, var(--audioui-adaptive-default-color) 50%, transparent);
30
+ --audioui-adaptive-20: color-mix(in srgb, var(--audioui-adaptive-default-color) 20%, transparent);
31
+ /* Adaptive luminosity variants - lighter for dark mode, darker for light mode */
32
+ --audioui-adaptive-light: color-mix(in srgb, var(--audioui-adaptive-default-color) 80%, white);
33
+ --audioui-adaptive-dark: color-mix(in srgb, var(--audioui-adaptive-default-color) 80%, black);
34
+
35
+ /* Color variants (computed via color-mix) */
36
+ --audioui-primary-50: color-mix(in srgb, var(--audioui-primary-color) 50%, transparent);
37
+ --audioui-primary-20: color-mix(in srgb, var(--audioui-primary-color) 20%, transparent);
38
+ /* Primary luminosity variants - lighter and darker versions */
39
+ --audioui-primary-light: color-mix(in srgb, var(--audioui-primary-color) 80%, white);
40
+ --audioui-primary-dark: color-mix(in srgb, var(--audioui-primary-color) 80%, black);
41
+
42
+ /* Text and typography */
43
+ --audioui-text-color: var(--audioui-nearblack);
44
+ --audioui-default-font-size: 14px;
45
+
46
+ /* Interactive highlight effect - users can customize or disable entirely */
47
+ /* Set to 'none' to disable, or any valid CSS filter value for custom effects */
48
+ --audioui-highlight-effect: brightness(1.15) contrast(1.05)
49
+ drop-shadow(
50
+ 0 0 0.5em color-mix(in srgb, var(--audioui-primary-color, var(--audioui-text-color)) 35%, transparent)
51
+ );
52
+ --audioui-highlight-transition-duration: 50ms;
53
+
54
+ /* Cursor styles for interactive components - users can customize cursor types */
55
+ /* Variables are named after interaction functionality, not cursor type */
56
+ /* Default cursor values use SVG data URIs to ensure consistent behavior across browsers (fixing Safari regression with variable-based keyword cursors) */
57
+ --audioui-cursor-clickable: pointer; /* Clickable controls (Button, CycleButton, click-only controls) */
58
+ --audioui-cursor-bidirectional:
59
+ url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTYgN3YxOE03IDE2aDE4TTE2IDdsLTQgNE0xNiA3bDQgNE0xNiAyNWwtNC00TTE2IDI1bDQtNE03IDE2bDQtNE03IDE2bDQgNE0yNSAxNmwtNC00TTI1IDE2bC00IDQiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PHBhdGggZD0iTTE2IDd2MThNNyAxNmgxOE0xNiA3bC00IDRNMTYgN2w0IDRNMTYgMjVsLTQtNE0xNiAyNWw0LTRNNyAxNmw0LTRNNyAxNmw0IDRNMjUgMTZsLTQtNE0yNSAxNmwtNCA0IiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjwvc3ZnPg==")
60
+ 16 16,
61
+ move; /* Continuous controls with direction="both" */
62
+ --audioui-cursor-horizontal:
63
+ url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNyAxNmgxOE03IDE2bDUtNU03IDE2bDUgNU0yNSAxNmwtNS01TTI1IDE2bC01IDUiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PHBhdGggZD0iTTcgMTZoMThNNyAxNmw1LTVNNyAxNmw1IDVNMjUgMTZsLTUtNU0yNSAxNmwtNSA1IiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjwvc3ZnPg==")
64
+ 16 16,
65
+ ew-resize; /* Horizontal drag (horizontal sliders, horizontal knobs) */
66
+ --audioui-cursor-vertical:
67
+ url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTYgN3YxOE0xNiA3bC01IDVNMTYgN2w1IDVNMTYgMjVsLTUtNU0xNiAyNWw1LTUiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PHBhdGggZD0iTTE2IDd2MThNMTYgN2wtNSA1TTE2IDdsNSA1TTE2IDI1bC01LTVNMTYgMjVsNS01IiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjwvc3ZnPg==")
68
+ 16 16,
69
+ ns-resize; /* Vertical drag (vertical sliders, wheel-only controls) */
70
+ --audioui-cursor-circular:
71
+ url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSIxNiIgY3k9IjE2IiByPSIxMCIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSI0Ii8+PGNpcmNsZSBjeD0iMTYiIGN5PSIxNiIgcj0iMTAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMiIvPjwvc3ZnPg==")
72
+ 16 16,
73
+ move; /* Circular drag (knobs with direction="circular") */
74
+ --audioui-cursor-noneditable: default; /* Non-editable controls */
75
+ --audioui-cursor-disabled: not-allowed; /* Disabled controls */
76
+
77
+ /* Classic Piano Key Colors */
78
+ --audioui-keys-ivory: hsl(40, 20%, 95%); /* Warm off-white color for classic white keys */
79
+ --audioui-keys-ivory-stroke: hsl(40, 20%, 85%); /* Slightly darker for stroke contrast */
80
+ --audioui-keys-ebony: hsl(0, 0%, 15%); /* Deep black color for classic black keys */
81
+ --audioui-keys-ebony-stroke: hsl(0, 0%, 25%); /* Slightly lighter for stroke contrast */
82
+
83
+ /* Other component style customization */
84
+ --audioui-knob-cap-fill: #303030;
85
+ --audioui-button-stroke-width: 5px;
86
+
87
+ /* Slider component colors */
88
+ --audioui-slider-track-color: var(
89
+ --audioui-adaptive-20
90
+ ); /* Background track color (for all variants except abstract) */
91
+ --audioui-slider-strip-color: var(--audioui-primary-color); /* Foreground value strip color */
92
+ --audioui-slider-cursor-color: var(--audioui-primary-color); /* Cursor fill color */
93
+ --audioui-slider-cursor-border-color: var(
94
+ --audioui-primary-light
95
+ ); /* Cursor border color (luminosity variant for visibility) */
96
+ --audioui-slider-cursor-border-width: 5px; /* Cursor border width */
97
+
98
+ /* Component-specific roundness (calculated from base) */
99
+ --audioui-roundness-button: calc(var(--audioui-roundness-base) * 50px);
100
+ --audioui-roundness-knob: var(--audioui-roundness-base); /* Used as boolean in JS or linecap in CSS */
101
+ --audioui-roundness-slider: calc(var(--audioui-roundness-base) * 20px);
102
+ --audioui-roundness-keys: calc(var(--audioui-roundness-base) * 12px);
103
+
104
+ /* Derived Internal Variables - Not intended for direct customization */
105
+ /* These variables are automatically managed by the roundness attribute via theme setters and hooks */
106
+ --audioui-linecap-base: round; /* Inferred: 0.0 -> square, >0.0 -> round */
107
+ --audioui-linecap-knob: var(--audioui-linecap-base);
108
+ --audioui-linecap-slider: var(--audioui-linecap-base);
109
+ --audioui-linecap-button: var(--audioui-linecap-base);
110
+
111
+ /* Size System - Base Unit */
112
+ /* The atomic unit for consistent sizing across all components */
113
+ --audioui-unit: 48px;
114
+
115
+ /* Size Multipliers */
116
+ --audioui-size-mult-xsmall: 1;
117
+ --audioui-size-mult-small: 1.25;
118
+ --audioui-size-mult-normal: 1.5;
119
+ --audioui-size-mult-large: 2;
120
+ --audioui-size-mult-xlarge: 2.5;
121
+
122
+ /* Square Components (1x1): Button, Knob, CycleButton */
123
+ --audioui-size-square-xsmall: var(--audioui-unit);
124
+ --audioui-size-square-small: calc(var(--audioui-unit) * var(--audioui-size-mult-small));
125
+ --audioui-size-square-normal: calc(var(--audioui-unit) * var(--audioui-size-mult-normal));
126
+ --audioui-size-square-large: calc(var(--audioui-unit) * var(--audioui-size-mult-large));
127
+ --audioui-size-square-xlarge: calc(var(--audioui-unit) * var(--audioui-size-mult-xlarge));
128
+
129
+ /* Horizontal Slider (1x2): height = base, width = 2 * base (width > height) */
130
+ --audioui-size-hslider-height-xsmall: var(--audioui-unit);
131
+ --audioui-size-hslider-height-small: calc(var(--audioui-unit) * var(--audioui-size-mult-small));
132
+ --audioui-size-hslider-height-normal: calc(var(--audioui-unit) * var(--audioui-size-mult-normal));
133
+ --audioui-size-hslider-height-large: calc(var(--audioui-unit) * var(--audioui-size-mult-large));
134
+ --audioui-size-hslider-height-xlarge: calc(var(--audioui-unit) * var(--audioui-size-mult-xlarge));
135
+
136
+ --audioui-size-hslider-width-xsmall: calc(var(--audioui-size-hslider-height-xsmall) * 2);
137
+ --audioui-size-hslider-width-small: calc(var(--audioui-size-hslider-height-small) * 2);
138
+ --audioui-size-hslider-width-normal: calc(var(--audioui-size-hslider-height-normal) * 2);
139
+ --audioui-size-hslider-width-large: calc(var(--audioui-size-hslider-height-large) * 2);
140
+ --audioui-size-hslider-width-xlarge: calc(var(--audioui-size-hslider-height-xlarge) * 2);
141
+
142
+ /* Vertical Slider (2x1): width = base, height = 2 * base (height > width) */
143
+ --audioui-size-vslider-width-xsmall: var(--audioui-unit);
144
+ --audioui-size-vslider-width-small: calc(var(--audioui-unit) * var(--audioui-size-mult-small));
145
+ --audioui-size-vslider-width-normal: calc(var(--audioui-unit) * var(--audioui-size-mult-normal));
146
+ --audioui-size-vslider-width-large: calc(var(--audioui-unit) * var(--audioui-size-mult-large));
147
+ --audioui-size-vslider-width-xlarge: calc(var(--audioui-unit) * var(--audioui-size-mult-xlarge));
148
+
149
+ --audioui-size-vslider-height-xsmall: calc(var(--audioui-size-vslider-width-xsmall) * 2);
150
+ --audioui-size-vslider-height-small: calc(var(--audioui-size-vslider-width-small) * 2);
151
+ --audioui-size-vslider-height-normal: calc(var(--audioui-size-vslider-width-normal) * 2);
152
+ --audioui-size-vslider-height-large: calc(var(--audioui-size-vslider-width-large) * 2);
153
+ --audioui-size-vslider-height-xlarge: calc(var(--audioui-size-vslider-width-xlarge) * 2);
154
+
155
+ /* Keys (1x5): height = base, width = 5 * base (width > height) */
156
+ --audioui-size-keys-height-xsmall: var(--audioui-unit);
157
+ --audioui-size-keys-height-small: calc(var(--audioui-unit) * var(--audioui-size-mult-small));
158
+ --audioui-size-keys-height-normal: calc(var(--audioui-unit) * var(--audioui-size-mult-normal));
159
+ --audioui-size-keys-height-large: calc(var(--audioui-unit) * var(--audioui-size-mult-large));
160
+ --audioui-size-keys-height-xlarge: calc(var(--audioui-unit) * var(--audioui-size-mult-xlarge));
161
+
162
+ --audioui-size-keys-width-xsmall: calc(var(--audioui-size-keys-height-xsmall) * 5);
163
+ --audioui-size-keys-width-small: calc(var(--audioui-size-keys-height-small) * 5);
164
+ --audioui-size-keys-width-normal: calc(var(--audioui-size-keys-height-normal) * 5);
165
+ --audioui-size-keys-width-large: calc(var(--audioui-size-keys-height-large) * 5);
166
+ --audioui-size-keys-width-xlarge: calc(var(--audioui-size-keys-height-xlarge) * 5);
167
+ }
168
+
169
+ /* Dark mode overrides */
170
+ .dark {
171
+ /* Default theme — near-white ink in dark mode */
172
+ --audioui-theme-default: var(--audioui-nearwhite);
173
+ /* Adaptive default updates automatically via CSS variable */
174
+ --audioui-adaptive-default-color: var(--audioui-theme-default);
175
+
176
+ /* Named color themes (can have dark mode variants if needed) */
177
+ --audioui-theme-blue: hsl(204, 88%, 53%);
178
+ --audioui-theme-orange: hsl(29, 100%, 50%);
179
+ --audioui-theme-pink: hsl(332, 95%, 54%);
180
+ --audioui-theme-green: hsl(160, 98%, 37%);
181
+ --audioui-theme-purple: hsl(252, 100%, 67%);
182
+ --audioui-theme-yellow: hsl(50, 100%, 50%);
183
+
184
+ /* Text color for dark mode */
185
+ --audioui-text-color: var(--audioui-nearwhite);
186
+
187
+ /* Other component style customization */
188
+ --audioui-knob-cap-fill: #4a4d50;
189
+
190
+ --audioui-slider-cursor-border-color: var(
191
+ --audioui-primary-dark
192
+ ); /* Cursor border color (luminosity variant for visibility) */
193
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Size options for control components
3
+ */
4
+ export type SizeType = "xsmall" | "small" | "normal" | "large" | "xlarge";
5
+ /**
6
+ * Interaction modes for controls
7
+ */
8
+ export type InteractionMode = "drag" | "wheel" | "both";
9
+ /**
10
+ * Interaction directions for controls
11
+ */
12
+ export type InteractionDirection = "vertical" | "horizontal" | "circular" | "both";
13
+ /**
14
+ * MIDI resolution in bits
15
+ * Supported values: 7, 8, 14, 16, 32, 64
16
+ */
17
+ export type MidiResolution = 7 | 8 | 14 | 16 | 32 | 64;
18
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1E;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAExD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;AAEnF;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Detects if the current document is in dark mode.
3
+ *
4
+ * Checks both the document's class list (for `.dark` class) and the system preference
5
+ * via `prefers-color-scheme` media query. This ensures compatibility with frameworks
6
+ * like Tailwind CSS that use class-based dark mode.
7
+ *
8
+ * @returns true if dark mode is active, false otherwise
9
+ */
10
+ export declare function isDarkMode(): boolean;
11
+ /**
12
+ * Gets the adaptive default color (white in dark mode, black in light mode).
13
+ *
14
+ * Uses a CSS variable to ensure SSR and client render the same value, avoiding hydration mismatches.
15
+ * The actual color value is resolved by the browser based on the `.dark` class or system preference.
16
+ *
17
+ * @returns A CSS color value that adapts to the current color scheme
18
+ */
19
+ export declare function getAdaptiveDefaultColor(): string;
20
+ /**
21
+ * Generates a luminosity-based variant of a color.
22
+ *
23
+ * For named colors (blue, orange, pink, etc.), this function uses pre-computed HSL values
24
+ * for precise control. For other colors, it uses CSS `color-mix()` with black to darken.
25
+ *
26
+ * This is useful for creating visual hierarchies (e.g., primary50, primary20 variants)
27
+ * where you want progressively darker versions of a color.
28
+ *
29
+ * @param baseColor The base color (any valid CSS color value)
30
+ * @param luminosityPercentage The percentage of the original luminosity (0-100)
31
+ * @returns A CSS color value with adjusted luminosity
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * generateLuminosityVariant("blue", 50); // 50% darker blue
36
+ * generateLuminosityVariant("#ff0000", 20); // Much darker red
37
+ * ```
38
+ */
39
+ export declare function generateLuminosityVariant(baseColor: string, luminosityPercentage: number): string;
40
+ /**
41
+ * Generates a transparency-based variant of a color.
42
+ *
43
+ * Uses CSS `color-mix()` to blend the color with transparent, creating a semi-transparent
44
+ * version. This is useful for hover states, disabled states, or layered visual effects.
45
+ *
46
+ * @param baseColor The base color (any valid CSS color value)
47
+ * @param opacityPercentage The opacity percentage (0-100, where 100 is fully opaque)
48
+ * @returns A CSS color value with adjusted opacity
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * generateTransparencyVariant("blue", 50); // 50% transparent blue
53
+ * ```
54
+ */
55
+ export declare function generateTransparencyVariant(baseColor: string, opacityPercentage: number): string;
56
+ /**
57
+ * Generates a highlight color variant suitable for drop-shadow and glow effects.
58
+ *
59
+ * For HSL colors, this increases both saturation and lightness to create a brighter,
60
+ * more vibrant version. For other color formats, it blends with white.
61
+ *
62
+ * This is typically used for focus states, active states, or visual feedback effects.
63
+ *
64
+ * @param baseColor The base color (any valid CSS color value)
65
+ * @returns A CSS color value optimized for highlight effects
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * generateHighlightColor("blue"); // Brighter, more saturated blue for highlights
70
+ * ```
71
+ */
72
+ export declare function generateHighlightColor(baseColor: string): string;
73
+ /**
74
+ * Generates a complete set of color variants for a component.
75
+ *
76
+ * This is the main utility for creating theme color palettes. It generates:
77
+ * - `primary`: The base color
78
+ * - `primary50`: A 50% variant (luminosity or transparency based on `variant` parameter)
79
+ * - `primary20`: A 20% variant (luminosity or transparency based on `variant` parameter)
80
+ * - `highlight`: A brighter variant optimized for focus/active states
81
+ *
82
+ * The `variant` parameter determines how `primary50` and `primary20` are calculated:
83
+ * - `"luminosity"`: Darker versions of the base color (good for backgrounds, tracks)
84
+ * - `"transparency"`: Semi-transparent versions (good for overlays, disabled states)
85
+ *
86
+ * @param baseColor The base color (any valid CSS color value)
87
+ * @param variant The variant type ('luminosity' or 'transparency')
88
+ * @returns An object with primary, primary50, primary20, and highlight color values
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * const colors = generateColorVariants("blue", "luminosity");
93
+ * // { primary: "hsl(204, 88%, 53%)", primary50: "...", primary20: "...", highlight: "..." }
94
+ * ```
95
+ */
96
+ export declare function generateColorVariants(baseColor: string, variant?: "luminosity" | "transparency"): {
97
+ primary: string;
98
+ primary50: string;
99
+ primary20: string;
100
+ highlight: string;
101
+ };
102
+ //# sourceMappingURL=colorUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colorUtils.d.ts","sourceRoot":"","sources":["../../src/utils/colorUtils.ts"],"names":[],"mappings":"AA+BA;;;;;;;;GAQG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAKpC;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAgBjG;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAEhG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAgBhE;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,qBAAqB,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,YAAY,GAAG,cAA6B,GACtD;IACC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACrB,CAqBA"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Shared SVG helper utilities for audio-ui components
3
+ */
4
+ /**
5
+ * Convert polar coordinates to Cartesian coordinates.
6
+ *
7
+ * This function is used extensively in circular controls (knobs, rotary switches) to position
8
+ * elements around a circle. The angle system follows SVG conventions where 0° is at 3 o'clock
9
+ * and angles increase clockwise.
10
+ *
11
+ * @param centerX - X coordinate of the center point
12
+ * @param centerY - Y coordinate of the center point
13
+ * @param radius - Radius from center
14
+ * @param angleInDegrees - Angle in degrees (0° = 3 o'clock, increasing clockwise)
15
+ * @returns Object with x and y Cartesian coordinates
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * // Position at 12 o'clock (top center)
20
+ * const { x, y } = polarToCartesian(50, 50, 30, 360);
21
+ * // x ≈ 50, y ≈ 20
22
+ * ```
23
+ */
24
+ export declare const polarToCartesian: (centerX: number, centerY: number, radius: number, angleInDegrees: number) => {
25
+ x: number;
26
+ y: number;
27
+ };
28
+ /**
29
+ * Result of arc angle calculations
30
+ */
31
+ export interface ArcAngleResult {
32
+ /** Normalized value (0-1, clamped) */
33
+ normalizedValue: number;
34
+ /** Openness in degrees (0-360, clamped) */
35
+ openness: number;
36
+ /** Start angle of the arc range in degrees (offset by rotation) */
37
+ startAngle: number;
38
+ /** End angle of the arc range in degrees (offset by rotation) */
39
+ endAngle: number;
40
+ /** Current angle in degrees based on normalized value (offset by rotation) */
41
+ valueToAngle: number;
42
+ /** Start angle for the value arc (foreground). Handles bipolar logic (starts at center) vs unipolar (starts at range start). */
43
+ valueStartAngle: number;
44
+ }
45
+ /**
46
+ * Calculates arc angles for rotary controls (ValueRing, RotaryImage components, or any other circular control).
47
+ *
48
+ * Calculates the angular range based on openness and converts a normalized value (0-1)
49
+ * to an angle within that range.
50
+ *
51
+ * The angle system:
52
+ * - 0 degrees is at 3 o'clock, increasing clockwise
53
+ * - Standard knob (90° openness) goes from ~225° (7:30) to ~495° (4:30)
54
+ * - 360° corresponds to UP (12 o'clock)
55
+ *
56
+ * @param normalizedValue Normalized value between 0 and 1
57
+ * @param openness Openness of the arc in degrees (0-360, default 90)
58
+ * @param rotation Rotation angle offset in degrees (default 0)
59
+ * @param bipolar Whether to start the value arc from the center (12 o'clock) instead of the start angle (default false)
60
+ * @param positions Optional number of discrete positions. When defined, the value will snap to the nearest position. Defaults to undefined (continuous mode).
61
+ * @returns Calculated angles and normalized values
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * // Standard knob at 50% value
66
+ * const result = calculateArcAngles(0.5, 90);
67
+ * // result.valueToAngle = 360 (12 o'clock)
68
+ * // result.startAngle = 225 (7:30)
69
+ * // result.endAngle = 495 (4:30)
70
+ *
71
+ * // Bipolar knob (pan control) at center
72
+ * const bipolar = calculateArcAngles(0.5, 90, 0, true);
73
+ * // bipolar.valueStartAngle = 360 (starts from center)
74
+ *
75
+ * // Discrete positions (5-way switch)
76
+ * const discrete = calculateArcAngles(0.37, 90, 0, false, 5);
77
+ * // discrete.normalizedValue = 0.25 (snapped to nearest position)
78
+ * ```
79
+ */
80
+ export declare function calculateArcAngles(normalizedValue: number, openness?: number, rotation?: number, bipolar?: boolean, positions?: number): ArcAngleResult;
81
+ /**
82
+ * Calculates the cursor Y position for linear controls (sliders, faders).
83
+ *
84
+ * The cursor represents the current value position along a linear strip.
85
+ * The strip extends along the Y-axis (in unrotated coordinate space) from
86
+ * (cy - length/2) to (cy + length/2).
87
+ *
88
+ * The cursor position is independent of bipolar mode - it always maps:
89
+ * - value 0 = bottom (cy + length/2)
90
+ * - value 1 = top (cy - length/2)
91
+ *
92
+ * Bipolar mode only affects how the rectangle is drawn (from center vs from bottom),
93
+ * not the cursor position itself.
94
+ *
95
+ * @param cy Y coordinate of the strip center point
96
+ * @param length Length of the strip
97
+ * @param normalizedValue Normalized value between 0 and 1
98
+ * @returns Y coordinate of the cursor center
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * // Cursor moves from bottom to top based on value
103
+ * const cursorY = calculateLinearPosition(150, 260, 0.65);
104
+ * // cursorY = 31 (65% from bottom to top)
105
+ * ```
106
+ */
107
+ export declare function calculateLinearPosition(cy: number, length: number, normalizedValue: number): number;
108
+ //# sourceMappingURL=math.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../../src/utils/math.ts"],"names":[],"mappings":"AAMA;;GAEG;AAEH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,gBAAgB,GACzB,SAAS,MAAM,EACf,SAAS,MAAM,EACf,QAAQ,MAAM,EACd,gBAAgB,MAAM,KACvB;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAMxB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,sCAAsC;IACtC,eAAe,EAAE,MAAM,CAAC;IACxB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,YAAY,EAAE,MAAM,CAAC;IACrB,gIAAgI;IAChI,eAAe,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,kBAAkB,CAC9B,eAAe,EAAE,MAAM,EACvB,QAAQ,GAAE,MAAW,EACrB,QAAQ,GAAE,MAAU,EACpB,OAAO,GAAE,OAAe,EACxB,SAAS,CAAC,EAAE,MAAM,GACnB,cAAc,CA6ChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAQnG"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Utility functions for translating normalized (0.0-1.0) roundness and thickness values
3
+ * to component-specific legacy ranges.
4
+ *
5
+ * All components accept normalized values (0.0-1.0) and translate them internally
6
+ * to their legacy ranges for rendering.
7
+ */
8
+ /**
9
+ * Clamp a value to the 0.0-1.0 range
10
+ */
11
+ export declare function clampNormalized(value: number): number;
12
+ /**
13
+ * Translate normalized roundness (0.0-1.0) to KnobView legacy value.
14
+ * 0.0 = square (legacy: 0), >0.0 = round (legacy: 1+)
15
+ */
16
+ export declare function translateKnobRoundness(normalized: number): number;
17
+ export declare function translateKnobThickness(normalized: number): number;
18
+ export declare function translateSliderRoundness(normalized: number): number;
19
+ export declare function translateSliderThickness(normalized: number): number;
20
+ export declare function translateButtonRoundness(normalized: number): number;
21
+ export declare function translateKeysRoundness(normalized: number): number;
22
+ //# sourceMappingURL=normalizedProps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizedProps.d.ts","sourceRoot":"","sources":["../../src/utils/normalizedProps.ts"],"names":[],"mappings":"AAMA;;;;;;GAMG;AAEH;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGjE;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGjE;AAED,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGnE;AAED,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGnE;AAED,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGnE;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGjE"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Utility functions for working with musical notes and MIDI note numbers
3
+ *
4
+ * Terminology:
5
+ * - Note: A pitch with octave (e.g., "C4", "F#5")
6
+ * - NoteName: The actual note without octave (e.g., "C", "F#")
7
+ * - NoteNum: The MIDI note number (e.g., 60 for C4)
8
+ */
9
+ /**
10
+ * Array of note names in chromatic order (C to B with sharps)
11
+ */
12
+ export declare const CHROMATIC_NOTES: readonly ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
13
+ /**
14
+ * Array of white key note names in order (C to B)
15
+ */
16
+ export declare const WHITE_KEY_NAMES: readonly ["C", "D", "E", "F", "G", "A", "B"];
17
+ /**
18
+ * Mapping from white key index to chromatic offset
19
+ * This represents the semitone positions of white keys in a standard piano layout
20
+ * C=0, D=2, E=4, F=5, G=7, A=9, B=11
21
+ */
22
+ export declare const WHITE_KEY_TO_CHROMATIC: readonly [0, 2, 4, 5, 7, 9, 11];
23
+ /**
24
+ * Mapping from diatonic note names to chromatic indices
25
+ */
26
+ export declare const DIATONIC_TO_CHROMATIC: Record<string, number>;
27
+ /**
28
+ * Set of chromatic positions that correspond to white keys (C, D, E, F, G, A, B)
29
+ * Used to determine if a note is a white key or black key
30
+ */
31
+ export declare const WHITE_KEY_POSITIONS: Set<number>;
32
+ /**
33
+ * Converts a MIDI note number to a note string using a pre-computed lookup table
34
+ * MIDI note 60 is middle C (C4)
35
+ *
36
+ * @param noteNum - The MIDI note number to convert
37
+ * @returns The corresponding note (e.g., "C4", "F#5")
38
+ */
39
+ export declare const noteNumToNote: (noteNum: number) => string;
40
+ /**
41
+ * Converts a note string to a MIDI note number using a pre-computed lookup table
42
+ *
43
+ * @param note - The note to convert (e.g., "C4", "F#5")
44
+ * @returns The corresponding MIDI note number, or -1 if the note is invalid
45
+ */
46
+ export declare const noteToNoteNum: (note: string) => number;
47
+ /**
48
+ * Creates a Set of MIDI note numbers from an array of notes (strings and/or numbers)
49
+ * This can be used for efficient note lookups, especially when memoized in components
50
+ *
51
+ * @param notesOn - Array of notes that are on (can contain string notes and/or MIDI note numbers)
52
+ * @returns A Set of MIDI note numbers
53
+ */
54
+ export declare const createNoteNumSet: (notesOn: (string | number)[]) => Set<number>;
55
+ /**
56
+ * Checks if a note is in the notesOn array, handling both string notes and MIDI note numbers
57
+ * Uses a Set for O(1) lookups instead of array includes
58
+ *
59
+ * @param noteInput - The note to check (either a string note like "C4" or a MIDI note number)
60
+ * @param notesOn - Array of notes that are on (can contain string notes and/or MIDI note numbers)
61
+ * @returns True if the note is in the notesOn array, false otherwise
62
+ */
63
+ export declare const isNoteOn: (noteInput: string | number, notesOn: (string | number)[]) => boolean;
64
+ /**
65
+ * Checks if a given MIDI note number corresponds to a black key
66
+ *
67
+ * @param noteNum - The MIDI note number
68
+ * @returns true if black key, false if white key
69
+ */
70
+ export declare const isBlackKey: (noteNum: number) => boolean;
71
+ //# sourceMappingURL=noteUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noteUtils.d.ts","sourceRoot":"","sources":["../../src/utils/noteUtils.ts"],"names":[],"mappings":"AAMA;;;;;;;GAOG;AAEH;;GAEG;AACH,eAAO,MAAM,eAAe,4EAA6E,CAAC;AAE1G;;GAEG;AACH,eAAO,MAAM,eAAe,8CAA+C,CAAC;AAE5E;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,iCAAkC,CAAC;AAEtE;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQxD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,aAAkC,CAAC;AAsBnE;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,MAW/C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,MAoB5C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,KAAG,GAAG,CAAC,MAAM,CAiBzE,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,GAAI,WAAW,MAAM,GAAG,MAAM,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,KAAG,OAcnF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,KAAG,OAM5C,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Creates a comparison function for memoization to prevent unnecessary re-renders.
3
+ *
4
+ * This utility creates a function that performs shallow comparison of primitive props
5
+ * and uses fast-deep-equal for deep comparison of objects like style.
6
+ *
7
+ * @param options - Configuration options for the comparison
8
+ * @param options.deepCompareProps - Array of prop names that should be deeply compared
9
+ * @param options.alwaysCompareProps - Array of prop names that should always be directly compared (===)
10
+ * @returns A comparison function
11
+ *
12
+ * @example
13
+ * // Basic usage with style deep comparison
14
+ * const comparator = createPropComparator({
15
+ * deepCompareProps: ['style']
16
+ * });
17
+ */
18
+ export declare function createPropComparator<T extends Record<string, unknown>>({ deepCompareProps, alwaysCompareProps, }?: {
19
+ deepCompareProps?: Array<keyof T>;
20
+ alwaysCompareProps?: Array<keyof T>;
21
+ }): (prevProps: T, nextProps: T) => boolean;
22
+ //# sourceMappingURL=propCompare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"propCompare.d.ts","sourceRoot":"","sources":["../../src/utils/propCompare.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EACpE,gBAA4B,EAC5B,kBAAiC,GACpC,GAAE;IACC,gBAAgB,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAClC,kBAAkB,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;CAClC,IAK4B,WAAW,CAAC,EAAE,WAAW,CAAC,KAAG,OAAO,CA4BrE"}
@@ -0,0 +1,39 @@
1
+ import { SizeType } from '../types';
2
+
3
+ /**
4
+ * Maps size values to CSS class names for square components (Button, Knob, CycleButton)
5
+ */
6
+ export declare const squareSizeClassMap: Record<SizeType, string>;
7
+ /**
8
+ * Maps size values to CSS class names for horizontal slider
9
+ */
10
+ export declare const horizontalSliderSizeClassMap: Record<SizeType, string>;
11
+ /**
12
+ * Maps size values to CSS class names for vertical slider
13
+ */
14
+ export declare const verticalSliderSizeClassMap: Record<SizeType, string>;
15
+ /**
16
+ * Maps size values to CSS class names for keys
17
+ */
18
+ export declare const keysSizeClassMap: Record<SizeType, string>;
19
+ /**
20
+ * Gets the appropriate size class name for a component
21
+ * @param componentType The type of component ('knob', 'button', 'keys', or 'slider')
22
+ * @param size The size value
23
+ * @param orientation The orientation for slider components ('vertical' or 'horizontal')
24
+ * @returns The CSS class name for the component size
25
+ */
26
+ export declare function getSizeClassForComponent(componentType: "knob" | "button" | "keys" | "slider", size?: SizeType, orientation?: "vertical" | "horizontal"): string;
27
+ /**
28
+ * Gets the CSS variable references for a component's size dimensions.
29
+ * Used to apply size as inline styles (which override AdaptiveBox's default 100%).
30
+ * @param componentType The type of component ('knob', 'button', 'keys', or 'slider')
31
+ * @param size The size value
32
+ * @param orientation The orientation for slider components ('vertical' or 'horizontal')
33
+ * @returns An object with width and height CSS variable references
34
+ */
35
+ export declare function getSizeStyleForComponent(componentType: "knob" | "button" | "keys" | "slider", size?: SizeType, orientation?: "vertical" | "horizontal"): {
36
+ width: string;
37
+ height: string;
38
+ };
39
+ //# sourceMappingURL=sizing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sizing.d.ts","sourceRoot":"","sources":["../../src/utils/sizing.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAMvD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,4BAA4B,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAMjE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAM/D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAMrD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACpC,aAAa,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,EACpD,IAAI,GAAE,QAAmB,EACzB,WAAW,GAAE,UAAU,GAAG,YAAyB,GACpD,MAAM,CAYR;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACpC,aAAa,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,EACpD,IAAI,GAAE,QAAmB,EACzB,WAAW,GAAE,UAAU,GAAG,YAAyB,GACpD;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CA4BnC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Calculate SVG arc path for circular controls (like knobs).
3
+ *
4
+ * This function generates the SVG path data for drawing arcs, which is essential for rendering
5
+ * circular controls. The path is rounded to avoid hydration mismatches between server and client.
6
+ *
7
+ * The angle system follows SVG conventions:
8
+ * - 0° is at 3 o'clock (right)
9
+ * - Angles increase clockwise
10
+ * - 360° is at 12 o'clock (top)
11
+ *
12
+ * @param cx - X coordinate of the center point
13
+ * @param cy - Y coordinate of the center point
14
+ * @param startAngle - Starting angle in degrees
15
+ * @param endAngle - Ending angle in degrees
16
+ * @param radius - Radius of the arc
17
+ * @param direction - Direction to draw the arc. "counter-clockwise" (default) draws from End to Start (standard for static shapes). "clockwise" draws from Start to End (useful for path animations).
18
+ * @returns SVG path string for the arc (e.g., "M 10 20 A 30 30 0 0 1 40 50")
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * // Draw a 90-degree arc from 7:30 to 4:30 (standard knob range)
23
+ * const path = calculateArcPath(50, 50, 225, 495, 30);
24
+ * ```
25
+ */
26
+ export declare const calculateArcPath: (cx: number, cy: number, startAngle: number, endAngle: number, radius: number, direction?: "clockwise" | "counter-clockwise") => string;
27
+ //# sourceMappingURL=svg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svg.d.ts","sourceRoot":"","sources":["../../src/utils/svg.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,gBAAgB,GACzB,IAAI,MAAM,EACV,IAAI,MAAM,EACV,YAAY,MAAM,EAClB,UAAU,MAAM,EAChB,QAAQ,MAAM,EACd,YAAW,WAAW,GAAG,mBAAyC,KACnE,MAgBF,CAAC"}