react-avatar-studio 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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mohammed Sinan Mp
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,163 @@
1
+ # React Avatar Studio
2
+
3
+ A production-ready, engine-agnostic React + TypeScript NPM package for avatar customization, featuring `react-nice-avatar` as the default v1 rendering engine.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Engine-Agnostic Architecture**: Designed to support multiple avatar rendering engines in the future.
8
+ - 🎨 **Modular & Reusable Components**: `AvatarPreview`, `AvatarCustomizeInline`, and `AvatarCustomizeModal` components, heavily decomposed under the hood into single-responsibility atomic components for maximum flexibility.
9
+ - 📦 **Lightweight & Tree-shakable**: ESM and CJS exports bundled with `tsup`.
10
+ - 🛠 **Highly Configurable API**: Control sections, orders, grids, labels, layouts, and positioning easily.
11
+ - 🧩 **Deep Customization (Slots & Overrides)**: Replace internal components entirely using `components` / `slots`, and apply specific HTML attributes via `slotProps`.
12
+ - 💅 **Minimal CSS**: Comes with a lightweight `.css` file using a slot-based `ras-` class approach for easy overriding without tying you into Tailwind, MUI, or Chakra.
13
+ - 🛡 **TypeScript First**: End-to-end typed for excellent Developer Experience.
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install react-avatar-studio react-nice-avatar
19
+ ```
20
+
21
+ _(Requires `react-nice-avatar` as a peer dependency since it powers the defaults)._
22
+
23
+ ## Usage
24
+
25
+ ### 1. Simple Avatar Preview
26
+
27
+ ```tsx
28
+ import { AvatarPreview } from "react-avatar-studio";
29
+
30
+ function Profile() {
31
+ return (
32
+ <div style={{ width: "100px", height: "100px" }}>
33
+ <AvatarPreview
34
+ config={{ hairStyle: "mohawk" }}
35
+ className="my-custom-preview"
36
+ />
37
+ </div>
38
+ );
39
+ }
40
+ ```
41
+
42
+ ### 2. Inline Avatar Customizer
43
+
44
+ ```tsx
45
+ import { useState } from "react";
46
+ import { AvatarCustomizeInline, AvatarConfig } from "react-avatar-studio";
47
+
48
+ function AvatarCreator() {
49
+ const [config, setConfig] = useState<AvatarConfig>();
50
+
51
+ return (
52
+ <AvatarCustomizeInline
53
+ value={config}
54
+ onChange={setConfig}
55
+ onSave={(finalConfig, exportData) => {
56
+ console.log("Saved!", finalConfig);
57
+ console.log("SVG String: ", exportData.svg);
58
+ console.log("PNG Data URL: ", exportData.pngDataUrl);
59
+ }}
60
+ onCancel={() => console.log("Cancelled!")}
61
+ />
62
+ );
63
+ }
64
+ ```
65
+
66
+ ### 3. Modal Avatar Customize
67
+
68
+ ```tsx
69
+ import { useState } from "react";
70
+ import { AvatarCustomizeModal } from "react-avatar-studio";
71
+
72
+ function Settings() {
73
+ const [open, setOpen] = useState(false);
74
+
75
+ return (
76
+ <>
77
+ <button onClick={() => setOpen(true)}>Edit Avatar</button>
78
+ <AvatarCustomizeModal
79
+ open={open}
80
+ onClose={() => setOpen(false)}
81
+ onSave={(newConfig, exportData) => {
82
+ // save to DB
83
+ console.log(newConfig, exportData);
84
+ setOpen(false);
85
+ }}
86
+ />
87
+ </>
88
+ );
89
+ }
90
+ ```
91
+
92
+ ## Advanced API Configuration & Customization
93
+
94
+ The library exposes a highly configurable API. You can drastically alter the appearance and behavior without modifying the core code by passing props:
95
+
96
+ ### 1. Theming and Styling Variations
97
+
98
+ - **`theme`**: Accepts `'light'`, `'dark'`, or a custom object with CSS variables to instantly match your app's branding.
99
+ - **`classes` / `classNames`**: Map standard elements to your own utility classes (like Tailwind!). Provide classes to internal slots such as `container`, `categoryNav`, `optionBtn`, `actionBtn`, `tabs`, etc.
100
+ - **`unstyled`**: Set to `true` to completely strip default library styles, giving you 100% control over the CSS.
101
+
102
+ ### 2. Layout & Positioning
103
+
104
+ - **`layout`**: Choose between `'sidebar'` (default), `'tabs'`, or `'accordion'` layouts for the option settings.
105
+ - **`previewPosition`**: Position the avatar preview to the `'top'`, `'left'`, `'right'`, or `'bottom'` relative to the settings panel.
106
+ - **`columns`**: Control the grid column count for customization options (e.g. `columns={3}`).
107
+
108
+ ### 3. Deep Component Overrides (Slots API)
109
+
110
+ Take absolute control of the component behaviors by bypassing our default render tree:
111
+
112
+ - **`components` (or `slots`)**: Swap out functional visual blocks with your custom components: `SectionWrapper`, `SectionHeader`, `OptionButton`, `Footer`, `PreviewWrapper`, `Tabs`, `TabButton`, `Button`, or `Modal`.
113
+ - **`slotProps`**: Forward `HTMLAttributes` (like aria tags, custom event handlers, `data-testid` properties) onto intrinsic DOM components (e.g. `saveButton`, `colorButton`, `categoryTab`).
114
+
115
+ ### 4. API & Data Control
116
+
117
+ - **`hiddenSections`**: An array of strings describing which avatar sections to hide from the user (e.g., `['glassesStyle', 'hatStyle']`).
118
+ - **`sectionOrder`**: An array to manually dictate the top-to-bottom rendering order of customization sections.
119
+ - **`sectionOptionOverrides`**: Restrict or dictate the available selectable options per section.
120
+ - **`labels`**: A dictionary to rename default section labels (e.g., `{ hairStyle: 'Cool Hair' }`).
121
+ - **`value` / `defaultValue`**: Configure initial avatar state or fully control the component state.
122
+
123
+ **Example of an advanced configuration:**
124
+
125
+ ```tsx
126
+ <AvatarCustomizeInline
127
+ theme="dark"
128
+ layout="tabs"
129
+ previewPosition="right"
130
+ columns={4}
131
+ hiddenSections={["glassesStyle", "hatStyle"]}
132
+ sectionOrder={["faceColor", "hairStyle", "hairColor"]}
133
+ labels={{
134
+ hairStyle: "Cool Hair",
135
+ }}
136
+ classes={{
137
+ actionBtn: "my-custom-button-class",
138
+ categoryTab: "font-semibold text-lg",
139
+ }}
140
+ slotProps={{
141
+ saveButton: { "data-testid": "avatar-save" },
142
+ }}
143
+ />
144
+ ```
145
+
146
+ ## Styling Overrides
147
+
148
+ If you prefer not to use the `classes` prop or CSS-in-JS, you can override the default styles by targeting `.ras-*` classes. Standard classes include:
149
+
150
+ - `.ras-container`
151
+ - `.ras-layout`
152
+ - `.ras-preview-column`
153
+ - `.ras-settings-column`
154
+ - `.ras-category-nav`
155
+ - `.ras-options-grid`
156
+ - `.ras-modal-overlay`
157
+ - _and many more..._
158
+
159
+ ## Future Roadmap (Extensibility)
160
+
161
+ The architecture is deliberately built with an `AvatarEngine` interface in mind. We currently implement a robust mapping for the `react-nice-avatar` library to our generic UI controls.
162
+
163
+ If you want to plug in a custom renderer (like DiceBear or your own SVG strings), you have ultimate flexibility leveraging the internal atomic subcomponents and hooks!
@@ -0,0 +1,2 @@
1
+ import{a,b}from"./chunk-WBTMPEY3.mjs";export{b as downloadAvatarAsPng,a as getAvatarData};
2
+ //# sourceMappingURL=avatarHelpers-6323LQJA.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,14 @@
1
+ async function m(o){let t=document.getElementById(o);if(!t)return console.error(`Avatar node with id "${o}" not found.`),null;let a=t.offsetWidth,n=t.offsetHeight,c=t.innerHTML,d=`
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="${a}" height="${n}">
3
+ <foreignObject width="100%" height="100%">
4
+ <div xmlns="http://www.w3.org/1999/xhtml" style="width:100%;height:100%;">
5
+ <style>
6
+ * { box-sizing: content-box !important; }
7
+ svg { display: inline !important; max-width: none !important; max-height: none !important; margin: 0; padding: 0; transform-origin: center center; }
8
+ </style>
9
+ ${c}
10
+ </div>
11
+ </foreignObject>
12
+ </svg>
13
+ `;return new Promise(s=>{let i=new Image;i.src="data:image/svg+xml;charset=utf-8,"+encodeURIComponent(d.trim()),i.onload=()=>{let e=document.createElement("canvas"),r=2;e.width=a*r,e.height=n*r;let g=e.getContext("2d");if(g){g.scale(r,r),g.drawImage(i,0,0);let l=e.toDataURL("image/png");s({svg:c,pngDataUrl:l})}else s(null)},i.onerror=e=>{console.error("Failed to generate PNG from Avatar HTML:",e),s(null)}})}async function h(o,t="avatar.png"){let a=await m(o);if(a){let n=document.createElement("a");n.download=t,n.href=a.pngDataUrl,n.click()}}export{m as a,h as b};
14
+ //# sourceMappingURL=chunk-WBTMPEY3.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/avatarHelpers.ts"],"sourcesContent":["/**\n * Utility to extract fully rendered SVG and high-resolution PNG data URLs from the avatar DOM node.\n */\nexport async function getAvatarData(elementId: string): Promise<{ svg: string; pngDataUrl: string } | null> {\n const node = document.getElementById(elementId);\n if (!node) {\n console.error(`Avatar node with id \"${elementId}\" not found.`);\n return null;\n }\n \n const width = node.offsetWidth;\n const height = node.offsetHeight;\n const rawHtml = node.innerHTML;\n \n const data = `\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\">\n <foreignObject width=\"100%\" height=\"100%\">\n <div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"width:100%;height:100%;\">\n <style>\n * { box-sizing: content-box !important; }\n svg { display: inline !important; max-width: none !important; max-height: none !important; margin: 0; padding: 0; transform-origin: center center; }\n </style>\n ${rawHtml}\n </div>\n </foreignObject>\n </svg>\n `;\n \n return new Promise((resolve) => {\n const img = new Image();\n img.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(data.trim());\n \n img.onload = () => {\n const canvas = document.createElement('canvas');\n const scale = 2; // 2x resolution\n canvas.width = width * scale;\n canvas.height = height * scale;\n \n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.scale(scale, scale);\n ctx.drawImage(img, 0, 0);\n const pngDataUrl = canvas.toDataURL('image/png');\n resolve({ svg: rawHtml, pngDataUrl });\n } else {\n resolve(null);\n }\n };\n \n img.onerror = (e) => {\n console.error('Failed to generate PNG from Avatar HTML:', e);\n resolve(null);\n };\n });\n}\n\n/**\n * Utility to download the avatar DOM node directly as a PNG.\n */\nexport async function downloadAvatarAsPng(elementId: string, filename = 'avatar.png') {\n const data = await getAvatarData(elementId);\n if (data) {\n const a = document.createElement('a');\n a.download = filename;\n a.href = data.pngDataUrl;\n a.click();\n }\n}\n"],"mappings":"AAGA,eAAsBA,EAAcC,EAAwE,CAC1G,IAAMC,EAAO,SAAS,eAAeD,CAAS,EAC9C,GAAI,CAACC,EACH,eAAQ,MAAM,wBAAwBD,CAAS,cAAc,EACtD,KAGT,IAAME,EAAQD,EAAK,YACbE,EAASF,EAAK,aACdG,EAAUH,EAAK,UAEfI,EAAO;AAAA,qDACsCH,CAAK,aAAaC,CAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAOjEC,CAAO;AAAA;AAAA;AAAA;AAAA,IAMjB,OAAO,IAAI,QAASE,GAAY,CAC9B,IAAMC,EAAM,IAAI,MAChBA,EAAI,IAAM,oCAAsC,mBAAmBF,EAAK,KAAK,CAAC,EAE9EE,EAAI,OAAS,IAAM,CACjB,IAAMC,EAAS,SAAS,cAAc,QAAQ,EACxCC,EAAQ,EACdD,EAAO,MAAQN,EAAQO,EACvBD,EAAO,OAASL,EAASM,EAEzB,IAAMC,EAAMF,EAAO,WAAW,IAAI,EAClC,GAAIE,EAAK,CACPA,EAAI,MAAMD,EAAOA,CAAK,EACtBC,EAAI,UAAUH,EAAK,EAAG,CAAC,EACvB,IAAMI,EAAaH,EAAO,UAAU,WAAW,EAC/CF,EAAQ,CAAE,IAAKF,EAAS,WAAAO,CAAW,CAAC,CACtC,MACEL,EAAQ,IAAI,CAEhB,EAEAC,EAAI,QAAW,GAAM,CACnB,QAAQ,MAAM,2CAA4C,CAAC,EAC3DD,EAAQ,IAAI,CACd,CACF,CAAC,CACH,CAKA,eAAsBM,EAAoBZ,EAAmBa,EAAW,aAAc,CACpF,IAAMR,EAAO,MAAMN,EAAcC,CAAS,EAC1C,GAAIK,EAAM,CACR,IAAMS,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,SAAWD,EACbC,EAAE,KAAOT,EAAK,WACdS,EAAE,MAAM,CACV,CACF","names":["getAvatarData","elementId","node","width","height","rawHtml","data","resolve","img","canvas","scale","ctx","pngDataUrl","downloadAvatarAsPng","filename","a"]}
@@ -0,0 +1,148 @@
1
+ import { AvatarConfig } from 'react-nice-avatar';
2
+ import * as react from 'react';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+
5
+ type AvatarStudioTheme = 'light' | 'dark' | Record<string, string>;
6
+ interface AvatarStudioClasses {
7
+ container?: string;
8
+ previewWrapper?: string;
9
+ avatarColumn?: string;
10
+ settingsColumn?: string;
11
+ categoryNav?: string;
12
+ categoryTab?: string;
13
+ sectionBlock?: string;
14
+ sectionTitle?: string;
15
+ optionsGrid?: string;
16
+ optionBtn?: string;
17
+ colorBtn?: string;
18
+ footer?: string;
19
+ actionBtn?: string;
20
+ }
21
+ interface AvatarCustomizeClassNames {
22
+ root?: string;
23
+ preview?: string;
24
+ sectionNav?: string;
25
+ optionButton?: string;
26
+ actionBar?: string;
27
+ }
28
+ interface AvatarCustomizeComponents {
29
+ SectionWrapper?: React.ElementType;
30
+ SectionHeader?: React.ElementType;
31
+ OptionButton?: React.ElementType;
32
+ Footer?: React.ElementType;
33
+ PreviewWrapper?: React.ElementType;
34
+ Modal?: React.ElementType;
35
+ Tabs?: React.ElementType;
36
+ TabButton?: React.ElementType;
37
+ Button?: React.ElementType;
38
+ }
39
+ interface AvatarCustomizeSlotProps {
40
+ root?: React.HTMLAttributes<HTMLDivElement>;
41
+ previewWrapper?: React.HTMLAttributes<HTMLDivElement>;
42
+ optionButton?: React.ButtonHTMLAttributes<HTMLButtonElement>;
43
+ colorButton?: React.ButtonHTMLAttributes<HTMLButtonElement>;
44
+ categoryTab?: React.ButtonHTMLAttributes<HTMLButtonElement>;
45
+ saveButton?: React.ButtonHTMLAttributes<HTMLButtonElement>;
46
+ cancelButton?: React.ButtonHTMLAttributes<HTMLButtonElement>;
47
+ randomizeButton?: React.ButtonHTMLAttributes<HTMLButtonElement>;
48
+ downloadButton?: React.ButtonHTMLAttributes<HTMLButtonElement>;
49
+ sectionHeader?: React.HTMLAttributes<HTMLDivElement>;
50
+ sectionWrapper?: React.HTMLAttributes<HTMLDivElement>;
51
+ footer?: React.HTMLAttributes<HTMLDivElement>;
52
+ }
53
+ interface AvatarExportData {
54
+ config: AvatarConfig;
55
+ svg: string;
56
+ pngDataUrl: string;
57
+ }
58
+ interface AvatarCustomizeProps {
59
+ value?: AvatarConfig;
60
+ defaultValue?: AvatarConfig;
61
+ onChange?: (config: AvatarConfig) => void;
62
+ onSave?: (config: AvatarConfig, exportData: AvatarExportData) => void;
63
+ onCancel?: () => void;
64
+ hiddenSections?: string[];
65
+ sectionOrder?: string[];
66
+ sectionOptionOverrides?: Record<string, string[]>;
67
+ labels?: Record<string, string>;
68
+ className?: string;
69
+ style?: React.CSSProperties;
70
+ theme?: AvatarStudioTheme;
71
+ classes?: AvatarStudioClasses;
72
+ classNames?: AvatarCustomizeClassNames;
73
+ slots?: AvatarCustomizeComponents;
74
+ components?: AvatarCustomizeComponents;
75
+ slotProps?: AvatarCustomizeSlotProps;
76
+ unstyled?: boolean;
77
+ layout?: 'sidebar' | 'tabs' | 'accordion';
78
+ previewPosition?: 'top' | 'left' | 'right' | 'bottom';
79
+ columns?: number;
80
+ }
81
+ interface AvatarCustomizeModalProps extends AvatarCustomizeProps {
82
+ open: boolean;
83
+ onClose: () => void;
84
+ modalClassName?: string;
85
+ overlayClassName?: string;
86
+ }
87
+ interface AvatarPreviewProps {
88
+ config?: AvatarConfig;
89
+ className?: string;
90
+ style?: React.CSSProperties;
91
+ id?: string;
92
+ }
93
+
94
+ interface AvatarOption {
95
+ value: string | number;
96
+ label: string;
97
+ colorHex?: string;
98
+ imageUrl?: string;
99
+ }
100
+ interface AvatarSection {
101
+ id: string;
102
+ label: string;
103
+ type: 'select' | 'color' | 'slider';
104
+ options: AvatarOption[];
105
+ defaultValue: any;
106
+ group?: string;
107
+ description?: string;
108
+ hidden?: boolean;
109
+ }
110
+ declare const REACT_NICE_AVATAR_SECTIONS: AvatarSection[];
111
+
112
+ /**
113
+ * Utility to extract fully rendered SVG and high-resolution PNG data URLs from the avatar DOM node.
114
+ */
115
+ declare function getAvatarData(elementId: string): Promise<{
116
+ svg: string;
117
+ pngDataUrl: string;
118
+ } | null>;
119
+ /**
120
+ * Utility to download the avatar DOM node directly as a PNG.
121
+ */
122
+ declare function downloadAvatarAsPng(elementId: string, filename?: string): Promise<void>;
123
+
124
+ interface UseAvatarCustomizeProps {
125
+ value?: AvatarConfig;
126
+ defaultValue?: AvatarConfig;
127
+ onChange?: (config: AvatarConfig) => void;
128
+ hiddenSections?: string[];
129
+ sectionOrder?: string[];
130
+ }
131
+ declare function useAvatarCustomize({ value, defaultValue, onChange, hiddenSections, sectionOrder, }: UseAvatarCustomizeProps): {
132
+ config: AvatarConfig;
133
+ sections: AvatarSection[];
134
+ activeSectionId: string | null;
135
+ setActiveSectionId: react.Dispatch<react.SetStateAction<string | null>>;
136
+ updateConfig: (newConfigPartial: Partial<AvatarConfig>) => void;
137
+ handleOptionChange: (sectionId: string, value: any) => void;
138
+ randomize: () => void;
139
+ reset: () => void;
140
+ };
141
+
142
+ declare function AvatarPreview({ config, className, style, id }: AvatarPreviewProps): react_jsx_runtime.JSX.Element;
143
+
144
+ declare function AvatarCustomizeInline(props: AvatarCustomizeProps): react_jsx_runtime.JSX.Element;
145
+
146
+ declare function AvatarCustomizeModal(props: AvatarCustomizeModalProps): react_jsx_runtime.JSX.Element | null;
147
+
148
+ export { type AvatarCustomizeClassNames, type AvatarCustomizeComponents, AvatarCustomizeInline, AvatarCustomizeModal, type AvatarCustomizeModalProps, type AvatarCustomizeProps, type AvatarCustomizeSlotProps, type AvatarExportData, type AvatarOption, AvatarPreview, type AvatarPreviewProps, type AvatarSection, type AvatarStudioClasses, type AvatarStudioTheme, REACT_NICE_AVATAR_SECTIONS, type UseAvatarCustomizeProps, downloadAvatarAsPng, getAvatarData, useAvatarCustomize };
@@ -0,0 +1,148 @@
1
+ import { AvatarConfig } from 'react-nice-avatar';
2
+ import * as react from 'react';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+
5
+ type AvatarStudioTheme = 'light' | 'dark' | Record<string, string>;
6
+ interface AvatarStudioClasses {
7
+ container?: string;
8
+ previewWrapper?: string;
9
+ avatarColumn?: string;
10
+ settingsColumn?: string;
11
+ categoryNav?: string;
12
+ categoryTab?: string;
13
+ sectionBlock?: string;
14
+ sectionTitle?: string;
15
+ optionsGrid?: string;
16
+ optionBtn?: string;
17
+ colorBtn?: string;
18
+ footer?: string;
19
+ actionBtn?: string;
20
+ }
21
+ interface AvatarCustomizeClassNames {
22
+ root?: string;
23
+ preview?: string;
24
+ sectionNav?: string;
25
+ optionButton?: string;
26
+ actionBar?: string;
27
+ }
28
+ interface AvatarCustomizeComponents {
29
+ SectionWrapper?: React.ElementType;
30
+ SectionHeader?: React.ElementType;
31
+ OptionButton?: React.ElementType;
32
+ Footer?: React.ElementType;
33
+ PreviewWrapper?: React.ElementType;
34
+ Modal?: React.ElementType;
35
+ Tabs?: React.ElementType;
36
+ TabButton?: React.ElementType;
37
+ Button?: React.ElementType;
38
+ }
39
+ interface AvatarCustomizeSlotProps {
40
+ root?: React.HTMLAttributes<HTMLDivElement>;
41
+ previewWrapper?: React.HTMLAttributes<HTMLDivElement>;
42
+ optionButton?: React.ButtonHTMLAttributes<HTMLButtonElement>;
43
+ colorButton?: React.ButtonHTMLAttributes<HTMLButtonElement>;
44
+ categoryTab?: React.ButtonHTMLAttributes<HTMLButtonElement>;
45
+ saveButton?: React.ButtonHTMLAttributes<HTMLButtonElement>;
46
+ cancelButton?: React.ButtonHTMLAttributes<HTMLButtonElement>;
47
+ randomizeButton?: React.ButtonHTMLAttributes<HTMLButtonElement>;
48
+ downloadButton?: React.ButtonHTMLAttributes<HTMLButtonElement>;
49
+ sectionHeader?: React.HTMLAttributes<HTMLDivElement>;
50
+ sectionWrapper?: React.HTMLAttributes<HTMLDivElement>;
51
+ footer?: React.HTMLAttributes<HTMLDivElement>;
52
+ }
53
+ interface AvatarExportData {
54
+ config: AvatarConfig;
55
+ svg: string;
56
+ pngDataUrl: string;
57
+ }
58
+ interface AvatarCustomizeProps {
59
+ value?: AvatarConfig;
60
+ defaultValue?: AvatarConfig;
61
+ onChange?: (config: AvatarConfig) => void;
62
+ onSave?: (config: AvatarConfig, exportData: AvatarExportData) => void;
63
+ onCancel?: () => void;
64
+ hiddenSections?: string[];
65
+ sectionOrder?: string[];
66
+ sectionOptionOverrides?: Record<string, string[]>;
67
+ labels?: Record<string, string>;
68
+ className?: string;
69
+ style?: React.CSSProperties;
70
+ theme?: AvatarStudioTheme;
71
+ classes?: AvatarStudioClasses;
72
+ classNames?: AvatarCustomizeClassNames;
73
+ slots?: AvatarCustomizeComponents;
74
+ components?: AvatarCustomizeComponents;
75
+ slotProps?: AvatarCustomizeSlotProps;
76
+ unstyled?: boolean;
77
+ layout?: 'sidebar' | 'tabs' | 'accordion';
78
+ previewPosition?: 'top' | 'left' | 'right' | 'bottom';
79
+ columns?: number;
80
+ }
81
+ interface AvatarCustomizeModalProps extends AvatarCustomizeProps {
82
+ open: boolean;
83
+ onClose: () => void;
84
+ modalClassName?: string;
85
+ overlayClassName?: string;
86
+ }
87
+ interface AvatarPreviewProps {
88
+ config?: AvatarConfig;
89
+ className?: string;
90
+ style?: React.CSSProperties;
91
+ id?: string;
92
+ }
93
+
94
+ interface AvatarOption {
95
+ value: string | number;
96
+ label: string;
97
+ colorHex?: string;
98
+ imageUrl?: string;
99
+ }
100
+ interface AvatarSection {
101
+ id: string;
102
+ label: string;
103
+ type: 'select' | 'color' | 'slider';
104
+ options: AvatarOption[];
105
+ defaultValue: any;
106
+ group?: string;
107
+ description?: string;
108
+ hidden?: boolean;
109
+ }
110
+ declare const REACT_NICE_AVATAR_SECTIONS: AvatarSection[];
111
+
112
+ /**
113
+ * Utility to extract fully rendered SVG and high-resolution PNG data URLs from the avatar DOM node.
114
+ */
115
+ declare function getAvatarData(elementId: string): Promise<{
116
+ svg: string;
117
+ pngDataUrl: string;
118
+ } | null>;
119
+ /**
120
+ * Utility to download the avatar DOM node directly as a PNG.
121
+ */
122
+ declare function downloadAvatarAsPng(elementId: string, filename?: string): Promise<void>;
123
+
124
+ interface UseAvatarCustomizeProps {
125
+ value?: AvatarConfig;
126
+ defaultValue?: AvatarConfig;
127
+ onChange?: (config: AvatarConfig) => void;
128
+ hiddenSections?: string[];
129
+ sectionOrder?: string[];
130
+ }
131
+ declare function useAvatarCustomize({ value, defaultValue, onChange, hiddenSections, sectionOrder, }: UseAvatarCustomizeProps): {
132
+ config: AvatarConfig;
133
+ sections: AvatarSection[];
134
+ activeSectionId: string | null;
135
+ setActiveSectionId: react.Dispatch<react.SetStateAction<string | null>>;
136
+ updateConfig: (newConfigPartial: Partial<AvatarConfig>) => void;
137
+ handleOptionChange: (sectionId: string, value: any) => void;
138
+ randomize: () => void;
139
+ reset: () => void;
140
+ };
141
+
142
+ declare function AvatarPreview({ config, className, style, id }: AvatarPreviewProps): react_jsx_runtime.JSX.Element;
143
+
144
+ declare function AvatarCustomizeInline(props: AvatarCustomizeProps): react_jsx_runtime.JSX.Element;
145
+
146
+ declare function AvatarCustomizeModal(props: AvatarCustomizeModalProps): react_jsx_runtime.JSX.Element | null;
147
+
148
+ export { type AvatarCustomizeClassNames, type AvatarCustomizeComponents, AvatarCustomizeInline, AvatarCustomizeModal, type AvatarCustomizeModalProps, type AvatarCustomizeProps, type AvatarCustomizeSlotProps, type AvatarExportData, type AvatarOption, AvatarPreview, type AvatarPreviewProps, type AvatarSection, type AvatarStudioClasses, type AvatarStudioTheme, REACT_NICE_AVATAR_SECTIONS, type UseAvatarCustomizeProps, downloadAvatarAsPng, getAvatarData, useAvatarCustomize };
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ "use strict";var la=Object.create;var D=Object.defineProperty;var ca=Object.getOwnPropertyDescriptor;var da=Object.getOwnPropertyNames;var pa=Object.getPrototypeOf,ma=Object.prototype.hasOwnProperty;var ua=(r,a)=>()=>(r&&(a=r(r=0)),a);var J=(r,a)=>{for(var e in a)D(r,e,{get:a[e],enumerable:!0})},Q=(r,a,e,o)=>{if(a&&typeof a=="object"||typeof a=="function")for(let t of da(a))!ma.call(r,t)&&t!==e&&D(r,t,{get:()=>a[t],enumerable:!(o=ca(a,t))||o.enumerable});return r};var va=(r,a,e)=>(e=r!=null?la(pa(r)):{},Q(a||!r||!r.__esModule?D(e,"default",{value:r,enumerable:!0}):e,r)),fa=r=>Q(D({},"__esModule",{value:!0}),r);var U={};J(U,{downloadAvatarAsPng:()=>X,getAvatarData:()=>W});async function W(r){let a=document.getElementById(r);if(!a)return console.error(`Avatar node with id "${r}" not found.`),null;let e=a.offsetWidth,o=a.offsetHeight,t=a.innerHTML,n=`
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="${e}" height="${o}">
3
+ <foreignObject width="100%" height="100%">
4
+ <div xmlns="http://www.w3.org/1999/xhtml" style="width:100%;height:100%;">
5
+ <style>
6
+ * { box-sizing: content-box !important; }
7
+ svg { display: inline !important; max-width: none !important; max-height: none !important; margin: 0; padding: 0; transform-origin: center center; }
8
+ </style>
9
+ ${t}
10
+ </div>
11
+ </foreignObject>
12
+ </svg>
13
+ `;return new Promise(d=>{let c=new Image;c.src="data:image/svg+xml;charset=utf-8,"+encodeURIComponent(n.trim()),c.onload=()=>{let s=document.createElement("canvas"),u=2;s.width=e*u,s.height=o*u;let i=s.getContext("2d");if(i){i.scale(u,u),i.drawImage(c,0,0);let v=s.toDataURL("image/png");d({svg:t,pngDataUrl:v})}else d(null)},c.onerror=s=>{console.error("Failed to generate PNG from Avatar HTML:",s),d(null)}})}async function X(r,a="avatar.png"){let e=await W(r);if(e){let o=document.createElement("a");o.download=a,o.href=e.pngDataUrl,o.click()}}var E=ua(()=>{"use strict"});var ba={};J(ba,{AvatarCustomizeInline:()=>q,AvatarCustomizeModal:()=>ga,AvatarPreview:()=>_,REACT_NICE_AVATAR_SECTIONS:()=>V,downloadAvatarAsPng:()=>X,getAvatarData:()=>W,useAvatarCustomize:()=>G});module.exports=fa(ba);var V=[{id:"sex",label:"Sex",type:"select",group:"Face & Body",options:[{value:"man",label:"Man"},{value:"woman",label:"Woman"}],defaultValue:"man"},{id:"faceColor",label:"Face Color",type:"color",group:"Face & Body",options:[{value:"#F9C9B6",label:"Light",colorHex:"#F9C9B6"},{value:"#AC6651",label:"Dark",colorHex:"#AC6651"}],defaultValue:"#F9C9B6"},{id:"earSize",label:"Ear Size",type:"select",group:"Face & Body",options:[{value:"small",label:"Small"},{value:"big",label:"Big"}],defaultValue:"small"},{id:"hairColor",label:"Hair Color",type:"color",group:"Hair",options:[{value:"#000",label:"Black",colorHex:"#000"},{value:"#fff",label:"White",colorHex:"#fff"},{value:"#77311D",label:"Brown",colorHex:"#77311D"},{value:"#FC909F",label:"Pink",colorHex:"#FC909F"},{value:"#D2EFF3",label:"Light Blue",colorHex:"#D2EFF3"},{value:"#506AF4",label:"Blue",colorHex:"#506AF4"},{value:"#F48150",label:"Orange",colorHex:"#F48150"}],defaultValue:"#000"},{id:"hairStyle",label:"Hair Style",type:"select",group:"Hair",options:[{value:"normal",label:"Normal"},{value:"thick",label:"Thick"},{value:"mohawk",label:"Mohawk"},{value:"womanLong",label:"Long"},{value:"womanShort",label:"Short"}],defaultValue:"normal"},{id:"hatStyle",label:"Hat Style",type:"select",group:"Accessories",options:[{value:"none",label:"None"},{value:"beanie",label:"Beanie"},{value:"turban",label:"Turban"}],defaultValue:"none"},{id:"hatColor",label:"Hat Color",type:"color",group:"Accessories",options:[{value:"#000",label:"Black",colorHex:"#000"},{value:"#fff",label:"White",colorHex:"#fff"},{value:"#77311D",label:"Brown",colorHex:"#77311D"},{value:"#FC909F",label:"Pink",colorHex:"#FC909F"},{value:"#D2EFF3",label:"Light Blue",colorHex:"#D2EFF3"},{value:"#506AF4",label:"Blue",colorHex:"#506AF4"},{value:"#F48150",label:"Orange",colorHex:"#F48150"}],defaultValue:"#000"},{id:"eyeStyle",label:"Eye Style",type:"select",group:"Face & Body",options:[{value:"circle",label:"Circle"},{value:"oval",label:"Oval"},{value:"smile",label:"Smile"}],defaultValue:"circle"},{id:"glassesStyle",label:"Glasses Style",type:"select",group:"Accessories",options:[{value:"none",label:"None"},{value:"round",label:"Round"},{value:"square",label:"Square"}],defaultValue:"none"},{id:"noseStyle",label:"Nose Style",type:"select",group:"Face & Body",options:[{value:"short",label:"Short"},{value:"long",label:"Long"},{value:"round",label:"Round"}],defaultValue:"short"},{id:"mouthStyle",label:"Mouth Style",type:"select",group:"Face & Body",options:[{value:"laugh",label:"Laugh"},{value:"smile",label:"Smile"},{value:"peace",label:"Peace"}],defaultValue:"smile"},{id:"shirtStyle",label:"Shirt Style",type:"select",group:"Clothing",options:[{value:"hoody",label:"Hoody"},{value:"short",label:"Short"},{value:"polo",label:"Polo"}],defaultValue:"short"},{id:"shirtColor",label:"Shirt Color",type:"color",group:"Clothing",options:[{value:"#9287FF",label:"Purple",colorHex:"#9287FF"},{value:"#6BD9E9",label:"Light Blue",colorHex:"#6BD9E9"},{value:"#FC909F",label:"Pink",colorHex:"#FC909F"},{value:"#F4D150",label:"Yellow",colorHex:"#F4D150"},{value:"#77311D",label:"Brown",colorHex:"#77311D"}],defaultValue:"#9287FF"},{id:"bgColor",label:"Background",type:"color",group:"Background",options:[{value:"#9287FF",label:"Purple",colorHex:"#9287FF"},{value:"#6BD9E9",label:"Light Blue",colorHex:"#6BD9E9"},{value:"#FC909F",label:"Pink",colorHex:"#FC909F"},{value:"#F4D150",label:"Yellow",colorHex:"#F4D150"},{value:"#E0DDFF",label:"Light Purple",colorHex:"#E0DDFF"},{value:"#D2EFF3",label:"Ice",colorHex:"#D2EFF3"},{value:"#FFEDEF",label:"Light Pink",colorHex:"#FFEDEF"},{value:"#FFEBA4",label:"Light Yellow",colorHex:"#FFEBA4"},{value:"#506AF4",label:"Blue",colorHex:"#506AF4"},{value:"#F48150",label:"Orange",colorHex:"#F48150"},{value:"#74D153",label:"Green",colorHex:"#74D153"}],defaultValue:"#E0DDFF"}];E();var w=require("react"),O=require("react-nice-avatar");function G({value:r,defaultValue:a,onChange:e,hiddenSections:o=[],sectionOrder:t=[]}){let n=r!==void 0,[d,c]=(0,w.useState)(()=>r??a??(0,O.genConfig)()),[s,u]=(0,w.useState)(null),i=n?r:d,m=[...V.filter(l=>!l.hidden&&!o.includes(l.id))].sort((l,b)=>{if(t.length===0)return 0;let h=t.indexOf(l.id),F=t.indexOf(b.id);return h===-1&&F===-1?0:h===-1?1:F===-1?-1:h-F});(0,w.useEffect)(()=>{!s&&m.length>0&&u(m[0].id)},[m,s]);let y=(0,w.useCallback)(l=>{let b={...i,...l};n||c(b),e?.(b)},[i,n,e]),g=(0,w.useCallback)(()=>{let l=(0,O.genConfig)({isRandom:!0});n||c(l),e?.(l)},[n,e]),x=(0,w.useCallback)(()=>{let l=a??(0,O.genConfig)();n||c(l),e?.(l)},[a,n,e]),C=(0,w.useCallback)((l,b)=>{y({[l]:b})},[y]);return{config:i,sections:m,activeSectionId:s,setActiveSectionId:u,updateConfig:y,handleOptionChange:C,randomize:g,reset:x}}var R=va(require("react-nice-avatar")),$=require("react/jsx-runtime");function _({config:r,className:a,style:e,id:o}){let t=r||(0,R.genConfig)();return(0,$.jsx)("div",{id:o,className:`ras-preview ${a||""}`,style:e,children:(0,$.jsx)(R.default,{style:{width:"100%",height:"100%"},...t})})}var P=require("react");var Z=require("react");function aa(r){return(0,Z.useMemo)(()=>{if(!r||typeof r=="string")return{};let a=r,e={...a};return a.primary&&(e["--avatar-customize-primary"]=a.primary),a.bg&&(e["--avatar-customize-bg"]=a.bg),a.surface&&(e["--avatar-customize-option-bg"]=a.surface),a.border&&(e["--avatar-customize-border"]=a.border),a.textMain&&(e["--avatar-customize-text"]=a.textMain),a.textMuted&&(e["--avatar-customize-muted"]=a.textMuted),e},[r])}function p(...r){return r.filter(Boolean).join(" ")||void 0}var A=require("react/jsx-runtime");function ea({config:r,randomize:a,unstyled:e,classes:o,classNames:t,components:n,slots:d,slotProps:c}){let u=(n||d)?.PreviewWrapper||"div",i=c?.previewWrapper||{},v=c?.randomizeButton||{},f=c?.downloadButton||{},m=e?"":"ras-preview-wrapper",y=e?"":"ras-btn ras-btn-secondary ras-download-btn";return(0,A.jsxs)("div",{className:p(e?void 0:"ras-avatar-column",o?.avatarColumn),children:[(0,A.jsx)(u,{...i,className:p(m,o?.previewWrapper,t?.preview,i.className),style:i.style,children:(0,A.jsx)(_,{config:r,id:"ras-avatar-download-target",className:"ras-preview-large"})}),(0,A.jsxs)("div",{className:p(e?void 0:"ras-avatar-actions",t?.actionBar),children:[(0,A.jsxs)("button",{...v,className:p(e?void 0:"ras-btn ras-btn-secondary ras-randomize-btn",o?.actionBtn,v.className),onClick:g=>{a(),v.onClick&&v.onClick(g)},children:[(0,A.jsx)("span",{className:e?"":"ras-btn-icon",children:"\u{1F3B2}"})," Randomize"]}),(0,A.jsxs)("button",{...f,className:p(y,o?.actionBtn,f.className),onClick:g=>{Promise.resolve().then(()=>(E(),U)).then(x=>x.downloadAvatarAsPng("ras-avatar-download-target","my-avatar.png")),f.onClick&&f.onClick(g)},children:[(0,A.jsx)("span",{className:e?"":"ras-btn-icon",children:"\u2B07\uFE0F"})," Download"]})]})]})}var L=require("react/jsx-runtime");function ra({categories:r,activeCategory:a,setActiveCategory:e,layout:o,unstyled:t,classes:n,classNames:d,slotProps:c}){if(r.length<=1||o==="accordion")return null;let s=c?.categoryTab||{},u=t?"":"ras-category-tab";return(0,L.jsx)("div",{className:p(t?void 0:"ras-category-nav-wrapper",n?.categoryNav,d?.sectionNav),children:(0,L.jsx)("div",{className:t?"":"ras-category-nav",children:r.map(i=>(0,L.jsx)("button",{...s,className:p(u,a===i?"active":void 0,n?.categoryTab,s.className),onClick:v=>{e(i),s.onClick&&s.onClick(v)},children:i},i))})})}var S=require("react/jsx-runtime");function oa({config:r,section:a,handleOptionChange:e,unstyled:o,columns:t,classes:n,classNames:d,components:c,slots:s,slotProps:u}){let i=c||s,v=i?.OptionButton||i?.Button||"button",f=u?.optionButton||{},m=u?.colorButton||{},y=o?"":"ras-options-grid",g=o?"":"ras-option-btn",x=o?"":"ras-color-btn",C=t?{gridTemplateColumns:`repeat(${t}, minmax(0, 1fr))`}:void 0;return(0,S.jsx)("div",{className:p(y,a.type==="color"&&!o?"ras-options-color":void 0,n?.optionsGrid),style:C,children:a.options.map(l=>{let b=r[a.id]===l.value;return a.type==="color"?(0,S.jsx)(v,{...m,className:p(x,b?"active":void 0,n?.colorBtn,d?.optionButton,m.className),style:{backgroundColor:l.colorHex||String(l.value),...m.style},onClick:h=>{e(a.id,l.value),m.onClick&&m.onClick(h)},title:l.label,"aria-label":l.label,"aria-pressed":b,children:b&&(0,S.jsx)("span",{className:o?"":"ras-color-check",children:(0,S.jsx)("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round",strokeLinejoin:"round",children:(0,S.jsx)("polyline",{points:"20 6 9 17 4 12"})})})},String(l.value)):(0,S.jsx)(v,{...f,className:p(g,b?"active":void 0,n?.optionBtn,d?.optionButton,f.className),onClick:h=>{e(a.id,l.value),f.onClick&&f.onClick(h)},"aria-pressed":b,children:l.label},String(l.value))})})}var z=require("react/jsx-runtime");function ta({config:r,section:a,handleOptionChange:e,unstyled:o,labels:t,sectionOptionOverrides:n,classes:d,classNames:c,components:s,slots:u,slotProps:i,columns:v}){let f=s||u,m=f?.SectionWrapper||"div",y=f?.SectionHeader||"div",g=i?.sectionWrapper||{},x=i?.sectionHeader||{},C=o?"":"ras-section-block",l=o?"":"ras-section-header",b=o?"":"ras-section-title",h=o?"":"ras-section-desc",F=n?.[a.id],I=F?{...a,options:a.options.filter(M=>F.includes(M.value))}:a;return(0,z.jsxs)(m,{...g,className:p(C,d?.sectionBlock,g.className),children:[(0,z.jsxs)(y,{...x,className:p(l,x.className),children:[(0,z.jsx)("h3",{className:p(b,d?.sectionTitle),children:t?.[a.id]||a.label}),a.description&&(0,z.jsx)("p",{className:h,children:a.description})]}),(0,z.jsx)(oa,{config:r,section:I,handleOptionChange:e,unstyled:o,columns:v,classes:d,classNames:c,components:s,slots:u,slotProps:i})]})}var Y=require("react/jsx-runtime");function na({config:r,displaySections:a,handleOptionChange:e,unstyled:o,classes:t,classNames:n,components:d,slots:c,slotProps:s,labels:u,sectionOptionOverrides:i,columns:v,cx:f}){return(0,Y.jsx)("div",{className:o?"":"ras-category-content",children:a.map(m=>(0,Y.jsx)(ta,{config:r,section:m,handleOptionChange:e,unstyled:o,columns:v,classes:t,classNames:n,components:d,slots:c,slotProps:s,labels:u,sectionOptionOverrides:i},m.id))})}var H=require("react/jsx-runtime");function sa({config:r,onCancel:a,onSave:e,unstyled:o,classes:t,classNames:n,components:d,slots:c,slotProps:s}){if(!a&&!e)return null;let i=(d||c)?.Footer||"div",v=s?.footer||{},f=s?.saveButton||{},m=s?.cancelButton||{},y=o?"":"ras-footer-actions",g=o?"":"ras-btn ras-btn-ghost",x=o?"":"ras-btn ras-btn-primary";return(0,H.jsxs)(i,{...v,className:p(y,t?.footer,n?.actionBar,v.className),children:[a&&(0,H.jsx)("button",{...m,className:p(g,t?.actionBtn,m.className),onClick:C=>{a(),m.onClick&&m.onClick(C)},children:"Cancel"}),e&&(0,H.jsx)("button",{...f,className:p(x,t?.actionBtn,f.className),onClick:async C=>{let b=await(await Promise.resolve().then(()=>(E(),U))).getAvatarData("ras-avatar-download-target");e(r,{config:r,svg:b?.svg||"",pngDataUrl:b?.pngDataUrl||""}),f.onClick&&f.onClick(C)},children:"Save Avatar"})]})}function j(r,{insertAt:a}={}){if(!r||typeof document>"u")return;let e=document.head||document.getElementsByTagName("head")[0],o=document.createElement("style");o.type="text/css",a==="top"&&e.firstChild?e.insertBefore(o,e.firstChild):e.appendChild(o),o.styleSheet?o.styleSheet.cssText=r:o.appendChild(document.createTextNode(r))}j(`:root,.ras-theme-light{--avatar-customize-bg: #ffffff;--avatar-customize-border: #e9ecef;--avatar-customize-radius: 12px;--avatar-customize-text: #212529;--avatar-customize-muted: #868e96;--avatar-customize-primary: #aa3bff;--avatar-customize-primary-text: #ffffff;--avatar-customize-option-bg: #f8f9fa;--avatar-customize-option-active-bg: #aa3bff;--avatar-customize-option-active-border: #aa3bff;--avatar-customize-overlay: rgba(0, 0, 0, .4);--ras-primary: var(--avatar-customize-primary);--ras-primary-hover: #9b2cee;--ras-bg: var(--avatar-customize-bg);--ras-surface: var(--avatar-customize-option-bg);--ras-surface-hover: #f1f3f5;--ras-border: var(--avatar-customize-border);--ras-text-main: var(--avatar-customize-text);--ras-text-muted: var(--avatar-customize-muted);--ras-shadow-sm: 0 1px 3px rgba(0,0,0,.05);--ras-shadow-md: 0 4px 12px rgba(0,0,0,.08);--ras-shadow-lg: 0 12px 24px rgba(0,0,0,.12);--ras-radius-sm: 8px;--ras-radius-md: var(--avatar-customize-radius);--ras-radius-lg: 16px;--ras-radius-full: 9999px;--ras-transition: all .2s cubic-bezier(.4, 0, .2, 1);--ras-font: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif}.ras-theme-dark{--avatar-customize-bg: #18181b;--avatar-customize-border: #3f3f46;--avatar-customize-radius: 12px;--avatar-customize-text: #fafafa;--avatar-customize-muted: #a1a1aa;--avatar-customize-primary: #8b5cf6;--avatar-customize-primary-text: #ffffff;--avatar-customize-option-bg: #27272a;--avatar-customize-option-active-bg: #8b5cf6;--avatar-customize-option-active-border: #8b5cf6;--avatar-customize-overlay: rgba(0, 0, 0, .7);--ras-primary-hover: #7c3aed;--ras-surface-hover: #3f3f46;--ras-shadow-sm: 0 1px 3px rgba(0,0,0,.3);--ras-shadow-md: 0 4px 12px rgba(0,0,0,.4);--ras-shadow-lg: 0 12px 24px rgba(0,0,0,.5)}.ras-container{font-family:var(--ras-font);background:var(--ras-bg);color:var(--ras-text-main);border-radius:var(--ras-radius-lg);box-shadow:var(--ras-shadow-lg);overflow:hidden;max-width:1000px;margin:0 auto;border:1px solid var(--ras-border)}.ras-layout{display:flex;flex-direction:column}@media(min-width:768px){.ras-layout{flex-direction:row;min-height:500px}}.ras-avatar-column{flex:0 0 auto;padding:2rem;background:var(--ras-surface);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1.5rem;border-bottom:1px solid var(--ras-border)}@media(min-width:768px){.ras-avatar-column{width:340px;border-bottom:none;border-right:1px solid var(--ras-border)}}.ras-preview-wrapper{background:var(--ras-bg);padding:1.5rem;border-radius:var(--ras-radius-lg);box-shadow:var(--ras-shadow-md);transition:transform .3s ease}.ras-preview-wrapper:hover{transform:translateY(-4px)}.ras-preview-large{width:180px;height:180px;min-width:180px;min-height:180px;flex-shrink:0}.ras-preview div,.ras-preview svg,.ras-preview path{box-sizing:content-box!important;max-width:none!important;max-height:none!important;margin:0;padding:0;line-height:normal}.ras-preview svg{transform-origin:center center}.ras-avatar-actions{display:flex;width:100%;gap:.75rem}.ras-settings-column{flex:1 1 auto;display:flex;flex-direction:column;max-height:600px;background:var(--ras-bg)}.ras-category-nav-wrapper{padding:1rem 1.5rem 0;border-bottom:1px solid var(--ras-border);background:var(--ras-bg);z-index:10}.ras-category-nav{display:flex;gap:.5rem;overflow-x:auto;padding-bottom:1rem;scrollbar-width:none}.ras-category-nav::-webkit-scrollbar{display:none}.ras-category-tab{background:transparent;border:none;padding:.5rem 1rem;font-size:.95rem;font-weight:600;color:var(--ras-text-muted);cursor:pointer;border-radius:var(--ras-radius-full);white-space:nowrap;transition:var(--ras-transition)}.ras-category-tab:hover{color:var(--ras-text-main);background:var(--ras-surface)}.ras-category-tab.active{color:#fff;background:var(--ras-primary);box-shadow:0 2px 8px #aa3bff66}.ras-category-content{flex:1;overflow-y:auto;padding:1.5rem;display:flex;flex-direction:column;gap:2rem}.ras-category-content::-webkit-scrollbar{width:6px}.ras-category-content::-webkit-scrollbar-track{background:transparent}.ras-category-content::-webkit-scrollbar-thumb{background:var(--ras-border);border-radius:10px}.ras-category-content::-webkit-scrollbar-thumb:hover{background:var(--ras-text-muted)}.ras-section-block{display:flex;flex-direction:column;gap:.75rem}.ras-section-header{display:flex;flex-direction:column;gap:.25rem}.ras-section-title{margin:0;font-size:1rem;font-weight:600;color:var(--ras-text-main)}.ras-section-desc{margin:0;font-size:.85rem;color:var(--ras-text-muted)}.ras-options-grid{display:flex;flex-wrap:wrap;gap:.5rem}.ras-options-color{gap:.75rem}.ras-option-btn{background:var(--ras-surface);border:1px solid var(--ras-border);color:var(--ras-text-main);padding:.5rem 1rem;border-radius:var(--ras-radius-full);font-size:.9rem;font-weight:500;cursor:pointer;transition:var(--ras-transition)}.ras-option-btn:hover{background:var(--ras-surface-hover);border-color:var(--ras-text-muted)}.ras-option-btn.active{background:var(--ras-primary);border-color:var(--ras-primary);color:#fff;box-shadow:0 2px 6px #aa3bff4d}.ras-color-btn{width:36px;height:36px;border-radius:50%;border:2px solid transparent;cursor:pointer;transition:var(--ras-transition);position:relative;display:flex;align-items:center;justify-content:center;box-shadow:var(--ras-shadow-sm);padding:0}.ras-color-btn:hover{transform:scale(1.1);box-shadow:var(--ras-shadow-md)}.ras-color-btn.active{border-color:var(--ras-primary);transform:scale(1.1)}.ras-color-check{color:#ffffffe6;width:18px;height:18px;display:flex;align-items:center;justify-content:center;text-shadow:0 1px 2px rgba(0,0,0,.5);mix-blend-mode:difference}.ras-footer-actions{padding:1.25rem 1.5rem;border-top:1px solid var(--ras-border);background:var(--ras-surface);display:flex;justify-content:flex-end;gap:1rem}.ras-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;padding:.75rem 1.5rem;border-radius:var(--ras-radius-full);font-size:.95rem;font-weight:600;cursor:pointer;transition:var(--ras-transition);border:none;font-family:inherit}.ras-btn-primary{background:var(--ras-primary);color:#fff;box-shadow:0 4px 12px #aa3bff4d}.ras-btn-primary:hover{background:var(--ras-primary-hover);transform:translateY(-1px);box-shadow:0 6px 16px #aa3bff66}.ras-btn-secondary{background:var(--ras-bg);color:var(--ras-text-main);border:1px solid var(--ras-border);box-shadow:var(--ras-shadow-sm);width:100%}.ras-btn-secondary:hover{background:var(--ras-surface);border-color:var(--ras-text-muted)}.ras-btn-ghost{background:transparent;color:var(--ras-text-muted)}.ras-btn-ghost:hover{background:var(--ras-surface);color:var(--ras-text-main)}.ras-container[data-preview=top] .ras-layout{flex-direction:column}.ras-container[data-preview=bottom] .ras-layout{flex-direction:column-reverse}@media(min-width:768px){.ras-container[data-preview=left] .ras-layout{flex-direction:row}.ras-container[data-preview=right] .ras-layout{flex-direction:row-reverse}.ras-container[data-preview=right] .ras-avatar-column{border-right:none;border-left:1px solid var(--ras-border)}}
14
+ `);var k=require("react/jsx-runtime");function q(r){let{config:a,sections:e,handleOptionChange:o,randomize:t}=G(r),{theme:n,classes:d,classNames:c,style:s,className:u,unstyled:i=!1,layout:v="sidebar",previewPosition:f="left"}=r,m=aa(n),y={...s,...m},g=(0,P.useMemo)(()=>{let N=[];return e.forEach(ia=>{let K=ia.group||"General";N.includes(K)||N.push(K)}),N},[e]),[x,C]=(0,P.useState)(g[0]||"General");(0,P.useEffect)(()=>{g.length>0&&!g.includes(x)&&C(g[0])},[g,x]);let l=(0,P.useMemo)(()=>e.filter(N=>(N.group||"General")===x),[e,x]),b=v==="accordion"?e:l,h=r.slotProps?.root||{},F=i?"":`ras-container ${n==="dark"?"ras-theme-dark":"ras-theme-light"}`,I=i?"":"ras-layout",M=i?"":"ras-settings-column";return(0,k.jsx)("div",{...h,className:p(F,u,d?.container,c?.root,h.className),style:{...y,...h.style},"data-layout":v,"data-preview":f,children:(0,k.jsxs)("div",{className:I,children:[(0,k.jsx)(ea,{...r,config:a,randomize:t}),(0,k.jsxs)("div",{className:p(M,d?.settingsColumn),children:[(0,k.jsx)(ra,{...r,categories:g,activeCategory:x,setActiveCategory:C}),(0,k.jsx)(na,{...r,config:a,displaySections:b,handleOptionChange:o,cx:p}),(0,k.jsx)(sa,{...r,config:a})]})]})})}var T=require("react");var B=require("react/jsx-runtime");function ga(r){let{open:a,onClose:e,modalClassName:o,overlayClassName:t,...n}=r,d=(0,T.useRef)(null);return(0,T.useEffect)(()=>{let c=s=>{s.key==="Escape"&&a&&e()};return a?(document.addEventListener("keydown",c),document.body.style.overflow="hidden"):document.body.style.overflow="",()=>{document.removeEventListener("keydown",c),document.body.style.overflow=""}},[a,e]),a?(0,B.jsxs)("div",{className:`ras-modal-overlay ${t||""}`,children:[(0,B.jsx)("div",{className:"ras-modal-backdrop",onClick:e,"aria-hidden":"true"}),(0,B.jsx)("div",{className:`ras-modal-content ${o||""}`,ref:d,role:"dialog","aria-modal":"true",children:(0,B.jsx)("div",{className:"ras-modal-body",children:(0,B.jsx)(q,{...n,onCancel:()=>{n.onCancel&&n.onCancel(),e()},onSave:(c,s)=>{n.onSave&&n.onSave(c,s),e()}})})})]}):null}0&&(module.exports={AvatarCustomizeInline,AvatarCustomizeModal,AvatarPreview,REACT_NICE_AVATAR_SECTIONS,downloadAvatarAsPng,getAvatarData,useAvatarCustomize});
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/avatarHelpers.ts","../src/index.ts","../src/constants/avatarSections.ts","../src/hooks/useAvatarCustomize.ts","../src/components/AvatarPreview.tsx","../src/components/AvatarCustomizeInline.tsx","../src/hooks/useThemeStyles.ts","../src/utils/cx.ts","../src/components/AvatarPreviewColumn.tsx","../src/components/AvatarCategoryNav.tsx","../src/components/AvatarOptionGrid.tsx","../src/components/AvatarSection.tsx","../src/components/AvatarSectionList.tsx","../src/components/AvatarFooterActions.tsx","#style-inject:#style-inject","../src/styles/index.css","../src/components/AvatarCustomizeModal.tsx"],"sourcesContent":["/**\n * Utility to extract fully rendered SVG and high-resolution PNG data URLs from the avatar DOM node.\n */\nexport async function getAvatarData(elementId: string): Promise<{ svg: string; pngDataUrl: string } | null> {\n const node = document.getElementById(elementId);\n if (!node) {\n console.error(`Avatar node with id \"${elementId}\" not found.`);\n return null;\n }\n \n const width = node.offsetWidth;\n const height = node.offsetHeight;\n const rawHtml = node.innerHTML;\n \n const data = `\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\">\n <foreignObject width=\"100%\" height=\"100%\">\n <div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"width:100%;height:100%;\">\n <style>\n * { box-sizing: content-box !important; }\n svg { display: inline !important; max-width: none !important; max-height: none !important; margin: 0; padding: 0; transform-origin: center center; }\n </style>\n ${rawHtml}\n </div>\n </foreignObject>\n </svg>\n `;\n \n return new Promise((resolve) => {\n const img = new Image();\n img.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(data.trim());\n \n img.onload = () => {\n const canvas = document.createElement('canvas');\n const scale = 2; // 2x resolution\n canvas.width = width * scale;\n canvas.height = height * scale;\n \n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.scale(scale, scale);\n ctx.drawImage(img, 0, 0);\n const pngDataUrl = canvas.toDataURL('image/png');\n resolve({ svg: rawHtml, pngDataUrl });\n } else {\n resolve(null);\n }\n };\n \n img.onerror = (e) => {\n console.error('Failed to generate PNG from Avatar HTML:', e);\n resolve(null);\n };\n });\n}\n\n/**\n * Utility to download the avatar DOM node directly as a PNG.\n */\nexport async function downloadAvatarAsPng(elementId: string, filename = 'avatar.png') {\n const data = await getAvatarData(elementId);\n if (data) {\n const a = document.createElement('a');\n a.download = filename;\n a.href = data.pngDataUrl;\n a.click();\n }\n}\n","export * from './types';\nexport * from './constants/avatarSections';\nexport * from './utils/avatarHelpers';\nexport * from './hooks/useAvatarCustomize';\nexport * from './components/AvatarPreview';\nexport * from './components/AvatarCustomizeInline';\nexport * from './components/AvatarCustomizeModal';\n\nimport './styles/index.css';\n","export interface AvatarOption {\n value: string | number;\n label: string;\n colorHex?: string; // Optional hex for color palettes\n imageUrl?: string; // Optional image preview\n}\n\nexport interface AvatarSection {\n id: string; // Key in the config state\n label: string; // Display name\n type: 'select' | 'color' | 'slider';\n options: AvatarOption[];\n defaultValue: any;\n group?: string; // Category like 'Face', 'Hair', 'Clothing'\n description?: string;\n hidden?: boolean;\n}\n\nexport const REACT_NICE_AVATAR_SECTIONS: AvatarSection[] = [\n {\n id: 'sex',\n label: 'Sex',\n type: 'select',\n group: 'Face & Body',\n options: [\n { value: 'man', label: 'Man' },\n { value: 'woman', label: 'Woman' },\n ],\n defaultValue: 'man',\n },\n {\n id: 'faceColor',\n label: 'Face Color',\n type: 'color',\n group: 'Face & Body',\n options: [\n { value: '#F9C9B6', label: 'Light', colorHex: '#F9C9B6' },\n { value: '#AC6651', label: 'Dark', colorHex: '#AC6651' },\n ],\n defaultValue: '#F9C9B6',\n },\n {\n id: 'earSize',\n label: 'Ear Size',\n type: 'select',\n group: 'Face & Body',\n options: [\n { value: 'small', label: 'Small' },\n { value: 'big', label: 'Big' },\n ],\n defaultValue: 'small',\n },\n {\n id: 'hairColor',\n label: 'Hair Color',\n type: 'color',\n group: 'Hair',\n options: [\n { value: '#000', label: 'Black', colorHex: '#000' },\n { value: '#fff', label: 'White', colorHex: '#fff' },\n { value: '#77311D', label: 'Brown', colorHex: '#77311D' },\n { value: '#FC909F', label: 'Pink', colorHex: '#FC909F' },\n { value: '#D2EFF3', label: 'Light Blue', colorHex: '#D2EFF3' },\n { value: '#506AF4', label: 'Blue', colorHex: '#506AF4' },\n { value: '#F48150', label: 'Orange', colorHex: '#F48150' },\n ],\n defaultValue: '#000',\n },\n {\n id: 'hairStyle',\n label: 'Hair Style',\n type: 'select',\n group: 'Hair',\n options: [\n { value: 'normal', label: 'Normal' },\n { value: 'thick', label: 'Thick' },\n { value: 'mohawk', label: 'Mohawk' },\n { value: 'womanLong', label: 'Long' },\n { value: 'womanShort', label: 'Short' },\n ],\n defaultValue: 'normal',\n },\n {\n id: 'hatStyle',\n label: 'Hat Style',\n type: 'select',\n group: 'Accessories',\n options: [\n { value: 'none', label: 'None' },\n { value: 'beanie', label: 'Beanie' },\n { value: 'turban', label: 'Turban' },\n ],\n defaultValue: 'none',\n },\n {\n id: 'hatColor',\n label: 'Hat Color',\n type: 'color',\n group: 'Accessories',\n options: [\n { value: '#000', label: 'Black', colorHex: '#000' },\n { value: '#fff', label: 'White', colorHex: '#fff' },\n { value: '#77311D', label: 'Brown', colorHex: '#77311D' },\n { value: '#FC909F', label: 'Pink', colorHex: '#FC909F' },\n { value: '#D2EFF3', label: 'Light Blue', colorHex: '#D2EFF3' },\n { value: '#506AF4', label: 'Blue', colorHex: '#506AF4' },\n { value: '#F48150', label: 'Orange', colorHex: '#F48150' },\n ],\n defaultValue: '#000',\n },\n {\n id: 'eyeStyle',\n label: 'Eye Style',\n type: 'select',\n group: 'Face & Body',\n options: [\n { value: 'circle', label: 'Circle' },\n { value: 'oval', label: 'Oval' },\n { value: 'smile', label: 'Smile' },\n ],\n defaultValue: 'circle',\n },\n {\n id: 'glassesStyle',\n label: 'Glasses Style',\n type: 'select',\n group: 'Accessories',\n options: [\n { value: 'none', label: 'None' },\n { value: 'round', label: 'Round' },\n { value: 'square', label: 'Square' },\n ],\n defaultValue: 'none',\n },\n {\n id: 'noseStyle',\n label: 'Nose Style',\n type: 'select',\n group: 'Face & Body',\n options: [\n { value: 'short', label: 'Short' },\n { value: 'long', label: 'Long' },\n { value: 'round', label: 'Round' },\n ],\n defaultValue: 'short',\n },\n {\n id: 'mouthStyle',\n label: 'Mouth Style',\n type: 'select',\n group: 'Face & Body',\n options: [\n { value: 'laugh', label: 'Laugh' },\n { value: 'smile', label: 'Smile' },\n { value: 'peace', label: 'Peace' },\n ],\n defaultValue: 'smile',\n },\n {\n id: 'shirtStyle',\n label: 'Shirt Style',\n type: 'select',\n group: 'Clothing',\n options: [\n { value: 'hoody', label: 'Hoody' },\n { value: 'short', label: 'Short' },\n { value: 'polo', label: 'Polo' },\n ],\n defaultValue: 'short',\n },\n {\n id: 'shirtColor',\n label: 'Shirt Color',\n type: 'color',\n group: 'Clothing',\n options: [\n { value: '#9287FF', label: 'Purple', colorHex: '#9287FF' },\n { value: '#6BD9E9', label: 'Light Blue', colorHex: '#6BD9E9' },\n { value: '#FC909F', label: 'Pink', colorHex: '#FC909F' },\n { value: '#F4D150', label: 'Yellow', colorHex: '#F4D150' },\n { value: '#77311D', label: 'Brown', colorHex: '#77311D' },\n ],\n defaultValue: '#9287FF',\n },\n {\n id: 'bgColor',\n label: 'Background',\n type: 'color',\n group: 'Background',\n options: [\n { value: '#9287FF', label: 'Purple', colorHex: '#9287FF' },\n { value: '#6BD9E9', label: 'Light Blue', colorHex: '#6BD9E9' },\n { value: '#FC909F', label: 'Pink', colorHex: '#FC909F' },\n { value: '#F4D150', label: 'Yellow', colorHex: '#F4D150' },\n { value: '#E0DDFF', label: 'Light Purple', colorHex: '#E0DDFF' },\n { value: '#D2EFF3', label: 'Ice', colorHex: '#D2EFF3' },\n { value: '#FFEDEF', label: 'Light Pink', colorHex: '#FFEDEF' },\n { value: '#FFEBA4', label: 'Light Yellow', colorHex: '#FFEBA4' },\n { value: '#506AF4', label: 'Blue', colorHex: '#506AF4' },\n { value: '#F48150', label: 'Orange', colorHex: '#F48150' },\n { value: '#74D153', label: 'Green', colorHex: '#74D153' },\n ],\n defaultValue: '#E0DDFF',\n },\n];\n","import { useState, useEffect, useCallback } from 'react';\nimport { AvatarConfig, genConfig } from 'react-nice-avatar';\nimport { REACT_NICE_AVATAR_SECTIONS } from '../constants/avatarSections';\n\nexport interface UseAvatarCustomizeProps {\n value?: AvatarConfig;\n defaultValue?: AvatarConfig;\n onChange?: (config: AvatarConfig) => void;\n hiddenSections?: string[];\n sectionOrder?: string[];\n}\n\nexport function useAvatarCustomize({\n value,\n defaultValue,\n onChange,\n hiddenSections = [],\n sectionOrder = [],\n}: UseAvatarCustomizeProps) {\n // Use controlled value if provided, else uncontrolled internal state\n const isControlled = value !== undefined;\n \n const [internalConfig, setInternalConfig] = useState<AvatarConfig>(\n () => value ?? defaultValue ?? genConfig()\n );\n\n const [activeSectionId, setActiveSectionId] = useState<string | null>(null);\n\n const config = isControlled ? value : internalConfig;\n\n // Process sections from engine\n const rawSections = REACT_NICE_AVATAR_SECTIONS;\n const visibleSections = rawSections.filter(s => !s.hidden && !hiddenSections.includes(s.id));\n \n // Sort sections if order is provided\n const sections = [...visibleSections].sort((a, b) => {\n if (sectionOrder.length === 0) return 0;\n const indexA = sectionOrder.indexOf(a.id);\n const indexB = sectionOrder.indexOf(b.id);\n if (indexA === -1 && indexB === -1) return 0;\n if (indexA === -1) return 1;\n if (indexB === -1) return -1;\n return indexA - indexB;\n });\n\n // Set initial active section\n useEffect(() => {\n if (!activeSectionId && sections.length > 0) {\n setActiveSectionId(sections[0].id);\n }\n }, [sections, activeSectionId]);\n\n const updateConfig = useCallback(\n (newConfigPartial: Partial<AvatarConfig>) => {\n const updated = { ...config, ...newConfigPartial } as AvatarConfig;\n if (!isControlled) {\n setInternalConfig(updated);\n }\n onChange?.(updated);\n },\n [config, isControlled, onChange]\n );\n\n const randomize = useCallback(() => {\n const random = genConfig({ isRandom: true } as any);\n if (!isControlled) {\n setInternalConfig(random);\n }\n onChange?.(random);\n }, [isControlled, onChange]);\n\n const reset = useCallback(() => {\n const defaultConf = defaultValue ?? genConfig();\n if (!isControlled) {\n setInternalConfig(defaultConf);\n }\n onChange?.(defaultConf);\n }, [defaultValue, isControlled, onChange]);\n \n const handleOptionChange = useCallback((sectionId: string, value: any) => {\n updateConfig({ [sectionId]: value } as Partial<AvatarConfig>);\n }, [updateConfig]);\n\n return {\n config,\n sections,\n activeSectionId,\n setActiveSectionId,\n updateConfig,\n handleOptionChange,\n randomize,\n reset,\n };\n}\n","import React from 'react';\nimport Avatar, { genConfig } from 'react-nice-avatar';\nimport type { AvatarPreviewProps } from '../types';\n\nexport function AvatarPreview({\n config,\n className,\n style,\n id\n}: AvatarPreviewProps) {\n const finalConfig = config || genConfig();\n\n return (\n <div id={id} className={`ras-preview ${className || ''}`} style={style}>\n <Avatar style={{ width: '100%', height: '100%' }} {...finalConfig} />\n </div>\n );\n}\n\nexport default AvatarPreview;\n","import React, { useState, useMemo, useEffect } from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport { useAvatarCustomize } from '../hooks/useAvatarCustomize';\nimport { useThemeStyles } from '../hooks/useThemeStyles';\nimport { cx } from '../utils/cx';\nimport { AvatarPreviewColumn } from './AvatarPreviewColumn';\nimport { AvatarCategoryNav } from './AvatarCategoryNav';\nimport { AvatarSectionList } from './AvatarSectionList';\nimport { AvatarFooterActions } from './AvatarFooterActions';\nimport '../styles/index.css';\n\nexport function AvatarCustomizeInline(props: AvatarCustomizeProps) {\n const { config, sections, handleOptionChange, randomize } = useAvatarCustomize(props);\n\n const {\n theme, classes, classNames, style, className,\n unstyled = false, layout = 'sidebar', previewPosition = 'left',\n } = props;\n\n const themeStyles = useThemeStyles(theme);\n const containerStyle = { ...style, ...themeStyles };\n\n const categories = useMemo(() => {\n const cats: string[] = [];\n sections.forEach((s: any) => {\n const group = s.group || 'General';\n if (!cats.includes(group)) cats.push(group);\n });\n return cats;\n }, [sections]);\n\n const [activeCategory, setActiveCategory] = useState<string>(categories[0] || 'General');\n\n useEffect(() => {\n if (categories.length > 0 && !categories.includes(activeCategory)) {\n setActiveCategory(categories[0]);\n }\n }, [categories, activeCategory]);\n\n const activeSections = useMemo(\n () => sections.filter((s: any) => (s.group || 'General') === activeCategory),\n [sections, activeCategory],\n );\n\n const displaySections = layout === 'accordion' ? sections : activeSections;\n\n const rootProps = props.slotProps?.root || {};\n const containerClass = unstyled ? '' : `ras-container ${theme === 'dark' ? 'ras-theme-dark' : 'ras-theme-light'}`;\n const layoutClass = unstyled ? '' : 'ras-layout';\n const settingsClass = unstyled ? '' : 'ras-settings-column';\n\n return (\n <div\n {...rootProps}\n className={cx(containerClass, className, classes?.container, classNames?.root, rootProps.className)}\n style={{ ...containerStyle, ...rootProps.style }}\n data-layout={layout}\n data-preview={previewPosition}\n >\n <div className={layoutClass}>\n <AvatarPreviewColumn {...props} config={config} randomize={randomize} />\n\n <div className={cx(settingsClass, classes?.settingsColumn)}>\n <AvatarCategoryNav\n {...props}\n categories={categories}\n activeCategory={activeCategory}\n setActiveCategory={setActiveCategory}\n />\n <AvatarSectionList\n {...props}\n config={config}\n displaySections={displaySections}\n handleOptionChange={handleOptionChange}\n cx={cx}\n />\n <AvatarFooterActions {...props} config={config} />\n </div>\n </div>\n </div>\n );\n}\n\nexport default AvatarCustomizeInline;\n","import { useMemo } from 'react';\nimport type { AvatarStudioTheme } from '../types';\n\nexport function useThemeStyles(theme: AvatarStudioTheme | undefined): Record<string, string> {\n return useMemo(() => {\n if (!theme || typeof theme === 'string') return {};\n const t = theme as any;\n const s: any = { ...t };\n if (t.primary) s['--avatar-customize-primary'] = t.primary;\n if (t.bg) s['--avatar-customize-bg'] = t.bg;\n if (t.surface) s['--avatar-customize-option-bg'] = t.surface;\n if (t.border) s['--avatar-customize-border'] = t.border;\n if (t.textMain) s['--avatar-customize-text'] = t.textMain;\n if (t.textMuted) s['--avatar-customize-muted'] = t.textMuted;\n return s;\n }, [theme]);\n}\n","export function cx(...names: (string | undefined | null | false)[]): string | undefined {\n return names.filter(Boolean).join(' ') || undefined;\n}\n","import React from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport type { AvatarConfig } from 'react-nice-avatar';\nimport { AvatarPreview } from './AvatarPreview';\nimport { cx } from '../utils/cx';\n\ninterface Props extends AvatarCustomizeProps {\n config: AvatarConfig;\n randomize: () => void;\n}\n\nexport function AvatarPreviewColumn({\n config, randomize, unstyled, classes, classNames, components, slots, slotProps\n}: Props) {\n const resolvedSlots = components || slots;\n const PreviewWrapper = resolvedSlots?.PreviewWrapper || 'div';\n\n const previewProps = slotProps?.previewWrapper || {};\n const randomizeBtnProps = slotProps?.randomizeButton || {};\n const downloadBtnProps = slotProps?.downloadButton || {};\n\n const previewClass = unstyled ? '' : 'ras-preview-wrapper';\n const downloadBtnClass = unstyled ? '' : 'ras-btn ras-btn-secondary ras-download-btn';\n\n return (\n <div className={cx(!unstyled ? 'ras-avatar-column' : undefined, classes?.avatarColumn)}>\n <PreviewWrapper\n {...previewProps}\n className={cx(previewClass, classes?.previewWrapper, classNames?.preview, previewProps.className)}\n style={previewProps.style}\n >\n <AvatarPreview config={config} id=\"ras-avatar-download-target\" className=\"ras-preview-large\" />\n </PreviewWrapper>\n\n <div className={cx(!unstyled ? 'ras-avatar-actions' : undefined, classNames?.actionBar)}>\n <button\n {...randomizeBtnProps}\n className={cx(!unstyled ? 'ras-btn ras-btn-secondary ras-randomize-btn' : undefined, classes?.actionBtn, randomizeBtnProps.className)}\n onClick={(e) => {\n randomize();\n if (randomizeBtnProps.onClick) randomizeBtnProps.onClick(e);\n }}\n >\n <span className={!unstyled ? 'ras-btn-icon' : ''}>🎲</span> Randomize\n </button>\n\n <button\n {...downloadBtnProps}\n className={cx(downloadBtnClass, classes?.actionBtn, downloadBtnProps.className)}\n onClick={(e) => {\n import('../utils/avatarHelpers').then(m => m.downloadAvatarAsPng('ras-avatar-download-target', 'my-avatar.png'));\n if (downloadBtnProps.onClick) downloadBtnProps.onClick(e);\n }}\n >\n <span className={!unstyled ? 'ras-btn-icon' : ''}>⬇️</span> Download\n </button>\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport { cx } from '../utils/cx';\n\ninterface Props extends AvatarCustomizeProps {\n categories: string[];\n activeCategory: string;\n setActiveCategory: (cat: string) => void;\n}\n\nexport function AvatarCategoryNav({\n categories, activeCategory, setActiveCategory, layout, unstyled, classes, classNames, slotProps\n}: Props) {\n if (categories.length <= 1 || layout === 'accordion') return null;\n\n const tabProps = slotProps?.categoryTab || {};\n const tabClass = unstyled ? '' : 'ras-category-tab';\n\n return (\n <div className={cx(!unstyled ? 'ras-category-nav-wrapper' : undefined, classes?.categoryNav, classNames?.sectionNav)}>\n <div className={!unstyled ? 'ras-category-nav' : ''}>\n {categories.map(category => (\n <button\n key={category}\n {...tabProps}\n className={cx(tabClass, activeCategory === category ? 'active' : undefined, classes?.categoryTab, tabProps.className)}\n onClick={(e) => {\n setActiveCategory(category);\n if (tabProps.onClick) tabProps.onClick(e as any);\n }}\n >\n {category}\n </button>\n ))}\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport type { AvatarConfig } from 'react-nice-avatar';\nimport { cx } from '../utils/cx';\n\ninterface Props extends Pick<AvatarCustomizeProps,\n 'classes' | 'classNames' | 'components' | 'slots' | 'slotProps' | 'unstyled' | 'columns'\n> {\n config: AvatarConfig;\n section: any;\n handleOptionChange: (sectionId: string, value: string | number) => void;\n}\n\nexport function AvatarOptionGrid({\n config, section, handleOptionChange, unstyled, columns,\n classes, classNames, components, slots, slotProps\n}: Props) {\n const resolvedSlots = components || slots;\n const OptionButton = resolvedSlots?.OptionButton || (resolvedSlots as any)?.Button || 'button';\n\n const optionBtnProps = slotProps?.optionButton || {};\n const colorBtnProps = slotProps?.colorButton || {};\n\n const gridClass = unstyled ? '' : 'ras-options-grid';\n const optionBtnClass = unstyled ? '' : 'ras-option-btn';\n const colorBtnClass = unstyled ? '' : 'ras-color-btn';\n const gridStyle = columns ? { gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` } : undefined;\n\n return (\n <div\n className={cx(gridClass, section.type === 'color' && !unstyled ? 'ras-options-color' : undefined, classes?.optionsGrid)}\n style={gridStyle}\n >\n {section.options.map((option: any) => {\n const isSelected = (config as any)[section.id] === option.value;\n\n if (section.type === 'color') {\n return (\n <OptionButton\n key={String(option.value)}\n {...colorBtnProps}\n className={cx(colorBtnClass, isSelected ? 'active' : undefined, classes?.colorBtn, classNames?.optionButton, colorBtnProps.className)}\n style={{ backgroundColor: option.colorHex || String(option.value), ...colorBtnProps.style }}\n onClick={(e: any) => {\n handleOptionChange(section.id, option.value);\n if (colorBtnProps.onClick) colorBtnProps.onClick(e);\n }}\n title={option.label}\n aria-label={option.label}\n aria-pressed={isSelected}\n >\n {isSelected && (\n <span className={!unstyled ? 'ras-color-check' : ''}>\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </span>\n )}\n </OptionButton>\n );\n }\n\n return (\n <OptionButton\n key={String(option.value)}\n {...optionBtnProps}\n className={cx(optionBtnClass, isSelected ? 'active' : undefined, classes?.optionBtn, classNames?.optionButton, optionBtnProps.className)}\n onClick={(e: any) => {\n handleOptionChange(section.id, option.value);\n if (optionBtnProps.onClick) optionBtnProps.onClick(e);\n }}\n aria-pressed={isSelected}\n >\n {option.label}\n </OptionButton>\n );\n })}\n </div>\n );\n}\n","import React from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport type { AvatarConfig } from 'react-nice-avatar';\nimport { AvatarOptionGrid } from './AvatarOptionGrid';\nimport { cx } from '../utils/cx';\n\ninterface Props extends Pick<AvatarCustomizeProps,\n 'classes' | 'classNames' | 'components' | 'slots' | 'slotProps' | 'unstyled' | 'columns' | 'labels' | 'sectionOptionOverrides'\n> {\n config: AvatarConfig;\n section: any;\n handleOptionChange: (sectionId: string, value: string | number) => void;\n}\n\nexport function AvatarSection({\n config, section, handleOptionChange, unstyled, labels,\n sectionOptionOverrides, classes, classNames, components, slots, slotProps, columns\n}: Props) {\n const resolvedSlots = components || slots;\n const SectionWrapper = resolvedSlots?.SectionWrapper || 'div';\n const SectionHeader = resolvedSlots?.SectionHeader || 'div';\n\n const sectionWrapperProps = slotProps?.sectionWrapper || {};\n const sectionHeaderProps = slotProps?.sectionHeader || {};\n\n const wrapperClass = unstyled ? '' : 'ras-section-block';\n const headerClass = unstyled ? '' : 'ras-section-header';\n const titleClass = unstyled ? '' : 'ras-section-title';\n const descClass = unstyled ? '' : 'ras-section-desc';\n\n const overrides = sectionOptionOverrides?.[section.id];\n const filteredSection = overrides\n ? { ...section, options: section.options.filter((o: any) => overrides.includes(o.value)) }\n : section;\n\n return (\n <SectionWrapper\n {...sectionWrapperProps}\n className={cx(wrapperClass, classes?.sectionBlock, sectionWrapperProps.className)}\n >\n <SectionHeader\n {...sectionHeaderProps}\n className={cx(headerClass, sectionHeaderProps.className)}\n >\n <h3 className={cx(titleClass, classes?.sectionTitle)}>\n {labels?.[section.id] || section.label}\n </h3>\n {section.description && <p className={descClass}>{section.description}</p>}\n </SectionHeader>\n\n <AvatarOptionGrid\n config={config}\n section={filteredSection}\n handleOptionChange={handleOptionChange}\n unstyled={unstyled}\n columns={columns}\n classes={classes}\n classNames={classNames}\n components={components}\n slots={slots}\n slotProps={slotProps}\n />\n </SectionWrapper>\n );\n}\n","import React from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport type { AvatarConfig } from 'react-nice-avatar';\nimport { AvatarSection } from './AvatarSection';\n\ninterface Props extends AvatarCustomizeProps {\n config: AvatarConfig;\n displaySections: any[];\n handleOptionChange: (sectionId: string, value: string | number) => void;\n cx: (...names: (string | undefined)[]) => string | undefined;\n}\n\nexport function AvatarSectionList({\n config, displaySections, handleOptionChange, unstyled,\n classes, classNames, components, slots, slotProps,\n labels, sectionOptionOverrides, columns, cx\n}: Props) {\n return (\n <div className={!unstyled ? 'ras-category-content' : ''}>\n {displaySections.map((section: any) => (\n <AvatarSection\n key={section.id}\n config={config}\n section={section}\n handleOptionChange={handleOptionChange}\n unstyled={unstyled}\n columns={columns}\n classes={classes}\n classNames={classNames}\n components={components}\n slots={slots}\n slotProps={slotProps}\n labels={labels}\n sectionOptionOverrides={sectionOptionOverrides}\n />\n ))}\n </div>\n );\n}\n","import React from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport type { AvatarConfig } from 'react-nice-avatar';\nimport { cx } from '../utils/cx';\n\ninterface Props extends AvatarCustomizeProps {\n config: AvatarConfig;\n}\n\nexport function AvatarFooterActions({\n config, onCancel, onSave, unstyled, classes, classNames, components, slots, slotProps\n}: Props) {\n if (!onCancel && !onSave) return null;\n\n const resolvedSlots = components || slots;\n const Footer = resolvedSlots?.Footer || 'div';\n\n const footerProps = slotProps?.footer || {};\n const saveBtnProps = slotProps?.saveButton || {};\n const cancelBtnProps = slotProps?.cancelButton || {};\n\n const footerClass = unstyled ? '' : 'ras-footer-actions';\n const cancelClass = unstyled ? '' : 'ras-btn ras-btn-ghost';\n const saveClass = unstyled ? '' : 'ras-btn ras-btn-primary';\n\n return (\n <Footer\n {...footerProps}\n className={cx(footerClass, classes?.footer, classNames?.actionBar, footerProps.className)}\n >\n {onCancel && (\n <button\n {...cancelBtnProps}\n className={cx(cancelClass, classes?.actionBtn, cancelBtnProps.className)}\n onClick={(e) => {\n onCancel();\n if (cancelBtnProps.onClick) cancelBtnProps.onClick(e);\n }}\n >\n Cancel\n </button>\n )}\n {onSave && (\n <button\n {...saveBtnProps}\n className={cx(saveClass, classes?.actionBtn, saveBtnProps.className)}\n onClick={async (e) => {\n const helpers = await import('../utils/avatarHelpers');\n const exportData = await helpers.getAvatarData('ras-avatar-download-target');\n onSave(config, {\n config,\n svg: exportData?.svg || '',\n pngDataUrl: exportData?.pngDataUrl || '',\n });\n if (saveBtnProps.onClick) saveBtnProps.onClick(e);\n }}\n >\n Save Avatar\n </button>\n )}\n </Footer>\n );\n}\n","\n export default function styleInject(css, { insertAt } = {}) {\n if (!css || typeof document === 'undefined') return\n \n const head = document.head || document.getElementsByTagName('head')[0]\n const style = document.createElement('style')\n style.type = 'text/css'\n \n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild)\n } else {\n head.appendChild(style)\n }\n } else {\n head.appendChild(style)\n }\n \n if (style.styleSheet) {\n style.styleSheet.cssText = css\n } else {\n style.appendChild(document.createTextNode(css))\n }\n }\n ","import styleInject from '#style-inject';styleInject(\":root,.ras-theme-light{--avatar-customize-bg: #ffffff;--avatar-customize-border: #e9ecef;--avatar-customize-radius: 12px;--avatar-customize-text: #212529;--avatar-customize-muted: #868e96;--avatar-customize-primary: #aa3bff;--avatar-customize-primary-text: #ffffff;--avatar-customize-option-bg: #f8f9fa;--avatar-customize-option-active-bg: #aa3bff;--avatar-customize-option-active-border: #aa3bff;--avatar-customize-overlay: rgba(0, 0, 0, .4);--ras-primary: var(--avatar-customize-primary);--ras-primary-hover: #9b2cee;--ras-bg: var(--avatar-customize-bg);--ras-surface: var(--avatar-customize-option-bg);--ras-surface-hover: #f1f3f5;--ras-border: var(--avatar-customize-border);--ras-text-main: var(--avatar-customize-text);--ras-text-muted: var(--avatar-customize-muted);--ras-shadow-sm: 0 1px 3px rgba(0,0,0,.05);--ras-shadow-md: 0 4px 12px rgba(0,0,0,.08);--ras-shadow-lg: 0 12px 24px rgba(0,0,0,.12);--ras-radius-sm: 8px;--ras-radius-md: var(--avatar-customize-radius);--ras-radius-lg: 16px;--ras-radius-full: 9999px;--ras-transition: all .2s cubic-bezier(.4, 0, .2, 1);--ras-font: system-ui, -apple-system, BlinkMacSystemFont, \\\"Segoe UI\\\", Roboto, sans-serif}.ras-theme-dark{--avatar-customize-bg: #18181b;--avatar-customize-border: #3f3f46;--avatar-customize-radius: 12px;--avatar-customize-text: #fafafa;--avatar-customize-muted: #a1a1aa;--avatar-customize-primary: #8b5cf6;--avatar-customize-primary-text: #ffffff;--avatar-customize-option-bg: #27272a;--avatar-customize-option-active-bg: #8b5cf6;--avatar-customize-option-active-border: #8b5cf6;--avatar-customize-overlay: rgba(0, 0, 0, .7);--ras-primary-hover: #7c3aed;--ras-surface-hover: #3f3f46;--ras-shadow-sm: 0 1px 3px rgba(0,0,0,.3);--ras-shadow-md: 0 4px 12px rgba(0,0,0,.4);--ras-shadow-lg: 0 12px 24px rgba(0,0,0,.5)}.ras-container{font-family:var(--ras-font);background:var(--ras-bg);color:var(--ras-text-main);border-radius:var(--ras-radius-lg);box-shadow:var(--ras-shadow-lg);overflow:hidden;max-width:1000px;margin:0 auto;border:1px solid var(--ras-border)}.ras-layout{display:flex;flex-direction:column}@media(min-width:768px){.ras-layout{flex-direction:row;min-height:500px}}.ras-avatar-column{flex:0 0 auto;padding:2rem;background:var(--ras-surface);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1.5rem;border-bottom:1px solid var(--ras-border)}@media(min-width:768px){.ras-avatar-column{width:340px;border-bottom:none;border-right:1px solid var(--ras-border)}}.ras-preview-wrapper{background:var(--ras-bg);padding:1.5rem;border-radius:var(--ras-radius-lg);box-shadow:var(--ras-shadow-md);transition:transform .3s ease}.ras-preview-wrapper:hover{transform:translateY(-4px)}.ras-preview-large{width:180px;height:180px;min-width:180px;min-height:180px;flex-shrink:0}.ras-preview div,.ras-preview svg,.ras-preview path{box-sizing:content-box!important;max-width:none!important;max-height:none!important;margin:0;padding:0;line-height:normal}.ras-preview svg{transform-origin:center center}.ras-avatar-actions{display:flex;width:100%;gap:.75rem}.ras-settings-column{flex:1 1 auto;display:flex;flex-direction:column;max-height:600px;background:var(--ras-bg)}.ras-category-nav-wrapper{padding:1rem 1.5rem 0;border-bottom:1px solid var(--ras-border);background:var(--ras-bg);z-index:10}.ras-category-nav{display:flex;gap:.5rem;overflow-x:auto;padding-bottom:1rem;scrollbar-width:none}.ras-category-nav::-webkit-scrollbar{display:none}.ras-category-tab{background:transparent;border:none;padding:.5rem 1rem;font-size:.95rem;font-weight:600;color:var(--ras-text-muted);cursor:pointer;border-radius:var(--ras-radius-full);white-space:nowrap;transition:var(--ras-transition)}.ras-category-tab:hover{color:var(--ras-text-main);background:var(--ras-surface)}.ras-category-tab.active{color:#fff;background:var(--ras-primary);box-shadow:0 2px 8px #aa3bff66}.ras-category-content{flex:1;overflow-y:auto;padding:1.5rem;display:flex;flex-direction:column;gap:2rem}.ras-category-content::-webkit-scrollbar{width:6px}.ras-category-content::-webkit-scrollbar-track{background:transparent}.ras-category-content::-webkit-scrollbar-thumb{background:var(--ras-border);border-radius:10px}.ras-category-content::-webkit-scrollbar-thumb:hover{background:var(--ras-text-muted)}.ras-section-block{display:flex;flex-direction:column;gap:.75rem}.ras-section-header{display:flex;flex-direction:column;gap:.25rem}.ras-section-title{margin:0;font-size:1rem;font-weight:600;color:var(--ras-text-main)}.ras-section-desc{margin:0;font-size:.85rem;color:var(--ras-text-muted)}.ras-options-grid{display:flex;flex-wrap:wrap;gap:.5rem}.ras-options-color{gap:.75rem}.ras-option-btn{background:var(--ras-surface);border:1px solid var(--ras-border);color:var(--ras-text-main);padding:.5rem 1rem;border-radius:var(--ras-radius-full);font-size:.9rem;font-weight:500;cursor:pointer;transition:var(--ras-transition)}.ras-option-btn:hover{background:var(--ras-surface-hover);border-color:var(--ras-text-muted)}.ras-option-btn.active{background:var(--ras-primary);border-color:var(--ras-primary);color:#fff;box-shadow:0 2px 6px #aa3bff4d}.ras-color-btn{width:36px;height:36px;border-radius:50%;border:2px solid transparent;cursor:pointer;transition:var(--ras-transition);position:relative;display:flex;align-items:center;justify-content:center;box-shadow:var(--ras-shadow-sm);padding:0}.ras-color-btn:hover{transform:scale(1.1);box-shadow:var(--ras-shadow-md)}.ras-color-btn.active{border-color:var(--ras-primary);transform:scale(1.1)}.ras-color-check{color:#ffffffe6;width:18px;height:18px;display:flex;align-items:center;justify-content:center;text-shadow:0 1px 2px rgba(0,0,0,.5);mix-blend-mode:difference}.ras-footer-actions{padding:1.25rem 1.5rem;border-top:1px solid var(--ras-border);background:var(--ras-surface);display:flex;justify-content:flex-end;gap:1rem}.ras-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;padding:.75rem 1.5rem;border-radius:var(--ras-radius-full);font-size:.95rem;font-weight:600;cursor:pointer;transition:var(--ras-transition);border:none;font-family:inherit}.ras-btn-primary{background:var(--ras-primary);color:#fff;box-shadow:0 4px 12px #aa3bff4d}.ras-btn-primary:hover{background:var(--ras-primary-hover);transform:translateY(-1px);box-shadow:0 6px 16px #aa3bff66}.ras-btn-secondary{background:var(--ras-bg);color:var(--ras-text-main);border:1px solid var(--ras-border);box-shadow:var(--ras-shadow-sm);width:100%}.ras-btn-secondary:hover{background:var(--ras-surface);border-color:var(--ras-text-muted)}.ras-btn-ghost{background:transparent;color:var(--ras-text-muted)}.ras-btn-ghost:hover{background:var(--ras-surface);color:var(--ras-text-main)}.ras-container[data-preview=top] .ras-layout{flex-direction:column}.ras-container[data-preview=bottom] .ras-layout{flex-direction:column-reverse}@media(min-width:768px){.ras-container[data-preview=left] .ras-layout{flex-direction:row}.ras-container[data-preview=right] .ras-layout{flex-direction:row-reverse}.ras-container[data-preview=right] .ras-avatar-column{border-right:none;border-left:1px solid var(--ras-border)}}\\n\")","import React, { useEffect, useRef } from 'react';\nimport type { AvatarCustomizeModalProps } from '../types';\nimport { AvatarCustomizeInline } from './AvatarCustomizeInline';\nimport '../styles/index.css';\n\nexport function AvatarCustomizeModal(props: AvatarCustomizeModalProps) {\n const { open, onClose, modalClassName, overlayClassName, ...inlineProps } = props;\n const modalRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && open) {\n onClose();\n }\n };\n\n if (open) {\n document.addEventListener('keydown', handleKeyDown);\n // Optional: Prevent body scroll here\n document.body.style.overflow = 'hidden';\n } else {\n document.body.style.overflow = '';\n }\n\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n document.body.style.overflow = '';\n };\n }, [open, onClose]);\n\n if (!open) return null;\n\n return (\n <div className={`ras-modal-overlay ${overlayClassName || ''}`}>\n <div \n className=\"ras-modal-backdrop\" \n onClick={onClose}\n aria-hidden=\"true\"\n />\n <div \n className={`ras-modal-content ${modalClassName || ''}`} \n ref={modalRef}\n role=\"dialog\"\n aria-modal=\"true\"\n >\n <div className=\"ras-modal-body\">\n <AvatarCustomizeInline\n {...inlineProps}\n onCancel={() => {\n if (inlineProps.onCancel) inlineProps.onCancel();\n onClose();\n }}\n onSave={(config, exportData) => {\n if (inlineProps.onSave) inlineProps.onSave(config, exportData);\n onClose();\n }}\n />\n </div>\n </div>\n </div>\n );\n}\n\nexport default AvatarCustomizeModal;\n"],"mappings":"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","names":["avatarHelpers_exports","__export","downloadAvatarAsPng","getAvatarData","elementId","node","width","height","rawHtml","data","resolve","img","canvas","scale","ctx","pngDataUrl","e","filename","a","init_avatarHelpers","__esmMin","index_exports","__export","AvatarCustomizeInline","AvatarCustomizeModal","AvatarPreview","REACT_NICE_AVATAR_SECTIONS","downloadAvatarAsPng","getAvatarData","useAvatarCustomize","__toCommonJS","REACT_NICE_AVATAR_SECTIONS","init_avatarHelpers","import_react","import_react_nice_avatar","useAvatarCustomize","value","defaultValue","onChange","hiddenSections","sectionOrder","isControlled","internalConfig","setInternalConfig","activeSectionId","setActiveSectionId","config","sections","REACT_NICE_AVATAR_SECTIONS","s","a","indexA","indexB","updateConfig","newConfigPartial","updated","randomize","random","reset","defaultConf","handleOptionChange","sectionId","import_react_nice_avatar","import_jsx_runtime","AvatarPreview","config","className","style","id","finalConfig","Avatar","import_react","import_react","useThemeStyles","theme","t","s","cx","names","import_jsx_runtime","AvatarPreviewColumn","config","randomize","unstyled","classes","classNames","components","slots","slotProps","PreviewWrapper","previewProps","randomizeBtnProps","downloadBtnProps","previewClass","downloadBtnClass","cx","AvatarPreview","e","m","import_jsx_runtime","AvatarCategoryNav","categories","activeCategory","setActiveCategory","layout","unstyled","classes","classNames","slotProps","tabProps","tabClass","cx","category","e","import_jsx_runtime","AvatarOptionGrid","config","section","handleOptionChange","unstyled","columns","classes","classNames","components","slots","slotProps","resolvedSlots","OptionButton","optionBtnProps","colorBtnProps","gridClass","optionBtnClass","colorBtnClass","gridStyle","cx","option","isSelected","e","import_jsx_runtime","AvatarSection","config","section","handleOptionChange","unstyled","labels","sectionOptionOverrides","classes","classNames","components","slots","slotProps","columns","resolvedSlots","SectionWrapper","SectionHeader","sectionWrapperProps","sectionHeaderProps","wrapperClass","headerClass","titleClass","descClass","overrides","filteredSection","o","cx","AvatarOptionGrid","import_jsx_runtime","AvatarSectionList","config","displaySections","handleOptionChange","unstyled","classes","classNames","components","slots","slotProps","labels","sectionOptionOverrides","columns","cx","section","AvatarSection","import_jsx_runtime","AvatarFooterActions","config","onCancel","onSave","unstyled","classes","classNames","components","slots","slotProps","Footer","footerProps","saveBtnProps","cancelBtnProps","footerClass","cancelClass","saveClass","cx","e","exportData","styleInject","css","insertAt","head","style","styleInject","import_jsx_runtime","AvatarCustomizeInline","props","config","sections","handleOptionChange","randomize","useAvatarCustomize","theme","classes","classNames","style","className","unstyled","layout","previewPosition","themeStyles","useThemeStyles","containerStyle","categories","cats","s","group","activeCategory","setActiveCategory","activeSections","displaySections","rootProps","containerClass","layoutClass","settingsClass","cx","AvatarPreviewColumn","AvatarCategoryNav","AvatarSectionList","AvatarFooterActions","import_react","import_jsx_runtime","AvatarCustomizeModal","props","open","onClose","modalClassName","overlayClassName","inlineProps","modalRef","handleKeyDown","e","AvatarCustomizeInline","config","exportData"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,3 @@
1
+ import{a as ua,b as ma}from"./chunk-WBTMPEY3.mjs";var L=[{id:"sex",label:"Sex",type:"select",group:"Face & Body",options:[{value:"man",label:"Man"},{value:"woman",label:"Woman"}],defaultValue:"man"},{id:"faceColor",label:"Face Color",type:"color",group:"Face & Body",options:[{value:"#F9C9B6",label:"Light",colorHex:"#F9C9B6"},{value:"#AC6651",label:"Dark",colorHex:"#AC6651"}],defaultValue:"#F9C9B6"},{id:"earSize",label:"Ear Size",type:"select",group:"Face & Body",options:[{value:"small",label:"Small"},{value:"big",label:"Big"}],defaultValue:"small"},{id:"hairColor",label:"Hair Color",type:"color",group:"Hair",options:[{value:"#000",label:"Black",colorHex:"#000"},{value:"#fff",label:"White",colorHex:"#fff"},{value:"#77311D",label:"Brown",colorHex:"#77311D"},{value:"#FC909F",label:"Pink",colorHex:"#FC909F"},{value:"#D2EFF3",label:"Light Blue",colorHex:"#D2EFF3"},{value:"#506AF4",label:"Blue",colorHex:"#506AF4"},{value:"#F48150",label:"Orange",colorHex:"#F48150"}],defaultValue:"#000"},{id:"hairStyle",label:"Hair Style",type:"select",group:"Hair",options:[{value:"normal",label:"Normal"},{value:"thick",label:"Thick"},{value:"mohawk",label:"Mohawk"},{value:"womanLong",label:"Long"},{value:"womanShort",label:"Short"}],defaultValue:"normal"},{id:"hatStyle",label:"Hat Style",type:"select",group:"Accessories",options:[{value:"none",label:"None"},{value:"beanie",label:"Beanie"},{value:"turban",label:"Turban"}],defaultValue:"none"},{id:"hatColor",label:"Hat Color",type:"color",group:"Accessories",options:[{value:"#000",label:"Black",colorHex:"#000"},{value:"#fff",label:"White",colorHex:"#fff"},{value:"#77311D",label:"Brown",colorHex:"#77311D"},{value:"#FC909F",label:"Pink",colorHex:"#FC909F"},{value:"#D2EFF3",label:"Light Blue",colorHex:"#D2EFF3"},{value:"#506AF4",label:"Blue",colorHex:"#506AF4"},{value:"#F48150",label:"Orange",colorHex:"#F48150"}],defaultValue:"#000"},{id:"eyeStyle",label:"Eye Style",type:"select",group:"Face & Body",options:[{value:"circle",label:"Circle"},{value:"oval",label:"Oval"},{value:"smile",label:"Smile"}],defaultValue:"circle"},{id:"glassesStyle",label:"Glasses Style",type:"select",group:"Accessories",options:[{value:"none",label:"None"},{value:"round",label:"Round"},{value:"square",label:"Square"}],defaultValue:"none"},{id:"noseStyle",label:"Nose Style",type:"select",group:"Face & Body",options:[{value:"short",label:"Short"},{value:"long",label:"Long"},{value:"round",label:"Round"}],defaultValue:"short"},{id:"mouthStyle",label:"Mouth Style",type:"select",group:"Face & Body",options:[{value:"laugh",label:"Laugh"},{value:"smile",label:"Smile"},{value:"peace",label:"Peace"}],defaultValue:"smile"},{id:"shirtStyle",label:"Shirt Style",type:"select",group:"Clothing",options:[{value:"hoody",label:"Hoody"},{value:"short",label:"Short"},{value:"polo",label:"Polo"}],defaultValue:"short"},{id:"shirtColor",label:"Shirt Color",type:"color",group:"Clothing",options:[{value:"#9287FF",label:"Purple",colorHex:"#9287FF"},{value:"#6BD9E9",label:"Light Blue",colorHex:"#6BD9E9"},{value:"#FC909F",label:"Pink",colorHex:"#FC909F"},{value:"#F4D150",label:"Yellow",colorHex:"#F4D150"},{value:"#77311D",label:"Brown",colorHex:"#77311D"}],defaultValue:"#9287FF"},{id:"bgColor",label:"Background",type:"color",group:"Background",options:[{value:"#9287FF",label:"Purple",colorHex:"#9287FF"},{value:"#6BD9E9",label:"Light Blue",colorHex:"#6BD9E9"},{value:"#FC909F",label:"Pink",colorHex:"#FC909F"},{value:"#F4D150",label:"Yellow",colorHex:"#F4D150"},{value:"#E0DDFF",label:"Light Purple",colorHex:"#E0DDFF"},{value:"#D2EFF3",label:"Ice",colorHex:"#D2EFF3"},{value:"#FFEDEF",label:"Light Pink",colorHex:"#FFEDEF"},{value:"#FFEBA4",label:"Light Yellow",colorHex:"#FFEBA4"},{value:"#506AF4",label:"Blue",colorHex:"#506AF4"},{value:"#F48150",label:"Orange",colorHex:"#F48150"},{value:"#74D153",label:"Green",colorHex:"#74D153"}],defaultValue:"#E0DDFF"}];import{useState as I,useEffect as ra,useCallback as S}from"react";import{genConfig as D}from"react-nice-avatar";function V({value:o,defaultValue:a,onChange:e,hiddenSections:r=[],sectionOrder:i=[]}){let t=o!==void 0,[u,d]=I(()=>o??a??D()),[l,g]=I(null),n=t?o:u,p=[...L.filter(s=>!s.hidden&&!r.includes(s.id))].sort((s,b)=>{if(i.length===0)return 0;let h=i.indexOf(s.id),w=i.indexOf(b.id);return h===-1&&w===-1?0:h===-1?1:w===-1?-1:h-w});ra(()=>{!l&&p.length>0&&g(p[0].id)},[p,l]);let y=S(s=>{let b={...n,...s};t||d(b),e?.(b)},[n,t,e]),f=S(()=>{let s=D({isRandom:!0});t||d(s),e?.(s)},[t,e]),x=S(()=>{let s=a??D();t||d(s),e?.(s)},[a,t,e]),C=S((s,b)=>{y({[s]:b})},[y]);return{config:n,sections:p,activeSectionId:l,setActiveSectionId:g,updateConfig:y,handleOptionChange:C,randomize:f,reset:x}}import oa,{genConfig as ta}from"react-nice-avatar";import{jsx as M}from"react/jsx-runtime";function W({config:o,className:a,style:e,id:r}){let i=o||ta();return M("div",{id:r,className:`ras-preview ${a||""}`,style:e,children:M(oa,{style:{width:"100%",height:"100%"},...i})})}import{useState as na,useMemo as X,useEffect as la}from"react";import{useMemo as sa}from"react";function G(o){return sa(()=>{if(!o||typeof o=="string")return{};let a=o,e={...a};return a.primary&&(e["--avatar-customize-primary"]=a.primary),a.bg&&(e["--avatar-customize-bg"]=a.bg),a.surface&&(e["--avatar-customize-option-bg"]=a.surface),a.border&&(e["--avatar-customize-border"]=a.border),a.textMain&&(e["--avatar-customize-text"]=a.textMain),a.textMuted&&(e["--avatar-customize-muted"]=a.textMuted),e},[o])}function c(...o){return o.filter(Boolean).join(" ")||void 0}import{jsx as z,jsxs as B}from"react/jsx-runtime";function U({config:o,randomize:a,unstyled:e,classes:r,classNames:i,components:t,slots:u,slotProps:d}){let g=(t||u)?.PreviewWrapper||"div",n=d?.previewWrapper||{},v=d?.randomizeButton||{},m=d?.downloadButton||{},p=e?"":"ras-preview-wrapper",y=e?"":"ras-btn ras-btn-secondary ras-download-btn";return B("div",{className:c(e?void 0:"ras-avatar-column",r?.avatarColumn),children:[z(g,{...n,className:c(p,r?.previewWrapper,i?.preview,n.className),style:n.style,children:z(W,{config:o,id:"ras-avatar-download-target",className:"ras-preview-large"})}),B("div",{className:c(e?void 0:"ras-avatar-actions",i?.actionBar),children:[B("button",{...v,className:c(e?void 0:"ras-btn ras-btn-secondary ras-randomize-btn",r?.actionBtn,v.className),onClick:f=>{a(),v.onClick&&v.onClick(f)},children:[z("span",{className:e?"":"ras-btn-icon",children:"\u{1F3B2}"})," Randomize"]}),B("button",{...m,className:c(y,r?.actionBtn,m.className),onClick:f=>{import("./avatarHelpers-6323LQJA.mjs").then(x=>x.downloadAvatarAsPng("ras-avatar-download-target","my-avatar.png")),m.onClick&&m.onClick(f)},children:[z("span",{className:e?"":"ras-btn-icon",children:"\u2B07\uFE0F"})," Download"]})]})]})}import{jsx as E}from"react/jsx-runtime";function _({categories:o,activeCategory:a,setActiveCategory:e,layout:r,unstyled:i,classes:t,classNames:u,slotProps:d}){if(o.length<=1||r==="accordion")return null;let l=d?.categoryTab||{},g=i?"":"ras-category-tab";return E("div",{className:c(i?void 0:"ras-category-nav-wrapper",t?.categoryNav,u?.sectionNav),children:E("div",{className:i?"":"ras-category-nav",children:o.map(n=>E("button",{...l,className:c(g,a===n?"active":void 0,t?.categoryTab,l.className),onClick:v=>{e(n),l.onClick&&l.onClick(v)},children:n},n))})})}import{jsx as A}from"react/jsx-runtime";function Y({config:o,section:a,handleOptionChange:e,unstyled:r,columns:i,classes:t,classNames:u,components:d,slots:l,slotProps:g}){let n=d||l,v=n?.OptionButton||n?.Button||"button",m=g?.optionButton||{},p=g?.colorButton||{},y=r?"":"ras-options-grid",f=r?"":"ras-option-btn",x=r?"":"ras-color-btn",C=i?{gridTemplateColumns:`repeat(${i}, minmax(0, 1fr))`}:void 0;return A("div",{className:c(y,a.type==="color"&&!r?"ras-options-color":void 0,t?.optionsGrid),style:C,children:a.options.map(s=>{let b=o[a.id]===s.value;return a.type==="color"?A(v,{...p,className:c(x,b?"active":void 0,t?.colorBtn,u?.optionButton,p.className),style:{backgroundColor:s.colorHex||String(s.value),...p.style},onClick:h=>{e(a.id,s.value),p.onClick&&p.onClick(h)},title:s.label,"aria-label":s.label,"aria-pressed":b,children:b&&A("span",{className:r?"":"ras-color-check",children:A("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round",strokeLinejoin:"round",children:A("polyline",{points:"20 6 9 17 4 12"})})})},String(s.value)):A(v,{...m,className:c(f,b?"active":void 0,t?.optionBtn,u?.optionButton,m.className),onClick:h=>{e(a.id,s.value),m.onClick&&m.onClick(h)},"aria-pressed":b,children:s.label},String(s.value))})})}import{jsx as O,jsxs as $}from"react/jsx-runtime";function q({config:o,section:a,handleOptionChange:e,unstyled:r,labels:i,sectionOptionOverrides:t,classes:u,classNames:d,components:l,slots:g,slotProps:n,columns:v}){let m=l||g,p=m?.SectionWrapper||"div",y=m?.SectionHeader||"div",f=n?.sectionWrapper||{},x=n?.sectionHeader||{},C=r?"":"ras-section-block",s=r?"":"ras-section-header",b=r?"":"ras-section-title",h=r?"":"ras-section-desc",w=t?.[a.id],N=w?{...a,options:a.options.filter(H=>w.includes(H.value))}:a;return $(p,{...f,className:c(C,u?.sectionBlock,f.className),children:[$(y,{...x,className:c(s,x.className),children:[O("h3",{className:c(b,u?.sectionTitle),children:i?.[a.id]||a.label}),a.description&&O("p",{className:h,children:a.description})]}),O(Y,{config:o,section:N,handleOptionChange:e,unstyled:r,columns:v,classes:u,classNames:d,components:l,slots:g,slotProps:n})]})}import{jsx as K}from"react/jsx-runtime";function j({config:o,displaySections:a,handleOptionChange:e,unstyled:r,classes:i,classNames:t,components:u,slots:d,slotProps:l,labels:g,sectionOptionOverrides:n,columns:v,cx:m}){return K("div",{className:r?"":"ras-category-content",children:a.map(p=>K(q,{config:o,section:p,handleOptionChange:e,unstyled:r,columns:v,classes:i,classNames:t,components:u,slots:d,slotProps:l,labels:g,sectionOptionOverrides:n},p.id))})}import{jsx as J,jsxs as ia}from"react/jsx-runtime";function Q({config:o,onCancel:a,onSave:e,unstyled:r,classes:i,classNames:t,components:u,slots:d,slotProps:l}){if(!a&&!e)return null;let n=(u||d)?.Footer||"div",v=l?.footer||{},m=l?.saveButton||{},p=l?.cancelButton||{},y=r?"":"ras-footer-actions",f=r?"":"ras-btn ras-btn-ghost",x=r?"":"ras-btn ras-btn-primary";return ia(n,{...v,className:c(y,i?.footer,t?.actionBar,v.className),children:[a&&J("button",{...p,className:c(f,i?.actionBtn,p.className),onClick:C=>{a(),p.onClick&&p.onClick(C)},children:"Cancel"}),e&&J("button",{...m,className:c(x,i?.actionBtn,m.className),onClick:async C=>{let b=await(await import("./avatarHelpers-6323LQJA.mjs")).getAvatarData("ras-avatar-download-target");e(o,{config:o,svg:b?.svg||"",pngDataUrl:b?.pngDataUrl||""}),m.onClick&&m.onClick(C)},children:"Save Avatar"})]})}function R(o,{insertAt:a}={}){if(!o||typeof document>"u")return;let e=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css",a==="top"&&e.firstChild?e.insertBefore(r,e.firstChild):e.appendChild(r),r.styleSheet?r.styleSheet.cssText=o:r.appendChild(document.createTextNode(o))}R(`:root,.ras-theme-light{--avatar-customize-bg: #ffffff;--avatar-customize-border: #e9ecef;--avatar-customize-radius: 12px;--avatar-customize-text: #212529;--avatar-customize-muted: #868e96;--avatar-customize-primary: #aa3bff;--avatar-customize-primary-text: #ffffff;--avatar-customize-option-bg: #f8f9fa;--avatar-customize-option-active-bg: #aa3bff;--avatar-customize-option-active-border: #aa3bff;--avatar-customize-overlay: rgba(0, 0, 0, .4);--ras-primary: var(--avatar-customize-primary);--ras-primary-hover: #9b2cee;--ras-bg: var(--avatar-customize-bg);--ras-surface: var(--avatar-customize-option-bg);--ras-surface-hover: #f1f3f5;--ras-border: var(--avatar-customize-border);--ras-text-main: var(--avatar-customize-text);--ras-text-muted: var(--avatar-customize-muted);--ras-shadow-sm: 0 1px 3px rgba(0,0,0,.05);--ras-shadow-md: 0 4px 12px rgba(0,0,0,.08);--ras-shadow-lg: 0 12px 24px rgba(0,0,0,.12);--ras-radius-sm: 8px;--ras-radius-md: var(--avatar-customize-radius);--ras-radius-lg: 16px;--ras-radius-full: 9999px;--ras-transition: all .2s cubic-bezier(.4, 0, .2, 1);--ras-font: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif}.ras-theme-dark{--avatar-customize-bg: #18181b;--avatar-customize-border: #3f3f46;--avatar-customize-radius: 12px;--avatar-customize-text: #fafafa;--avatar-customize-muted: #a1a1aa;--avatar-customize-primary: #8b5cf6;--avatar-customize-primary-text: #ffffff;--avatar-customize-option-bg: #27272a;--avatar-customize-option-active-bg: #8b5cf6;--avatar-customize-option-active-border: #8b5cf6;--avatar-customize-overlay: rgba(0, 0, 0, .7);--ras-primary-hover: #7c3aed;--ras-surface-hover: #3f3f46;--ras-shadow-sm: 0 1px 3px rgba(0,0,0,.3);--ras-shadow-md: 0 4px 12px rgba(0,0,0,.4);--ras-shadow-lg: 0 12px 24px rgba(0,0,0,.5)}.ras-container{font-family:var(--ras-font);background:var(--ras-bg);color:var(--ras-text-main);border-radius:var(--ras-radius-lg);box-shadow:var(--ras-shadow-lg);overflow:hidden;max-width:1000px;margin:0 auto;border:1px solid var(--ras-border)}.ras-layout{display:flex;flex-direction:column}@media(min-width:768px){.ras-layout{flex-direction:row;min-height:500px}}.ras-avatar-column{flex:0 0 auto;padding:2rem;background:var(--ras-surface);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1.5rem;border-bottom:1px solid var(--ras-border)}@media(min-width:768px){.ras-avatar-column{width:340px;border-bottom:none;border-right:1px solid var(--ras-border)}}.ras-preview-wrapper{background:var(--ras-bg);padding:1.5rem;border-radius:var(--ras-radius-lg);box-shadow:var(--ras-shadow-md);transition:transform .3s ease}.ras-preview-wrapper:hover{transform:translateY(-4px)}.ras-preview-large{width:180px;height:180px;min-width:180px;min-height:180px;flex-shrink:0}.ras-preview div,.ras-preview svg,.ras-preview path{box-sizing:content-box!important;max-width:none!important;max-height:none!important;margin:0;padding:0;line-height:normal}.ras-preview svg{transform-origin:center center}.ras-avatar-actions{display:flex;width:100%;gap:.75rem}.ras-settings-column{flex:1 1 auto;display:flex;flex-direction:column;max-height:600px;background:var(--ras-bg)}.ras-category-nav-wrapper{padding:1rem 1.5rem 0;border-bottom:1px solid var(--ras-border);background:var(--ras-bg);z-index:10}.ras-category-nav{display:flex;gap:.5rem;overflow-x:auto;padding-bottom:1rem;scrollbar-width:none}.ras-category-nav::-webkit-scrollbar{display:none}.ras-category-tab{background:transparent;border:none;padding:.5rem 1rem;font-size:.95rem;font-weight:600;color:var(--ras-text-muted);cursor:pointer;border-radius:var(--ras-radius-full);white-space:nowrap;transition:var(--ras-transition)}.ras-category-tab:hover{color:var(--ras-text-main);background:var(--ras-surface)}.ras-category-tab.active{color:#fff;background:var(--ras-primary);box-shadow:0 2px 8px #aa3bff66}.ras-category-content{flex:1;overflow-y:auto;padding:1.5rem;display:flex;flex-direction:column;gap:2rem}.ras-category-content::-webkit-scrollbar{width:6px}.ras-category-content::-webkit-scrollbar-track{background:transparent}.ras-category-content::-webkit-scrollbar-thumb{background:var(--ras-border);border-radius:10px}.ras-category-content::-webkit-scrollbar-thumb:hover{background:var(--ras-text-muted)}.ras-section-block{display:flex;flex-direction:column;gap:.75rem}.ras-section-header{display:flex;flex-direction:column;gap:.25rem}.ras-section-title{margin:0;font-size:1rem;font-weight:600;color:var(--ras-text-main)}.ras-section-desc{margin:0;font-size:.85rem;color:var(--ras-text-muted)}.ras-options-grid{display:flex;flex-wrap:wrap;gap:.5rem}.ras-options-color{gap:.75rem}.ras-option-btn{background:var(--ras-surface);border:1px solid var(--ras-border);color:var(--ras-text-main);padding:.5rem 1rem;border-radius:var(--ras-radius-full);font-size:.9rem;font-weight:500;cursor:pointer;transition:var(--ras-transition)}.ras-option-btn:hover{background:var(--ras-surface-hover);border-color:var(--ras-text-muted)}.ras-option-btn.active{background:var(--ras-primary);border-color:var(--ras-primary);color:#fff;box-shadow:0 2px 6px #aa3bff4d}.ras-color-btn{width:36px;height:36px;border-radius:50%;border:2px solid transparent;cursor:pointer;transition:var(--ras-transition);position:relative;display:flex;align-items:center;justify-content:center;box-shadow:var(--ras-shadow-sm);padding:0}.ras-color-btn:hover{transform:scale(1.1);box-shadow:var(--ras-shadow-md)}.ras-color-btn.active{border-color:var(--ras-primary);transform:scale(1.1)}.ras-color-check{color:#ffffffe6;width:18px;height:18px;display:flex;align-items:center;justify-content:center;text-shadow:0 1px 2px rgba(0,0,0,.5);mix-blend-mode:difference}.ras-footer-actions{padding:1.25rem 1.5rem;border-top:1px solid var(--ras-border);background:var(--ras-surface);display:flex;justify-content:flex-end;gap:1rem}.ras-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;padding:.75rem 1.5rem;border-radius:var(--ras-radius-full);font-size:.95rem;font-weight:600;cursor:pointer;transition:var(--ras-transition);border:none;font-family:inherit}.ras-btn-primary{background:var(--ras-primary);color:#fff;box-shadow:0 4px 12px #aa3bff4d}.ras-btn-primary:hover{background:var(--ras-primary-hover);transform:translateY(-1px);box-shadow:0 6px 16px #aa3bff66}.ras-btn-secondary{background:var(--ras-bg);color:var(--ras-text-main);border:1px solid var(--ras-border);box-shadow:var(--ras-shadow-sm);width:100%}.ras-btn-secondary:hover{background:var(--ras-surface);border-color:var(--ras-text-muted)}.ras-btn-ghost{background:transparent;color:var(--ras-text-muted)}.ras-btn-ghost:hover{background:var(--ras-surface);color:var(--ras-text-main)}.ras-container[data-preview=top] .ras-layout{flex-direction:column}.ras-container[data-preview=bottom] .ras-layout{flex-direction:column-reverse}@media(min-width:768px){.ras-container[data-preview=left] .ras-layout{flex-direction:row}.ras-container[data-preview=right] .ras-layout{flex-direction:row-reverse}.ras-container[data-preview=right] .ras-avatar-column{border-right:none;border-left:1px solid var(--ras-border)}}
2
+ `);import{jsx as F,jsxs as Z}from"react/jsx-runtime";function aa(o){let{config:a,sections:e,handleOptionChange:r,randomize:i}=V(o),{theme:t,classes:u,classNames:d,style:l,className:g,unstyled:n=!1,layout:v="sidebar",previewPosition:m="left"}=o,p=G(t),y={...l,...p},f=X(()=>{let k=[];return e.forEach(ea=>{let T=ea.group||"General";k.includes(T)||k.push(T)}),k},[e]),[x,C]=na(f[0]||"General");la(()=>{f.length>0&&!f.includes(x)&&C(f[0])},[f,x]);let s=X(()=>e.filter(k=>(k.group||"General")===x),[e,x]),b=v==="accordion"?e:s,h=o.slotProps?.root||{},w=n?"":`ras-container ${t==="dark"?"ras-theme-dark":"ras-theme-light"}`,N=n?"":"ras-layout",H=n?"":"ras-settings-column";return F("div",{...h,className:c(w,g,u?.container,d?.root,h.className),style:{...y,...h.style},"data-layout":v,"data-preview":m,children:Z("div",{className:N,children:[F(U,{...o,config:a,randomize:i}),Z("div",{className:c(H,u?.settingsColumn),children:[F(_,{...o,categories:f,activeCategory:x,setActiveCategory:C}),F(j,{...o,config:a,displaySections:b,handleOptionChange:r,cx:c}),F(Q,{...o,config:a})]})]})})}import{useEffect as ca,useRef as da}from"react";import{jsx as P,jsxs as pa}from"react/jsx-runtime";function de(o){let{open:a,onClose:e,modalClassName:r,overlayClassName:i,...t}=o,u=da(null);return ca(()=>{let d=l=>{l.key==="Escape"&&a&&e()};return a?(document.addEventListener("keydown",d),document.body.style.overflow="hidden"):document.body.style.overflow="",()=>{document.removeEventListener("keydown",d),document.body.style.overflow=""}},[a,e]),a?pa("div",{className:`ras-modal-overlay ${i||""}`,children:[P("div",{className:"ras-modal-backdrop",onClick:e,"aria-hidden":"true"}),P("div",{className:`ras-modal-content ${r||""}`,ref:u,role:"dialog","aria-modal":"true",children:P("div",{className:"ras-modal-body",children:P(aa,{...t,onCancel:()=>{t.onCancel&&t.onCancel(),e()},onSave:(d,l)=>{t.onSave&&t.onSave(d,l),e()}})})})]}):null}export{aa as AvatarCustomizeInline,de as AvatarCustomizeModal,W as AvatarPreview,L as REACT_NICE_AVATAR_SECTIONS,ma as downloadAvatarAsPng,ua as getAvatarData,V as useAvatarCustomize};
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants/avatarSections.ts","../src/hooks/useAvatarCustomize.ts","../src/components/AvatarPreview.tsx","../src/components/AvatarCustomizeInline.tsx","../src/hooks/useThemeStyles.ts","../src/utils/cx.ts","../src/components/AvatarPreviewColumn.tsx","../src/components/AvatarCategoryNav.tsx","../src/components/AvatarOptionGrid.tsx","../src/components/AvatarSection.tsx","../src/components/AvatarSectionList.tsx","../src/components/AvatarFooterActions.tsx","#style-inject:#style-inject","../src/styles/index.css","../src/components/AvatarCustomizeModal.tsx"],"sourcesContent":["export interface AvatarOption {\n value: string | number;\n label: string;\n colorHex?: string; // Optional hex for color palettes\n imageUrl?: string; // Optional image preview\n}\n\nexport interface AvatarSection {\n id: string; // Key in the config state\n label: string; // Display name\n type: 'select' | 'color' | 'slider';\n options: AvatarOption[];\n defaultValue: any;\n group?: string; // Category like 'Face', 'Hair', 'Clothing'\n description?: string;\n hidden?: boolean;\n}\n\nexport const REACT_NICE_AVATAR_SECTIONS: AvatarSection[] = [\n {\n id: 'sex',\n label: 'Sex',\n type: 'select',\n group: 'Face & Body',\n options: [\n { value: 'man', label: 'Man' },\n { value: 'woman', label: 'Woman' },\n ],\n defaultValue: 'man',\n },\n {\n id: 'faceColor',\n label: 'Face Color',\n type: 'color',\n group: 'Face & Body',\n options: [\n { value: '#F9C9B6', label: 'Light', colorHex: '#F9C9B6' },\n { value: '#AC6651', label: 'Dark', colorHex: '#AC6651' },\n ],\n defaultValue: '#F9C9B6',\n },\n {\n id: 'earSize',\n label: 'Ear Size',\n type: 'select',\n group: 'Face & Body',\n options: [\n { value: 'small', label: 'Small' },\n { value: 'big', label: 'Big' },\n ],\n defaultValue: 'small',\n },\n {\n id: 'hairColor',\n label: 'Hair Color',\n type: 'color',\n group: 'Hair',\n options: [\n { value: '#000', label: 'Black', colorHex: '#000' },\n { value: '#fff', label: 'White', colorHex: '#fff' },\n { value: '#77311D', label: 'Brown', colorHex: '#77311D' },\n { value: '#FC909F', label: 'Pink', colorHex: '#FC909F' },\n { value: '#D2EFF3', label: 'Light Blue', colorHex: '#D2EFF3' },\n { value: '#506AF4', label: 'Blue', colorHex: '#506AF4' },\n { value: '#F48150', label: 'Orange', colorHex: '#F48150' },\n ],\n defaultValue: '#000',\n },\n {\n id: 'hairStyle',\n label: 'Hair Style',\n type: 'select',\n group: 'Hair',\n options: [\n { value: 'normal', label: 'Normal' },\n { value: 'thick', label: 'Thick' },\n { value: 'mohawk', label: 'Mohawk' },\n { value: 'womanLong', label: 'Long' },\n { value: 'womanShort', label: 'Short' },\n ],\n defaultValue: 'normal',\n },\n {\n id: 'hatStyle',\n label: 'Hat Style',\n type: 'select',\n group: 'Accessories',\n options: [\n { value: 'none', label: 'None' },\n { value: 'beanie', label: 'Beanie' },\n { value: 'turban', label: 'Turban' },\n ],\n defaultValue: 'none',\n },\n {\n id: 'hatColor',\n label: 'Hat Color',\n type: 'color',\n group: 'Accessories',\n options: [\n { value: '#000', label: 'Black', colorHex: '#000' },\n { value: '#fff', label: 'White', colorHex: '#fff' },\n { value: '#77311D', label: 'Brown', colorHex: '#77311D' },\n { value: '#FC909F', label: 'Pink', colorHex: '#FC909F' },\n { value: '#D2EFF3', label: 'Light Blue', colorHex: '#D2EFF3' },\n { value: '#506AF4', label: 'Blue', colorHex: '#506AF4' },\n { value: '#F48150', label: 'Orange', colorHex: '#F48150' },\n ],\n defaultValue: '#000',\n },\n {\n id: 'eyeStyle',\n label: 'Eye Style',\n type: 'select',\n group: 'Face & Body',\n options: [\n { value: 'circle', label: 'Circle' },\n { value: 'oval', label: 'Oval' },\n { value: 'smile', label: 'Smile' },\n ],\n defaultValue: 'circle',\n },\n {\n id: 'glassesStyle',\n label: 'Glasses Style',\n type: 'select',\n group: 'Accessories',\n options: [\n { value: 'none', label: 'None' },\n { value: 'round', label: 'Round' },\n { value: 'square', label: 'Square' },\n ],\n defaultValue: 'none',\n },\n {\n id: 'noseStyle',\n label: 'Nose Style',\n type: 'select',\n group: 'Face & Body',\n options: [\n { value: 'short', label: 'Short' },\n { value: 'long', label: 'Long' },\n { value: 'round', label: 'Round' },\n ],\n defaultValue: 'short',\n },\n {\n id: 'mouthStyle',\n label: 'Mouth Style',\n type: 'select',\n group: 'Face & Body',\n options: [\n { value: 'laugh', label: 'Laugh' },\n { value: 'smile', label: 'Smile' },\n { value: 'peace', label: 'Peace' },\n ],\n defaultValue: 'smile',\n },\n {\n id: 'shirtStyle',\n label: 'Shirt Style',\n type: 'select',\n group: 'Clothing',\n options: [\n { value: 'hoody', label: 'Hoody' },\n { value: 'short', label: 'Short' },\n { value: 'polo', label: 'Polo' },\n ],\n defaultValue: 'short',\n },\n {\n id: 'shirtColor',\n label: 'Shirt Color',\n type: 'color',\n group: 'Clothing',\n options: [\n { value: '#9287FF', label: 'Purple', colorHex: '#9287FF' },\n { value: '#6BD9E9', label: 'Light Blue', colorHex: '#6BD9E9' },\n { value: '#FC909F', label: 'Pink', colorHex: '#FC909F' },\n { value: '#F4D150', label: 'Yellow', colorHex: '#F4D150' },\n { value: '#77311D', label: 'Brown', colorHex: '#77311D' },\n ],\n defaultValue: '#9287FF',\n },\n {\n id: 'bgColor',\n label: 'Background',\n type: 'color',\n group: 'Background',\n options: [\n { value: '#9287FF', label: 'Purple', colorHex: '#9287FF' },\n { value: '#6BD9E9', label: 'Light Blue', colorHex: '#6BD9E9' },\n { value: '#FC909F', label: 'Pink', colorHex: '#FC909F' },\n { value: '#F4D150', label: 'Yellow', colorHex: '#F4D150' },\n { value: '#E0DDFF', label: 'Light Purple', colorHex: '#E0DDFF' },\n { value: '#D2EFF3', label: 'Ice', colorHex: '#D2EFF3' },\n { value: '#FFEDEF', label: 'Light Pink', colorHex: '#FFEDEF' },\n { value: '#FFEBA4', label: 'Light Yellow', colorHex: '#FFEBA4' },\n { value: '#506AF4', label: 'Blue', colorHex: '#506AF4' },\n { value: '#F48150', label: 'Orange', colorHex: '#F48150' },\n { value: '#74D153', label: 'Green', colorHex: '#74D153' },\n ],\n defaultValue: '#E0DDFF',\n },\n];\n","import { useState, useEffect, useCallback } from 'react';\nimport { AvatarConfig, genConfig } from 'react-nice-avatar';\nimport { REACT_NICE_AVATAR_SECTIONS } from '../constants/avatarSections';\n\nexport interface UseAvatarCustomizeProps {\n value?: AvatarConfig;\n defaultValue?: AvatarConfig;\n onChange?: (config: AvatarConfig) => void;\n hiddenSections?: string[];\n sectionOrder?: string[];\n}\n\nexport function useAvatarCustomize({\n value,\n defaultValue,\n onChange,\n hiddenSections = [],\n sectionOrder = [],\n}: UseAvatarCustomizeProps) {\n // Use controlled value if provided, else uncontrolled internal state\n const isControlled = value !== undefined;\n \n const [internalConfig, setInternalConfig] = useState<AvatarConfig>(\n () => value ?? defaultValue ?? genConfig()\n );\n\n const [activeSectionId, setActiveSectionId] = useState<string | null>(null);\n\n const config = isControlled ? value : internalConfig;\n\n // Process sections from engine\n const rawSections = REACT_NICE_AVATAR_SECTIONS;\n const visibleSections = rawSections.filter(s => !s.hidden && !hiddenSections.includes(s.id));\n \n // Sort sections if order is provided\n const sections = [...visibleSections].sort((a, b) => {\n if (sectionOrder.length === 0) return 0;\n const indexA = sectionOrder.indexOf(a.id);\n const indexB = sectionOrder.indexOf(b.id);\n if (indexA === -1 && indexB === -1) return 0;\n if (indexA === -1) return 1;\n if (indexB === -1) return -1;\n return indexA - indexB;\n });\n\n // Set initial active section\n useEffect(() => {\n if (!activeSectionId && sections.length > 0) {\n setActiveSectionId(sections[0].id);\n }\n }, [sections, activeSectionId]);\n\n const updateConfig = useCallback(\n (newConfigPartial: Partial<AvatarConfig>) => {\n const updated = { ...config, ...newConfigPartial } as AvatarConfig;\n if (!isControlled) {\n setInternalConfig(updated);\n }\n onChange?.(updated);\n },\n [config, isControlled, onChange]\n );\n\n const randomize = useCallback(() => {\n const random = genConfig({ isRandom: true } as any);\n if (!isControlled) {\n setInternalConfig(random);\n }\n onChange?.(random);\n }, [isControlled, onChange]);\n\n const reset = useCallback(() => {\n const defaultConf = defaultValue ?? genConfig();\n if (!isControlled) {\n setInternalConfig(defaultConf);\n }\n onChange?.(defaultConf);\n }, [defaultValue, isControlled, onChange]);\n \n const handleOptionChange = useCallback((sectionId: string, value: any) => {\n updateConfig({ [sectionId]: value } as Partial<AvatarConfig>);\n }, [updateConfig]);\n\n return {\n config,\n sections,\n activeSectionId,\n setActiveSectionId,\n updateConfig,\n handleOptionChange,\n randomize,\n reset,\n };\n}\n","import React from 'react';\nimport Avatar, { genConfig } from 'react-nice-avatar';\nimport type { AvatarPreviewProps } from '../types';\n\nexport function AvatarPreview({\n config,\n className,\n style,\n id\n}: AvatarPreviewProps) {\n const finalConfig = config || genConfig();\n\n return (\n <div id={id} className={`ras-preview ${className || ''}`} style={style}>\n <Avatar style={{ width: '100%', height: '100%' }} {...finalConfig} />\n </div>\n );\n}\n\nexport default AvatarPreview;\n","import React, { useState, useMemo, useEffect } from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport { useAvatarCustomize } from '../hooks/useAvatarCustomize';\nimport { useThemeStyles } from '../hooks/useThemeStyles';\nimport { cx } from '../utils/cx';\nimport { AvatarPreviewColumn } from './AvatarPreviewColumn';\nimport { AvatarCategoryNav } from './AvatarCategoryNav';\nimport { AvatarSectionList } from './AvatarSectionList';\nimport { AvatarFooterActions } from './AvatarFooterActions';\nimport '../styles/index.css';\n\nexport function AvatarCustomizeInline(props: AvatarCustomizeProps) {\n const { config, sections, handleOptionChange, randomize } = useAvatarCustomize(props);\n\n const {\n theme, classes, classNames, style, className,\n unstyled = false, layout = 'sidebar', previewPosition = 'left',\n } = props;\n\n const themeStyles = useThemeStyles(theme);\n const containerStyle = { ...style, ...themeStyles };\n\n const categories = useMemo(() => {\n const cats: string[] = [];\n sections.forEach((s: any) => {\n const group = s.group || 'General';\n if (!cats.includes(group)) cats.push(group);\n });\n return cats;\n }, [sections]);\n\n const [activeCategory, setActiveCategory] = useState<string>(categories[0] || 'General');\n\n useEffect(() => {\n if (categories.length > 0 && !categories.includes(activeCategory)) {\n setActiveCategory(categories[0]);\n }\n }, [categories, activeCategory]);\n\n const activeSections = useMemo(\n () => sections.filter((s: any) => (s.group || 'General') === activeCategory),\n [sections, activeCategory],\n );\n\n const displaySections = layout === 'accordion' ? sections : activeSections;\n\n const rootProps = props.slotProps?.root || {};\n const containerClass = unstyled ? '' : `ras-container ${theme === 'dark' ? 'ras-theme-dark' : 'ras-theme-light'}`;\n const layoutClass = unstyled ? '' : 'ras-layout';\n const settingsClass = unstyled ? '' : 'ras-settings-column';\n\n return (\n <div\n {...rootProps}\n className={cx(containerClass, className, classes?.container, classNames?.root, rootProps.className)}\n style={{ ...containerStyle, ...rootProps.style }}\n data-layout={layout}\n data-preview={previewPosition}\n >\n <div className={layoutClass}>\n <AvatarPreviewColumn {...props} config={config} randomize={randomize} />\n\n <div className={cx(settingsClass, classes?.settingsColumn)}>\n <AvatarCategoryNav\n {...props}\n categories={categories}\n activeCategory={activeCategory}\n setActiveCategory={setActiveCategory}\n />\n <AvatarSectionList\n {...props}\n config={config}\n displaySections={displaySections}\n handleOptionChange={handleOptionChange}\n cx={cx}\n />\n <AvatarFooterActions {...props} config={config} />\n </div>\n </div>\n </div>\n );\n}\n\nexport default AvatarCustomizeInline;\n","import { useMemo } from 'react';\nimport type { AvatarStudioTheme } from '../types';\n\nexport function useThemeStyles(theme: AvatarStudioTheme | undefined): Record<string, string> {\n return useMemo(() => {\n if (!theme || typeof theme === 'string') return {};\n const t = theme as any;\n const s: any = { ...t };\n if (t.primary) s['--avatar-customize-primary'] = t.primary;\n if (t.bg) s['--avatar-customize-bg'] = t.bg;\n if (t.surface) s['--avatar-customize-option-bg'] = t.surface;\n if (t.border) s['--avatar-customize-border'] = t.border;\n if (t.textMain) s['--avatar-customize-text'] = t.textMain;\n if (t.textMuted) s['--avatar-customize-muted'] = t.textMuted;\n return s;\n }, [theme]);\n}\n","export function cx(...names: (string | undefined | null | false)[]): string | undefined {\n return names.filter(Boolean).join(' ') || undefined;\n}\n","import React from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport type { AvatarConfig } from 'react-nice-avatar';\nimport { AvatarPreview } from './AvatarPreview';\nimport { cx } from '../utils/cx';\n\ninterface Props extends AvatarCustomizeProps {\n config: AvatarConfig;\n randomize: () => void;\n}\n\nexport function AvatarPreviewColumn({\n config, randomize, unstyled, classes, classNames, components, slots, slotProps\n}: Props) {\n const resolvedSlots = components || slots;\n const PreviewWrapper = resolvedSlots?.PreviewWrapper || 'div';\n\n const previewProps = slotProps?.previewWrapper || {};\n const randomizeBtnProps = slotProps?.randomizeButton || {};\n const downloadBtnProps = slotProps?.downloadButton || {};\n\n const previewClass = unstyled ? '' : 'ras-preview-wrapper';\n const downloadBtnClass = unstyled ? '' : 'ras-btn ras-btn-secondary ras-download-btn';\n\n return (\n <div className={cx(!unstyled ? 'ras-avatar-column' : undefined, classes?.avatarColumn)}>\n <PreviewWrapper\n {...previewProps}\n className={cx(previewClass, classes?.previewWrapper, classNames?.preview, previewProps.className)}\n style={previewProps.style}\n >\n <AvatarPreview config={config} id=\"ras-avatar-download-target\" className=\"ras-preview-large\" />\n </PreviewWrapper>\n\n <div className={cx(!unstyled ? 'ras-avatar-actions' : undefined, classNames?.actionBar)}>\n <button\n {...randomizeBtnProps}\n className={cx(!unstyled ? 'ras-btn ras-btn-secondary ras-randomize-btn' : undefined, classes?.actionBtn, randomizeBtnProps.className)}\n onClick={(e) => {\n randomize();\n if (randomizeBtnProps.onClick) randomizeBtnProps.onClick(e);\n }}\n >\n <span className={!unstyled ? 'ras-btn-icon' : ''}>🎲</span> Randomize\n </button>\n\n <button\n {...downloadBtnProps}\n className={cx(downloadBtnClass, classes?.actionBtn, downloadBtnProps.className)}\n onClick={(e) => {\n import('../utils/avatarHelpers').then(m => m.downloadAvatarAsPng('ras-avatar-download-target', 'my-avatar.png'));\n if (downloadBtnProps.onClick) downloadBtnProps.onClick(e);\n }}\n >\n <span className={!unstyled ? 'ras-btn-icon' : ''}>⬇️</span> Download\n </button>\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport { cx } from '../utils/cx';\n\ninterface Props extends AvatarCustomizeProps {\n categories: string[];\n activeCategory: string;\n setActiveCategory: (cat: string) => void;\n}\n\nexport function AvatarCategoryNav({\n categories, activeCategory, setActiveCategory, layout, unstyled, classes, classNames, slotProps\n}: Props) {\n if (categories.length <= 1 || layout === 'accordion') return null;\n\n const tabProps = slotProps?.categoryTab || {};\n const tabClass = unstyled ? '' : 'ras-category-tab';\n\n return (\n <div className={cx(!unstyled ? 'ras-category-nav-wrapper' : undefined, classes?.categoryNav, classNames?.sectionNav)}>\n <div className={!unstyled ? 'ras-category-nav' : ''}>\n {categories.map(category => (\n <button\n key={category}\n {...tabProps}\n className={cx(tabClass, activeCategory === category ? 'active' : undefined, classes?.categoryTab, tabProps.className)}\n onClick={(e) => {\n setActiveCategory(category);\n if (tabProps.onClick) tabProps.onClick(e as any);\n }}\n >\n {category}\n </button>\n ))}\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport type { AvatarConfig } from 'react-nice-avatar';\nimport { cx } from '../utils/cx';\n\ninterface Props extends Pick<AvatarCustomizeProps,\n 'classes' | 'classNames' | 'components' | 'slots' | 'slotProps' | 'unstyled' | 'columns'\n> {\n config: AvatarConfig;\n section: any;\n handleOptionChange: (sectionId: string, value: string | number) => void;\n}\n\nexport function AvatarOptionGrid({\n config, section, handleOptionChange, unstyled, columns,\n classes, classNames, components, slots, slotProps\n}: Props) {\n const resolvedSlots = components || slots;\n const OptionButton = resolvedSlots?.OptionButton || (resolvedSlots as any)?.Button || 'button';\n\n const optionBtnProps = slotProps?.optionButton || {};\n const colorBtnProps = slotProps?.colorButton || {};\n\n const gridClass = unstyled ? '' : 'ras-options-grid';\n const optionBtnClass = unstyled ? '' : 'ras-option-btn';\n const colorBtnClass = unstyled ? '' : 'ras-color-btn';\n const gridStyle = columns ? { gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` } : undefined;\n\n return (\n <div\n className={cx(gridClass, section.type === 'color' && !unstyled ? 'ras-options-color' : undefined, classes?.optionsGrid)}\n style={gridStyle}\n >\n {section.options.map((option: any) => {\n const isSelected = (config as any)[section.id] === option.value;\n\n if (section.type === 'color') {\n return (\n <OptionButton\n key={String(option.value)}\n {...colorBtnProps}\n className={cx(colorBtnClass, isSelected ? 'active' : undefined, classes?.colorBtn, classNames?.optionButton, colorBtnProps.className)}\n style={{ backgroundColor: option.colorHex || String(option.value), ...colorBtnProps.style }}\n onClick={(e: any) => {\n handleOptionChange(section.id, option.value);\n if (colorBtnProps.onClick) colorBtnProps.onClick(e);\n }}\n title={option.label}\n aria-label={option.label}\n aria-pressed={isSelected}\n >\n {isSelected && (\n <span className={!unstyled ? 'ras-color-check' : ''}>\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </span>\n )}\n </OptionButton>\n );\n }\n\n return (\n <OptionButton\n key={String(option.value)}\n {...optionBtnProps}\n className={cx(optionBtnClass, isSelected ? 'active' : undefined, classes?.optionBtn, classNames?.optionButton, optionBtnProps.className)}\n onClick={(e: any) => {\n handleOptionChange(section.id, option.value);\n if (optionBtnProps.onClick) optionBtnProps.onClick(e);\n }}\n aria-pressed={isSelected}\n >\n {option.label}\n </OptionButton>\n );\n })}\n </div>\n );\n}\n","import React from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport type { AvatarConfig } from 'react-nice-avatar';\nimport { AvatarOptionGrid } from './AvatarOptionGrid';\nimport { cx } from '../utils/cx';\n\ninterface Props extends Pick<AvatarCustomizeProps,\n 'classes' | 'classNames' | 'components' | 'slots' | 'slotProps' | 'unstyled' | 'columns' | 'labels' | 'sectionOptionOverrides'\n> {\n config: AvatarConfig;\n section: any;\n handleOptionChange: (sectionId: string, value: string | number) => void;\n}\n\nexport function AvatarSection({\n config, section, handleOptionChange, unstyled, labels,\n sectionOptionOverrides, classes, classNames, components, slots, slotProps, columns\n}: Props) {\n const resolvedSlots = components || slots;\n const SectionWrapper = resolvedSlots?.SectionWrapper || 'div';\n const SectionHeader = resolvedSlots?.SectionHeader || 'div';\n\n const sectionWrapperProps = slotProps?.sectionWrapper || {};\n const sectionHeaderProps = slotProps?.sectionHeader || {};\n\n const wrapperClass = unstyled ? '' : 'ras-section-block';\n const headerClass = unstyled ? '' : 'ras-section-header';\n const titleClass = unstyled ? '' : 'ras-section-title';\n const descClass = unstyled ? '' : 'ras-section-desc';\n\n const overrides = sectionOptionOverrides?.[section.id];\n const filteredSection = overrides\n ? { ...section, options: section.options.filter((o: any) => overrides.includes(o.value)) }\n : section;\n\n return (\n <SectionWrapper\n {...sectionWrapperProps}\n className={cx(wrapperClass, classes?.sectionBlock, sectionWrapperProps.className)}\n >\n <SectionHeader\n {...sectionHeaderProps}\n className={cx(headerClass, sectionHeaderProps.className)}\n >\n <h3 className={cx(titleClass, classes?.sectionTitle)}>\n {labels?.[section.id] || section.label}\n </h3>\n {section.description && <p className={descClass}>{section.description}</p>}\n </SectionHeader>\n\n <AvatarOptionGrid\n config={config}\n section={filteredSection}\n handleOptionChange={handleOptionChange}\n unstyled={unstyled}\n columns={columns}\n classes={classes}\n classNames={classNames}\n components={components}\n slots={slots}\n slotProps={slotProps}\n />\n </SectionWrapper>\n );\n}\n","import React from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport type { AvatarConfig } from 'react-nice-avatar';\nimport { AvatarSection } from './AvatarSection';\n\ninterface Props extends AvatarCustomizeProps {\n config: AvatarConfig;\n displaySections: any[];\n handleOptionChange: (sectionId: string, value: string | number) => void;\n cx: (...names: (string | undefined)[]) => string | undefined;\n}\n\nexport function AvatarSectionList({\n config, displaySections, handleOptionChange, unstyled,\n classes, classNames, components, slots, slotProps,\n labels, sectionOptionOverrides, columns, cx\n}: Props) {\n return (\n <div className={!unstyled ? 'ras-category-content' : ''}>\n {displaySections.map((section: any) => (\n <AvatarSection\n key={section.id}\n config={config}\n section={section}\n handleOptionChange={handleOptionChange}\n unstyled={unstyled}\n columns={columns}\n classes={classes}\n classNames={classNames}\n components={components}\n slots={slots}\n slotProps={slotProps}\n labels={labels}\n sectionOptionOverrides={sectionOptionOverrides}\n />\n ))}\n </div>\n );\n}\n","import React from 'react';\nimport type { AvatarCustomizeProps } from '../types';\nimport type { AvatarConfig } from 'react-nice-avatar';\nimport { cx } from '../utils/cx';\n\ninterface Props extends AvatarCustomizeProps {\n config: AvatarConfig;\n}\n\nexport function AvatarFooterActions({\n config, onCancel, onSave, unstyled, classes, classNames, components, slots, slotProps\n}: Props) {\n if (!onCancel && !onSave) return null;\n\n const resolvedSlots = components || slots;\n const Footer = resolvedSlots?.Footer || 'div';\n\n const footerProps = slotProps?.footer || {};\n const saveBtnProps = slotProps?.saveButton || {};\n const cancelBtnProps = slotProps?.cancelButton || {};\n\n const footerClass = unstyled ? '' : 'ras-footer-actions';\n const cancelClass = unstyled ? '' : 'ras-btn ras-btn-ghost';\n const saveClass = unstyled ? '' : 'ras-btn ras-btn-primary';\n\n return (\n <Footer\n {...footerProps}\n className={cx(footerClass, classes?.footer, classNames?.actionBar, footerProps.className)}\n >\n {onCancel && (\n <button\n {...cancelBtnProps}\n className={cx(cancelClass, classes?.actionBtn, cancelBtnProps.className)}\n onClick={(e) => {\n onCancel();\n if (cancelBtnProps.onClick) cancelBtnProps.onClick(e);\n }}\n >\n Cancel\n </button>\n )}\n {onSave && (\n <button\n {...saveBtnProps}\n className={cx(saveClass, classes?.actionBtn, saveBtnProps.className)}\n onClick={async (e) => {\n const helpers = await import('../utils/avatarHelpers');\n const exportData = await helpers.getAvatarData('ras-avatar-download-target');\n onSave(config, {\n config,\n svg: exportData?.svg || '',\n pngDataUrl: exportData?.pngDataUrl || '',\n });\n if (saveBtnProps.onClick) saveBtnProps.onClick(e);\n }}\n >\n Save Avatar\n </button>\n )}\n </Footer>\n );\n}\n","\n export default function styleInject(css, { insertAt } = {}) {\n if (!css || typeof document === 'undefined') return\n \n const head = document.head || document.getElementsByTagName('head')[0]\n const style = document.createElement('style')\n style.type = 'text/css'\n \n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild)\n } else {\n head.appendChild(style)\n }\n } else {\n head.appendChild(style)\n }\n \n if (style.styleSheet) {\n style.styleSheet.cssText = css\n } else {\n style.appendChild(document.createTextNode(css))\n }\n }\n ","import styleInject from '#style-inject';styleInject(\":root,.ras-theme-light{--avatar-customize-bg: #ffffff;--avatar-customize-border: #e9ecef;--avatar-customize-radius: 12px;--avatar-customize-text: #212529;--avatar-customize-muted: #868e96;--avatar-customize-primary: #aa3bff;--avatar-customize-primary-text: #ffffff;--avatar-customize-option-bg: #f8f9fa;--avatar-customize-option-active-bg: #aa3bff;--avatar-customize-option-active-border: #aa3bff;--avatar-customize-overlay: rgba(0, 0, 0, .4);--ras-primary: var(--avatar-customize-primary);--ras-primary-hover: #9b2cee;--ras-bg: var(--avatar-customize-bg);--ras-surface: var(--avatar-customize-option-bg);--ras-surface-hover: #f1f3f5;--ras-border: var(--avatar-customize-border);--ras-text-main: var(--avatar-customize-text);--ras-text-muted: var(--avatar-customize-muted);--ras-shadow-sm: 0 1px 3px rgba(0,0,0,.05);--ras-shadow-md: 0 4px 12px rgba(0,0,0,.08);--ras-shadow-lg: 0 12px 24px rgba(0,0,0,.12);--ras-radius-sm: 8px;--ras-radius-md: var(--avatar-customize-radius);--ras-radius-lg: 16px;--ras-radius-full: 9999px;--ras-transition: all .2s cubic-bezier(.4, 0, .2, 1);--ras-font: system-ui, -apple-system, BlinkMacSystemFont, \\\"Segoe UI\\\", Roboto, sans-serif}.ras-theme-dark{--avatar-customize-bg: #18181b;--avatar-customize-border: #3f3f46;--avatar-customize-radius: 12px;--avatar-customize-text: #fafafa;--avatar-customize-muted: #a1a1aa;--avatar-customize-primary: #8b5cf6;--avatar-customize-primary-text: #ffffff;--avatar-customize-option-bg: #27272a;--avatar-customize-option-active-bg: #8b5cf6;--avatar-customize-option-active-border: #8b5cf6;--avatar-customize-overlay: rgba(0, 0, 0, .7);--ras-primary-hover: #7c3aed;--ras-surface-hover: #3f3f46;--ras-shadow-sm: 0 1px 3px rgba(0,0,0,.3);--ras-shadow-md: 0 4px 12px rgba(0,0,0,.4);--ras-shadow-lg: 0 12px 24px rgba(0,0,0,.5)}.ras-container{font-family:var(--ras-font);background:var(--ras-bg);color:var(--ras-text-main);border-radius:var(--ras-radius-lg);box-shadow:var(--ras-shadow-lg);overflow:hidden;max-width:1000px;margin:0 auto;border:1px solid var(--ras-border)}.ras-layout{display:flex;flex-direction:column}@media(min-width:768px){.ras-layout{flex-direction:row;min-height:500px}}.ras-avatar-column{flex:0 0 auto;padding:2rem;background:var(--ras-surface);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1.5rem;border-bottom:1px solid var(--ras-border)}@media(min-width:768px){.ras-avatar-column{width:340px;border-bottom:none;border-right:1px solid var(--ras-border)}}.ras-preview-wrapper{background:var(--ras-bg);padding:1.5rem;border-radius:var(--ras-radius-lg);box-shadow:var(--ras-shadow-md);transition:transform .3s ease}.ras-preview-wrapper:hover{transform:translateY(-4px)}.ras-preview-large{width:180px;height:180px;min-width:180px;min-height:180px;flex-shrink:0}.ras-preview div,.ras-preview svg,.ras-preview path{box-sizing:content-box!important;max-width:none!important;max-height:none!important;margin:0;padding:0;line-height:normal}.ras-preview svg{transform-origin:center center}.ras-avatar-actions{display:flex;width:100%;gap:.75rem}.ras-settings-column{flex:1 1 auto;display:flex;flex-direction:column;max-height:600px;background:var(--ras-bg)}.ras-category-nav-wrapper{padding:1rem 1.5rem 0;border-bottom:1px solid var(--ras-border);background:var(--ras-bg);z-index:10}.ras-category-nav{display:flex;gap:.5rem;overflow-x:auto;padding-bottom:1rem;scrollbar-width:none}.ras-category-nav::-webkit-scrollbar{display:none}.ras-category-tab{background:transparent;border:none;padding:.5rem 1rem;font-size:.95rem;font-weight:600;color:var(--ras-text-muted);cursor:pointer;border-radius:var(--ras-radius-full);white-space:nowrap;transition:var(--ras-transition)}.ras-category-tab:hover{color:var(--ras-text-main);background:var(--ras-surface)}.ras-category-tab.active{color:#fff;background:var(--ras-primary);box-shadow:0 2px 8px #aa3bff66}.ras-category-content{flex:1;overflow-y:auto;padding:1.5rem;display:flex;flex-direction:column;gap:2rem}.ras-category-content::-webkit-scrollbar{width:6px}.ras-category-content::-webkit-scrollbar-track{background:transparent}.ras-category-content::-webkit-scrollbar-thumb{background:var(--ras-border);border-radius:10px}.ras-category-content::-webkit-scrollbar-thumb:hover{background:var(--ras-text-muted)}.ras-section-block{display:flex;flex-direction:column;gap:.75rem}.ras-section-header{display:flex;flex-direction:column;gap:.25rem}.ras-section-title{margin:0;font-size:1rem;font-weight:600;color:var(--ras-text-main)}.ras-section-desc{margin:0;font-size:.85rem;color:var(--ras-text-muted)}.ras-options-grid{display:flex;flex-wrap:wrap;gap:.5rem}.ras-options-color{gap:.75rem}.ras-option-btn{background:var(--ras-surface);border:1px solid var(--ras-border);color:var(--ras-text-main);padding:.5rem 1rem;border-radius:var(--ras-radius-full);font-size:.9rem;font-weight:500;cursor:pointer;transition:var(--ras-transition)}.ras-option-btn:hover{background:var(--ras-surface-hover);border-color:var(--ras-text-muted)}.ras-option-btn.active{background:var(--ras-primary);border-color:var(--ras-primary);color:#fff;box-shadow:0 2px 6px #aa3bff4d}.ras-color-btn{width:36px;height:36px;border-radius:50%;border:2px solid transparent;cursor:pointer;transition:var(--ras-transition);position:relative;display:flex;align-items:center;justify-content:center;box-shadow:var(--ras-shadow-sm);padding:0}.ras-color-btn:hover{transform:scale(1.1);box-shadow:var(--ras-shadow-md)}.ras-color-btn.active{border-color:var(--ras-primary);transform:scale(1.1)}.ras-color-check{color:#ffffffe6;width:18px;height:18px;display:flex;align-items:center;justify-content:center;text-shadow:0 1px 2px rgba(0,0,0,.5);mix-blend-mode:difference}.ras-footer-actions{padding:1.25rem 1.5rem;border-top:1px solid var(--ras-border);background:var(--ras-surface);display:flex;justify-content:flex-end;gap:1rem}.ras-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;padding:.75rem 1.5rem;border-radius:var(--ras-radius-full);font-size:.95rem;font-weight:600;cursor:pointer;transition:var(--ras-transition);border:none;font-family:inherit}.ras-btn-primary{background:var(--ras-primary);color:#fff;box-shadow:0 4px 12px #aa3bff4d}.ras-btn-primary:hover{background:var(--ras-primary-hover);transform:translateY(-1px);box-shadow:0 6px 16px #aa3bff66}.ras-btn-secondary{background:var(--ras-bg);color:var(--ras-text-main);border:1px solid var(--ras-border);box-shadow:var(--ras-shadow-sm);width:100%}.ras-btn-secondary:hover{background:var(--ras-surface);border-color:var(--ras-text-muted)}.ras-btn-ghost{background:transparent;color:var(--ras-text-muted)}.ras-btn-ghost:hover{background:var(--ras-surface);color:var(--ras-text-main)}.ras-container[data-preview=top] .ras-layout{flex-direction:column}.ras-container[data-preview=bottom] .ras-layout{flex-direction:column-reverse}@media(min-width:768px){.ras-container[data-preview=left] .ras-layout{flex-direction:row}.ras-container[data-preview=right] .ras-layout{flex-direction:row-reverse}.ras-container[data-preview=right] .ras-avatar-column{border-right:none;border-left:1px solid var(--ras-border)}}\\n\")","import React, { useEffect, useRef } from 'react';\nimport type { AvatarCustomizeModalProps } from '../types';\nimport { AvatarCustomizeInline } from './AvatarCustomizeInline';\nimport '../styles/index.css';\n\nexport function AvatarCustomizeModal(props: AvatarCustomizeModalProps) {\n const { open, onClose, modalClassName, overlayClassName, ...inlineProps } = props;\n const modalRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && open) {\n onClose();\n }\n };\n\n if (open) {\n document.addEventListener('keydown', handleKeyDown);\n // Optional: Prevent body scroll here\n document.body.style.overflow = 'hidden';\n } else {\n document.body.style.overflow = '';\n }\n\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n document.body.style.overflow = '';\n };\n }, [open, onClose]);\n\n if (!open) return null;\n\n return (\n <div className={`ras-modal-overlay ${overlayClassName || ''}`}>\n <div \n className=\"ras-modal-backdrop\" \n onClick={onClose}\n aria-hidden=\"true\"\n />\n <div \n className={`ras-modal-content ${modalClassName || ''}`} \n ref={modalRef}\n role=\"dialog\"\n aria-modal=\"true\"\n >\n <div className=\"ras-modal-body\">\n <AvatarCustomizeInline\n {...inlineProps}\n onCancel={() => {\n if (inlineProps.onCancel) inlineProps.onCancel();\n onClose();\n }}\n onSave={(config, exportData) => {\n if (inlineProps.onSave) inlineProps.onSave(config, exportData);\n onClose();\n }}\n />\n </div>\n </div>\n </div>\n );\n}\n\nexport default AvatarCustomizeModal;\n"],"mappings":"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","names":["REACT_NICE_AVATAR_SECTIONS","useState","useEffect","useCallback","genConfig","useAvatarCustomize","value","defaultValue","onChange","hiddenSections","sectionOrder","isControlled","internalConfig","setInternalConfig","useState","genConfig","activeSectionId","setActiveSectionId","config","sections","REACT_NICE_AVATAR_SECTIONS","a","indexA","indexB","useEffect","updateConfig","useCallback","newConfigPartial","updated","randomize","random","reset","defaultConf","handleOptionChange","sectionId","Avatar","genConfig","jsx","AvatarPreview","config","className","style","id","finalConfig","useState","useMemo","useEffect","useMemo","useThemeStyles","theme","t","s","cx","names","jsx","jsxs","AvatarPreviewColumn","config","randomize","unstyled","classes","classNames","components","slots","slotProps","PreviewWrapper","previewProps","randomizeBtnProps","downloadBtnProps","previewClass","downloadBtnClass","cx","AvatarPreview","e","m","jsx","AvatarCategoryNav","categories","activeCategory","setActiveCategory","layout","unstyled","classes","classNames","slotProps","tabProps","tabClass","cx","category","e","jsx","AvatarOptionGrid","config","section","handleOptionChange","unstyled","columns","classes","classNames","components","slots","slotProps","resolvedSlots","OptionButton","optionBtnProps","colorBtnProps","gridClass","optionBtnClass","colorBtnClass","gridStyle","cx","option","isSelected","e","jsx","jsxs","AvatarSection","config","section","handleOptionChange","unstyled","labels","sectionOptionOverrides","classes","classNames","components","slots","slotProps","columns","resolvedSlots","SectionWrapper","SectionHeader","sectionWrapperProps","sectionHeaderProps","wrapperClass","headerClass","titleClass","descClass","overrides","filteredSection","o","cx","AvatarOptionGrid","jsx","AvatarSectionList","config","displaySections","handleOptionChange","unstyled","classes","classNames","components","slots","slotProps","labels","sectionOptionOverrides","columns","cx","section","AvatarSection","jsx","jsxs","AvatarFooterActions","config","onCancel","onSave","unstyled","classes","classNames","components","slots","slotProps","Footer","footerProps","saveBtnProps","cancelBtnProps","footerClass","cancelClass","saveClass","cx","e","exportData","styleInject","css","insertAt","head","style","styleInject","jsx","jsxs","AvatarCustomizeInline","props","config","sections","handleOptionChange","randomize","useAvatarCustomize","theme","classes","classNames","style","className","unstyled","layout","previewPosition","themeStyles","useThemeStyles","containerStyle","categories","useMemo","cats","s","group","activeCategory","setActiveCategory","useState","useEffect","activeSections","displaySections","rootProps","containerClass","layoutClass","settingsClass","cx","AvatarPreviewColumn","AvatarCategoryNav","AvatarSectionList","AvatarFooterActions","useEffect","useRef","jsx","jsxs","AvatarCustomizeModal","props","open","onClose","modalClassName","overlayClassName","inlineProps","modalRef","useRef","useEffect","handleKeyDown","e","AvatarCustomizeInline","config","exportData"]}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "react-avatar-studio",
3
+ "version": "1.0.0",
4
+ "description": "A production-ready, highly modular, engine-agnostic React + TypeScript NPM package for avatar customization.",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/Sinan0333/react-avatar-studio.git"
14
+ },
15
+ "homepage": "https://github.com/Sinan0333/react-avatar-studio#readme",
16
+ "bugs": {
17
+ "url": "https://github.com/Sinan0333/react-avatar-studio/issues"
18
+ },
19
+ "scripts": {
20
+ "build": "tsup",
21
+ "dev": "tsup --watch",
22
+ "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
23
+ },
24
+ "keywords": [
25
+ "react",
26
+ "avatar",
27
+ "avatar-generator",
28
+ "avatar-creator",
29
+ "react-nice-avatar",
30
+ "customizer",
31
+ "ui-components",
32
+ "typescript",
33
+ "profile-picture",
34
+ "builder"
35
+ ],
36
+ "author": "Sinan <sinan.m.p333@gmail.com>",
37
+ "license": "MIT",
38
+ "peerDependencies": {
39
+ "react": ">=16",
40
+ "react-dom": ">=16"
41
+ },
42
+ "dependencies": {
43
+ "react-nice-avatar": "^1.5.0"
44
+ },
45
+ "devDependencies": {
46
+ "@types/react": "^18.2.0",
47
+ "@types/react-dom": "^18.2.0",
48
+ "typescript": "^5.0.0",
49
+ "tsup": "^8.0.0",
50
+ "eslint": "^8.0.0"
51
+ }
52
+ }