@pixygon/avatar 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.
@@ -0,0 +1,476 @@
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/components/index.ts
21
+ var components_exports = {};
22
+ __export(components_exports, {
23
+ AvatarEditor: () => AvatarEditor
24
+ });
25
+ module.exports = __toCommonJS(components_exports);
26
+
27
+ // src/types/index.ts
28
+ var STYLE_COUNTS = {
29
+ eye: 12,
30
+ brow: 8,
31
+ nose: 8,
32
+ mouth: 8,
33
+ hair: 16,
34
+ facial_hair: 8,
35
+ glasses: 6
36
+ };
37
+
38
+ // src/presets.ts
39
+ var SKIN_PRESETS = [
40
+ [0.98, 0.89, 0.78],
41
+ // Porcelain
42
+ [0.96, 0.84, 0.71],
43
+ // Fair
44
+ [0.92, 0.78, 0.63],
45
+ // Light
46
+ [0.87, 0.72, 0.55],
47
+ // Medium-light
48
+ [0.78, 0.62, 0.46],
49
+ // Medium
50
+ [0.68, 0.51, 0.36],
51
+ // Olive
52
+ [0.58, 0.42, 0.3],
53
+ // Tan
54
+ [0.47, 0.33, 0.22],
55
+ // Brown
56
+ [0.36, 0.24, 0.16],
57
+ // Dark
58
+ [0.26, 0.17, 0.11]
59
+ // Deep
60
+ ];
61
+ var EYE_COLOR_PRESETS = [
62
+ [0.1, 0.1, 0.1],
63
+ // Black
64
+ [0.35, 0.22, 0.1],
65
+ // Brown
66
+ [0.55, 0.35, 0.15],
67
+ // Hazel
68
+ [0.25, 0.5, 0.25],
69
+ // Green
70
+ [0.2, 0.4, 0.7],
71
+ // Blue
72
+ [0.45, 0.45, 0.5],
73
+ // Gray
74
+ [0.55, 0.25, 0.25],
75
+ // Red
76
+ [0.5, 0.3, 0.6]
77
+ // Violet
78
+ ];
79
+ var HAIR_COLOR_PRESETS = [
80
+ [0.08, 0.06, 0.05],
81
+ // Black
82
+ [0.22, 0.14, 0.08],
83
+ // Dark brown
84
+ [0.4, 0.26, 0.14],
85
+ // Brown
86
+ [0.58, 0.42, 0.24],
87
+ // Light brown
88
+ [0.78, 0.62, 0.34],
89
+ // Dirty blonde
90
+ [0.9, 0.78, 0.48],
91
+ // Blonde
92
+ [0.72, 0.26, 0.12],
93
+ // Red
94
+ [0.88, 0.52, 0.22],
95
+ // Ginger
96
+ [0.6, 0.6, 0.62],
97
+ // Gray
98
+ [0.92, 0.92, 0.94]
99
+ // White
100
+ ];
101
+
102
+ // src/hooks/useAvatarEditor.ts
103
+ var import_react = require("react");
104
+
105
+ // src/defaults.ts
106
+ function defaultAppearance() {
107
+ return {
108
+ body: { height: 0.5, build: 0.5 },
109
+ head: {
110
+ width: 1,
111
+ height: 1,
112
+ eye_style: 0,
113
+ eye_color: [...EYE_COLOR_PRESETS[1]],
114
+ eye_y: 0.5,
115
+ eye_spacing: 0.5,
116
+ eye_size: 0.5,
117
+ eye_rotation: 0.5,
118
+ brow_style: 0,
119
+ brow_color: [...HAIR_COLOR_PRESETS[0]],
120
+ brow_y: 0.5,
121
+ brow_spacing: 0.5,
122
+ brow_size: 0.5,
123
+ brow_rotation: 0.5,
124
+ nose_style: 0,
125
+ nose_y: 0.5,
126
+ nose_size: 0.5,
127
+ mouth_style: 0,
128
+ mouth_y: 0.5,
129
+ mouth_size: 0.5,
130
+ mouth_color: [0.75, 0.35, 0.35],
131
+ hair_style: 0,
132
+ hair_color: [...HAIR_COLOR_PRESETS[2]],
133
+ facial_hair_style: 0,
134
+ facial_hair_color: [...HAIR_COLOR_PRESETS[0]],
135
+ glasses_style: 0,
136
+ glasses_color: [0.1, 0.1, 0.1]
137
+ },
138
+ skin_color: [...SKIN_PRESETS[2]]
139
+ };
140
+ }
141
+ function randomAppearance() {
142
+ const rng = (min, max) => min + Math.random() * (max - min);
143
+ const rngInt = (max) => Math.floor(Math.random() * max);
144
+ const pick = (arr) => arr[rngInt(arr.length)];
145
+ const hairColor = pick(HAIR_COLOR_PRESETS);
146
+ return {
147
+ body: {
148
+ height: rng(0.2, 0.8),
149
+ build: rng(0.2, 0.8)
150
+ },
151
+ head: {
152
+ width: rng(0.7, 1.3),
153
+ height: rng(0.7, 1.3),
154
+ eye_style: rngInt(STYLE_COUNTS.eye),
155
+ eye_color: [...pick(EYE_COLOR_PRESETS)],
156
+ eye_y: rng(0.3, 0.7),
157
+ eye_spacing: rng(0.3, 0.7),
158
+ eye_size: rng(0.3, 0.7),
159
+ eye_rotation: 0.5,
160
+ brow_style: rngInt(STYLE_COUNTS.brow),
161
+ brow_color: [...hairColor],
162
+ brow_y: rng(0.3, 0.7),
163
+ brow_spacing: rng(0.3, 0.7),
164
+ brow_size: rng(0.3, 0.7),
165
+ brow_rotation: 0.5,
166
+ nose_style: rngInt(STYLE_COUNTS.nose),
167
+ nose_y: rng(0.3, 0.7),
168
+ nose_size: rng(0.3, 0.7),
169
+ mouth_style: rngInt(STYLE_COUNTS.mouth),
170
+ mouth_y: rng(0.3, 0.7),
171
+ mouth_size: rng(0.3, 0.7),
172
+ mouth_color: [0.75, 0.35, 0.35],
173
+ hair_style: rngInt(STYLE_COUNTS.hair),
174
+ hair_color: [...hairColor],
175
+ facial_hair_style: Math.random() < 0.3 ? 1 + rngInt(STYLE_COUNTS.facial_hair - 1) : 0,
176
+ facial_hair_color: [...hairColor],
177
+ glasses_style: Math.random() < 0.2 ? 1 + rngInt(STYLE_COUNTS.glasses - 1) : 0,
178
+ glasses_color: [0.1, 0.1, 0.1]
179
+ },
180
+ skin_color: [...pick(SKIN_PRESETS)]
181
+ };
182
+ }
183
+
184
+ // src/hooks/useAvatarEditor.ts
185
+ function useAvatarEditor(initial) {
186
+ const [appearance, setAppearance] = (0, import_react.useState)(
187
+ () => initial ?? defaultAppearance()
188
+ );
189
+ const [tab, setTab] = (0, import_react.useState)("body");
190
+ const update = (0, import_react.useCallback)((path, value) => {
191
+ setAppearance((prev) => {
192
+ const next = structuredClone(prev);
193
+ const parts = path.split(".");
194
+ let obj = next;
195
+ for (let i = 0; i < parts.length - 1; i++) {
196
+ obj = obj[parts[i]];
197
+ }
198
+ obj[parts[parts.length - 1]] = value;
199
+ return next;
200
+ });
201
+ }, []);
202
+ const randomize = (0, import_react.useCallback)(() => setAppearance(randomAppearance()), []);
203
+ const reset = (0, import_react.useCallback)(() => setAppearance(initial ?? defaultAppearance()), [initial]);
204
+ return { appearance, tab, setTab, update, randomize, reset };
205
+ }
206
+
207
+ // src/components/AvatarEditor.tsx
208
+ var import_jsx_runtime = require("react/jsx-runtime");
209
+ var TABS = [
210
+ { key: "body", label: "Body" },
211
+ { key: "head", label: "Head" },
212
+ { key: "eyes", label: "Eyes" },
213
+ { key: "brows", label: "Brows" },
214
+ { key: "nose", label: "Nose" },
215
+ { key: "mouth", label: "Mouth" },
216
+ { key: "hair", label: "Hair" },
217
+ { key: "extras", label: "Extras" }
218
+ ];
219
+ function AvatarEditor({
220
+ initial,
221
+ onChange,
222
+ onDone,
223
+ onCancel,
224
+ className
225
+ }) {
226
+ const { appearance, tab, setTab, update, randomize, reset } = useAvatarEditor(initial);
227
+ const handleUpdate = (path, value) => {
228
+ update(path, value);
229
+ setTimeout(() => onChange?.(appearance), 0);
230
+ };
231
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className, style: rootStyle, children: [
232
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: headerStyle, children: [
233
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontWeight: 700, fontSize: 18 }, children: "Avatar Editor" }),
234
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
235
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: btnStyle, onClick: randomize, children: "Randomize" }),
236
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: btnStyle, onClick: reset, children: "Reset" }),
237
+ onCancel && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: btnStyle, onClick: onCancel, children: "Cancel" }),
238
+ onDone && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: { ...btnStyle, background: "#3b6" }, onClick: () => onDone(appearance), children: "Done" })
239
+ ] })
240
+ ] }),
241
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: tabBarStyle, children: TABS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
242
+ "button",
243
+ {
244
+ onClick: () => setTab(t.key),
245
+ style: {
246
+ ...tabStyle,
247
+ ...tab === t.key ? tabActiveStyle : {}
248
+ },
249
+ children: t.label
250
+ },
251
+ t.key
252
+ )) }),
253
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: contentStyle, children: [
254
+ tab === "body" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BodyTab, { appearance, onUpdate: handleUpdate }),
255
+ tab === "head" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HeadTab, { appearance, onUpdate: handleUpdate }),
256
+ tab === "eyes" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EyesTab, { appearance, onUpdate: handleUpdate }),
257
+ tab === "brows" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BrowsTab, { appearance, onUpdate: handleUpdate }),
258
+ tab === "nose" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NoseTab, { appearance, onUpdate: handleUpdate }),
259
+ tab === "mouth" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MouthTab, { appearance, onUpdate: handleUpdate }),
260
+ tab === "hair" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HairTab, { appearance, onUpdate: handleUpdate }),
261
+ tab === "extras" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ExtrasTab, { appearance, onUpdate: handleUpdate })
262
+ ] })
263
+ ] });
264
+ }
265
+ function BodyTab({ appearance, onUpdate }) {
266
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
267
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionLabel, { children: "Body" }),
268
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Height", value: appearance.body.height, onChange: (v) => onUpdate("body.height", v) }),
269
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Build", value: appearance.body.build, onChange: (v) => onUpdate("body.build", v) }),
270
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionLabel, { children: "Skin Colour" }),
271
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ColourPresets, { current: appearance.skin_color, presets: SKIN_PRESETS, onPick: (c) => onUpdate("skin_color", c) })
272
+ ] });
273
+ }
274
+ function HeadTab({ appearance, onUpdate }) {
275
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
276
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionLabel, { children: "Head Shape" }),
277
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Width", value: appearance.head.width, min: 0.5, max: 1.5, onChange: (v) => onUpdate("head.width", v) }),
278
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Height", value: appearance.head.height, min: 0.5, max: 1.5, onChange: (v) => onUpdate("head.height", v) })
279
+ ] });
280
+ }
281
+ function EyesTab({ appearance, onUpdate }) {
282
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
283
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionLabel, { children: "Eyes" }),
284
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StyleSelector, { label: "Style", value: appearance.head.eye_style, count: STYLE_COUNTS.eye, onChange: (v) => onUpdate("head.eye_style", v) }),
285
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ColourPresets, { current: appearance.head.eye_color, presets: EYE_COLOR_PRESETS, onPick: (c) => onUpdate("head.eye_color", c) }),
286
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Vertical Pos", value: appearance.head.eye_y, onChange: (v) => onUpdate("head.eye_y", v) }),
287
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Spacing", value: appearance.head.eye_spacing, onChange: (v) => onUpdate("head.eye_spacing", v) }),
288
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Size", value: appearance.head.eye_size, onChange: (v) => onUpdate("head.eye_size", v) }),
289
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Rotation", value: appearance.head.eye_rotation, onChange: (v) => onUpdate("head.eye_rotation", v) })
290
+ ] });
291
+ }
292
+ function BrowsTab({ appearance, onUpdate }) {
293
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
294
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionLabel, { children: "Eyebrows" }),
295
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StyleSelector, { label: "Style", value: appearance.head.brow_style, count: STYLE_COUNTS.brow, onChange: (v) => onUpdate("head.brow_style", v) }),
296
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ColourPresets, { current: appearance.head.brow_color, presets: HAIR_COLOR_PRESETS, onPick: (c) => onUpdate("head.brow_color", c) }),
297
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Vertical Pos", value: appearance.head.brow_y, onChange: (v) => onUpdate("head.brow_y", v) }),
298
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Spacing", value: appearance.head.brow_spacing, onChange: (v) => onUpdate("head.brow_spacing", v) }),
299
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Size", value: appearance.head.brow_size, onChange: (v) => onUpdate("head.brow_size", v) }),
300
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Rotation", value: appearance.head.brow_rotation, onChange: (v) => onUpdate("head.brow_rotation", v) })
301
+ ] });
302
+ }
303
+ function NoseTab({ appearance, onUpdate }) {
304
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
305
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionLabel, { children: "Nose" }),
306
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StyleSelector, { label: "Style", value: appearance.head.nose_style, count: STYLE_COUNTS.nose, onChange: (v) => onUpdate("head.nose_style", v) }),
307
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Vertical Pos", value: appearance.head.nose_y, onChange: (v) => onUpdate("head.nose_y", v) }),
308
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Size", value: appearance.head.nose_size, onChange: (v) => onUpdate("head.nose_size", v) })
309
+ ] });
310
+ }
311
+ function MouthTab({ appearance, onUpdate }) {
312
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
313
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionLabel, { children: "Mouth" }),
314
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StyleSelector, { label: "Style", value: appearance.head.mouth_style, count: STYLE_COUNTS.mouth, onChange: (v) => onUpdate("head.mouth_style", v) }),
315
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Vertical Pos", value: appearance.head.mouth_y, onChange: (v) => onUpdate("head.mouth_y", v) }),
316
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slider, { label: "Size", value: appearance.head.mouth_size, onChange: (v) => onUpdate("head.mouth_size", v) })
317
+ ] });
318
+ }
319
+ function HairTab({ appearance, onUpdate }) {
320
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
321
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionLabel, { children: "Hair" }),
322
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StyleSelector, { label: "Style", value: appearance.head.hair_style, count: STYLE_COUNTS.hair, onChange: (v) => onUpdate("head.hair_style", v) }),
323
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionLabel, { children: "Colour" }),
324
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ColourPresets, { current: appearance.head.hair_color, presets: HAIR_COLOR_PRESETS, onPick: (c) => onUpdate("head.hair_color", c) })
325
+ ] });
326
+ }
327
+ function ExtrasTab({ appearance, onUpdate }) {
328
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
329
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionLabel, { children: "Facial Hair" }),
330
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StyleSelector, { label: "Style", value: appearance.head.facial_hair_style, count: STYLE_COUNTS.facial_hair, onChange: (v) => onUpdate("head.facial_hair_style", v) }),
331
+ appearance.head.facial_hair_style > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ColourPresets, { current: appearance.head.facial_hair_color, presets: HAIR_COLOR_PRESETS, onPick: (c) => onUpdate("head.facial_hair_color", c) }),
332
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionLabel, { children: "Glasses" }),
333
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StyleSelector, { label: "Style", value: appearance.head.glasses_style, count: STYLE_COUNTS.glasses, onChange: (v) => onUpdate("head.glasses_style", v) })
334
+ ] });
335
+ }
336
+ function SectionLabel({ children }) {
337
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: "#ccc", fontWeight: 600, fontSize: 13, margin: "8px 0 4px" }, children });
338
+ }
339
+ function Slider({
340
+ label,
341
+ value,
342
+ min = 0,
343
+ max = 1,
344
+ onChange
345
+ }) {
346
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: sliderRowStyle, children: [
347
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { minWidth: 90, color: "#aab" }, children: label }),
348
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
349
+ "input",
350
+ {
351
+ type: "range",
352
+ min,
353
+ max,
354
+ step: 0.01,
355
+ value,
356
+ onChange: (e) => onChange(parseFloat(e.target.value)),
357
+ style: { flex: 1 }
358
+ }
359
+ ),
360
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { minWidth: 40, textAlign: "right", color: "#889", fontSize: 12 }, children: value.toFixed(2) })
361
+ ] });
362
+ }
363
+ function StyleSelector({
364
+ label,
365
+ value,
366
+ count,
367
+ onChange
368
+ }) {
369
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, margin: "4px 0" }, children: [
370
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "#aab", minWidth: 50 }, children: label }),
371
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: smallBtnStyle, onClick: () => onChange(Math.max(0, value - 1)), disabled: value <= 0, children: "<" }),
372
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { color: "#fff", minWidth: 40, textAlign: "center" }, children: [
373
+ value + 1,
374
+ "/",
375
+ count
376
+ ] }),
377
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: smallBtnStyle, onClick: () => onChange(Math.min(count - 1, value + 1)), disabled: value >= count - 1, children: ">" })
378
+ ] });
379
+ }
380
+ function ColourPresets({
381
+ current,
382
+ presets,
383
+ onPick
384
+ }) {
385
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 4, margin: "4px 0" }, children: presets.map((p, i) => {
386
+ const selected = Math.abs(current[0] - p[0]) < 0.01 && Math.abs(current[1] - p[1]) < 0.01 && Math.abs(current[2] - p[2]) < 0.01;
387
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
388
+ "button",
389
+ {
390
+ onClick: () => onPick([...p]),
391
+ style: {
392
+ width: selected ? 26 : 22,
393
+ height: selected ? 26 : 22,
394
+ borderRadius: 4,
395
+ border: selected ? "2px solid #fff" : "1px solid #555",
396
+ background: `rgb(${p[0] * 255}, ${p[1] * 255}, ${p[2] * 255})`,
397
+ cursor: "pointer",
398
+ padding: 0
399
+ }
400
+ },
401
+ i
402
+ );
403
+ }) });
404
+ }
405
+ var rootStyle = {
406
+ display: "flex",
407
+ flexDirection: "column",
408
+ background: "#1e1e2a",
409
+ color: "#ddd",
410
+ borderRadius: 8,
411
+ overflow: "hidden",
412
+ fontFamily: "system-ui, sans-serif",
413
+ fontSize: 14
414
+ };
415
+ var headerStyle = {
416
+ display: "flex",
417
+ justifyContent: "space-between",
418
+ alignItems: "center",
419
+ padding: "10px 14px",
420
+ background: "#16161f"
421
+ };
422
+ var tabBarStyle = {
423
+ display: "flex",
424
+ gap: 2,
425
+ padding: "0 8px",
426
+ background: "#1a1a26",
427
+ overflowX: "auto"
428
+ };
429
+ var tabStyle = {
430
+ padding: "8px 12px",
431
+ background: "transparent",
432
+ border: "none",
433
+ color: "#99a",
434
+ cursor: "pointer",
435
+ fontSize: 13,
436
+ whiteSpace: "nowrap"
437
+ };
438
+ var tabActiveStyle = {
439
+ color: "#fff",
440
+ fontWeight: 700,
441
+ borderBottom: "2px solid #6af"
442
+ };
443
+ var contentStyle = {
444
+ padding: "8px 14px 14px",
445
+ overflowY: "auto",
446
+ flex: 1
447
+ };
448
+ var btnStyle = {
449
+ padding: "6px 14px",
450
+ border: "none",
451
+ borderRadius: 4,
452
+ background: "#333",
453
+ color: "#ddd",
454
+ cursor: "pointer",
455
+ fontSize: 13
456
+ };
457
+ var smallBtnStyle = {
458
+ width: 28,
459
+ height: 28,
460
+ border: "1px solid #444",
461
+ borderRadius: 4,
462
+ background: "#2a2a36",
463
+ color: "#ccc",
464
+ cursor: "pointer",
465
+ fontSize: 14
466
+ };
467
+ var sliderRowStyle = {
468
+ display: "flex",
469
+ alignItems: "center",
470
+ gap: 8,
471
+ margin: "4px 0"
472
+ };
473
+ // Annotate the CommonJS export names for ESM import in node:
474
+ 0 && (module.exports = {
475
+ AvatarEditor
476
+ });