customizable-gradient-picker 1.1.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 +604 -0
- package/dist/components/alpha-input/alpha-input.style.d.ts +8 -0
- package/dist/components/alpha-input/helpers.d.ts +3 -0
- package/dist/components/alpha-input/index.d.ts +28 -0
- package/dist/components/alpha-slider/index.d.ts +11 -0
- package/dist/components/angle-input/index.d.ts +22 -0
- package/dist/components/color-square/index.d.ts +9 -0
- package/dist/components/delete-stop/index.d.ts +10 -0
- package/dist/components/eye-dropper/index.d.ts +11 -0
- package/dist/components/gradient-formats/const.d.ts +3 -0
- package/dist/components/gradient-formats/index.d.ts +19 -0
- package/dist/components/gradient-preview/index.d.ts +4 -0
- package/dist/components/gradient-slider/const.d.ts +1 -0
- package/dist/components/gradient-slider/helpers.d.ts +28 -0
- package/dist/components/gradient-slider/index.d.ts +11 -0
- package/dist/components/gradient-string/index.d.ts +13 -0
- package/dist/components/hex-input/helpers.d.ts +1 -0
- package/dist/components/hex-input/index.d.ts +14 -0
- package/dist/components/hex-preview/index.d.ts +4 -0
- package/dist/components/hue-slider/const.d.ts +1 -0
- package/dist/components/hue-slider/index.d.ts +10 -0
- package/dist/components/index.d.ts +16 -0
- package/dist/components/render-icon.d.ts +2 -0
- package/dist/components/rgba-input/const.d.ts +2 -0
- package/dist/components/rgba-input/helpers.d.ts +5 -0
- package/dist/components/rgba-input/index.d.ts +28 -0
- package/dist/components/rgba-preview/index.d.ts +4 -0
- package/dist/components/stop-position/helpers.d.ts +6 -0
- package/dist/components/stop-position/index.d.ts +33 -0
- package/dist/const.d.ts +2 -0
- package/dist/context/color-provider.d.ts +8 -0
- package/dist/context/color.d.ts +5 -0
- package/dist/context/compose.d.ts +30 -0
- package/dist/context/gradient-provider.d.ts +15 -0
- package/dist/context/gradient.d.ts +12 -0
- package/dist/context/index.d.ts +7 -0
- package/dist/context/stops-provider.d.ts +15 -0
- package/dist/context/stops.d.ts +12 -0
- package/dist/helpers/color.d.ts +46 -0
- package/dist/helpers/function.d.ts +8 -0
- package/dist/helpers/gradient.d.ts +19 -0
- package/dist/helpers/index.d.ts +6 -0
- package/dist/helpers/number.d.ts +1 -0
- package/dist/helpers/string.d.ts +2 -0
- package/dist/helpers/styles.d.ts +1 -0
- package/dist/hooks/gradient/helpers.d.ts +9 -0
- package/dist/hooks/gradient/index.d.ts +4 -0
- package/dist/hooks/gradient/types.d.ts +53 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/icons/angle-icon.d.ts +2 -0
- package/dist/icons/bin-icon.d.ts +2 -0
- package/dist/icons/chevron-icon.d.ts +2 -0
- package/dist/icons/clipboard-icon.d.ts +2 -0
- package/dist/icons/conic-gradient-icon.d.ts +2 -0
- package/dist/icons/dropper-icon.d.ts +2 -0
- package/dist/icons/index.d.ts +8 -0
- package/dist/icons/linear-gradient-icon.d.ts +2 -0
- package/dist/icons/radial-gradient-icon.d.ts +2 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +2886 -0
- package/dist/store/context.d.ts +7 -0
- package/dist/store/hooks.d.ts +2 -0
- package/dist/store/index.d.ts +4 -0
- package/dist/store/store.d.ts +8 -0
- package/dist/store/types.d.ts +40 -0
- package/dist/types.d.ts +37 -0
- package/package.json +78 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vladyslav
|
|
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,604 @@
|
|
|
1
|
+
[TRY INTERACTIVE DEMO >>](https://customizable-gradient-picker.vercel.app/)
|
|
2
|
+
|
|
3
|
+
# Customizable Gradient Picker
|
|
4
|
+
|
|
5
|
+
A composable React gradient picker for building anything from a minimal editor to a full-featured gradient design panel.
|
|
6
|
+
|
|
7
|
+
This library is built around a controlled CSS gradient string and a flexible set of UI primitives. You can use the picker as a simple drop-in component, or compose your own interface with the provided controls and hook.
|
|
8
|
+
|
|
9
|
+
## Contents
|
|
10
|
+
|
|
11
|
+
- [Features](#features)
|
|
12
|
+
- [Installation](#installation)
|
|
13
|
+
- [Requirements](#requirements)
|
|
14
|
+
- [Quick start](#quick-start)
|
|
15
|
+
- [How it works](#how-it-works)
|
|
16
|
+
- [Supported gradient formats](#supported-gradient-formats)
|
|
17
|
+
- [Basic usage patterns](#basic-usage-patterns)
|
|
18
|
+
- [GradientPicker API](#gradientpicker-api)
|
|
19
|
+
- [Available grid nodes](#available-grid-nodes)
|
|
20
|
+
- [Using the hook](#using-the-hook)
|
|
21
|
+
- [useGradient return value](#usegradient-return-value)
|
|
22
|
+
- [Stop structure](#stop-structure)
|
|
23
|
+
- [Common operations](#common-operations)
|
|
24
|
+
- [Exported components](#exported-components)
|
|
25
|
+
- [Styling and customization](#styling-and-customization)
|
|
26
|
+
- [Browser notes](#browser-notes)
|
|
27
|
+
- [Practical notes](#practical-notes)
|
|
28
|
+
- [Next.js example](#nextjs-example)
|
|
29
|
+
- [When to use this library](#when-to-use-this-library)
|
|
30
|
+
- [Summary](#summary)
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- Supports `linear-gradient`, `radial-gradient`, and `conic-gradient`
|
|
35
|
+
- Controlled API via `gradient` and `onChange`
|
|
36
|
+
- Composable UI primitives
|
|
37
|
+
- Optional grid-based layout rendering
|
|
38
|
+
- Shared internal store support
|
|
39
|
+
- Hook for custom controls and advanced integrations
|
|
40
|
+
- Class-based styling customization
|
|
41
|
+
- Custom icon overrides
|
|
42
|
+
- Works well in modern React and Next.js applications
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install customizable-gradient-picker
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Requirements
|
|
51
|
+
|
|
52
|
+
- React 18+
|
|
53
|
+
- React DOM 18+
|
|
54
|
+
|
|
55
|
+
If you use Next.js App Router, render the picker inside a client component.
|
|
56
|
+
|
|
57
|
+
## Quick start
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
'use client';
|
|
61
|
+
|
|
62
|
+
import { useState } from 'react';
|
|
63
|
+
import {
|
|
64
|
+
GradientPicker,
|
|
65
|
+
ColorSquare,
|
|
66
|
+
HueSlider,
|
|
67
|
+
AlphaSlider,
|
|
68
|
+
StopPosition,
|
|
69
|
+
GradientSlider,
|
|
70
|
+
} from 'customizable-gradient-picker';
|
|
71
|
+
|
|
72
|
+
export default function Example() {
|
|
73
|
+
const [gradient, setGradient] = useState(
|
|
74
|
+
'linear-gradient(90deg, rgb(39, 109, 35) 0%, rgba(163, 0, 255, 1) 100%)',
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<GradientPicker gradient={gradient} onChange={setGradient}>
|
|
79
|
+
<div style={{ display: 'grid', gap: 12 }}>
|
|
80
|
+
<ColorSquare />
|
|
81
|
+
<HueSlider />
|
|
82
|
+
<AlphaSlider />
|
|
83
|
+
<StopPosition />
|
|
84
|
+
<GradientSlider />
|
|
85
|
+
</div>
|
|
86
|
+
</GradientPicker>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## How it works
|
|
92
|
+
|
|
93
|
+
The library accepts a CSS gradient string as input and emits a new CSS gradient string every time the user changes the gradient.
|
|
94
|
+
|
|
95
|
+
That means you can:
|
|
96
|
+
|
|
97
|
+
- store the gradient in React state
|
|
98
|
+
- save it in a database
|
|
99
|
+
- preview it directly in CSS
|
|
100
|
+
- share the same value across different parts of your UI
|
|
101
|
+
|
|
102
|
+
## Supported gradient formats
|
|
103
|
+
|
|
104
|
+
- `linear-gradient`
|
|
105
|
+
- `radial-gradient`
|
|
106
|
+
- `conic-gradient`
|
|
107
|
+
|
|
108
|
+
Default internal prefixes:
|
|
109
|
+
|
|
110
|
+
- `linear-gradient`: no prefix
|
|
111
|
+
- `radial-gradient`: `circle at center`
|
|
112
|
+
- `conic-gradient`: `from 90deg at 50% 50%`
|
|
113
|
+
|
|
114
|
+
## Basic usage patterns
|
|
115
|
+
|
|
116
|
+
### 1. Compose the picker manually
|
|
117
|
+
|
|
118
|
+
Use this when you want full control over layout and markup.
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
<GradientPicker gradient={gradient} onChange={setGradient}>
|
|
122
|
+
<div className="my-layout">
|
|
123
|
+
<ColorSquare />
|
|
124
|
+
<HueSlider />
|
|
125
|
+
<AlphaSlider />
|
|
126
|
+
<StopPosition />
|
|
127
|
+
<GradientSlider />
|
|
128
|
+
<GradientString />
|
|
129
|
+
</div>
|
|
130
|
+
</GradientPicker>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 2. Render from a grid definition
|
|
134
|
+
|
|
135
|
+
Use this when you want the library to render a layout from predefined node names.
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
<GradientPicker
|
|
139
|
+
gradient={gradient}
|
|
140
|
+
onChange={setGradient}
|
|
141
|
+
grid={[
|
|
142
|
+
'color-square',
|
|
143
|
+
'hue-slider',
|
|
144
|
+
'alpha-slider',
|
|
145
|
+
{
|
|
146
|
+
className: 'row',
|
|
147
|
+
children: ['stop-position', 'gradient-formats'],
|
|
148
|
+
},
|
|
149
|
+
'gradient-slider',
|
|
150
|
+
'gradient-string',
|
|
151
|
+
]}
|
|
152
|
+
/>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## `GradientPicker` API
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
type GradientPickerProps =
|
|
159
|
+
| {
|
|
160
|
+
gradient: string;
|
|
161
|
+
onChange: (gradient: string) => void;
|
|
162
|
+
updateDelay?: number;
|
|
163
|
+
wrapperClassName?: string;
|
|
164
|
+
childrenProps?: ChildrenProps;
|
|
165
|
+
store?: GradientPickerStore;
|
|
166
|
+
grid: Grid;
|
|
167
|
+
}
|
|
168
|
+
| {
|
|
169
|
+
gradient: string;
|
|
170
|
+
onChange: (gradient: string) => void;
|
|
171
|
+
updateDelay?: number;
|
|
172
|
+
wrapperClassName?: string;
|
|
173
|
+
childrenProps?: ChildrenProps;
|
|
174
|
+
store?: GradientPickerStore;
|
|
175
|
+
children: React.ReactNode;
|
|
176
|
+
};
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Props
|
|
180
|
+
|
|
181
|
+
#### `gradient`
|
|
182
|
+
The current CSS gradient string.
|
|
183
|
+
|
|
184
|
+
#### `onChange`
|
|
185
|
+
Called with the updated CSS gradient string.
|
|
186
|
+
|
|
187
|
+
#### `updateDelay`
|
|
188
|
+
Optional delay for gradient output updates. Default is `0`.
|
|
189
|
+
|
|
190
|
+
#### `wrapperClassName`
|
|
191
|
+
Custom class name for the root picker wrapper.
|
|
192
|
+
|
|
193
|
+
#### `store`
|
|
194
|
+
Optional external store. Useful when you want built-in components and your own custom UI to share the same picker state.
|
|
195
|
+
|
|
196
|
+
#### `children`
|
|
197
|
+
Manual rendering mode. Use this when you want to fully control layout.
|
|
198
|
+
|
|
199
|
+
#### `grid`
|
|
200
|
+
Grid rendering mode. Use this when you want the library to generate the layout from known node names.
|
|
201
|
+
|
|
202
|
+
#### `childrenProps`
|
|
203
|
+
Optional props passed into built-in grid nodes.
|
|
204
|
+
|
|
205
|
+
## Available grid nodes
|
|
206
|
+
|
|
207
|
+
You can use the following names inside `grid`:
|
|
208
|
+
|
|
209
|
+
- `color-square`
|
|
210
|
+
- `hue-slider`
|
|
211
|
+
- `alpha-slider`
|
|
212
|
+
- `alpha-input`
|
|
213
|
+
- `eye-dropper`
|
|
214
|
+
- `stop-position`
|
|
215
|
+
- `stop-delete`
|
|
216
|
+
- `gradient-slider`
|
|
217
|
+
- `gradient-formats`
|
|
218
|
+
- `gradient-preview`
|
|
219
|
+
- `gradient-string`
|
|
220
|
+
- `angle-input`
|
|
221
|
+
- `hex-input`
|
|
222
|
+
- `hex-preview`
|
|
223
|
+
- `rgba-input`
|
|
224
|
+
- `rgba-preview`
|
|
225
|
+
|
|
226
|
+
Example with `childrenProps`:
|
|
227
|
+
|
|
228
|
+
```tsx
|
|
229
|
+
<GradientPicker
|
|
230
|
+
gradient={gradient}
|
|
231
|
+
onChange={setGradient}
|
|
232
|
+
grid={['gradient-formats', 'gradient-slider', 'gradient-string']}
|
|
233
|
+
childrenProps={{
|
|
234
|
+
gradientFormats: {
|
|
235
|
+
allowedFormats: ['linear-gradient', 'radial-gradient'],
|
|
236
|
+
},
|
|
237
|
+
gradientString: {
|
|
238
|
+
onCopyClick: () => console.log('Copied'),
|
|
239
|
+
},
|
|
240
|
+
}}
|
|
241
|
+
/>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Using the hook
|
|
245
|
+
|
|
246
|
+
Use `useGradient` when you want to build a custom editor, connect outside controls, or directly read and manipulate picker state.
|
|
247
|
+
|
|
248
|
+
```tsx
|
|
249
|
+
'use client';
|
|
250
|
+
|
|
251
|
+
import { useMemo } from 'react';
|
|
252
|
+
import {
|
|
253
|
+
GradientPicker,
|
|
254
|
+
ColorSquare,
|
|
255
|
+
HueSlider,
|
|
256
|
+
AlphaSlider,
|
|
257
|
+
GradientSlider,
|
|
258
|
+
StopPosition,
|
|
259
|
+
useGradient,
|
|
260
|
+
} from 'customizable-gradient-picker';
|
|
261
|
+
|
|
262
|
+
export default function Example() {
|
|
263
|
+
const {
|
|
264
|
+
store,
|
|
265
|
+
gradientString,
|
|
266
|
+
stops,
|
|
267
|
+
activeStopId,
|
|
268
|
+
hex,
|
|
269
|
+
rgba,
|
|
270
|
+
angle,
|
|
271
|
+
format,
|
|
272
|
+
setHex,
|
|
273
|
+
setAngle,
|
|
274
|
+
setFormat,
|
|
275
|
+
setActiveStop,
|
|
276
|
+
setStopPosition,
|
|
277
|
+
addStop,
|
|
278
|
+
removeStop,
|
|
279
|
+
} = useGradient(
|
|
280
|
+
'linear-gradient(90deg, rgb(39, 109, 35) 0%, rgba(163, 0, 255, 1) 100%)',
|
|
281
|
+
next => {
|
|
282
|
+
console.log('New gradient:', next);
|
|
283
|
+
},
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
const activeStop = useMemo(
|
|
287
|
+
() => stops.find(stop => stop.id === activeStopId) ?? null,
|
|
288
|
+
[stops, activeStopId],
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
return (
|
|
292
|
+
<div style={{ display: 'grid', gap: 16 }}>
|
|
293
|
+
<GradientPicker store={store} gradient={gradientString} onChange={() => {}}>
|
|
294
|
+
<div style={{ display: 'grid', gap: 12 }}>
|
|
295
|
+
<ColorSquare />
|
|
296
|
+
<HueSlider />
|
|
297
|
+
<AlphaSlider />
|
|
298
|
+
<StopPosition />
|
|
299
|
+
<GradientSlider />
|
|
300
|
+
</div>
|
|
301
|
+
</GradientPicker>
|
|
302
|
+
|
|
303
|
+
<div>
|
|
304
|
+
<div>Format: {format}</div>
|
|
305
|
+
<div>Angle: {angle}</div>
|
|
306
|
+
<div>HEX: {hex}</div>
|
|
307
|
+
<div>RGBA: {rgba}</div>
|
|
308
|
+
<div>Active stop: {activeStop?.id ?? 'none'}</div>
|
|
309
|
+
</div>
|
|
310
|
+
</div>
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## `useGradient` return value
|
|
316
|
+
|
|
317
|
+
The hook returns both state and actions.
|
|
318
|
+
|
|
319
|
+
### State
|
|
320
|
+
|
|
321
|
+
- `store`
|
|
322
|
+
- `stops`
|
|
323
|
+
- `activeStopId`
|
|
324
|
+
- `activeStopPosition`
|
|
325
|
+
- `angle`
|
|
326
|
+
- `format`
|
|
327
|
+
- `isDragging`
|
|
328
|
+
- `recentlyUsedColors`
|
|
329
|
+
- `libraryColors`
|
|
330
|
+
- `hex`
|
|
331
|
+
- `rgba`
|
|
332
|
+
- `rgbaString`
|
|
333
|
+
- `gradientString`
|
|
334
|
+
- `opacity`
|
|
335
|
+
|
|
336
|
+
### Actions
|
|
337
|
+
|
|
338
|
+
- `setR`
|
|
339
|
+
- `setG`
|
|
340
|
+
- `setB`
|
|
341
|
+
- `setA`
|
|
342
|
+
- `setHex`
|
|
343
|
+
- `setAngle`
|
|
344
|
+
- `setFormat`
|
|
345
|
+
- `setOpacity`
|
|
346
|
+
- `setStopColor`
|
|
347
|
+
- `setActiveStop`
|
|
348
|
+
- `setStopPosition`
|
|
349
|
+
- `setLibraryColors`
|
|
350
|
+
- `setRecentlyUsedColors`
|
|
351
|
+
- `addStop`
|
|
352
|
+
- `addColorToLibrary`
|
|
353
|
+
- `addColorToRecentlyUsed`
|
|
354
|
+
- `removeStop`
|
|
355
|
+
- `removeColorFromLibrary`
|
|
356
|
+
- `removeColorFromRecentlyUsed`
|
|
357
|
+
- `convertColor`
|
|
358
|
+
|
|
359
|
+
## Stop structure
|
|
360
|
+
|
|
361
|
+
Each stop returned from the hook is normalized into a predictable shape:
|
|
362
|
+
|
|
363
|
+
```ts
|
|
364
|
+
type StopItem = {
|
|
365
|
+
position: number;
|
|
366
|
+
id: string;
|
|
367
|
+
hex: string;
|
|
368
|
+
rgbaString: string;
|
|
369
|
+
rgba: {
|
|
370
|
+
r: number;
|
|
371
|
+
g: number;
|
|
372
|
+
b: number;
|
|
373
|
+
a: number;
|
|
374
|
+
};
|
|
375
|
+
opacity: number;
|
|
376
|
+
};
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## Common operations
|
|
380
|
+
|
|
381
|
+
### Set the active stop
|
|
382
|
+
|
|
383
|
+
```tsx
|
|
384
|
+
setActiveStop('stop2');
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Change a stop color
|
|
388
|
+
|
|
389
|
+
```tsx
|
|
390
|
+
setStopColor('stop2', 'rgba(255, 0, 0, 1)');
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Move a stop
|
|
394
|
+
|
|
395
|
+
```tsx
|
|
396
|
+
setStopPosition('stop2', 75);
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### Add a stop
|
|
400
|
+
|
|
401
|
+
```tsx
|
|
402
|
+
addStop(50, 'rgba(255, 255, 255, 1)');
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Remove a stop
|
|
406
|
+
|
|
407
|
+
```tsx
|
|
408
|
+
removeStop('stop2');
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Change gradient format
|
|
412
|
+
|
|
413
|
+
```tsx
|
|
414
|
+
setFormat('radial-gradient');
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Change angle
|
|
418
|
+
|
|
419
|
+
```tsx
|
|
420
|
+
setAngle(135);
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Convert between color formats
|
|
424
|
+
|
|
425
|
+
```tsx
|
|
426
|
+
const hex = convertColor('rgba', 'hex', 'rgba(255, 0, 0, 1)');
|
|
427
|
+
const rgba = convertColor('hex', 'rgba', 'FF0000');
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
## Exported components
|
|
431
|
+
|
|
432
|
+
### Core
|
|
433
|
+
|
|
434
|
+
- `GradientPicker`
|
|
435
|
+
- `useGradient`
|
|
436
|
+
|
|
437
|
+
### UI primitives
|
|
438
|
+
|
|
439
|
+
- `ColorSquare`
|
|
440
|
+
- `HueSlider`
|
|
441
|
+
- `AlphaSlider`
|
|
442
|
+
- `AlphaInput`
|
|
443
|
+
- `AngleInput`
|
|
444
|
+
- `DeleteStop`
|
|
445
|
+
- `EyeDropper`
|
|
446
|
+
- `GradientSlider`
|
|
447
|
+
- `PickGradientFormats`
|
|
448
|
+
- `GradientPreview`
|
|
449
|
+
- `GradientString`
|
|
450
|
+
- `HexInput`
|
|
451
|
+
- `HexPreview`
|
|
452
|
+
- `RgbaInput`
|
|
453
|
+
- `RgbaPreview`
|
|
454
|
+
- `StopPosition`
|
|
455
|
+
|
|
456
|
+
## Styling and customization
|
|
457
|
+
|
|
458
|
+
Most components expose `classNames` props so you can control their styles without rewriting their logic.
|
|
459
|
+
|
|
460
|
+
Example:
|
|
461
|
+
|
|
462
|
+
```tsx
|
|
463
|
+
<HueSlider
|
|
464
|
+
classNames={{
|
|
465
|
+
wrapper: 'my-hue-wrapper',
|
|
466
|
+
thumb: 'my-hue-thumb',
|
|
467
|
+
canvas: 'my-hue-canvas',
|
|
468
|
+
}}
|
|
469
|
+
/>
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Custom gradient format button styles
|
|
473
|
+
|
|
474
|
+
```tsx
|
|
475
|
+
<PickGradientFormats
|
|
476
|
+
classNames={{
|
|
477
|
+
wrapper: 'formats',
|
|
478
|
+
button: {
|
|
479
|
+
base: 'format-button',
|
|
480
|
+
activeBase: 'format-button-active',
|
|
481
|
+
icon: 'format-icon',
|
|
482
|
+
},
|
|
483
|
+
buttons: {
|
|
484
|
+
'linear-gradient': {
|
|
485
|
+
base: 'format-linear',
|
|
486
|
+
},
|
|
487
|
+
'radial-gradient': {
|
|
488
|
+
base: 'format-radial',
|
|
489
|
+
},
|
|
490
|
+
'conic-gradient': {
|
|
491
|
+
base: 'format-conic',
|
|
492
|
+
},
|
|
493
|
+
},
|
|
494
|
+
}}
|
|
495
|
+
/>
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### Custom icons
|
|
499
|
+
|
|
500
|
+
Some controls let you replace built-in icons with your own components.
|
|
501
|
+
|
|
502
|
+
```tsx
|
|
503
|
+
<PickGradientFormats
|
|
504
|
+
icons={{
|
|
505
|
+
'linear-gradient': MyLinearIcon,
|
|
506
|
+
'radial-gradient': MyRadialIcon,
|
|
507
|
+
'conic-gradient': MyConicIcon,
|
|
508
|
+
}}
|
|
509
|
+
/>
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
Other components such as `AngleInput`, `GradientString`, `EyeDropper`, `HexInput`, and `RgbaInput` also support icon overrides.
|
|
513
|
+
|
|
514
|
+
## Browser notes
|
|
515
|
+
|
|
516
|
+
### Clipboard support
|
|
517
|
+
|
|
518
|
+
`GradientString` uses the Clipboard API for copying the generated gradient string.
|
|
519
|
+
|
|
520
|
+
### EyeDropper support
|
|
521
|
+
|
|
522
|
+
`EyeDropper` depends on the browser EyeDropper API. If the browser does not support it, that control will not be available as expected.
|
|
523
|
+
|
|
524
|
+
## Practical notes
|
|
525
|
+
|
|
526
|
+
### The library is controlled
|
|
527
|
+
|
|
528
|
+
Even though the picker has an internal store, the main usage model is controlled through `gradient` and `onChange`.
|
|
529
|
+
|
|
530
|
+
### Use the hook for advanced editors
|
|
531
|
+
|
|
532
|
+
If you need presets, custom side panels, linked inputs, recent colors, or full control over behavior, `useGradient` is the right entry point.
|
|
533
|
+
|
|
534
|
+
### Minimum stop count
|
|
535
|
+
|
|
536
|
+
The hook does not remove stops when only two remain.
|
|
537
|
+
|
|
538
|
+
### HEX input support
|
|
539
|
+
|
|
540
|
+
`setHex` supports common HEX lengths such as 3, 4, 6, and 8 characters.
|
|
541
|
+
|
|
542
|
+
### Recently used colors limit
|
|
543
|
+
|
|
544
|
+
Recently used colors are trimmed to the latest 24 entries.
|
|
545
|
+
|
|
546
|
+
## Next.js example
|
|
547
|
+
|
|
548
|
+
```tsx
|
|
549
|
+
'use client';
|
|
550
|
+
|
|
551
|
+
import { useState } from 'react';
|
|
552
|
+
import {
|
|
553
|
+
GradientPicker,
|
|
554
|
+
ColorSquare,
|
|
555
|
+
HueSlider,
|
|
556
|
+
AlphaSlider,
|
|
557
|
+
GradientSlider,
|
|
558
|
+
StopPosition,
|
|
559
|
+
GradientString,
|
|
560
|
+
} from 'customizable-gradient-picker';
|
|
561
|
+
|
|
562
|
+
export default function GradientEditor() {
|
|
563
|
+
const [gradient, setGradient] = useState(
|
|
564
|
+
'linear-gradient(90deg, rgba(255, 126, 95, 1) 15%, rgba(254, 180, 123, 1) 85%)',
|
|
565
|
+
);
|
|
566
|
+
|
|
567
|
+
return (
|
|
568
|
+
<div style={{ display: 'grid', gap: 16 }}>
|
|
569
|
+
<div
|
|
570
|
+
style={{
|
|
571
|
+
height: 180,
|
|
572
|
+
borderRadius: 16,
|
|
573
|
+
background: gradient,
|
|
574
|
+
}}
|
|
575
|
+
/>
|
|
576
|
+
|
|
577
|
+
<GradientPicker gradient={gradient} onChange={setGradient}>
|
|
578
|
+
<div style={{ display: 'grid', gap: 12 }}>
|
|
579
|
+
<ColorSquare />
|
|
580
|
+
<HueSlider />
|
|
581
|
+
<AlphaSlider />
|
|
582
|
+
<StopPosition />
|
|
583
|
+
<GradientSlider />
|
|
584
|
+
<GradientString />
|
|
585
|
+
</div>
|
|
586
|
+
</GradientPicker>
|
|
587
|
+
</div>
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
## When to use this library
|
|
593
|
+
|
|
594
|
+
This library is a good fit when you need:
|
|
595
|
+
|
|
596
|
+
- a gradient picker with a controlled API
|
|
597
|
+
- composable building blocks instead of a fixed UI
|
|
598
|
+
- support for multiple CSS gradient types
|
|
599
|
+
- a custom editor with shared state
|
|
600
|
+
- a picker that can scale from simple inputs to a full design tool
|
|
601
|
+
|
|
602
|
+
## Summary
|
|
603
|
+
|
|
604
|
+
Customizable Gradient Picker is designed for teams that need flexibility. You can start with the built-in controls, then gradually move toward a fully custom experience without changing the underlying gradient model.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
export declare const alphaInputWrapper: CSSProperties;
|
|
3
|
+
export declare const alphaInputField: CSSProperties;
|
|
4
|
+
export declare const alphaInputSuffix: CSSProperties;
|
|
5
|
+
export declare const alphaInputSteppers: CSSProperties;
|
|
6
|
+
export declare const alphaInputStepperButton: CSSProperties;
|
|
7
|
+
export declare const alphaInputStepperDecrement: CSSProperties;
|
|
8
|
+
export declare const alphaInputStepperButtonIcon: CSSProperties;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Icon } from '../../types';
|
|
2
|
+
type Icons = 'increment' | 'decrement';
|
|
3
|
+
type ButtonClassNames = {
|
|
4
|
+
button: string;
|
|
5
|
+
icon: string;
|
|
6
|
+
};
|
|
7
|
+
type InputClassNames = {
|
|
8
|
+
wrapper: string;
|
|
9
|
+
field: string;
|
|
10
|
+
steppers: {
|
|
11
|
+
wrapper: string;
|
|
12
|
+
increment: ButtonClassNames;
|
|
13
|
+
decrement: ButtonClassNames;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export type AlphaInputClassNames = {
|
|
17
|
+
wrapper?: string;
|
|
18
|
+
input?: Partial<InputClassNames>;
|
|
19
|
+
suffix?: string;
|
|
20
|
+
};
|
|
21
|
+
export type AlphaInputProps = {
|
|
22
|
+
classNames?: AlphaInputClassNames;
|
|
23
|
+
updateDelay?: number;
|
|
24
|
+
suffix?: string;
|
|
25
|
+
icons?: Record<Icons, Icon>;
|
|
26
|
+
};
|
|
27
|
+
export declare const AlphaInput: ({ classNames, updateDelay, suffix, icons, }: AlphaInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
export * from './helpers';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type AlphaSliderClassNames = {
|
|
2
|
+
wrapper: string;
|
|
3
|
+
track: string;
|
|
4
|
+
thumb: string;
|
|
5
|
+
thumbInner: string;
|
|
6
|
+
canvas: string;
|
|
7
|
+
};
|
|
8
|
+
export type AlphaSliderProps = {
|
|
9
|
+
classNames?: Partial<AlphaSliderClassNames>;
|
|
10
|
+
};
|
|
11
|
+
export declare const AlphaSlider: ({ classNames }: AlphaSliderProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Icon } from '../../types';
|
|
2
|
+
export type AngleInputClassNames = {
|
|
3
|
+
wrapper?: string;
|
|
4
|
+
input?: string;
|
|
5
|
+
inputWrapper?: string;
|
|
6
|
+
icon?: string;
|
|
7
|
+
steppers?: string;
|
|
8
|
+
incrementButton?: string;
|
|
9
|
+
incrementIcon?: string;
|
|
10
|
+
decrementButton?: string;
|
|
11
|
+
decrementIcon?: string;
|
|
12
|
+
degree?: string;
|
|
13
|
+
};
|
|
14
|
+
export type AngleInputProps = {
|
|
15
|
+
icons?: {
|
|
16
|
+
angle?: Icon;
|
|
17
|
+
increment?: Icon;
|
|
18
|
+
decrement?: Icon;
|
|
19
|
+
};
|
|
20
|
+
classNames?: AngleInputClassNames;
|
|
21
|
+
};
|
|
22
|
+
export declare const AngleInput: ({ classNames, icons }: AngleInputProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type ColorSquareClassNames = {
|
|
2
|
+
wrapper?: string;
|
|
3
|
+
canvas?: string;
|
|
4
|
+
thumb?: string;
|
|
5
|
+
};
|
|
6
|
+
export type ColorSquareProps = {
|
|
7
|
+
classNames?: ColorSquareClassNames;
|
|
8
|
+
};
|
|
9
|
+
export declare const ColorSquare: ({ classNames }: ColorSquareProps) => import("react/jsx-runtime").JSX.Element;
|