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 +21 -0
- package/README.md +163 -0
- package/dist/avatarHelpers-6323LQJA.mjs +2 -0
- package/dist/avatarHelpers-6323LQJA.mjs.map +1 -0
- package/dist/chunk-WBTMPEY3.mjs +14 -0
- package/dist/chunk-WBTMPEY3.mjs.map +1 -0
- package/dist/index.d.mts +148 -0
- package/dist/index.d.ts +148 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +52 -0
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 @@
|
|
|
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"]}
|
package/dist/index.d.mts
ADDED
|
@@ -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.d.ts
ADDED
|
@@ -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
|
+
}
|