@studiotoolkit/color-wheel 1.0.0
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/LICENSE +21 -0
- package/README.md +152 -0
- package/dist/ColorWheel.d.ts +35 -0
- package/dist/ColorWheel.d.ts.map +1 -0
- package/dist/ThemeContext.d.ts +11 -0
- package/dist/ThemeContext.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +364 -0
- package/dist/style.css +1 -0
- package/package.json +78 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Studio Toolkit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Color Wheel
|
|
2
|
+
|
|
3
|
+
Interactive color wheel React component for creating and manipulating color harmonies with support for multiple harmony modes and customization options.
|
|
4
|
+
|
|
5
|
+
**Play around and Generate component code here:**
|
|
6
|
+
https://studiotoolkit.github.io/build-color-wheel
|
|
7
|
+
|
|
8
|
+
**Complete Demo:**
|
|
9
|
+
https://studiotoolkit.github.io/demo-all
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
### Harmony Modes
|
|
14
|
+
|
|
15
|
+
<table>
|
|
16
|
+
<tr>
|
|
17
|
+
<td align="center"><img src="assets/analogous.png" width="100"/><br/>Analogous</td>
|
|
18
|
+
<td align="center"><img src="assets/complementary.png" width="100"/><br/>Complementary</td>
|
|
19
|
+
<td align="center"><img src="assets/monochromatic.png" width="100"/><br/>Monochromatic</td>
|
|
20
|
+
<td align="center"><img src="assets/simple.png" width="100"/><br/>Simple</td>
|
|
21
|
+
</tr>
|
|
22
|
+
<tr>
|
|
23
|
+
<td align="center"><img src="assets/split-complementary.png" width="100"/><br/>Split Complementary</td>
|
|
24
|
+
<td align="center"><img src="assets/square.png" width="100"/><br/>Square</td>
|
|
25
|
+
<td align="center"><img src="assets/triadic.png" width="100"/><br/>Triadic</td>
|
|
26
|
+
<td align="center"></td>
|
|
27
|
+
</tr>
|
|
28
|
+
</table>
|
|
29
|
+
|
|
30
|
+
### Customization Options
|
|
31
|
+
|
|
32
|
+
<table>
|
|
33
|
+
<tr>
|
|
34
|
+
<td align="center"><img src="assets/background-image.png" width="100"/><br/>Background Color</td>
|
|
35
|
+
<td align="center"><img src="assets/center-dot.png" width="100"/><br/>Center Dot</td>
|
|
36
|
+
<td align="center"><img src="assets/harmony-polygon.png" width="100"/><br/>Harmony Polygon</td>
|
|
37
|
+
<td align="center"><img src="assets/thickness.png" width="100"/><br/>Thickness</td>
|
|
38
|
+
</tr>
|
|
39
|
+
<tr>
|
|
40
|
+
<td align="center"><img src="assets/thickness2.png" width="100"/><br/>Thickness variation</td>
|
|
41
|
+
<td align="center"></td>
|
|
42
|
+
<td align="center"></td>
|
|
43
|
+
<td align="center"></td>
|
|
44
|
+
</tr>
|
|
45
|
+
</table>
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Using pnpm
|
|
51
|
+
pnpm add @studiotoolkit/color-wheel
|
|
52
|
+
|
|
53
|
+
# Using npm
|
|
54
|
+
npm install @studiotoolkit/color-wheel
|
|
55
|
+
|
|
56
|
+
# Using yarn
|
|
57
|
+
yarn add @studiotoolkit/color-wheel
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**React Version:** `^18.0.0` or higher
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
### Basic Usage
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import { ColorWheel } from '@studiotoolkit/color-wheel';
|
|
68
|
+
import '@studiotoolkit/color-wheel/style.css';
|
|
69
|
+
|
|
70
|
+
function App() {
|
|
71
|
+
const handleColorsChange = (palette) => {
|
|
72
|
+
console.log('Selected colors:', palette);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<ColorWheel
|
|
77
|
+
onColorsChange={handleColorsChange}
|
|
78
|
+
harmonyMode="complementary"
|
|
79
|
+
width={300}
|
|
80
|
+
height={300}
|
|
81
|
+
/>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Sample Output:**
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"split": ["#00b1ff", "#ff0031", "#ffce00"]
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### With Custom Styling
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
import { ColorWheel } from '@studiotoolkit/color-wheel';
|
|
98
|
+
import '@studiotoolkit/color-wheel/style.css';
|
|
99
|
+
|
|
100
|
+
function App() {
|
|
101
|
+
const handleColorsChange = (palette) => {
|
|
102
|
+
console.log('Selected colors:', palette);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<ColorWheel
|
|
107
|
+
onColorsChange={handleColorsChange}
|
|
108
|
+
harmonyMode="triadic"
|
|
109
|
+
saturation={100}
|
|
110
|
+
brightness={50}
|
|
111
|
+
width={400}
|
|
112
|
+
height={400}
|
|
113
|
+
wheelThickness={80}
|
|
114
|
+
dotSize={5}
|
|
115
|
+
dotPosition="outer"
|
|
116
|
+
handleThickness={2}
|
|
117
|
+
handleColor="#000000"
|
|
118
|
+
harmonyPolygon={true}
|
|
119
|
+
polygonColor="#000000"
|
|
120
|
+
polygonThickness={1}
|
|
121
|
+
showCenterDot={true}
|
|
122
|
+
centerDot="#ffffff"
|
|
123
|
+
borderColor="#ffffff"
|
|
124
|
+
canvasBackgroundColor="transparent"
|
|
125
|
+
/>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Harmony Modes
|
|
131
|
+
|
|
132
|
+
The ColorWheel supports the following harmony modes:
|
|
133
|
+
|
|
134
|
+
- `complementary` - Colors opposite on the color wheel
|
|
135
|
+
- `analogous` - Adjacent colors on the color wheel
|
|
136
|
+
- `monochromatic` - Variations of a single hue
|
|
137
|
+
- `split` - Split complementary harmony
|
|
138
|
+
- `triadic` - Three evenly spaced colors
|
|
139
|
+
- `square` - Four evenly spaced colors
|
|
140
|
+
- `simple` - Single color selection
|
|
141
|
+
|
|
142
|
+
## Contributors
|
|
143
|
+
|
|
144
|
+
[StudioToolkit](https://github.com/studiotoolkit)
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
Licensed under the MIT License.
|
|
149
|
+
|
|
150
|
+
## Keywords
|
|
151
|
+
|
|
152
|
+
color-wheel, color-picker, color-harmony, harmony-polygon, react-color, color-selection, design-tools, ui-components
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import "./ColorWheel.css";
|
|
2
|
+
type HarmonyMode = "complementary" | "analogous" | "monochromatic" | "split" | "triadic" | "square" | "simple";
|
|
3
|
+
type DotPosition = "center" | "inner" | "outer";
|
|
4
|
+
export interface ColorData {
|
|
5
|
+
HEX: string;
|
|
6
|
+
RGB: [number, number, number];
|
|
7
|
+
HSL: [number, number, number];
|
|
8
|
+
}
|
|
9
|
+
export interface PaletteOutput {
|
|
10
|
+
[key: string]: string[];
|
|
11
|
+
}
|
|
12
|
+
interface ColorWheelProps {
|
|
13
|
+
onColorsChange?: (palette: PaletteOutput) => void;
|
|
14
|
+
harmonyMode?: HarmonyMode;
|
|
15
|
+
saturation?: number;
|
|
16
|
+
brightness?: number;
|
|
17
|
+
circleRadius?: number;
|
|
18
|
+
wheelThickness?: number;
|
|
19
|
+
dotSize?: number;
|
|
20
|
+
dotPosition?: DotPosition;
|
|
21
|
+
handleThickness?: number;
|
|
22
|
+
handleColor?: string;
|
|
23
|
+
harmonyPolygon?: boolean;
|
|
24
|
+
polygonColor?: string;
|
|
25
|
+
polygonThickness?: number;
|
|
26
|
+
centerDot?: string;
|
|
27
|
+
showCenterDot?: boolean;
|
|
28
|
+
borderColor?: string;
|
|
29
|
+
canvasBackgroundColor?: string;
|
|
30
|
+
width?: number;
|
|
31
|
+
height?: number;
|
|
32
|
+
}
|
|
33
|
+
export default function ColorWheel({ onColorsChange, harmonyMode: propHarmonyMode, saturation: propSaturation, brightness: propBrightness, circleRadius: propCircleRadius, wheelThickness: propWheelThickness, dotSize: propDotSize, dotPosition: propDotPosition, handleThickness: propHandleThickness, handleColor: propHandleColor, harmonyPolygon: propHarmonyPolygon, polygonColor: propPolygonColor, polygonThickness: propPolygonThickness, centerDot: propCenterDot, showCenterDot: propShowCenterDot, borderColor: propBorderColor, canvasBackgroundColor: propCanvasBackgroundColor, width, height, }: ColorWheelProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=ColorWheel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColorWheel.d.ts","sourceRoot":"","sources":["../src/ColorWheel.tsx"],"names":[],"mappings":"AACA,OAAO,kBAAkB,CAAC;AAG1B,KAAK,WAAW,GACZ,eAAe,GACf,WAAW,GACX,eAAe,GACf,OAAO,GACP,SAAS,GACT,QAAQ,GACR,QAAQ,CAAC;AACb,KAAK,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAEhD,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACzB;AAUD,UAAU,eAAe;IACvB,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAClD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAwHD,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EACjC,cAAc,EACd,WAAW,EAAE,eAAe,EAC5B,UAAU,EAAE,cAAc,EAC1B,UAAU,EAAE,cAAc,EAC1B,YAAY,EAAE,gBAAgB,EAC9B,cAAc,EAAE,kBAAkB,EAClC,OAAO,EAAE,WAAW,EACpB,WAAW,EAAE,eAAe,EAC5B,eAAe,EAAE,mBAAmB,EACpC,WAAW,EAAE,eAAe,EAC5B,cAAc,EAAE,kBAAkB,EAClC,YAAY,EAAE,gBAAgB,EAC9B,gBAAgB,EAAE,oBAAoB,EACtC,SAAS,EAAE,aAAa,EACxB,aAAa,EAAE,iBAAyB,EACxC,WAAW,EAAE,eAA2B,EACxC,qBAAqB,EAAE,yBAAyC,EAChE,KAAW,EACX,MAAY,GACb,EAAE,eAAe,2CAuejB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
interface ThemeContextType {
|
|
3
|
+
isDark: boolean;
|
|
4
|
+
setIsDark: (v: boolean | ((prev: boolean) => boolean)) => void;
|
|
5
|
+
}
|
|
6
|
+
export declare function ThemeProvider({ children }: {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export declare function useTheme(): ThemeContextType;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=ThemeContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThemeContext.d.ts","sourceRoot":"","sources":["../src/ThemeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvF,UAAU,gBAAgB;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,IAAI,CAAC;CAChE;AAOD,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CASlE;AAED,wBAAgB,QAAQ,qBAEvB"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const F=require("react/jsx-runtime"),t=require("react"),me=t.createContext({isDark:!1,setIsDark:()=>{}});function Ye({children:S}){const[i,g]=t.useState(()=>localStorage.getItem("theme")==="dark");return t.useEffect(()=>{document.documentElement.setAttribute("data-theme",i?"dark":"light"),localStorage.setItem("theme",i?"dark":"light")},[i]),F.jsx(me.Provider,{value:{isDark:i,setIsDark:g},children:S})}function ge(){return t.useContext(me)}const he={complementary:[0,180],analogous:[-30,0,30],monochromatic:[0],split:[0,150,-150],triadic:[0,120,240],square:[0,90,180,270],simple:[0]},ze=[{name:"Harmony Mode",attribute:"harmony-mode",default:"split",show:!0,notes:""},{name:"Saturation",attribute:"saturation",default:100,show:!0,notes:""},{name:"Brightness",attribute:"brightness",default:50,show:!0,notes:""},{name:"Circle Radius",attribute:"circle-radius",default:1,show:!1,notes:"If not passed, default it is false"},{name:"Wheel Thickness",attribute:"wheel-thickness",default:80,show:!1,notes:"If not passed, default it is false"},{name:"Dot Size",attribute:"dot-size",default:5,show:!1,notes:"If not passed, default it is false"},{name:"Dot Position",attribute:"dot-position",default:"outer",show:!1,notes:"If not passed, default it is false"},{name:"Handle Thickness",attribute:"handle-thickness",default:2,show:!1,notes:"If not passed, default it is false"},{name:"Handle Color",attribute:"handle-color",default:"#000000",show:!1,notes:"If not passed, default it is false"},{name:"Show Harmony Polygon",attribute:"harmony-polygon",default:!1,show:!1,notes:"If not passed, default it is false"},{name:"Polygon Color",attribute:"polygon-color",default:"#000000",show:!1,notes:"If not passed, default it is false"},{name:"Polygon Thickness",attribute:"polygon-thickness",default:1,show:!1,notes:"If not passed, default it is false"},{name:"Center Dot",attribute:"center-dot",default:"#ffffff",show:!1,notes:"If not passed, default it is false"},{name:"Palette",attribute:"palette",default:null,show:!1,notes:"If not passed, default it is false"},{name:"Palette JSON",attribute:"palette-json",default:null,show:!1,notes:"If not passed, default it is false"}];function Ae({onColorsChange:S,harmonyMode:i,saturation:g,brightness:E,circleRadius:b,wheelThickness:y,dotSize:k,dotPosition:P,handleThickness:C,handleColor:I,harmonyPolygon:T,polygonColor:R,polygonThickness:D,centerDot:j,showCenterDot:H=!1,borderColor:U="#ffffff",canvasBackgroundColor:Y="transparent",width:W=450,height:L=450}){const O=t.useRef(null),[be,z]=t.useState(!1),{isDark:G}=ge(),l=e=>ze.find(s=>s.attribute===e),[c,ye]=t.useState(i||l("harmony-mode").default),[N,ke]=t.useState(g??l("saturation").default),[$,we]=t.useState(E??l("brightness").default),A=t.useCallback(()=>{const e=l("circle-radius").default;if(b!==void 0)return b;if(e===1){const s=Math.min(W,L),a=y??l("wheel-thickness").default,n=k??l("dot-size").default;return s/2-a/2-n-10}return e},[W,L,b,y,k]),[w,J]=t.useState(A()),[v,Se]=t.useState(y??l("wheel-thickness").default),[K,ve]=t.useState(k??l("dot-size").default),[X,Me]=t.useState(P||l("dot-position").default),[Q,Ee]=t.useState(C??l("handle-thickness").default),[V,Pe]=t.useState(I||(l("handle-color").default==="black"?"#000000":l("handle-color").default)),[Z,Ce]=t.useState(T??l("harmony-polygon").default),[x,Ie]=t.useState(R||(l("polygon-color").default==="black"?"#000000":l("polygon-color").default)),[p,Te]=t.useState(D??l("polygon-thickness").default),[ee,Re]=t.useState(j||(l("center-dot").default==="white"?"#ffffff":l("center-dot").default)),[te,De]=t.useState(H),[_,je]=t.useState(U),[M,We]=t.useState(Y),[d,se]=t.useState(0);t.useEffect(()=>{i!==void 0&&ye(i)},[i]),t.useEffect(()=>{g!==void 0&&ke(g)},[g]),t.useEffect(()=>{E!==void 0&&we(E)},[E]),t.useEffect(()=>{J(b!==void 0?b:A())},[b,A]),t.useEffect(()=>{y!==void 0&&Se(y)},[y]),t.useEffect(()=>{k!==void 0&&ve(k)},[k]),t.useEffect(()=>{P!==void 0&&Me(P)},[P]),t.useEffect(()=>{C!==void 0&&Ee(C)},[C]),t.useEffect(()=>{I!==void 0&&Pe(I)},[I]),t.useEffect(()=>{T!==void 0&&Ce(T)},[T]),t.useEffect(()=>{R!==void 0&&Ie(R)},[R]),t.useEffect(()=>{D!==void 0&&Te(D)},[D]),t.useEffect(()=>{j!==void 0&&Re(j)},[j]),t.useEffect(()=>{De(H)},[H]),t.useEffect(()=>{je(U)},[U]),t.useEffect(()=>{We(Y)},[Y]);const o={x:W/2,y:L/2},B=e=>(e+360)%360,ae=t.useCallback((e,s=N,a=$)=>`hsl(${e}, ${s}%, ${a}%)`,[N,$]),Le=(e,s,a)=>{s/=100,a/=100;const n=(1-Math.abs(2*a-1))*s,f=n*(1-Math.abs(e/60%2-1)),u=a-n/2;let r=0,h=0,m=0;return e<60?[r,h,m]=[n,f,0]:e<120?[r,h,m]=[f,n,0]:e<180?[r,h,m]=[0,n,f]:e<240?[r,h,m]=[0,f,n]:e<300?[r,h,m]=[f,0,n]:[r,h,m]=[n,0,f],{r:Math.round((r+u)*255),g:Math.round((h+u)*255),b:Math.round((m+u)*255)}},Oe=(e,s,a)=>"#"+[e,s,a].map(n=>n.toString(16).padStart(2,"0")).join(""),ne=t.useCallback(()=>X==="center"?w:X==="inner"?w-v/2:w+v/2,[X,w,v]),le=t.useCallback(e=>{const s=(e-90)*Math.PI/180,a=ne();return{x:o.x+a*Math.cos(s),y:o.y+a*Math.sin(s)}},[o.x,o.y,ne]),oe=(e,s)=>{const a=e-o.x,n=s-o.y,f=Math.atan2(n,a)*180/Math.PI;return B(f+90)},fe=t.useCallback(()=>{let e=[];c==="monochromatic"?e=[{h:d,l:30},{h:d,l:50},{h:d,l:70}]:e=he[c].map(a=>({h:B(d+a),l:$}));const s=e.map(a=>{const n=Le(a.h,N,a.l);return Oe(n.r,n.g,n.b)});return{[c]:s}},[c,d,N,$]),ie=t.useCallback(e=>{for(let s=0;s<360;s++)e.beginPath(),e.strokeStyle=`hsl(${s},100%,50%)`,e.lineWidth=v,e.arc(o.x,o.y,w,(s-90)*Math.PI/180,(s-89)*Math.PI/180),e.stroke()},[o.x,o.y,w,v]),ue=t.useCallback((e,s)=>{!Z||s.length<3||(e.beginPath(),e.moveTo(s[0].x,s[0].y),s.slice(1).forEach(a=>{e.lineTo(a.x,a.y)}),e.closePath(),e.strokeStyle=x,e.lineWidth=p,e.stroke())},[Z,x,p]),ce=t.useCallback(e=>{if(c==="simple")return;const s=he[c],a=[];s.forEach(n=>{const f=B(d+n),u=le(f);a.push(u),e.beginPath(),e.moveTo(o.x,o.y),e.lineTo(u.x,u.y),e.strokeStyle=V,e.lineWidth=Q,e.stroke(),e.beginPath(),e.arc(u.x,u.y,K,0,Math.PI*2),e.fillStyle=ae(f),e.fill(),e.strokeStyle="white",e.stroke()}),ue(e,a),te&&(e.beginPath(),e.arc(o.x,o.y,5,0,Math.PI*2),e.fillStyle=ee,e.fill(),e.strokeStyle="white",e.lineWidth=1,e.stroke())},[c,d,o.x,o.y,K,Q,V,ee,te,le,ae,ue]),de=t.useCallback(()=>{const e=O.current;if(!e)return;const s=e.getContext("2d");s&&(s.clearRect(0,0,e.width,e.height),M&&M!=="transparent"?(s.fillStyle=M,s.fillRect(0,0,e.width,e.height)):M==="transparent"&&(s.fillStyle=G?"#1a1a1a":"#ffffff",s.fillRect(0,0,e.width,e.height)),ie(s),ce(s),_&&(s.strokeStyle=_,s.lineWidth=1,s.strokeRect(0,0,e.width,e.height)))},[ie,ce,_,M,G]),Ne=()=>z(!0),$e=()=>z(!1),qe=()=>z(!1),He=e=>{if(!be)return;const s=O.current;if(!s)return;const a=s.getBoundingClientRect(),n=oe(e.clientX-a.left,e.clientY-a.top);se(n)},Ue=e=>{const s=O.current;if(!s)return;const a=s.getBoundingClientRect(),n=oe(e.clientX-a.left,e.clientY-a.top);se(n)};t.useEffect(()=>{de()},[de]);const q=t.useMemo(()=>fe(),[fe]);t.useEffect(()=>{S&&S(q)},[q,S]);const re=t.useCallback(()=>q,[q]);return t.useEffect(()=>(window.getColorWheelPalette=re,()=>{delete window.getColorWheelPalette}),[re]),F.jsx("div",{className:"color-wheel-container",children:F.jsx("canvas",{ref:O,width:W,height:L,onMouseDown:Ne,onMouseUp:$e,onMouseLeave:qe,onMouseMove:He,onClick:Ue,style:{display:"block",margin:"0 auto",cursor:"pointer"}})})}exports.ColorWheel=Ae;exports.ThemeProvider=Ye;exports.useTheme=ge;
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { jsx as J } from "react/jsx-runtime";
|
|
2
|
+
import { useContext as Ae, useState as o, useEffect as a, createContext as Xe, useRef as _e, useCallback as d, useMemo as qe } from "react";
|
|
3
|
+
const ye = Xe({
|
|
4
|
+
isDark: !1,
|
|
5
|
+
setIsDark: () => {
|
|
6
|
+
}
|
|
7
|
+
});
|
|
8
|
+
function Ke({ children: P }) {
|
|
9
|
+
const [u, b] = o(() => localStorage.getItem("theme") === "dark");
|
|
10
|
+
return a(() => {
|
|
11
|
+
document.documentElement.setAttribute("data-theme", u ? "dark" : "light"), localStorage.setItem("theme", u ? "dark" : "light");
|
|
12
|
+
}, [u]), /* @__PURE__ */ J(ye.Provider, { value: { isDark: u, setIsDark: b }, children: P });
|
|
13
|
+
}
|
|
14
|
+
function Be() {
|
|
15
|
+
return Ae(ye);
|
|
16
|
+
}
|
|
17
|
+
const ge = {
|
|
18
|
+
complementary: [0, 180],
|
|
19
|
+
analogous: [-30, 0, 30],
|
|
20
|
+
monochromatic: [0],
|
|
21
|
+
split: [0, 150, -150],
|
|
22
|
+
triadic: [0, 120, 240],
|
|
23
|
+
square: [0, 90, 180, 270],
|
|
24
|
+
simple: [0]
|
|
25
|
+
}, Fe = [
|
|
26
|
+
{
|
|
27
|
+
name: "Harmony Mode",
|
|
28
|
+
attribute: "harmony-mode",
|
|
29
|
+
default: "split",
|
|
30
|
+
show: !0,
|
|
31
|
+
notes: ""
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "Saturation",
|
|
35
|
+
attribute: "saturation",
|
|
36
|
+
default: 100,
|
|
37
|
+
show: !0,
|
|
38
|
+
notes: ""
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "Brightness",
|
|
42
|
+
attribute: "brightness",
|
|
43
|
+
default: 50,
|
|
44
|
+
show: !0,
|
|
45
|
+
notes: ""
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: "Circle Radius",
|
|
49
|
+
attribute: "circle-radius",
|
|
50
|
+
default: 1,
|
|
51
|
+
show: !1,
|
|
52
|
+
notes: "If not passed, default it is false"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: "Wheel Thickness",
|
|
56
|
+
attribute: "wheel-thickness",
|
|
57
|
+
default: 80,
|
|
58
|
+
show: !1,
|
|
59
|
+
notes: "If not passed, default it is false"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "Dot Size",
|
|
63
|
+
attribute: "dot-size",
|
|
64
|
+
default: 5,
|
|
65
|
+
show: !1,
|
|
66
|
+
notes: "If not passed, default it is false"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: "Dot Position",
|
|
70
|
+
attribute: "dot-position",
|
|
71
|
+
default: "outer",
|
|
72
|
+
show: !1,
|
|
73
|
+
notes: "If not passed, default it is false"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: "Handle Thickness",
|
|
77
|
+
attribute: "handle-thickness",
|
|
78
|
+
default: 2,
|
|
79
|
+
show: !1,
|
|
80
|
+
notes: "If not passed, default it is false"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "Handle Color",
|
|
84
|
+
attribute: "handle-color",
|
|
85
|
+
default: "#000000",
|
|
86
|
+
show: !1,
|
|
87
|
+
notes: "If not passed, default it is false"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: "Show Harmony Polygon",
|
|
91
|
+
attribute: "harmony-polygon",
|
|
92
|
+
default: !1,
|
|
93
|
+
show: !1,
|
|
94
|
+
notes: "If not passed, default it is false"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "Polygon Color",
|
|
98
|
+
attribute: "polygon-color",
|
|
99
|
+
default: "#000000",
|
|
100
|
+
show: !1,
|
|
101
|
+
notes: "If not passed, default it is false"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "Polygon Thickness",
|
|
105
|
+
attribute: "polygon-thickness",
|
|
106
|
+
default: 1,
|
|
107
|
+
show: !1,
|
|
108
|
+
notes: "If not passed, default it is false"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: "Center Dot",
|
|
112
|
+
attribute: "center-dot",
|
|
113
|
+
default: "#ffffff",
|
|
114
|
+
show: !1,
|
|
115
|
+
notes: "If not passed, default it is false"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: "Palette",
|
|
119
|
+
attribute: "palette",
|
|
120
|
+
default: null,
|
|
121
|
+
show: !1,
|
|
122
|
+
notes: "If not passed, default it is false"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: "Palette JSON",
|
|
126
|
+
attribute: "palette-json",
|
|
127
|
+
default: null,
|
|
128
|
+
show: !1,
|
|
129
|
+
notes: "If not passed, default it is false"
|
|
130
|
+
}
|
|
131
|
+
];
|
|
132
|
+
function Qe({
|
|
133
|
+
onColorsChange: P,
|
|
134
|
+
harmonyMode: u,
|
|
135
|
+
saturation: b,
|
|
136
|
+
brightness: C,
|
|
137
|
+
circleRadius: w,
|
|
138
|
+
wheelThickness: k,
|
|
139
|
+
dotSize: v,
|
|
140
|
+
dotPosition: R,
|
|
141
|
+
handleThickness: T,
|
|
142
|
+
handleColor: D,
|
|
143
|
+
harmonyPolygon: E,
|
|
144
|
+
polygonColor: L,
|
|
145
|
+
polygonThickness: W,
|
|
146
|
+
centerDot: N,
|
|
147
|
+
showCenterDot: z = !1,
|
|
148
|
+
borderColor: A = "#ffffff",
|
|
149
|
+
canvasBackgroundColor: X = "transparent",
|
|
150
|
+
width: O = 450,
|
|
151
|
+
height: $ = 450
|
|
152
|
+
}) {
|
|
153
|
+
const j = _e(null), [be, _] = o(!1), { isDark: K } = Be(), l = (e) => Fe.find((t) => t.attribute === e), [c, we] = o(
|
|
154
|
+
u || l("harmony-mode").default
|
|
155
|
+
), [H, ke] = o(
|
|
156
|
+
b ?? l("saturation").default
|
|
157
|
+
), [U, ve] = o(
|
|
158
|
+
C ?? l("brightness").default
|
|
159
|
+
), q = d(() => {
|
|
160
|
+
const e = l("circle-radius").default;
|
|
161
|
+
if (w !== void 0) return w;
|
|
162
|
+
if (e === 1) {
|
|
163
|
+
const t = Math.min(O, $), s = k ?? l("wheel-thickness").default, n = v ?? l("dot-size").default;
|
|
164
|
+
return t / 2 - s / 2 - n - 10;
|
|
165
|
+
}
|
|
166
|
+
return e;
|
|
167
|
+
}, [O, $, w, k, v]), [M, Q] = o(q()), [I, Me] = o(
|
|
168
|
+
k ?? l("wheel-thickness").default
|
|
169
|
+
), [V, Pe] = o(
|
|
170
|
+
v ?? l("dot-size").default
|
|
171
|
+
), [B, Ie] = o(
|
|
172
|
+
R || l("dot-position").default
|
|
173
|
+
), [Z, Se] = o(
|
|
174
|
+
T ?? l("handle-thickness").default
|
|
175
|
+
), [x, Ce] = o(
|
|
176
|
+
D || (l("handle-color").default === "black" ? "#000000" : l("handle-color").default)
|
|
177
|
+
), [p, Re] = o(
|
|
178
|
+
E ?? l("harmony-polygon").default
|
|
179
|
+
), [ee, Te] = o(
|
|
180
|
+
L || (l("polygon-color").default === "black" ? "#000000" : l("polygon-color").default)
|
|
181
|
+
), [te, De] = o(
|
|
182
|
+
W ?? l("polygon-thickness").default
|
|
183
|
+
), [se, Ee] = o(
|
|
184
|
+
N || (l("center-dot").default === "white" ? "#ffffff" : l("center-dot").default)
|
|
185
|
+
), [ne, Le] = o(z), [F, We] = o(A), [S, Ne] = o(
|
|
186
|
+
X
|
|
187
|
+
), [h, ae] = o(0);
|
|
188
|
+
a(() => {
|
|
189
|
+
u !== void 0 && we(u);
|
|
190
|
+
}, [u]), a(() => {
|
|
191
|
+
b !== void 0 && ke(b);
|
|
192
|
+
}, [b]), a(() => {
|
|
193
|
+
C !== void 0 && ve(C);
|
|
194
|
+
}, [C]), a(() => {
|
|
195
|
+
Q(w !== void 0 ? w : q());
|
|
196
|
+
}, [w, q]), a(() => {
|
|
197
|
+
k !== void 0 && Me(k);
|
|
198
|
+
}, [k]), a(() => {
|
|
199
|
+
v !== void 0 && Pe(v);
|
|
200
|
+
}, [v]), a(() => {
|
|
201
|
+
R !== void 0 && Ie(R);
|
|
202
|
+
}, [R]), a(() => {
|
|
203
|
+
T !== void 0 && Se(T);
|
|
204
|
+
}, [T]), a(() => {
|
|
205
|
+
D !== void 0 && Ce(D);
|
|
206
|
+
}, [D]), a(() => {
|
|
207
|
+
E !== void 0 && Re(E);
|
|
208
|
+
}, [E]), a(() => {
|
|
209
|
+
L !== void 0 && Te(L);
|
|
210
|
+
}, [L]), a(() => {
|
|
211
|
+
W !== void 0 && De(W);
|
|
212
|
+
}, [W]), a(() => {
|
|
213
|
+
N !== void 0 && Ee(N);
|
|
214
|
+
}, [N]), a(() => {
|
|
215
|
+
Le(z);
|
|
216
|
+
}, [z]), a(() => {
|
|
217
|
+
We(A);
|
|
218
|
+
}, [A]), a(() => {
|
|
219
|
+
Ne(X);
|
|
220
|
+
}, [X]);
|
|
221
|
+
const i = { x: O / 2, y: $ / 2 }, G = (e) => (e + 360) % 360, oe = d(
|
|
222
|
+
(e, t = H, s = U) => `hsl(${e}, ${t}%, ${s}%)`,
|
|
223
|
+
[H, U]
|
|
224
|
+
), Oe = (e, t, s) => {
|
|
225
|
+
t /= 100, s /= 100;
|
|
226
|
+
const n = (1 - Math.abs(2 * s - 1)) * t, f = n * (1 - Math.abs(e / 60 % 2 - 1)), r = s - n / 2;
|
|
227
|
+
let m = 0, g = 0, y = 0;
|
|
228
|
+
return e < 60 ? [m, g, y] = [n, f, 0] : e < 120 ? [m, g, y] = [f, n, 0] : e < 180 ? [m, g, y] = [0, n, f] : e < 240 ? [m, g, y] = [0, f, n] : e < 300 ? [m, g, y] = [f, 0, n] : [m, g, y] = [n, 0, f], {
|
|
229
|
+
r: Math.round((m + r) * 255),
|
|
230
|
+
g: Math.round((g + r) * 255),
|
|
231
|
+
b: Math.round((y + r) * 255)
|
|
232
|
+
};
|
|
233
|
+
}, $e = (e, t, s) => "#" + [e, t, s].map((n) => n.toString(16).padStart(2, "0")).join(""), le = d(() => B === "center" ? M : B === "inner" ? M - I / 2 : M + I / 2, [B, M, I]), ie = d(
|
|
234
|
+
(e) => {
|
|
235
|
+
const t = (e - 90) * Math.PI / 180, s = le();
|
|
236
|
+
return {
|
|
237
|
+
x: i.x + s * Math.cos(t),
|
|
238
|
+
y: i.y + s * Math.sin(t)
|
|
239
|
+
};
|
|
240
|
+
},
|
|
241
|
+
[i.x, i.y, le]
|
|
242
|
+
), fe = (e, t) => {
|
|
243
|
+
const s = e - i.x, n = t - i.y, f = Math.atan2(n, s) * 180 / Math.PI;
|
|
244
|
+
return G(f + 90);
|
|
245
|
+
}, de = d(() => {
|
|
246
|
+
let e = [];
|
|
247
|
+
c === "monochromatic" ? e = [
|
|
248
|
+
{ h, l: 30 },
|
|
249
|
+
{ h, l: 50 },
|
|
250
|
+
{ h, l: 70 }
|
|
251
|
+
] : e = ge[c].map((s) => ({
|
|
252
|
+
h: G(h + s),
|
|
253
|
+
l: U
|
|
254
|
+
}));
|
|
255
|
+
const t = e.map((s) => {
|
|
256
|
+
const n = Oe(s.h, H, s.l);
|
|
257
|
+
return $e(n.r, n.g, n.b);
|
|
258
|
+
});
|
|
259
|
+
return {
|
|
260
|
+
[c]: t
|
|
261
|
+
};
|
|
262
|
+
}, [c, h, H, U]), ue = d(
|
|
263
|
+
(e) => {
|
|
264
|
+
for (let t = 0; t < 360; t++)
|
|
265
|
+
e.beginPath(), e.strokeStyle = `hsl(${t},100%,50%)`, e.lineWidth = I, e.arc(
|
|
266
|
+
i.x,
|
|
267
|
+
i.y,
|
|
268
|
+
M,
|
|
269
|
+
(t - 90) * Math.PI / 180,
|
|
270
|
+
(t - 89) * Math.PI / 180
|
|
271
|
+
), e.stroke();
|
|
272
|
+
},
|
|
273
|
+
[i.x, i.y, M, I]
|
|
274
|
+
), re = d(
|
|
275
|
+
(e, t) => {
|
|
276
|
+
!p || t.length < 3 || (e.beginPath(), e.moveTo(t[0].x, t[0].y), t.slice(1).forEach((s) => {
|
|
277
|
+
e.lineTo(s.x, s.y);
|
|
278
|
+
}), e.closePath(), e.strokeStyle = ee, e.lineWidth = te, e.stroke());
|
|
279
|
+
},
|
|
280
|
+
[p, ee, te]
|
|
281
|
+
), ce = d(
|
|
282
|
+
(e) => {
|
|
283
|
+
if (c === "simple")
|
|
284
|
+
return;
|
|
285
|
+
const t = ge[c], s = [];
|
|
286
|
+
t.forEach((n) => {
|
|
287
|
+
const f = G(h + n), r = ie(f);
|
|
288
|
+
s.push(r), e.beginPath(), e.moveTo(i.x, i.y), e.lineTo(r.x, r.y), e.strokeStyle = x, e.lineWidth = Z, e.stroke(), e.beginPath(), e.arc(r.x, r.y, V, 0, Math.PI * 2), e.fillStyle = oe(f), e.fill(), e.strokeStyle = "white", e.stroke();
|
|
289
|
+
}), re(e, s), ne && (e.beginPath(), e.arc(i.x, i.y, 5, 0, Math.PI * 2), e.fillStyle = se, e.fill(), e.strokeStyle = "white", e.lineWidth = 1, e.stroke());
|
|
290
|
+
},
|
|
291
|
+
[
|
|
292
|
+
c,
|
|
293
|
+
h,
|
|
294
|
+
i.x,
|
|
295
|
+
i.y,
|
|
296
|
+
V,
|
|
297
|
+
Z,
|
|
298
|
+
x,
|
|
299
|
+
se,
|
|
300
|
+
ne,
|
|
301
|
+
ie,
|
|
302
|
+
oe,
|
|
303
|
+
re
|
|
304
|
+
]
|
|
305
|
+
), he = d(() => {
|
|
306
|
+
const e = j.current;
|
|
307
|
+
if (!e) return;
|
|
308
|
+
const t = e.getContext("2d");
|
|
309
|
+
t && (t.clearRect(0, 0, e.width, e.height), S && S !== "transparent" ? (t.fillStyle = S, t.fillRect(0, 0, e.width, e.height)) : S === "transparent" && (t.fillStyle = K ? "#1a1a1a" : "#ffffff", t.fillRect(0, 0, e.width, e.height)), ue(t), ce(t), F && (t.strokeStyle = F, t.lineWidth = 1, t.strokeRect(0, 0, e.width, e.height)));
|
|
310
|
+
}, [
|
|
311
|
+
ue,
|
|
312
|
+
ce,
|
|
313
|
+
F,
|
|
314
|
+
S,
|
|
315
|
+
K
|
|
316
|
+
]), je = () => _(!0), He = () => _(!1), Ue = () => _(!1), Ye = (e) => {
|
|
317
|
+
if (!be) return;
|
|
318
|
+
const t = j.current;
|
|
319
|
+
if (!t) return;
|
|
320
|
+
const s = t.getBoundingClientRect(), n = fe(e.clientX - s.left, e.clientY - s.top);
|
|
321
|
+
ae(n);
|
|
322
|
+
}, ze = (e) => {
|
|
323
|
+
const t = j.current;
|
|
324
|
+
if (!t) return;
|
|
325
|
+
const s = t.getBoundingClientRect(), n = fe(e.clientX - s.left, e.clientY - s.top);
|
|
326
|
+
ae(n);
|
|
327
|
+
};
|
|
328
|
+
a(() => {
|
|
329
|
+
he();
|
|
330
|
+
}, [he]);
|
|
331
|
+
const Y = qe(() => de(), [de]);
|
|
332
|
+
a(() => {
|
|
333
|
+
P && P(Y);
|
|
334
|
+
}, [Y, P]);
|
|
335
|
+
const me = d(
|
|
336
|
+
() => Y,
|
|
337
|
+
[Y]
|
|
338
|
+
);
|
|
339
|
+
return a(() => (window.getColorWheelPalette = me, () => {
|
|
340
|
+
delete window.getColorWheelPalette;
|
|
341
|
+
}), [me]), /* @__PURE__ */ J("div", { className: "color-wheel-container", children: /* @__PURE__ */ J(
|
|
342
|
+
"canvas",
|
|
343
|
+
{
|
|
344
|
+
ref: j,
|
|
345
|
+
width: O,
|
|
346
|
+
height: $,
|
|
347
|
+
onMouseDown: je,
|
|
348
|
+
onMouseUp: He,
|
|
349
|
+
onMouseLeave: Ue,
|
|
350
|
+
onMouseMove: Ye,
|
|
351
|
+
onClick: ze,
|
|
352
|
+
style: {
|
|
353
|
+
display: "block",
|
|
354
|
+
margin: "0 auto",
|
|
355
|
+
cursor: "pointer"
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
) });
|
|
359
|
+
}
|
|
360
|
+
export {
|
|
361
|
+
Qe as ColorWheel,
|
|
362
|
+
Ke as ThemeProvider,
|
|
363
|
+
Be as useTheme
|
|
364
|
+
};
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.color-wheel-container{margin:0;font-family:sans-serif;background-color:#fff}[data-theme=dark] .color-wheel-container{background-color:#1a1a1a!important}.color-wheel-container h2{text-align:center;padding:15px;margin:0;background:#222;color:#fff}.layout{display:grid;grid-template-columns:20% 30% 50%;height:100vh}.panel{padding:15px;overflow-y:auto;border-right:1px solid #ddd;background-color:#fff}[data-theme=dark] .panel{background-color:#1a1a1a!important;border-right-color:#444;color:#e0e0e0}[data-theme=dark] .panel label{color:#e0e0e0}[data-theme=dark] .panel input,[data-theme=dark] .panel select{background-color:#2a2a2a;border:1px solid #444;color:#e0e0e0}[data-theme=dark] .panel hr{border-color:#444}.panel canvas{display:block;margin:auto;cursor:pointer}.panel label{font-weight:700;display:block;margin-top:12px}.panel input,.panel select{width:100%;margin-top:4px}.panel hr{margin:18px 0}.colors{display:flex;flex-wrap:wrap;gap:12px}.swatchBox{text-align:center;font-size:13px}.swatch{width:70px;height:70px;border-radius:10px;border:1px solid #ccc}.panel pre{background:#f3f3f3;padding:10px;border-radius:10px;font-size:12px;overflow-x:auto;max-height:320px}.panel h3{margin-top:0}
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@studiotoolkit/color-wheel",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "Interactive color wheel React component for creating and manipulating color harmonies with multiple harmony modes",
|
|
6
|
+
"author": "StudioToolkit",
|
|
7
|
+
"homepage": "https://studiotoolkit.github.io/build-color-wheel",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/studiotoolkit/studiotoolkit",
|
|
11
|
+
"directory": "packages/color-wheel"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/studiotoolkit/studiotoolkit/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"color-wheel",
|
|
18
|
+
"color-picker",
|
|
19
|
+
"color-harmony",
|
|
20
|
+
"harmony-polygon",
|
|
21
|
+
"react-color",
|
|
22
|
+
"color-selection",
|
|
23
|
+
"design-tools",
|
|
24
|
+
"ui-components",
|
|
25
|
+
"complementary",
|
|
26
|
+
"analogous",
|
|
27
|
+
"triadic"
|
|
28
|
+
],
|
|
29
|
+
"main": "./dist/index.js",
|
|
30
|
+
"module": "./dist/index.mjs",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"sideEffects": [
|
|
33
|
+
"*.css"
|
|
34
|
+
],
|
|
35
|
+
"exports": {
|
|
36
|
+
".": {
|
|
37
|
+
"types": "./dist/index.d.ts",
|
|
38
|
+
"import": "./dist/index.mjs",
|
|
39
|
+
"require": "./dist/index.js",
|
|
40
|
+
"default": "./dist/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./style.css": "./dist/ColorWheel.css",
|
|
43
|
+
"./src/ColorWheel.css": "./src/ColorWheel.css",
|
|
44
|
+
"./package.json": "./package.json"
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"dist",
|
|
48
|
+
"README.md",
|
|
49
|
+
"LICENSE"
|
|
50
|
+
],
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public"
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=16.0.0"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"react": "^18.0.0",
|
|
59
|
+
"react-dom": "^18.0.0"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@types/react": "^18.2.0",
|
|
63
|
+
"@types/react-dom": "^18.2.0",
|
|
64
|
+
"@vitejs/plugin-react": "^4.2.0",
|
|
65
|
+
"typescript": "^5.3.3",
|
|
66
|
+
"vite": "^5.0.0"
|
|
67
|
+
},
|
|
68
|
+
"scripts": {
|
|
69
|
+
"build": "npx tsc --project tsconfig.json && vite build",
|
|
70
|
+
"dev": "vite build --watch",
|
|
71
|
+
"clean": "rm -rf dist",
|
|
72
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
73
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
74
|
+
"test": "vitest run",
|
|
75
|
+
"test:watch": "vitest",
|
|
76
|
+
"test:ui": "vitest --ui"
|
|
77
|
+
}
|
|
78
|
+
}
|