react-circular-range 1.0.93 → 1.0.95
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.d.mts → CircularRange.d.ts} +5 -5
- package/dist/index.d.ts +1 -13
- package/dist/index.js +2 -0
- package/dist/index.js.LICENSE.txt +9 -0
- package/dist/styles.css +103 -0
- package/package.json +19 -11
- package/dist/index.cjs +0 -3
- package/dist/index.cjs.map +0 -1
- package/dist/index.css +0 -2
- package/dist/index.css.map +0 -1
- package/dist/index.mjs +0 -3
- package/dist/index.mjs.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
type StyleSlots = 'knob' | 'knobRing' | 'knobBackground' | 'knobBackgroundPath' | 'knobIndicator' | 'knobCenter' | 'active';
|
|
2
|
-
type CircularRangeThemeProps = Partial<Record<StyleSlots, string>>;
|
|
3
|
-
interface CircularRangeProps {
|
|
3
|
+
export type CircularRangeThemeProps = Partial<Record<StyleSlots, string>>;
|
|
4
|
+
export interface CircularRangeProps {
|
|
4
5
|
min?: number;
|
|
5
6
|
max?: number;
|
|
6
7
|
value?: number;
|
|
@@ -8,6 +9,5 @@ interface CircularRangeProps {
|
|
|
8
9
|
onChange?: (value: number) => void;
|
|
9
10
|
theme?: CircularRangeThemeProps;
|
|
10
11
|
}
|
|
11
|
-
declare const CircularRange: React.FC<CircularRangeProps>;
|
|
12
|
-
|
|
13
|
-
export { CircularRange, type CircularRangeProps, type CircularRangeThemeProps, type StyleSlots };
|
|
12
|
+
export declare const CircularRange: React.FC<CircularRangeProps>;
|
|
13
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1 @@
|
|
|
1
|
-
|
|
2
|
-
type CircularRangeThemeProps = Partial<Record<StyleSlots, string>>;
|
|
3
|
-
interface CircularRangeProps {
|
|
4
|
-
min?: number;
|
|
5
|
-
max?: number;
|
|
6
|
-
value?: number;
|
|
7
|
-
step?: number;
|
|
8
|
-
onChange?: (value: number) => void;
|
|
9
|
-
theme?: CircularRangeThemeProps;
|
|
10
|
-
}
|
|
11
|
-
declare const CircularRange: React.FC<CircularRangeProps>;
|
|
12
|
-
|
|
13
|
-
export { CircularRange, type CircularRangeProps, type CircularRangeThemeProps, type StyleSlots };
|
|
1
|
+
export * from './CircularRange';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see index.js.LICENSE.txt */
|
|
2
|
+
import{useCallback as e,useEffect as t,useRef as n,useState as r}from"react";var o={698(e,t){var n=Symbol.for("react.transitional.element");function r(e,t,r){var o=null;if(void 0!==r&&(o=""+r),void 0!==t.key&&(o=""+t.key),"key"in t)for(var s in r={},t)"key"!==s&&(r[s]=t[s]);else r=t;return t=r.ref,{$$typeof:n,type:e,key:o,ref:void 0!==t?t:null,props:r}}Symbol.for("react.fragment"),t.jsx=r,t.jsxs=r},848(e,t,n){e.exports=n(698)}},s={};function a(e){var t=s[e];if(void 0!==t)return t.exports;var n=s[e]={exports:{}};return o[e](n,n.exports,a),n.exports}a.d=(e,t)=>{for(var n in t)a.o(t,n)&&!a.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),a.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var c={};a.r(c);var u=a(848);const i=113.1,d=({min:o=0,max:s=100,value:a=0,step:d=.01,onChange:v,theme:l=c.default})=>{const m=n(null),[f,p]=r(a),[h,y]=r(!1),b=n(0),k=n(0);t(()=>{p(a)},[a]);const x=e(e=>(e-o)/(s-o),[o,s]),E=e(e=>{let t=(e=>Math.min(s,Math.max(o,e)))(e);d>0&&(t=Math.round(t/d)*d),p(t),v?.(t)},[o,s,d,v]),L=e=>{e.preventDefault(),y(!0);const t="touches"in e?e.touches[0].clientY:e.clientY;b.current=t,k.current=f},g=e=>{if(!h)return;e.preventDefault();const t="touches"in e?e.touches[0].clientY:e.clientY,n=.01*(b.current-t)*(s-o);E(k.current+n)},j=()=>{y(!1)},$=()=>{E((o+s)/2)};t(()=>{const e=m.current;if(e)return e.addEventListener("mousedown",L),e.addEventListener("touchstart",L),document.addEventListener("mousemove",g),document.addEventListener("touchmove",g),document.addEventListener("mouseup",j),document.addEventListener("touchend",j),e.addEventListener("dblclick",$),()=>{e.removeEventListener("mousedown",L),e.removeEventListener("touchstart",L),document.removeEventListener("mousemove",g),document.removeEventListener("touchmove",g),document.removeEventListener("mouseup",j),document.removeEventListener("touchend",j),e.removeEventListener("dblclick",$)}},[g,h]);const S=x(f),M=270*S-135,N=i-S*i;return(0,u.jsx)("div",{ref:m,className:`${l.knob} ${h?l.active:""}`,children:(0,u.jsxs)("div",{className:`${l.knobRing}`,children:[(0,u.jsx)("svg",{className:`${l.knobBackground}`,viewBox:"0 0 60 60",children:(0,u.jsx)("path",{className:`${l.knobBackgroundPath}`,d:"M 30 6 A 24 24 0 1 1 6 30",strokeDasharray:i,strokeDashoffset:N})}),(0,u.jsx)("div",{className:`${l.knobIndicator}`,style:{transform:`translateX(-50%) rotate(${M}deg)`}}),(0,u.jsx)("div",{className:`${l.knobCenter}`})]})})};export{d as CircularRange};
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
.CircularRange-module__knob--BAUKG {
|
|
2
|
+
width: 65px;
|
|
3
|
+
height: 65px;
|
|
4
|
+
position: relative;
|
|
5
|
+
cursor: pointer;
|
|
6
|
+
user-select: none;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.CircularRange-module__knobRing--F6qGP {
|
|
10
|
+
width: 100%;
|
|
11
|
+
height: 100%;
|
|
12
|
+
border: 3px solid #333;
|
|
13
|
+
border-radius: 50%;
|
|
14
|
+
background: linear-gradient(145deg, #1a1a1a, #252525);
|
|
15
|
+
box-shadow:
|
|
16
|
+
inset 2px 2px 5px rgba(0, 0, 0, 0.5),
|
|
17
|
+
inset -2px -2px 5px rgba(60, 60, 60, 0.1),
|
|
18
|
+
0 4px 8px rgba(0, 0, 0, 0.3);
|
|
19
|
+
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.CircularRange-module__knobBackground--qxu1s {
|
|
23
|
+
position: absolute;
|
|
24
|
+
top: 0;
|
|
25
|
+
left: 0;
|
|
26
|
+
width: 100%;
|
|
27
|
+
height: 100%;
|
|
28
|
+
pointer-events: none;
|
|
29
|
+
transform: rotate(-135deg);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.CircularRange-module__knobBackgroundPath--rxKDz {
|
|
33
|
+
fill: none;
|
|
34
|
+
stroke: #8b5cf6;
|
|
35
|
+
stroke-width: 3.5;
|
|
36
|
+
stroke-linecap: round;
|
|
37
|
+
stroke-dasharray: 113.1;
|
|
38
|
+
stroke-dashoffset: 113.1;
|
|
39
|
+
transition: stroke-dashoffset 0.1s ease-out;
|
|
40
|
+
filter: drop-shadow(0 0 3px rgba(139, 92, 246, 0.7));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.CircularRange-module__knobIndicator--lJKRO {
|
|
44
|
+
position: absolute;
|
|
45
|
+
width: 4px;
|
|
46
|
+
height: 20px;
|
|
47
|
+
background: linear-gradient(to bottom, #8b5cf6, #c084fc);
|
|
48
|
+
top: 5px;
|
|
49
|
+
left: 50%;
|
|
50
|
+
transform-origin: center 27.5px;
|
|
51
|
+
transform: translateX(-50%) rotate(-135deg);
|
|
52
|
+
border-radius: 2px;
|
|
53
|
+
z-index: 2;
|
|
54
|
+
/*transition: transform 0.05s ease-out;*/
|
|
55
|
+
box-shadow: 0 0 6px rgba(139, 92, 246, 0.8);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.CircularRange-module__knobCenter--UIeoG {
|
|
59
|
+
position: absolute;
|
|
60
|
+
width: 18px;
|
|
61
|
+
height: 18px;
|
|
62
|
+
background: radial-gradient(circle, #0a0a0a, #1a1a1a);
|
|
63
|
+
border-radius: 50%;
|
|
64
|
+
top: 50%;
|
|
65
|
+
left: 50%;
|
|
66
|
+
transform: translate(-50%, -50%);
|
|
67
|
+
box-shadow:
|
|
68
|
+
inset 1px 1px 3px rgba(0, 0, 0, 0.7),
|
|
69
|
+
0 1px 2px rgba(139, 92, 246, 0.3);
|
|
70
|
+
z-index: 3;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Hover states */
|
|
74
|
+
.CircularRange-module__knob--BAUKG:hover .CircularRange-module__knobRing--F6qGP {
|
|
75
|
+
border-color: #8b5cf6;
|
|
76
|
+
box-shadow:
|
|
77
|
+
inset 2px 2px 5px rgba(0, 0, 0, 0.5),
|
|
78
|
+
inset -2px -2px 5px rgba(60, 60, 60, 0.1),
|
|
79
|
+
0 4px 12px rgba(139, 92, 246, 0.4);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.CircularRange-module__knob--BAUKG:hover .CircularRange-module__knobIndicator--lJKRO {
|
|
83
|
+
background: linear-gradient(to bottom, #a78bfa, #c084fc);
|
|
84
|
+
box-shadow: 0 0 8px rgba(167, 139, 250, 0.9);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.CircularRange-module__knob--BAUKG.CircularRange-module__active--BqXnY .CircularRange-module__knobRing--F6qGP {
|
|
88
|
+
border-color: #a78bfa;
|
|
89
|
+
box-shadow:
|
|
90
|
+
inset 2px 2px 5px rgba(0, 0, 0, 0.6),
|
|
91
|
+
inset -2px -2px 5px rgba(60, 60, 60, 0.15),
|
|
92
|
+
0 4px 16px rgba(167, 139, 250, 0.5);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.CircularRange-module__knob--BAUKG.CircularRange-module__active--BqXnY .CircularRange-module__knobIndicator--lJKRO {
|
|
96
|
+
background: linear-gradient(to bottom, #a78bfa, #c084fc);
|
|
97
|
+
box-shadow: 0 0 10px rgba(167, 139, 250, 1);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.CircularRange-module__knob--BAUKG.CircularRange-module__active--BqXnY .CircularRange-module__knobBackgroundPath--rxKDz {
|
|
101
|
+
stroke: #a78bfa;
|
|
102
|
+
filter: drop-shadow(0 0 4px rgba(167, 139, 250, 0.9));
|
|
103
|
+
}
|
package/package.json
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-circular-range",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.95",
|
|
4
4
|
"description": "Simple VST-like circular slider/range.",
|
|
5
|
-
"main": "./dist/index.
|
|
6
|
-
"module": "./dist/index.
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
8
11
|
"exports": {
|
|
9
12
|
".": {
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.js"
|
|
16
|
+
}
|
|
14
17
|
},
|
|
15
|
-
"files": ["dist"],
|
|
16
18
|
"scripts": {
|
|
17
|
-
"build": "
|
|
19
|
+
"build": "webpack"
|
|
18
20
|
},
|
|
19
21
|
"repository": {
|
|
20
22
|
"type": "git",
|
|
@@ -41,7 +43,13 @@
|
|
|
41
43
|
},
|
|
42
44
|
"devDependencies": {
|
|
43
45
|
"@types/react": "^19.2.7",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
+
"@types/react-dom": "^19.2.3",
|
|
47
|
+
"css-loader": "^7.1.2",
|
|
48
|
+
"mini-css-extract-plugin": "^2.9.4",
|
|
49
|
+
"style-loader": "^4.0.0",
|
|
50
|
+
"ts-loader": "^9.5.4",
|
|
51
|
+
"typescript": "^5.9.3",
|
|
52
|
+
"webpack": "^5.104.1",
|
|
53
|
+
"webpack-cli": "^6.0.1"
|
|
46
54
|
}
|
|
47
55
|
}
|
package/dist/index.cjs
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
"use strict";var g=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var D=(o,t)=>{for(var r in t)g(o,r,{get:t[r],enumerable:!0})},V=(o,t,r,c)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of I(t))!T.call(o,a)&&a!==r&&g(o,a,{get:()=>t[a],enumerable:!(c=$(t,a))||c.enumerable});return o};var z=o=>V(g({},"__esModule",{value:!0}),o);var H={};D(H,{CircularRange:()=>y});module.exports=z(H);var n=require("react");var L={};var i=require("react/jsx-runtime"),x=113.1,y=({min:o=0,max:t=100,value:r=0,step:c=.01,onChange:a,theme:d=L})=>{let h=(0,n.useRef)(null),[v,k]=(0,n.useState)(r),[p,m]=(0,n.useState)(!1),f=(0,n.useRef)(0),E=(0,n.useRef)(0),P=.01;(0,n.useEffect)(()=>{k(r)},[r]);let Y=e=>Math.min(t,Math.max(o,e)),B=(0,n.useCallback)(e=>(e-o)/(t-o),[o,t]),w=(0,n.useCallback)(e=>{let s=Y(e);c>0&&(s=Math.round(s/c)*c),k(s),a?.(s)},[o,t,c,a]),l=e=>{e.preventDefault(),m(!0);let s="touches"in e?e.touches[0].clientY:e.clientY;f.current=s,E.current=v},u=e=>{if(!p)return;e.preventDefault();let s="touches"in e?e.touches[0].clientY:e.clientY,S=(f.current-s)*P*(t-o);w(E.current+S)},b=()=>{m(!1)},R=()=>{w((o+t)/2)};(0,n.useEffect)(()=>{let e=h.current;if(e)return e.addEventListener("mousedown",l),e.addEventListener("touchstart",l),document.addEventListener("mousemove",u),document.addEventListener("touchmove",u),document.addEventListener("mouseup",b),document.addEventListener("touchend",b),e.addEventListener("dblclick",R),()=>{e.removeEventListener("mousedown",l),e.removeEventListener("touchstart",l),document.removeEventListener("mousemove",u),document.removeEventListener("touchmove",u),document.removeEventListener("mouseup",b),document.removeEventListener("touchend",b),e.removeEventListener("dblclick",R)}},[u,p]);let C=B(v),M=C*270-135,N=x-C*x;return(0,i.jsx)("div",{ref:h,className:`${d.knob} ${p?d.active:""}`,children:(0,i.jsxs)("div",{className:`${d.knobRing}`,children:[(0,i.jsx)("svg",{className:`${d.knobBackground}`,viewBox:"0 0 60 60",children:(0,i.jsx)("path",{className:`${d.knobBackgroundPath}`,d:"M 30 6 A 24 24 0 1 1 6 30",strokeDasharray:x,strokeDashoffset:N})}),(0,i.jsx)("div",{className:`${d.knobIndicator}`,style:{transform:`translateX(-50%) rotate(${M}deg)`}}),(0,i.jsx)("div",{className:`${d.knobCenter}`})]})})};0&&(module.exports={CircularRange});
|
|
3
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/CircularRange.tsx","../src/CircularRange.module.css"],"sourcesContent":["export { CircularRange } from './CircularRange';\r\nexport type { CircularRangeProps, CircularRangeThemeProps, StyleSlots } from './CircularRange';","import {\r\n useCallback,\r\n useEffect,\r\n useRef,\r\n useState,\r\n} from \"react\";\r\n\r\nimport styles from \"./CircularRange.module.css\";\r\n\r\nexport type StyleSlots =\r\n | 'knob'\r\n | 'knobRing'\r\n | 'knobBackground'\r\n | 'knobBackgroundPath'\r\n | 'knobIndicator'\r\n | 'knobCenter'\r\n | 'active'\r\n\r\nexport type CircularRangeThemeProps = Partial<Record<StyleSlots, string>>;\r\n\r\nexport interface CircularRangeProps {\r\n min?: number;\r\n max?: number;\r\n value?: number;\r\n step?: number;\r\n onChange?: (value: number) => void;\r\n\r\n // override styles with css module\r\n theme?: CircularRangeThemeProps;\r\n}\r\n\r\nconst ARC_LENGTH = 113.1; // 270°\r\n\r\nexport const CircularRange: React.FC<CircularRangeProps> = ({\r\n min = 0,\r\n max = 100,\r\n value = 0,\r\n step = 0.01,\r\n onChange,\r\n theme = styles\r\n}) => {\r\n const knobRef = useRef<HTMLDivElement | null>(null);\r\n\r\n const [internalValue, setInternalValue] = useState(value);\r\n const [isActive, setIsActive] = useState(false);\r\n\r\n const startY = useRef(0);\r\n const startValue = useRef(0);\r\n const sensitivity = 0.01;\r\n useEffect(() => {\r\n setInternalValue(value);\r\n }, [value]);\r\n\r\n const clamp = (v: number) => Math.min(max, Math.max(min, v));\r\n\r\n const getNormalizedValue = useCallback(\r\n (v: number) => {\r\n return (v - min) / (max - min);\r\n },\r\n [min, max],\r\n );\r\n\r\n const setValue = useCallback(\r\n (v: number) => {\r\n let next = clamp(v);\r\n if (step > 0) {\r\n next = Math.round(next / step) * step;\r\n }\r\n setInternalValue(next);\r\n onChange?.(next);\r\n },\r\n [min, max, step, onChange],\r\n );\r\n\r\n const handleStart = (e: MouseEvent | TouchEvent) => {\r\n e.preventDefault();\r\n setIsActive(true);\r\n const clientY = \"touches\" in e ? e.touches[0].clientY : e.clientY;\r\n startY.current = clientY;\r\n startValue.current = internalValue;\r\n };\r\n\r\n const handleMove = (e: MouseEvent | TouchEvent) => {\r\n if (!isActive) return;\r\n e.preventDefault();\r\n\r\n const clientY = \"touches\" in e ? e.touches[0].clientY : e.clientY;\r\n const deltaY = startY.current - clientY;\r\n const deltaValue = deltaY * sensitivity * (max - min);\r\n\r\n setValue(startValue.current + deltaValue);\r\n };\r\n\r\n const handleEnd = () => {\r\n setIsActive(false);\r\n };\r\n\r\n const handleDoubleClick = () => {\r\n setValue((min + max) / 2);\r\n };\r\n\r\n useEffect(() => {\r\n const el = knobRef.current;\r\n if (!el) return;\r\n\r\n el.addEventListener(\"mousedown\", handleStart);\r\n el.addEventListener(\"touchstart\", handleStart);\r\n\r\n document.addEventListener(\"mousemove\", handleMove);\r\n document.addEventListener(\"touchmove\", handleMove);\r\n document.addEventListener(\"mouseup\", handleEnd);\r\n document.addEventListener(\"touchend\", handleEnd);\r\n\r\n el.addEventListener(\"dblclick\", handleDoubleClick);\r\n\r\n return () => {\r\n el.removeEventListener(\"mousedown\", handleStart);\r\n el.removeEventListener(\"touchstart\", handleStart);\r\n\r\n document.removeEventListener(\"mousemove\", handleMove);\r\n document.removeEventListener(\"touchmove\", handleMove);\r\n document.removeEventListener(\"mouseup\", handleEnd);\r\n document.removeEventListener(\"touchend\", handleEnd);\r\n\r\n el.removeEventListener(\"dblclick\", handleDoubleClick);\r\n };\r\n }, [handleMove, isActive]);\r\n\r\n const normalized = getNormalizedValue(internalValue);\r\n const rotation = normalized * 270 - 135;\r\n const dashOffset = ARC_LENGTH - normalized * ARC_LENGTH;\r\n\r\n return (\r\n <div\r\n ref={knobRef}\r\n className={`${theme.knob} ${isActive ? theme.active : \"\"}`}\r\n >\r\n <div className={`${theme.knobRing}`}>\r\n <svg\r\n className={`${theme.knobBackground}`}\r\n viewBox=\"0 0 60 60\"\r\n >\r\n <path\r\n className={`${theme.knobBackgroundPath}`}\r\n d=\"M 30 6 A 24 24 0 1 1 6 30\"\r\n strokeDasharray={ARC_LENGTH}\r\n strokeDashoffset={dashOffset}\r\n />\r\n </svg>\r\n\r\n <div\r\n className={`${theme.knobIndicator}`}\r\n style={{\r\n transform: `translateX(-50%) rotate(${rotation}deg)`,\r\n }}\r\n />\r\n\r\n <div\r\n className={`${theme.knobCenter}`}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n",".knob {\r\n width: 65px;\r\n height: 65px;\r\n position: relative;\r\n cursor: pointer;\r\n user-select: none;\r\n}\r\n\r\n.knobRing {\r\n width: 100%;\r\n height: 100%;\r\n border: 3px solid #333;\r\n border-radius: 50%;\r\n background: linear-gradient(145deg, #1a1a1a, #252525);\r\n box-shadow:\r\n inset 2px 2px 5px rgba(0, 0, 0, 0.5),\r\n inset -2px -2px 5px rgba(60, 60, 60, 0.1),\r\n 0 4px 8px rgba(0, 0, 0, 0.3);\r\n transition: border-color 0.2s ease, box-shadow 0.2s ease;\r\n}\r\n\r\n.knobBackground {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n pointer-events: none;\r\n transform: rotate(-135deg);\r\n}\r\n\r\n.knobBackgroundPath {\r\n fill: none;\r\n stroke: #8b5cf6;\r\n stroke-width: 3.5;\r\n stroke-linecap: round;\r\n stroke-dasharray: 113.1;\r\n stroke-dashoffset: 113.1;\r\n transition: stroke-dashoffset 0.1s ease-out;\r\n filter: drop-shadow(0 0 3px rgba(139, 92, 246, 0.7));\r\n}\r\n\r\n.knobIndicator {\r\n position: absolute;\r\n width: 4px;\r\n height: 20px;\r\n background: linear-gradient(to bottom, #8b5cf6, #c084fc);\r\n top: 5px;\r\n left: 50%;\r\n transform-origin: center 27.5px;\r\n transform: translateX(-50%) rotate(-135deg);\r\n border-radius: 2px;\r\n z-index: 2;\r\n /*transition: transform 0.05s ease-out;*/\r\n box-shadow: 0 0 6px rgba(139, 92, 246, 0.8);\r\n}\r\n\r\n.knobCenter {\r\n position: absolute;\r\n width: 18px;\r\n height: 18px;\r\n background: radial-gradient(circle, #0a0a0a, #1a1a1a);\r\n border-radius: 50%;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n box-shadow:\r\n inset 1px 1px 3px rgba(0, 0, 0, 0.7),\r\n 0 1px 2px rgba(139, 92, 246, 0.3);\r\n z-index: 3;\r\n}\r\n\r\n/* Hover states */\r\n.knob:hover .knobRing {\r\n border-color: #8b5cf6;\r\n box-shadow:\r\n inset 2px 2px 5px rgba(0, 0, 0, 0.5),\r\n inset -2px -2px 5px rgba(60, 60, 60, 0.1),\r\n 0 4px 12px rgba(139, 92, 246, 0.4);\r\n}\r\n\r\n.knob:hover .knobIndicator {\r\n background: linear-gradient(to bottom, #a78bfa, #c084fc);\r\n box-shadow: 0 0 8px rgba(167, 139, 250, 0.9);\r\n}\r\n\r\n.knob.active .knobRing {\r\n border-color: #a78bfa;\r\n box-shadow:\r\n inset 2px 2px 5px rgba(0, 0, 0, 0.6),\r\n inset -2px -2px 5px rgba(60, 60, 60, 0.15),\r\n 0 4px 16px rgba(167, 139, 250, 0.5);\r\n}\r\n\r\n.knob.active .knobIndicator {\r\n background: linear-gradient(to bottom, #a78bfa, #c084fc);\r\n box-shadow: 0 0 10px rgba(167, 139, 250, 1);\r\n}\r\n\r\n.knob.active .knobBackgroundPath {\r\n stroke: #a78bfa;\r\n filter: drop-shadow(0 0 4px rgba(167, 139, 250, 0.9));\r\n}"],"mappings":"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","names":["index_exports","__export","CircularRange","__toCommonJS","import_react","CircularRange_default","import_jsx_runtime","ARC_LENGTH","CircularRange","min","max","value","step","onChange","theme","CircularRange_default","knobRef","internalValue","setInternalValue","isActive","setIsActive","startY","startValue","sensitivity","clamp","v","getNormalizedValue","setValue","next","handleStart","clientY","handleMove","deltaValue","handleEnd","handleDoubleClick","el","normalized","rotation","dashOffset"]}
|
package/dist/index.css
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
.knob{width:65px;height:65px;position:relative;cursor:pointer;user-select:none}.knobRing{width:100%;height:100%;border:3px solid #333;border-radius:50%;background:linear-gradient(145deg,#1a1a1a,#252525);box-shadow:inset 2px 2px 5px #00000080,inset -2px -2px 5px #3c3c3c1a,0 4px 8px #0000004d;transition:border-color .2s ease,box-shadow .2s ease}.knobBackground{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;transform:rotate(-135deg)}.knobBackgroundPath{fill:none;stroke:#8b5cf6;stroke-width:3.5;stroke-linecap:round;stroke-dasharray:113.1;stroke-dashoffset:113.1;transition:stroke-dashoffset .1s ease-out;filter:drop-shadow(0 0 3px rgba(139,92,246,.7))}.knobIndicator{position:absolute;width:4px;height:20px;background:linear-gradient(to bottom,#8b5cf6,#c084fc);top:5px;left:50%;transform-origin:center 27.5px;transform:translate(-50%) rotate(-135deg);border-radius:2px;z-index:2;box-shadow:0 0 6px #8b5cf6cc}.knobCenter{position:absolute;width:18px;height:18px;background:radial-gradient(circle,#0a0a0a,#1a1a1a);border-radius:50%;top:50%;left:50%;transform:translate(-50%,-50%);box-shadow:inset 1px 1px 3px #000000b3,0 1px 2px #8b5cf64d;z-index:3}.knob:hover .knobRing{border-color:#8b5cf6;box-shadow:inset 2px 2px 5px #00000080,inset -2px -2px 5px #3c3c3c1a,0 4px 12px #8b5cf666}.knob:hover .knobIndicator{background:linear-gradient(to bottom,#a78bfa,#c084fc);box-shadow:0 0 8px #a78bfae6}.knob.active .knobRing{border-color:#a78bfa;box-shadow:inset 2px 2px 5px #0009,inset -2px -2px 5px #3c3c3c26,0 4px 16px #a78bfa80}.knob.active .knobIndicator{background:linear-gradient(to bottom,#a78bfa,#c084fc);box-shadow:0 0 10px #a78bfa}.knob.active .knobBackgroundPath{stroke:#a78bfa;filter:drop-shadow(0 0 4px rgba(167,139,250,.9))}
|
|
2
|
-
/*# sourceMappingURL=index.css.map */
|
package/dist/index.css.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/CircularRange.module.css"],"sourcesContent":[".knob {\r\n width: 65px;\r\n height: 65px;\r\n position: relative;\r\n cursor: pointer;\r\n user-select: none;\r\n}\r\n\r\n.knobRing {\r\n width: 100%;\r\n height: 100%;\r\n border: 3px solid #333;\r\n border-radius: 50%;\r\n background: linear-gradient(145deg, #1a1a1a, #252525);\r\n box-shadow:\r\n inset 2px 2px 5px rgba(0, 0, 0, 0.5),\r\n inset -2px -2px 5px rgba(60, 60, 60, 0.1),\r\n 0 4px 8px rgba(0, 0, 0, 0.3);\r\n transition: border-color 0.2s ease, box-shadow 0.2s ease;\r\n}\r\n\r\n.knobBackground {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n pointer-events: none;\r\n transform: rotate(-135deg);\r\n}\r\n\r\n.knobBackgroundPath {\r\n fill: none;\r\n stroke: #8b5cf6;\r\n stroke-width: 3.5;\r\n stroke-linecap: round;\r\n stroke-dasharray: 113.1;\r\n stroke-dashoffset: 113.1;\r\n transition: stroke-dashoffset 0.1s ease-out;\r\n filter: drop-shadow(0 0 3px rgba(139, 92, 246, 0.7));\r\n}\r\n\r\n.knobIndicator {\r\n position: absolute;\r\n width: 4px;\r\n height: 20px;\r\n background: linear-gradient(to bottom, #8b5cf6, #c084fc);\r\n top: 5px;\r\n left: 50%;\r\n transform-origin: center 27.5px;\r\n transform: translateX(-50%) rotate(-135deg);\r\n border-radius: 2px;\r\n z-index: 2;\r\n /*transition: transform 0.05s ease-out;*/\r\n box-shadow: 0 0 6px rgba(139, 92, 246, 0.8);\r\n}\r\n\r\n.knobCenter {\r\n position: absolute;\r\n width: 18px;\r\n height: 18px;\r\n background: radial-gradient(circle, #0a0a0a, #1a1a1a);\r\n border-radius: 50%;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n box-shadow:\r\n inset 1px 1px 3px rgba(0, 0, 0, 0.7),\r\n 0 1px 2px rgba(139, 92, 246, 0.3);\r\n z-index: 3;\r\n}\r\n\r\n/* Hover states */\r\n.knob:hover .knobRing {\r\n border-color: #8b5cf6;\r\n box-shadow:\r\n inset 2px 2px 5px rgba(0, 0, 0, 0.5),\r\n inset -2px -2px 5px rgba(60, 60, 60, 0.1),\r\n 0 4px 12px rgba(139, 92, 246, 0.4);\r\n}\r\n\r\n.knob:hover .knobIndicator {\r\n background: linear-gradient(to bottom, #a78bfa, #c084fc);\r\n box-shadow: 0 0 8px rgba(167, 139, 250, 0.9);\r\n}\r\n\r\n.knob.active .knobRing {\r\n border-color: #a78bfa;\r\n box-shadow:\r\n inset 2px 2px 5px rgba(0, 0, 0, 0.6),\r\n inset -2px -2px 5px rgba(60, 60, 60, 0.15),\r\n 0 4px 16px rgba(167, 139, 250, 0.5);\r\n}\r\n\r\n.knob.active .knobIndicator {\r\n background: linear-gradient(to bottom, #a78bfa, #c084fc);\r\n box-shadow: 0 0 10px rgba(167, 139, 250, 1);\r\n}\r\n\r\n.knob.active .knobBackgroundPath {\r\n stroke: #a78bfa;\r\n filter: drop-shadow(0 0 4px rgba(167, 139, 250, 0.9));\r\n}"],"mappings":"AAAA,CAAC,KACG,MAAO,KACP,OAAQ,KACR,SAAU,SACV,OAAQ,QACR,YAAa,IACjB,CAEA,CAAC,SACG,MAAO,KACP,OAAQ,KACR,OAAQ,IAAI,MAAM,KAXtB,cAYmB,IACf,WAAY,gBAAgB,MAAhB,CAAwB,OAAxB,CAAiC,SAC7C,WACQ,MAAM,IAAI,IAAI,IAAI,SAAkB,CACpC,MAAM,KAAK,KAAK,IAAI,SAAqB,CACzC,EAAE,IAAI,IAAI,UAClB,WAAY,aAAa,IAAK,IAAI,CAAE,WAAW,IAAK,IACxD,CAEA,CAAC,eACG,SAAU,SACV,IAAK,EACL,KAAM,EACN,MAAO,KACP,OAAQ,KACR,eAAgB,KAChB,UAAW,OAAO,QACtB,CAEA,CAAC,mBACG,KAAM,KACN,OAAQ,QACR,aAAc,IACd,eAAgB,MAChB,iBAAkB,MAClB,kBAAmB,MACnB,WAAY,kBAAkB,IAAK,SACnC,OAAQ,YAAY,EAAE,EAAE,IAAI,KAAK,GAAG,CAAE,EAAE,CAAE,GAAG,CAAE,IACnD,CAEA,CAAC,cACG,SAAU,SACV,MAAO,IACP,OAAQ,KACR,WAAY,gBAAgB,GAAG,MAAnB,CAA2B,OAA3B,CAAoC,SAChD,IAAK,IACL,KAAM,IACN,iBAAkB,OAAO,OACzB,UAAW,UAAW,MAAM,OAAO,SAlDvC,cAmDmB,IACf,QAAS,EAET,WAAY,EAAE,EAAE,IAAI,SACxB,CAEA,CAAC,WACG,SAAU,SACV,MAAO,KACP,OAAQ,KACR,WAAY,gBAAgB,MAAhB,CAAwB,OAAxB,CAAiC,SA7DjD,cA8DmB,IACf,IAAK,IACL,KAAM,IACN,UAAW,UAAU,IAAI,CAAE,MAC3B,WACQ,MAAM,IAAI,IAAI,IAAI,SAAkB,CACpC,EAAE,IAAI,IAAI,UAClB,QAAS,CACb,CAGA,CAzEC,IAyEI,OAAO,CAjEX,SAkEG,aAAc,QACd,WACQ,MAAM,IAAI,IAAI,IAAI,SAAkB,CACpC,MAAM,KAAK,KAAK,IAAI,SAAqB,CACzC,EAAE,IAAI,KAAK,SACvB,CAEA,CAjFC,IAiFI,OAAO,CAvCX,cAwCG,WAAY,gBAAgB,GAAG,MAAnB,CAA2B,OAA3B,CAAoC,SAChD,WAAY,EAAE,EAAE,IAAI,SACxB,CAEA,CAtFC,IAsFI,CAAC,OAAO,CA9EZ,SA+EG,aAAc,QACd,WACQ,MAAM,IAAI,IAAI,IAAI,KAAkB,CACpC,MAAM,KAAK,KAAK,IAAI,SAAsB,CAC1C,EAAE,IAAI,KAAK,SACvB,CAEA,CA9FC,IA8FI,CARC,OAQO,CApDZ,cAqDG,WAAY,gBAAgB,GAAG,MAAnB,CAA2B,OAA3B,CAAoC,SAChD,WAAY,EAAE,EAAE,KAAK,OACzB,CAEA,CAnGC,IAmGI,CAbC,OAaO,CApEZ,mBAqEG,OAAQ,QACR,OAAQ,YAAY,EAAE,EAAE,IAAI,KAAK,GAAG,CAAE,GAAG,CAAE,GAAG,CAAE,IACpD","names":[]}
|
package/dist/index.mjs
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import{useCallback as L,useEffect as y,useRef as b,useState as P}from"react";var C={};import{jsx as s,jsxs as D}from"react/jsx-runtime";var p=113.1,T=({min:o=0,max:r=100,value:u=0,step:i=.01,onChange:g,theme:n=C})=>{let x=b(null),[h,v]=P(u),[l,k]=P(!1),m=b(0),f=b(0),Y=.01;y(()=>{v(u)},[u]);let B=e=>Math.min(r,Math.max(o,e)),M=L(e=>(e-o)/(r-o),[o,r]),E=L(e=>{let t=B(e);i>0&&(t=Math.round(t/i)*i),v(t),g?.(t)},[o,r,i,g]),c=e=>{e.preventDefault(),k(!0);let t="touches"in e?e.touches[0].clientY:e.clientY;m.current=t,f.current=h},a=e=>{if(!l)return;e.preventDefault();let t="touches"in e?e.touches[0].clientY:e.clientY,$=(m.current-t)*Y*(r-o);E(f.current+$)},d=()=>{k(!1)},w=()=>{E((o+r)/2)};y(()=>{let e=x.current;if(e)return e.addEventListener("mousedown",c),e.addEventListener("touchstart",c),document.addEventListener("mousemove",a),document.addEventListener("touchmove",a),document.addEventListener("mouseup",d),document.addEventListener("touchend",d),e.addEventListener("dblclick",w),()=>{e.removeEventListener("mousedown",c),e.removeEventListener("touchstart",c),document.removeEventListener("mousemove",a),document.removeEventListener("touchmove",a),document.removeEventListener("mouseup",d),document.removeEventListener("touchend",d),e.removeEventListener("dblclick",w)}},[a,l]);let R=M(h),N=R*270-135,S=p-R*p;return s("div",{ref:x,className:`${n.knob} ${l?n.active:""}`,children:D("div",{className:`${n.knobRing}`,children:[s("svg",{className:`${n.knobBackground}`,viewBox:"0 0 60 60",children:s("path",{className:`${n.knobBackgroundPath}`,d:"M 30 6 A 24 24 0 1 1 6 30",strokeDasharray:p,strokeDashoffset:S})}),s("div",{className:`${n.knobIndicator}`,style:{transform:`translateX(-50%) rotate(${N}deg)`}}),s("div",{className:`${n.knobCenter}`})]})})};export{T as CircularRange};
|
|
3
|
-
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/CircularRange.tsx","../src/CircularRange.module.css"],"sourcesContent":["import {\r\n useCallback,\r\n useEffect,\r\n useRef,\r\n useState,\r\n} from \"react\";\r\n\r\nimport styles from \"./CircularRange.module.css\";\r\n\r\nexport type StyleSlots =\r\n | 'knob'\r\n | 'knobRing'\r\n | 'knobBackground'\r\n | 'knobBackgroundPath'\r\n | 'knobIndicator'\r\n | 'knobCenter'\r\n | 'active'\r\n\r\nexport type CircularRangeThemeProps = Partial<Record<StyleSlots, string>>;\r\n\r\nexport interface CircularRangeProps {\r\n min?: number;\r\n max?: number;\r\n value?: number;\r\n step?: number;\r\n onChange?: (value: number) => void;\r\n\r\n // override styles with css module\r\n theme?: CircularRangeThemeProps;\r\n}\r\n\r\nconst ARC_LENGTH = 113.1; // 270°\r\n\r\nexport const CircularRange: React.FC<CircularRangeProps> = ({\r\n min = 0,\r\n max = 100,\r\n value = 0,\r\n step = 0.01,\r\n onChange,\r\n theme = styles\r\n}) => {\r\n const knobRef = useRef<HTMLDivElement | null>(null);\r\n\r\n const [internalValue, setInternalValue] = useState(value);\r\n const [isActive, setIsActive] = useState(false);\r\n\r\n const startY = useRef(0);\r\n const startValue = useRef(0);\r\n const sensitivity = 0.01;\r\n useEffect(() => {\r\n setInternalValue(value);\r\n }, [value]);\r\n\r\n const clamp = (v: number) => Math.min(max, Math.max(min, v));\r\n\r\n const getNormalizedValue = useCallback(\r\n (v: number) => {\r\n return (v - min) / (max - min);\r\n },\r\n [min, max],\r\n );\r\n\r\n const setValue = useCallback(\r\n (v: number) => {\r\n let next = clamp(v);\r\n if (step > 0) {\r\n next = Math.round(next / step) * step;\r\n }\r\n setInternalValue(next);\r\n onChange?.(next);\r\n },\r\n [min, max, step, onChange],\r\n );\r\n\r\n const handleStart = (e: MouseEvent | TouchEvent) => {\r\n e.preventDefault();\r\n setIsActive(true);\r\n const clientY = \"touches\" in e ? e.touches[0].clientY : e.clientY;\r\n startY.current = clientY;\r\n startValue.current = internalValue;\r\n };\r\n\r\n const handleMove = (e: MouseEvent | TouchEvent) => {\r\n if (!isActive) return;\r\n e.preventDefault();\r\n\r\n const clientY = \"touches\" in e ? e.touches[0].clientY : e.clientY;\r\n const deltaY = startY.current - clientY;\r\n const deltaValue = deltaY * sensitivity * (max - min);\r\n\r\n setValue(startValue.current + deltaValue);\r\n };\r\n\r\n const handleEnd = () => {\r\n setIsActive(false);\r\n };\r\n\r\n const handleDoubleClick = () => {\r\n setValue((min + max) / 2);\r\n };\r\n\r\n useEffect(() => {\r\n const el = knobRef.current;\r\n if (!el) return;\r\n\r\n el.addEventListener(\"mousedown\", handleStart);\r\n el.addEventListener(\"touchstart\", handleStart);\r\n\r\n document.addEventListener(\"mousemove\", handleMove);\r\n document.addEventListener(\"touchmove\", handleMove);\r\n document.addEventListener(\"mouseup\", handleEnd);\r\n document.addEventListener(\"touchend\", handleEnd);\r\n\r\n el.addEventListener(\"dblclick\", handleDoubleClick);\r\n\r\n return () => {\r\n el.removeEventListener(\"mousedown\", handleStart);\r\n el.removeEventListener(\"touchstart\", handleStart);\r\n\r\n document.removeEventListener(\"mousemove\", handleMove);\r\n document.removeEventListener(\"touchmove\", handleMove);\r\n document.removeEventListener(\"mouseup\", handleEnd);\r\n document.removeEventListener(\"touchend\", handleEnd);\r\n\r\n el.removeEventListener(\"dblclick\", handleDoubleClick);\r\n };\r\n }, [handleMove, isActive]);\r\n\r\n const normalized = getNormalizedValue(internalValue);\r\n const rotation = normalized * 270 - 135;\r\n const dashOffset = ARC_LENGTH - normalized * ARC_LENGTH;\r\n\r\n return (\r\n <div\r\n ref={knobRef}\r\n className={`${theme.knob} ${isActive ? theme.active : \"\"}`}\r\n >\r\n <div className={`${theme.knobRing}`}>\r\n <svg\r\n className={`${theme.knobBackground}`}\r\n viewBox=\"0 0 60 60\"\r\n >\r\n <path\r\n className={`${theme.knobBackgroundPath}`}\r\n d=\"M 30 6 A 24 24 0 1 1 6 30\"\r\n strokeDasharray={ARC_LENGTH}\r\n strokeDashoffset={dashOffset}\r\n />\r\n </svg>\r\n\r\n <div\r\n className={`${theme.knobIndicator}`}\r\n style={{\r\n transform: `translateX(-50%) rotate(${rotation}deg)`,\r\n }}\r\n />\r\n\r\n <div\r\n className={`${theme.knobCenter}`}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n",".knob {\r\n width: 65px;\r\n height: 65px;\r\n position: relative;\r\n cursor: pointer;\r\n user-select: none;\r\n}\r\n\r\n.knobRing {\r\n width: 100%;\r\n height: 100%;\r\n border: 3px solid #333;\r\n border-radius: 50%;\r\n background: linear-gradient(145deg, #1a1a1a, #252525);\r\n box-shadow:\r\n inset 2px 2px 5px rgba(0, 0, 0, 0.5),\r\n inset -2px -2px 5px rgba(60, 60, 60, 0.1),\r\n 0 4px 8px rgba(0, 0, 0, 0.3);\r\n transition: border-color 0.2s ease, box-shadow 0.2s ease;\r\n}\r\n\r\n.knobBackground {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n pointer-events: none;\r\n transform: rotate(-135deg);\r\n}\r\n\r\n.knobBackgroundPath {\r\n fill: none;\r\n stroke: #8b5cf6;\r\n stroke-width: 3.5;\r\n stroke-linecap: round;\r\n stroke-dasharray: 113.1;\r\n stroke-dashoffset: 113.1;\r\n transition: stroke-dashoffset 0.1s ease-out;\r\n filter: drop-shadow(0 0 3px rgba(139, 92, 246, 0.7));\r\n}\r\n\r\n.knobIndicator {\r\n position: absolute;\r\n width: 4px;\r\n height: 20px;\r\n background: linear-gradient(to bottom, #8b5cf6, #c084fc);\r\n top: 5px;\r\n left: 50%;\r\n transform-origin: center 27.5px;\r\n transform: translateX(-50%) rotate(-135deg);\r\n border-radius: 2px;\r\n z-index: 2;\r\n /*transition: transform 0.05s ease-out;*/\r\n box-shadow: 0 0 6px rgba(139, 92, 246, 0.8);\r\n}\r\n\r\n.knobCenter {\r\n position: absolute;\r\n width: 18px;\r\n height: 18px;\r\n background: radial-gradient(circle, #0a0a0a, #1a1a1a);\r\n border-radius: 50%;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n box-shadow:\r\n inset 1px 1px 3px rgba(0, 0, 0, 0.7),\r\n 0 1px 2px rgba(139, 92, 246, 0.3);\r\n z-index: 3;\r\n}\r\n\r\n/* Hover states */\r\n.knob:hover .knobRing {\r\n border-color: #8b5cf6;\r\n box-shadow:\r\n inset 2px 2px 5px rgba(0, 0, 0, 0.5),\r\n inset -2px -2px 5px rgba(60, 60, 60, 0.1),\r\n 0 4px 12px rgba(139, 92, 246, 0.4);\r\n}\r\n\r\n.knob:hover .knobIndicator {\r\n background: linear-gradient(to bottom, #a78bfa, #c084fc);\r\n box-shadow: 0 0 8px rgba(167, 139, 250, 0.9);\r\n}\r\n\r\n.knob.active .knobRing {\r\n border-color: #a78bfa;\r\n box-shadow:\r\n inset 2px 2px 5px rgba(0, 0, 0, 0.6),\r\n inset -2px -2px 5px rgba(60, 60, 60, 0.15),\r\n 0 4px 16px rgba(167, 139, 250, 0.5);\r\n}\r\n\r\n.knob.active .knobIndicator {\r\n background: linear-gradient(to bottom, #a78bfa, #c084fc);\r\n box-shadow: 0 0 10px rgba(167, 139, 250, 1);\r\n}\r\n\r\n.knob.active .knobBackgroundPath {\r\n stroke: #a78bfa;\r\n filter: drop-shadow(0 0 4px rgba(167, 139, 250, 0.9));\r\n}"],"mappings":"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","names":["useCallback","useEffect","useRef","useState","CircularRange_default","jsx","jsxs","ARC_LENGTH","CircularRange","min","max","value","step","onChange","theme","CircularRange_default","knobRef","useRef","internalValue","setInternalValue","useState","isActive","setIsActive","startY","startValue","sensitivity","useEffect","clamp","v","getNormalizedValue","useCallback","setValue","next","handleStart","clientY","handleMove","deltaValue","handleEnd","handleDoubleClick","el","normalized","rotation","dashOffset"]}
|