@pieai/swimmer-avatar-kit 0.1.0 → 0.3.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/README.md CHANGED
@@ -20,6 +20,29 @@ React Three Fiber consumers also install compatible React and R3F versions:
20
20
  pnpm add react @react-three/fiber
21
21
  ```
22
22
 
23
+ ## Compact portraits
24
+
25
+ Use the same avatar identity in DOM UI without opening one WebGL context per
26
+ chip. The pure portrait helpers complete the recipe and preserve its palette,
27
+ species, body silhouette, eyes, mouth, facial mark, and dressed state.
28
+
29
+ ```ts
30
+ import {
31
+ createAvatarPortraitDataUrl,
32
+ randomRecipe,
33
+ } from "@pieai/swimmer-avatar-kit";
34
+
35
+ const recipe = randomRecipe("user-42");
36
+ const src = createAvatarPortraitDataUrl(recipe, {
37
+ size: 96,
38
+ title: "Ada's avatar",
39
+ });
40
+ ```
41
+
42
+ Use the returned URL in `<img src>`, CSS, canvas, or a native bridge. Use
43
+ `createAvatarPortraitSvg` when the caller needs the raw SVG. Both functions are
44
+ framework-neutral and deterministic; the host still owns storage and alt text.
45
+
23
46
  ## React Three Fiber
24
47
 
25
48
  ```tsx
@@ -52,8 +75,14 @@ import {
52
75
  } from "@pieai/swimmer-avatar-kit";
53
76
  import {
54
77
  createStudioMaterialLibrary,
78
+ dressScene,
55
79
  } from "@pieai/swimmer-avatar-kit/materials";
56
80
 
81
+ // Optional. `buildAvatar` never touches the scene it is mounted into, so a
82
+ // host that already has lighting keeps it. Call this to get the lighting the
83
+ // reference lab uses: ACES, a key light, hemisphere fill, background, floor.
84
+ dressScene(scene, renderer);
85
+
57
86
  const materials = createStudioMaterialLibrary(renderer);
58
87
  const avatar = buildAvatar(randomRecipe("user-42"), {
59
88
  materialFor: materials.materialFor,
@@ -98,7 +127,7 @@ identity policy.
98
127
 
99
128
  | Entry point | Purpose | Runtime |
100
129
  | --- | --- | --- |
101
- | `@pieai/swimmer-avatar-kit` | Recipes, metadata, build/update/dispose | Three.js |
130
+ | `@pieai/swimmer-avatar-kit` | Recipes, compact portraits, build/update/dispose | Pure SVG + Three.js |
102
131
  | `@pieai/swimmer-avatar-kit/materials` | Gloss materials and studio environment | Browser/WebGL |
103
132
  | `@pieai/swimmer-avatar-kit/react-three-fiber` | `<Avatar />` adapter | React + R3F |
104
133
 
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export { buildAvatar } from "./avatar.js";
2
+ export { createAvatarPortraitDataUrl, createAvatarPortraitSvg } from "./portrait.js";
3
+ export type { AvatarPortraitOptions } from "./portrait.js";
2
4
  export { assertAvatarRecipe, AVATAR_RECIPE_SCHEMA, AVATAR_RECIPE_VERSION, cloneAvatarRecipe, completeRecipe, createAvatarRecipe, createAvatarRecipeDocument, deserializeAvatarRecipe, EXPRESSIONS, fillRecipe, PALETTES, parseAvatarRecipeDocument, PARTS, randomRecipe, rerollPart, serializeAvatarRecipe, SPECIES, } from "./recipe.js";
3
5
  export type { AvatarBounds, AvatarBuildOptions, AvatarBuildStats, AvatarExpression, AvatarHandle, AvatarMaterialFor, AvatarOption, AvatarPaletteOption, AvatarPartRecipe, AvatarRecipe, AvatarRecipeDocument, AvatarRecipeDocumentV1, AvatarSeed, } from "./types.js";
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export { buildAvatar } from "./avatar.js";
2
+ export { createAvatarPortraitDataUrl, createAvatarPortraitSvg } from "./portrait.js";
2
3
  export { assertAvatarRecipe, AVATAR_RECIPE_SCHEMA, AVATAR_RECIPE_VERSION, cloneAvatarRecipe, completeRecipe, createAvatarRecipe, createAvatarRecipeDocument, deserializeAvatarRecipe, EXPRESSIONS, fillRecipe, PALETTES, parseAvatarRecipeDocument, PARTS, randomRecipe, rerollPart, serializeAvatarRecipe, SPECIES, } from "./recipe.js";
3
4
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,0BAA0B,EAC1B,uBAAuB,EACvB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,yBAAyB,EACzB,KAAK,EACL,YAAY,EACZ,UAAU,EACV,qBAAqB,EACrB,OAAO,GACR,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAErF,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,0BAA0B,EAC1B,uBAAuB,EACvB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,yBAAyB,EACzB,KAAK,EACL,YAAY,EACZ,UAAU,EACV,qBAAqB,EACrB,OAAO,GACR,MAAM,aAAa,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { Texture, WebGLRenderer } from "three";
1
+ import type { Object3D, Scene, Texture, WebGLRenderer } from "three";
2
2
  import type { AvatarMaterialFor, AvatarOption } from "./types.js";
3
3
  export interface AvatarMaterialLibrary {
4
4
  readonly environment: Texture;
@@ -18,3 +18,40 @@ export declare const FINISHES: readonly AvatarOption[];
18
18
  export declare function createGlossMaterialLibrary(environment: Texture, options?: AvatarMaterialLibraryOptions): AvatarMaterialLibrary;
19
19
  export declare function createStudioMaterialLibrary(renderer: WebGLRenderer): AvatarMaterialLibrary;
20
20
  export declare function acquireStudioMaterialLibrary(renderer: WebGLRenderer): AvatarMaterialLibraryLease;
21
+ export interface AvatarStudioOptions {
22
+ /** Width of the shadow-catching floor, in world units. Default 6.4. */
23
+ span?: number;
24
+ /** How dark the contact pool under the character reads. Default 0.19. */
25
+ pool?: number;
26
+ /**
27
+ * `true` for a floor, `"wall"` for a backdrop a grid of characters can throw
28
+ * short shadows onto, `false` for neither.
29
+ */
30
+ shadows?: boolean | "wall";
31
+ /** Depth of the backdrop when `shadows` is `"wall"`. Default 1.7. */
32
+ wallZ?: number;
33
+ }
34
+ export interface AvatarStudio {
35
+ /** The key light. */
36
+ readonly key: Object3D;
37
+ /** The shadow-catching ground plane. */
38
+ readonly floor: Object3D;
39
+ /** The backdrop, present only when `shadows` was `"wall"`. */
40
+ readonly wall?: Object3D;
41
+ }
42
+ /**
43
+ * Light a scene the way the generator's own studio does: ACES tone mapping and
44
+ * exposure on the renderer, a key light, hemisphere fill, a background, and a
45
+ * shadow-catching floor.
46
+ *
47
+ * This is deliberately separate from the material library. `Avatar` leases
48
+ * materials and builds a character; it does not touch the scene it is mounted
49
+ * into, because a host that already has its own lighting must not have it
50
+ * overwritten. A host that wants the character to look the way the reference
51
+ * lab looks calls this once, and this is the whole of the difference.
52
+ *
53
+ * It mutates `renderer` and `scene` rather than returning something to mount:
54
+ * tone mapping and shadow-map type are renderer state, and there is no honest
55
+ * way to express them as a returned object.
56
+ */
57
+ export declare function dressScene(scene: Scene, renderer: WebGLRenderer, options?: AvatarStudioOptions): AvatarStudio;
package/dist/materials.js CHANGED
@@ -1,4 +1,4 @@
1
- import { makeMaterialFactory, MATERIALS, studioEnv, } from "../vendor/kindergrimm/src/gloss/gmedia.js";
1
+ import { dressScene as dressSceneUpstream, makeMaterialFactory, MATERIALS, studioEnv, } from "../vendor/kindergrimm/src/gloss/gmedia.js";
2
2
  export const FINISHES = Object.freeze(MATERIALS.map((material) => ({ id: material.id, label: material.label })));
3
3
  export function createGlossMaterialLibrary(environment, options = {}) {
4
4
  const materialForUpstream = makeMaterialFactory(environment);
@@ -58,4 +58,22 @@ export function acquireStudioMaterialLibrary(renderer) {
58
58
  },
59
59
  };
60
60
  }
61
+ /**
62
+ * Light a scene the way the generator's own studio does: ACES tone mapping and
63
+ * exposure on the renderer, a key light, hemisphere fill, a background, and a
64
+ * shadow-catching floor.
65
+ *
66
+ * This is deliberately separate from the material library. `Avatar` leases
67
+ * materials and builds a character; it does not touch the scene it is mounted
68
+ * into, because a host that already has its own lighting must not have it
69
+ * overwritten. A host that wants the character to look the way the reference
70
+ * lab looks calls this once, and this is the whole of the difference.
71
+ *
72
+ * It mutates `renderer` and `scene` rather than returning something to mount:
73
+ * tone mapping and shadow-map type are renderer state, and there is no honest
74
+ * way to express them as a returned object.
75
+ */
76
+ export function dressScene(scene, renderer, options = {}) {
77
+ return dressSceneUpstream(scene, renderer, options);
78
+ }
61
79
  //# sourceMappingURL=materials.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"materials.js","sourceRoot":"","sources":["../src/materials.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,SAAS,GACV,MAAM,2CAA2C,CAAC;AAqBnD,MAAM,CAAC,MAAM,QAAQ,GAA4B,MAAM,CAAC,MAAM,CAC5D,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAC1E,CAAC;AAEF,MAAM,UAAU,0BAA0B,CACxC,WAAoB,EACpB,UAAwC,EAAE;IAE1C,MAAM,mBAAmB,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,IAAI,GAAG,EAAY,CAAC;IACtC,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,WAAW,GAAsB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QACrE,IAAI,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC5E,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAClE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxB,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO;QACL,WAAW;QACX,WAAW;QACX,IAAI,QAAQ;YACV,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO;YACL,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,KAAK,MAAM,QAAQ,IAAI,SAAS;gBAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrD,SAAS,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,OAAO,CAAC,kBAAkB,KAAK,IAAI;gBAAE,WAAW,CAAC,OAAO,EAAE,CAAC;QACjE,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,QAAuB;IACjE,OAAO,0BAA0B,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;AACvF,CAAC;AAOD,MAAM,YAAY,GAAG,IAAI,OAAO,EAAoC,CAAC;AAErE,MAAM,UAAU,4BAA4B,CAAC,QAAuB;IAClE,IAAI,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrC,KAAK,GAAG,EAAE,OAAO,EAAE,2BAA2B,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;QAC1E,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACpC,CAAC;IACD,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC;IACtB,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,QAAQ;YACV,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO;YACL,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC;YACtB,IAAI,KAAK,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;gBAC3B,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBACxB,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"materials.js","sourceRoot":"","sources":["../src/materials.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { AvatarRecipe } from "./types.js";
2
+ export interface AvatarPortraitOptions {
3
+ /** Raster display size. The SVG keeps a 100 × 100 viewBox. */
4
+ size?: number;
5
+ /** Optional accessible name embedded as an SVG title. */
6
+ title?: string;
7
+ }
8
+ /**
9
+ * Render a deterministic compact portrait from the same completed recipe as
10
+ * the 3D avatar. The result is pure SVG: no DOM, React, canvas, or WebGL.
11
+ */
12
+ export declare function createAvatarPortraitSvg(input: AvatarRecipe, options?: AvatarPortraitOptions): string;
13
+ /** A browser-ready data URL for `<img src>`, CSS, canvas, or native bridges. */
14
+ export declare function createAvatarPortraitDataUrl(recipe: AvatarRecipe, options?: AvatarPortraitOptions): string;
@@ -0,0 +1,167 @@
1
+ import { completeRecipe, PALETTES } from "./recipe.js";
2
+ const DEFAULT_SIZE = 96;
3
+ const MIN_SIZE = 16;
4
+ const MAX_SIZE = 1024;
5
+ const INK = "#20312d";
6
+ const PAPER = "#fff8e8";
7
+ function escapeXml(value) {
8
+ return value.replace(/[&<>"']/g, (character) => {
9
+ if (character === "&")
10
+ return "&amp;";
11
+ if (character === "<")
12
+ return "&lt;";
13
+ if (character === ">")
14
+ return "&gt;";
15
+ if (character === '"')
16
+ return "&quot;";
17
+ return "&apos;";
18
+ });
19
+ }
20
+ function paramsFor(recipe, partId) {
21
+ const value = recipe.parts[partId]?.params;
22
+ return typeof value === "object" && value !== null && !Array.isArray(value)
23
+ ? value
24
+ : {};
25
+ }
26
+ function stringParam(params, key, fallback) {
27
+ return typeof params[key] === "string" ? params[key] : fallback;
28
+ }
29
+ function booleanParam(params, key) {
30
+ return params[key] === true;
31
+ }
32
+ function numberParam(params, key, fallback) {
33
+ const value = params[key];
34
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
35
+ }
36
+ function portraitSize(size) {
37
+ if (size === undefined)
38
+ return DEFAULT_SIZE;
39
+ if (!Number.isFinite(size))
40
+ throw new TypeError("Avatar portrait size must be finite.");
41
+ return Math.round(Math.min(MAX_SIZE, Math.max(MIN_SIZE, size)));
42
+ }
43
+ function paletteColors(recipe) {
44
+ const palette = PALETTES.find((candidate) => candidate.id === recipe.palette) ?? PALETTES[0];
45
+ if (!palette)
46
+ return ["#cfc6d9", "#7b7bb0", "#f5c48a"];
47
+ const length = Math.max(1, palette.colors.length);
48
+ const index = Math.min(recipe.colorIx ?? 0, length - 1);
49
+ const primary = palette.colors[index] ?? palette.colors[0] ?? "#cfc6d9";
50
+ return [
51
+ primary,
52
+ palette.colors[(index + 1) % length] ?? primary,
53
+ palette.colors[(index + 2) % length] ?? primary,
54
+ ];
55
+ }
56
+ function crestMarkup(species, accent, secondary) {
57
+ if (species === "cat") {
58
+ return `<path d="M22 32 28 6 44 29ZM56 29 72 6 78 32Z" fill="${accent}" stroke="${INK}" stroke-width="4" stroke-linejoin="round"/><path d="m28 15 4 13h7zm44 0-4 13h-7z" fill="${secondary}"/>`;
59
+ }
60
+ if (species === "bunny") {
61
+ return `<rect x="25" y="2" width="17" height="39" rx="9" fill="${accent}" stroke="${INK}" stroke-width="4" transform="rotate(-7 33.5 21.5)"/><rect x="58" y="2" width="17" height="39" rx="9" fill="${accent}" stroke="${INK}" stroke-width="4" transform="rotate(7 66.5 21.5)"/><path d="M33 10v23M67 10v23" stroke="${secondary}" stroke-width="5" stroke-linecap="round"/>`;
62
+ }
63
+ if (species === "bear") {
64
+ return `<circle cx="25" cy="25" r="14" fill="${accent}" stroke="${INK}" stroke-width="4"/><circle cx="75" cy="25" r="14" fill="${accent}" stroke="${INK}" stroke-width="4"/><circle cx="25" cy="25" r="6" fill="${secondary}"/><circle cx="75" cy="25" r="6" fill="${secondary}"/>`;
65
+ }
66
+ if (species === "robot") {
67
+ return `<path d="M50 23V10" stroke="${INK}" stroke-width="5" stroke-linecap="round"/><circle cx="50" cy="8" r="6" fill="${secondary}" stroke="${INK}" stroke-width="3"/><rect x="22" y="17" width="13" height="15" rx="5" fill="${accent}" stroke="${INK}" stroke-width="4"/><rect x="65" y="17" width="13" height="15" rx="5" fill="${accent}" stroke="${INK}" stroke-width="4"/>`;
68
+ }
69
+ if (species === "monster") {
70
+ return `<path d="M25 31 17 8l23 19m35 4 8-23-23 19" fill="${secondary}" stroke="${INK}" stroke-width="4" stroke-linejoin="round"/>`;
71
+ }
72
+ if (species === "slime") {
73
+ return `<path d="M24 32Q28 8 39 27 50 3 61 27 72 8 76 32Z" fill="${accent}" stroke="${INK}" stroke-width="4" stroke-linejoin="round"/>`;
74
+ }
75
+ if (species === "rock") {
76
+ return `<path d="m30 31 8-21 12 13 11-16 10 24Z" fill="${accent}" stroke="${INK}" stroke-width="4" stroke-linejoin="round"/>`;
77
+ }
78
+ if (species === "humanoid") {
79
+ return `<path d="M21 35Q25 7 50 8t29 27Q67 23 50 28 35 20 21 35Z" fill="${accent}" stroke="${INK}" stroke-width="4"/>`;
80
+ }
81
+ return `<path d="m50 5 7 15 17 2-12 12 3 17-15-8-15 8 3-17-12-12 17-2Z" fill="${secondary}" stroke="${INK}" stroke-width="4" stroke-linejoin="round"/>`;
82
+ }
83
+ function headMarkup(body) {
84
+ if (body === "sphere") {
85
+ return `<ellipse cx="50" cy="52" rx="36" ry="33" fill="url(#avatar-head)" stroke="${INK}" stroke-width="4"/>`;
86
+ }
87
+ if (body === "rock") {
88
+ return `<path d="M18 35 31 19l26-5 24 17 5 27-15 25-34 3-23-20Z" fill="url(#avatar-head)" stroke="${INK}" stroke-width="4" stroke-linejoin="round"/>`;
89
+ }
90
+ if (body === "drop") {
91
+ return `<path d="M50 13C42 27 16 46 16 63c0 18 14 27 34 27s34-9 34-27C84 46 58 27 50 13Z" fill="url(#avatar-head)" stroke="${INK}" stroke-width="4"/>`;
92
+ }
93
+ return `<rect x="14" y="20" width="72" height="67" rx="18" fill="url(#avatar-head)" stroke="${INK}" stroke-width="4"/>`;
94
+ }
95
+ function eyeMarkup(style, wink, secondary) {
96
+ const left = wink
97
+ ? `<path d="M29 50q7 7 14 0" fill="none" stroke="${INK}" stroke-width="5" stroke-linecap="round"/>`
98
+ : eyeShape(style, 36, secondary);
99
+ return `${left}${eyeShape(style, 64, secondary)}`;
100
+ }
101
+ function eyeShape(style, x, secondary) {
102
+ if (style === "happy") {
103
+ return `<path d="M${x - 7} 52q7-8 14 0" fill="none" stroke="${INK}" stroke-width="5" stroke-linecap="round"/>`;
104
+ }
105
+ if (style === "sleepy") {
106
+ return `<path d="M${x - 8} 51q8 5 16 0" fill="none" stroke="${INK}" stroke-width="5" stroke-linecap="round"/>`;
107
+ }
108
+ if (style === "box" || style === "slab") {
109
+ return `<rect x="${x - 8}" y="43" width="16" height="14" rx="4" fill="${INK}"/><rect x="${x - 3}" y="46" width="6" height="5" rx="2" fill="${secondary}"/>`;
110
+ }
111
+ return `<ellipse cx="${x}" cy="50" rx="8" ry="10" fill="${INK}"/><circle cx="${x + 2}" cy="47" r="3" fill="${PAPER}"/>`;
112
+ }
113
+ function mouthMarkup(style, secondary) {
114
+ if (style === "flat") {
115
+ return `<path d="M42 69h16" stroke="${INK}" stroke-width="5" stroke-linecap="round"/>`;
116
+ }
117
+ if (style === "zig") {
118
+ return `<path d="m38 68 7-5 6 8 6-8 6 5" fill="none" stroke="${INK}" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>`;
119
+ }
120
+ if (style === "cat") {
121
+ return `<path d="M50 64v4m0 0q-8 8-13 0m13 0q8 8 13 0" fill="none" stroke="${INK}" stroke-width="4" stroke-linecap="round"/>`;
122
+ }
123
+ if (style === "grin") {
124
+ return `<path d="M36 64q14 18 28 0Z" fill="${PAPER}" stroke="${INK}" stroke-width="4" stroke-linejoin="round"/><path d="M43 67v6m7-7v10m7-9v6" stroke="${secondary}" stroke-width="2"/>`;
125
+ }
126
+ return `<path d="M38 65q12 13 24 0" fill="none" stroke="${INK}" stroke-width="5" stroke-linecap="round"/>`;
127
+ }
128
+ function markMarkup(style, side, secondary) {
129
+ const x = side < 0 ? 28 : 72;
130
+ if (style === "spot") {
131
+ return `<circle cx="${x}" cy="35" r="9" fill="${secondary}" opacity=".72"/>`;
132
+ }
133
+ if (style === "scar") {
134
+ return `<path d="m${x - 5} 35 10 16m-9-10 7-4m-4 10 7-4" stroke="${secondary}" stroke-width="3" stroke-linecap="round"/>`;
135
+ }
136
+ if (style === "sutures") {
137
+ return `<path d="m${x - 7} 35 14 17m-11-12 7-4m-3 9 7-4m-3 9 6-3" stroke="${secondary}" stroke-width="3" stroke-linecap="round"/>`;
138
+ }
139
+ return "";
140
+ }
141
+ /**
142
+ * Render a deterministic compact portrait from the same completed recipe as
143
+ * the 3D avatar. The result is pure SVG: no DOM, React, canvas, or WebGL.
144
+ */
145
+ export function createAvatarPortraitSvg(input, options = {}) {
146
+ const recipe = completeRecipe(input);
147
+ const size = portraitSize(options.size);
148
+ const species = recipe.species ?? "wildcard";
149
+ const body = recipe.body ?? "cube";
150
+ const [primary, accent, secondary] = paletteColors(recipe);
151
+ const eyeParams = paramsFor(recipe, "eyes");
152
+ const mouthParams = paramsFor(recipe, "mouth");
153
+ const markParams = paramsFor(recipe, "mark");
154
+ const frameParams = paramsFor(recipe, "frame");
155
+ const eyeStyle = stringParam(eyeParams, "style", "bead");
156
+ const mouthStyle = stringParam(mouthParams, "style", "smile");
157
+ const markStyle = stringParam(markParams, "style", "none");
158
+ const markSide = numberParam(markParams, "side", 1);
159
+ const dressed = booleanParam(frameParams, "dressed");
160
+ const title = options.title ? `<title>${escapeXml(options.title)}</title>` : "";
161
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 100 100" role="img" data-avatar-seed="${recipe.seed}" data-avatar-species="${escapeXml(species)}" data-avatar-palette="${escapeXml(recipe.palette ?? "unknown")}">${title}<defs><linearGradient id="avatar-bg" x1="0" y1="0" x2="1" y2="1"><stop stop-color="${secondary}"/><stop offset="1" stop-color="${accent}"/></linearGradient><linearGradient id="avatar-head" x1="0" y1="0" x2=".75" y2="1"><stop stop-color="${PAPER}" stop-opacity=".58"/><stop offset=".18" stop-color="${primary}"/><stop offset="1" stop-color="${accent}"/></linearGradient></defs><rect width="100" height="100" rx="50" fill="url(#avatar-bg)"/><circle cx="50" cy="49" r="44" fill="${PAPER}" opacity=".46"/><ellipse cx="50" cy="88" rx="30" ry="6" fill="${INK}" opacity=".2"/>${crestMarkup(species, accent, secondary)}${dressed ? `<path d="M25 86q25-18 50 0v10H25Z" fill="${secondary}" stroke="${INK}" stroke-width="4"/>` : ""}${headMarkup(body)}${markMarkup(markStyle, markSide, secondary)}${eyeMarkup(eyeStyle, booleanParam(eyeParams, "wink"), secondary)}${mouthMarkup(mouthStyle, secondary)}<path d="M28 31q18-13 39-2" fill="none" stroke="${PAPER}" stroke-width="5" stroke-linecap="round" opacity=".48"/></svg>`;
162
+ }
163
+ /** A browser-ready data URL for `<img src>`, CSS, canvas, or native bridges. */
164
+ export function createAvatarPortraitDataUrl(recipe, options = {}) {
165
+ return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(createAvatarPortraitSvg(recipe, options))}`;
166
+ }
167
+ //# sourceMappingURL=portrait.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portrait.js","sourceRoot":"","sources":["../src/portrait.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pieai/swimmer-avatar-kit",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Shared procedural 3D avatar recipes, Three.js runtime, and React Three Fiber adapter for PieAI products.",
5
5
  "keywords": [
6
6
  "avatar",