sanity-plugin-color-input 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 +114 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +423 -0
- package/dist/index.mjs +408 -0
- package/package.json +65 -0
- package/src/components/ColorInput.tsx +332 -0
- package/src/components/icons/EditIcon.tsx +5 -0
- package/src/constants/index.ts +25 -0
- package/src/index.ts +1 -0
- package/src/plugin.ts +15 -0
- package/src/schemas/colorType.ts +20 -0
- package/src/utils/index.test.ts +85 -0
- package/src/utils/index.ts +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Code-Journey
|
|
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,114 @@
|
|
|
1
|
+
# sanity-plugin-color-input
|
|
2
|
+
|
|
3
|
+
A beautifully designed, highly customizable color picker plugin for Sanity Studio v3.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎨 **Visual Color Picker**: A stunning visual interface to pick any color.
|
|
8
|
+
- 🌈 **Gradient Support**: Toggle between solid colors and gorgeous linear gradients.
|
|
9
|
+
- 💅 **Rich Return Format**: Provides HEX, RGBA, and HSL for solids, plus full CSS `linear-gradient` strings for gradients.
|
|
10
|
+
- ✨ **Customizable Color Presets**: Use our meticulously crafted predefined presets or provide your own custom branded colors via options.
|
|
11
|
+
- 📋 **One-Click Copy**: Easily copy HEX, RGBA, HSL, and CSS Gradient values to clipboard.
|
|
12
|
+
- 🚀 **Built for Sanity v3**: Fully compatible with the modern Sanity Studio V3 architecture.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Using npm
|
|
18
|
+
npm install sanity-plugin-color-input
|
|
19
|
+
|
|
20
|
+
# Using yarn
|
|
21
|
+
yarn add sanity-plugin-color-input
|
|
22
|
+
|
|
23
|
+
# Using pnpm
|
|
24
|
+
pnpm add sanity-plugin-color-input
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Setup & Usage
|
|
28
|
+
|
|
29
|
+
Compatible with **Node.js 18, 20, 22, and 24**.
|
|
30
|
+
|
|
31
|
+
Add it as a plugin in your `sanity.config.ts` (or `sanity.config.js`):
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import {defineConfig} from 'sanity'
|
|
35
|
+
import {customColorPicker} from 'sanity-plugin-color-input'
|
|
36
|
+
|
|
37
|
+
export default defineConfig({
|
|
38
|
+
// ...other config settings
|
|
39
|
+
plugins: [
|
|
40
|
+
// Add the plugin here
|
|
41
|
+
customColorPicker(),
|
|
42
|
+
],
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Schema Usage
|
|
47
|
+
|
|
48
|
+
Now you can use the `color` type in your schemas.
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
export default {
|
|
52
|
+
name: 'myDocument',
|
|
53
|
+
title: 'My Document',
|
|
54
|
+
type: 'document',
|
|
55
|
+
fields: [
|
|
56
|
+
{
|
|
57
|
+
name: 'brandColor',
|
|
58
|
+
title: 'Brand Color',
|
|
59
|
+
type: 'color',
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Customizing the Preset Colors
|
|
66
|
+
|
|
67
|
+
You can easily override the default color presets by providing your own `colors` array in your field's `options`:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
export default {
|
|
71
|
+
name: 'myDocument',
|
|
72
|
+
title: 'My Document',
|
|
73
|
+
type: 'document',
|
|
74
|
+
fields: [
|
|
75
|
+
{
|
|
76
|
+
name: 'brandColor',
|
|
77
|
+
title: 'Brand Color',
|
|
78
|
+
type: 'color',
|
|
79
|
+
options: {
|
|
80
|
+
// This will override the default presets, useful for restricting choices
|
|
81
|
+
// to brand-specific color palettes.
|
|
82
|
+
colors: [
|
|
83
|
+
// Solid color presets
|
|
84
|
+
'#1A1A1A',
|
|
85
|
+
'#F5F5F5',
|
|
86
|
+
// Gradient preset
|
|
87
|
+
{hex: '#E91E63', hex2: '#2196F3', angle: 45},
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Data Structure
|
|
96
|
+
|
|
97
|
+
The `color` field returns a solid color by default, or a gradient if selected:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"_type": "color",
|
|
102
|
+
"hex": "#f44336",
|
|
103
|
+
"rgba": "rgba(244, 67, 54, 1)",
|
|
104
|
+
"hsl": "hsl(4, 90%, 58%)",
|
|
105
|
+
"isGradient": true,
|
|
106
|
+
"hex2": "#000000",
|
|
107
|
+
"angle": 180,
|
|
108
|
+
"css": "linear-gradient(180deg, #f44336, #000000)"
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
MIT © Code-Journey
|
package/dist/index.d.mts
ADDED
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
customColorPicker: () => customColorPicker
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/plugin.ts
|
|
28
|
+
var import_sanity3 = require("sanity");
|
|
29
|
+
|
|
30
|
+
// src/schemas/colorType.ts
|
|
31
|
+
var import_sanity2 = require("sanity");
|
|
32
|
+
|
|
33
|
+
// src/components/ColorInput.tsx
|
|
34
|
+
var import_react = require("react");
|
|
35
|
+
var import_ui = require("@sanity/ui");
|
|
36
|
+
var import_sanity = require("sanity");
|
|
37
|
+
|
|
38
|
+
// src/components/icons/EditIcon.tsx
|
|
39
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
40
|
+
var EditIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "currentColor", ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" }) });
|
|
41
|
+
|
|
42
|
+
// src/constants/index.ts
|
|
43
|
+
var PRESET_COLORS = [
|
|
44
|
+
"#f44336",
|
|
45
|
+
"#e91e63",
|
|
46
|
+
"#9c27b0",
|
|
47
|
+
"#673ab7",
|
|
48
|
+
"#3f51b5",
|
|
49
|
+
"#2196f3",
|
|
50
|
+
"#03a9f4",
|
|
51
|
+
"#00bcd4",
|
|
52
|
+
"#009688",
|
|
53
|
+
"#4caf50",
|
|
54
|
+
"#8bc34a",
|
|
55
|
+
"#cddc39",
|
|
56
|
+
"#ffeb3b",
|
|
57
|
+
"#ffc107",
|
|
58
|
+
"#ff9800",
|
|
59
|
+
"#ff5722",
|
|
60
|
+
"#795548",
|
|
61
|
+
"#9e9e9e",
|
|
62
|
+
"#607d8b",
|
|
63
|
+
"#000000",
|
|
64
|
+
{ hex: "#ff9a9e", hex2: "#fad0c4", angle: 90 },
|
|
65
|
+
{ hex: "#a1c4fd", hex2: "#c2e9fb", angle: 180 },
|
|
66
|
+
{ hex: "#84fab0", hex2: "#8fd3f4", angle: 45 }
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
// src/utils/index.ts
|
|
70
|
+
function isValidHex(hex) {
|
|
71
|
+
return /^#([0-9A-F]{6})$/i.test(hex);
|
|
72
|
+
}
|
|
73
|
+
function getContrastColor(hex) {
|
|
74
|
+
if (!hex || !isValidHex(hex)) return "rgba(0,0,0,0.6)";
|
|
75
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
76
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
77
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
78
|
+
const brightness = (r * 299 + g * 587 + b * 114) / 1e3;
|
|
79
|
+
return brightness > 128 ? "rgba(0,0,0,0.6)" : "white";
|
|
80
|
+
}
|
|
81
|
+
function hexToRgba(hex) {
|
|
82
|
+
if (!isValidHex(hex)) return "";
|
|
83
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
84
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
85
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
86
|
+
return `rgba(${r}, ${g}, ${b}, 1)`;
|
|
87
|
+
}
|
|
88
|
+
function hexToHsl(hex) {
|
|
89
|
+
if (!isValidHex(hex)) return "";
|
|
90
|
+
let r = parseInt(hex.slice(1, 3), 16) / 255;
|
|
91
|
+
let g = parseInt(hex.slice(3, 5), 16) / 255;
|
|
92
|
+
let b = parseInt(hex.slice(5, 7), 16) / 255;
|
|
93
|
+
const max = Math.max(r, g, b);
|
|
94
|
+
const min = Math.min(r, g, b);
|
|
95
|
+
let h = 0, s = 0;
|
|
96
|
+
const l = (max + min) / 2;
|
|
97
|
+
if (max !== min) {
|
|
98
|
+
const d = max - min;
|
|
99
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
100
|
+
switch (max) {
|
|
101
|
+
case r:
|
|
102
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
103
|
+
break;
|
|
104
|
+
case g:
|
|
105
|
+
h = (b - r) / d + 2;
|
|
106
|
+
break;
|
|
107
|
+
case b:
|
|
108
|
+
h = (r - g) / d + 4;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
h /= 6;
|
|
112
|
+
}
|
|
113
|
+
return `hsl(${Math.round(h * 360)}, ${Math.round(s * 100)}%, ${Math.round(l * 100)}%)`;
|
|
114
|
+
}
|
|
115
|
+
function getGradientString(angle, color1, color2) {
|
|
116
|
+
return `linear-gradient(${angle}deg, ${color1}, ${color2})`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/components/ColorInput.tsx
|
|
120
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
121
|
+
function CustomColorPicker(props) {
|
|
122
|
+
const { value, onChange, elementProps, schemaType } = props;
|
|
123
|
+
const toast = (0, import_ui.useToast)();
|
|
124
|
+
const optionsColors = schemaType?.options?.colors;
|
|
125
|
+
const colorsList = Array.isArray(optionsColors) && optionsColors.length > 0 ? optionsColors : PRESET_COLORS;
|
|
126
|
+
const currentHex = value?.hex || "";
|
|
127
|
+
const currentHex2 = value?.hex2 || "#000000";
|
|
128
|
+
const currentIsGradient = value?.isGradient || false;
|
|
129
|
+
const currentAngle = value?.angle || 180;
|
|
130
|
+
const [localValue, setLocalValue] = (0, import_react.useState)(currentHex);
|
|
131
|
+
const [localValue2, setLocalValue2] = (0, import_react.useState)(currentHex2);
|
|
132
|
+
const [isGradient, setIsGradient] = (0, import_react.useState)(currentIsGradient);
|
|
133
|
+
const [angle, setAngle] = (0, import_react.useState)(currentAngle);
|
|
134
|
+
(0, import_react.useEffect)(() => {
|
|
135
|
+
setLocalValue(currentHex);
|
|
136
|
+
setLocalValue2(currentHex2);
|
|
137
|
+
setIsGradient(currentIsGradient);
|
|
138
|
+
setAngle(currentAngle);
|
|
139
|
+
}, [currentHex, currentHex2, currentIsGradient, currentAngle]);
|
|
140
|
+
(0, import_react.useEffect)(() => {
|
|
141
|
+
if (localValue === currentHex && localValue2 === currentHex2 && isGradient === currentIsGradient && angle === currentAngle)
|
|
142
|
+
return;
|
|
143
|
+
const timeout = setTimeout(() => {
|
|
144
|
+
if (!localValue) {
|
|
145
|
+
onChange(import_sanity.PatchEvent.from((0, import_sanity.unset)()));
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (!isValidHex(localValue)) return;
|
|
149
|
+
const patches = [
|
|
150
|
+
(0, import_sanity.setIfMissing)({ _type: "color" }),
|
|
151
|
+
(0, import_sanity.set)(localValue, ["hex"]),
|
|
152
|
+
(0, import_sanity.set)(hexToRgba(localValue), ["rgba"]),
|
|
153
|
+
(0, import_sanity.set)(hexToHsl(localValue), ["hsl"]),
|
|
154
|
+
(0, import_sanity.set)(isGradient, ["isGradient"])
|
|
155
|
+
];
|
|
156
|
+
if (isGradient) {
|
|
157
|
+
patches.push((0, import_sanity.set)(localValue2, ["hex2"]));
|
|
158
|
+
patches.push((0, import_sanity.set)(angle, ["angle"]));
|
|
159
|
+
patches.push((0, import_sanity.set)(getGradientString(angle, localValue, localValue2), ["css"]));
|
|
160
|
+
}
|
|
161
|
+
onChange(import_sanity.PatchEvent.from(patches));
|
|
162
|
+
}, 300);
|
|
163
|
+
return () => clearTimeout(timeout);
|
|
164
|
+
}, [
|
|
165
|
+
localValue,
|
|
166
|
+
localValue2,
|
|
167
|
+
isGradient,
|
|
168
|
+
angle,
|
|
169
|
+
currentHex,
|
|
170
|
+
currentHex2,
|
|
171
|
+
currentIsGradient,
|
|
172
|
+
currentAngle,
|
|
173
|
+
onChange
|
|
174
|
+
]);
|
|
175
|
+
const handleInputChange = (0, import_react.useCallback)((e) => {
|
|
176
|
+
setLocalValue(e.currentTarget.value);
|
|
177
|
+
}, []);
|
|
178
|
+
const handleInput2Change = (0, import_react.useCallback)((e) => {
|
|
179
|
+
setLocalValue2(e.currentTarget.value);
|
|
180
|
+
}, []);
|
|
181
|
+
const handleAngleChange = (0, import_react.useCallback)((e) => {
|
|
182
|
+
setAngle(Number(e.currentTarget.value));
|
|
183
|
+
}, []);
|
|
184
|
+
const handlePresetClick = (0, import_react.useCallback)(
|
|
185
|
+
(preset) => {
|
|
186
|
+
if (typeof preset === "string") {
|
|
187
|
+
setLocalValue(preset);
|
|
188
|
+
setIsGradient(false);
|
|
189
|
+
} else {
|
|
190
|
+
setLocalValue(preset.hex);
|
|
191
|
+
if (preset.hex2) {
|
|
192
|
+
setLocalValue2(preset.hex2);
|
|
193
|
+
setIsGradient(true);
|
|
194
|
+
if (preset.angle !== void 0) setAngle(preset.angle);
|
|
195
|
+
} else {
|
|
196
|
+
setIsGradient(false);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
[]
|
|
201
|
+
);
|
|
202
|
+
const copyToClipboard = async (text, label) => {
|
|
203
|
+
try {
|
|
204
|
+
await navigator.clipboard.writeText(text);
|
|
205
|
+
toast.push({ title: `Copied ${label}`, status: "success" });
|
|
206
|
+
} catch {
|
|
207
|
+
toast.push({ title: "Copy failed", status: "error" });
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
const contrastColor = (0, import_react.useMemo)(() => getContrastColor(localValue), [localValue]);
|
|
211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui.Stack, { space: 3, children: [
|
|
212
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.Card, { padding: 3, border: true, radius: 3, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui.Flex, { align: "center", gap: 3, children: [
|
|
213
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.Switch, { checked: isGradient, onChange: () => setIsGradient(!isGradient) }),
|
|
214
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.Label, { children: "Gradient Mode" })
|
|
215
|
+
] }) }),
|
|
216
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui.Stack, { space: 3, children: [
|
|
217
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui.Flex, { align: "center", gap: 3, children: [
|
|
218
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui.Box, { style: { position: "relative", width: 40, height: 40 }, children: [
|
|
219
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
220
|
+
import_ui.Flex,
|
|
221
|
+
{
|
|
222
|
+
align: "center",
|
|
223
|
+
justify: "center",
|
|
224
|
+
style: {
|
|
225
|
+
width: "100%",
|
|
226
|
+
height: "100%",
|
|
227
|
+
backgroundColor: localValue || "#ffffff",
|
|
228
|
+
borderRadius: 4,
|
|
229
|
+
border: "1px solid #dfe1e5",
|
|
230
|
+
position: "absolute"
|
|
231
|
+
},
|
|
232
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(EditIcon, { style: { color: getContrastColor(localValue), fontSize: 18 } })
|
|
233
|
+
}
|
|
234
|
+
),
|
|
235
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
236
|
+
"input",
|
|
237
|
+
{
|
|
238
|
+
type: "color",
|
|
239
|
+
value: isValidHex(localValue) ? localValue : "#000000",
|
|
240
|
+
onChange: handleInputChange,
|
|
241
|
+
style: {
|
|
242
|
+
position: "absolute",
|
|
243
|
+
width: "100%",
|
|
244
|
+
height: "100%",
|
|
245
|
+
opacity: 0,
|
|
246
|
+
cursor: "pointer"
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
)
|
|
250
|
+
] }),
|
|
251
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.Box, { flex: 1, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
252
|
+
import_ui.TextInput,
|
|
253
|
+
{
|
|
254
|
+
...elementProps,
|
|
255
|
+
value: localValue,
|
|
256
|
+
onChange: handleInputChange,
|
|
257
|
+
placeholder: "#000000"
|
|
258
|
+
}
|
|
259
|
+
) })
|
|
260
|
+
] }),
|
|
261
|
+
isGradient && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
262
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui.Flex, { align: "center", gap: 3, children: [
|
|
263
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui.Box, { style: { position: "relative", width: 40, height: 40 }, children: [
|
|
264
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
265
|
+
import_ui.Flex,
|
|
266
|
+
{
|
|
267
|
+
align: "center",
|
|
268
|
+
justify: "center",
|
|
269
|
+
style: {
|
|
270
|
+
width: "100%",
|
|
271
|
+
height: "100%",
|
|
272
|
+
backgroundColor: localValue2 || "#ffffff",
|
|
273
|
+
borderRadius: 4,
|
|
274
|
+
border: "1px solid #dfe1e5",
|
|
275
|
+
position: "absolute"
|
|
276
|
+
},
|
|
277
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(EditIcon, { style: { color: getContrastColor(localValue2), fontSize: 18 } })
|
|
278
|
+
}
|
|
279
|
+
),
|
|
280
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
281
|
+
"input",
|
|
282
|
+
{
|
|
283
|
+
type: "color",
|
|
284
|
+
value: isValidHex(localValue2) ? localValue2 : "#000000",
|
|
285
|
+
onChange: handleInput2Change,
|
|
286
|
+
style: {
|
|
287
|
+
position: "absolute",
|
|
288
|
+
width: "100%",
|
|
289
|
+
height: "100%",
|
|
290
|
+
opacity: 0,
|
|
291
|
+
cursor: "pointer"
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
)
|
|
295
|
+
] }),
|
|
296
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.Box, { flex: 1, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
297
|
+
import_ui.TextInput,
|
|
298
|
+
{
|
|
299
|
+
value: localValue2,
|
|
300
|
+
onChange: handleInput2Change,
|
|
301
|
+
placeholder: "#000000"
|
|
302
|
+
}
|
|
303
|
+
) })
|
|
304
|
+
] }),
|
|
305
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui.Stack, { space: 2, children: [
|
|
306
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui.Flex, { justify: "space-between", children: [
|
|
307
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.Text, { size: 1, weight: "bold", children: "Angle" }),
|
|
308
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui.Text, { size: 1, children: [
|
|
309
|
+
angle,
|
|
310
|
+
"\xB0"
|
|
311
|
+
] })
|
|
312
|
+
] }),
|
|
313
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
314
|
+
"input",
|
|
315
|
+
{
|
|
316
|
+
type: "range",
|
|
317
|
+
min: "0",
|
|
318
|
+
max: "360",
|
|
319
|
+
value: angle,
|
|
320
|
+
onChange: handleAngleChange,
|
|
321
|
+
style: { width: "100%" }
|
|
322
|
+
}
|
|
323
|
+
)
|
|
324
|
+
] })
|
|
325
|
+
] })
|
|
326
|
+
] }),
|
|
327
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.Card, { padding: 3, border: true, radius: 3, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui.Stack, { space: 2, children: [
|
|
328
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.Text, { size: 1, weight: "bold", muted: true, children: "Preview" }),
|
|
329
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
330
|
+
import_ui.Box,
|
|
331
|
+
{
|
|
332
|
+
style: {
|
|
333
|
+
height: 100,
|
|
334
|
+
width: "100%",
|
|
335
|
+
borderRadius: 8,
|
|
336
|
+
background: isGradient ? getGradientString(angle, localValue, localValue2) : localValue,
|
|
337
|
+
border: "1px solid #dfe1e5"
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
)
|
|
341
|
+
] }) }),
|
|
342
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.Card, { padding: 2, border: true, radius: 2, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.Grid, { columns: [5, 10], gap: 2, children: colorsList.map((color, index) => {
|
|
343
|
+
const isObj = typeof color === "object";
|
|
344
|
+
const h1 = isObj ? color.hex : color;
|
|
345
|
+
const h2 = isObj ? color.hex2 : null;
|
|
346
|
+
const ang = isObj ? color.angle || 180 : 180;
|
|
347
|
+
const bg = h2 ? getGradientString(ang, h1, h2) : h1;
|
|
348
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
349
|
+
import_ui.Box,
|
|
350
|
+
{
|
|
351
|
+
onClick: () => handlePresetClick(color),
|
|
352
|
+
style: {
|
|
353
|
+
width: 24,
|
|
354
|
+
height: 24,
|
|
355
|
+
borderRadius: "50%",
|
|
356
|
+
background: bg,
|
|
357
|
+
cursor: "pointer",
|
|
358
|
+
border: localValue === h1 ? "2px solid #1a0dab" : "2px solid transparent"
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
index
|
|
362
|
+
);
|
|
363
|
+
}) }) }),
|
|
364
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.Card, { padding: 3, border: true, radius: 3, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.Stack, { space: 3, children: [
|
|
365
|
+
{ label: "HEX", value: localValue.toUpperCase(), show: true },
|
|
366
|
+
{ label: "HEX 2", value: localValue2.toUpperCase(), show: isGradient },
|
|
367
|
+
{ label: "RGBA", value: hexToRgba(localValue), show: !isGradient },
|
|
368
|
+
{ label: "HSL", value: hexToHsl(localValue), show: !isGradient },
|
|
369
|
+
{
|
|
370
|
+
label: "CSS Gradient",
|
|
371
|
+
value: getGradientString(angle, localValue, localValue2),
|
|
372
|
+
show: isGradient
|
|
373
|
+
}
|
|
374
|
+
].filter((item) => item.show).map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui.Flex, { justify: "space-between", align: "center", children: [
|
|
375
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui.Box, { children: [
|
|
376
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.Text, { size: 1, weight: "bold", muted: true, children: item.label }),
|
|
377
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { style: { fontSize: 13, wordBreak: "break-all" }, children: item.value })
|
|
378
|
+
] }),
|
|
379
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
380
|
+
import_ui.Button,
|
|
381
|
+
{
|
|
382
|
+
mode: "ghost",
|
|
383
|
+
fontSize: 1,
|
|
384
|
+
text: "Copy",
|
|
385
|
+
onClick: () => copyToClipboard(item.value, item.label)
|
|
386
|
+
}
|
|
387
|
+
)
|
|
388
|
+
] }, item.label)) }) })
|
|
389
|
+
] });
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// src/schemas/colorType.ts
|
|
393
|
+
var colorType = (0, import_sanity2.defineType)({
|
|
394
|
+
name: "color",
|
|
395
|
+
title: "Color",
|
|
396
|
+
type: "object",
|
|
397
|
+
components: {
|
|
398
|
+
input: CustomColorPicker
|
|
399
|
+
},
|
|
400
|
+
fields: [
|
|
401
|
+
(0, import_sanity2.defineField)({ name: "hex", type: "string" }),
|
|
402
|
+
(0, import_sanity2.defineField)({ name: "rgba", type: "string" }),
|
|
403
|
+
(0, import_sanity2.defineField)({ name: "hsl", type: "string" }),
|
|
404
|
+
(0, import_sanity2.defineField)({ name: "isGradient", type: "boolean" }),
|
|
405
|
+
(0, import_sanity2.defineField)({ name: "hex2", type: "string" }),
|
|
406
|
+
(0, import_sanity2.defineField)({ name: "angle", type: "number" }),
|
|
407
|
+
(0, import_sanity2.defineField)({ name: "css", type: "string" })
|
|
408
|
+
]
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
// src/plugin.ts
|
|
412
|
+
var customColorPicker = (0, import_sanity3.definePlugin)((config) => {
|
|
413
|
+
return {
|
|
414
|
+
name: "sanity-plugin-color-input",
|
|
415
|
+
schema: {
|
|
416
|
+
types: [colorType]
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
});
|
|
420
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
421
|
+
0 && (module.exports = {
|
|
422
|
+
customColorPicker
|
|
423
|
+
});
|