@inlaylab/opaline-angular 1.0.0 → 1.1.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.
|
@@ -52,6 +52,7 @@ var OpalineAvatar = class OpalineAvatar {
|
|
|
52
52
|
finish = input(...ngDevMode ? [void 0, { debugName: "finish" }] : /* istanbul ignore next */ []);
|
|
53
53
|
body = input(...ngDevMode ? [void 0, { debugName: "body" }] : /* istanbul ignore next */ []);
|
|
54
54
|
ears = input(...ngDevMode ? [void 0, { debugName: "ears" }] : /* istanbul ignore next */ []);
|
|
55
|
+
text = input(...ngDevMode ? [void 0, { debugName: "text" }] : /* istanbul ignore next */ []);
|
|
55
56
|
state = signal("loading", ...ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []);
|
|
56
57
|
svg = computed(() => {
|
|
57
58
|
const svg = createAvatar(this.look(), {
|
|
@@ -67,7 +68,8 @@ var OpalineAvatar = class OpalineAvatar {
|
|
|
67
68
|
shape: this.shape(),
|
|
68
69
|
finish: this.finish(),
|
|
69
70
|
body: this.body(),
|
|
70
|
-
ears: this.ears()
|
|
71
|
+
ears: this.ears(),
|
|
72
|
+
text: this.text()
|
|
71
73
|
}).svg;
|
|
72
74
|
return this.sanitizer.bypassSecurityTrustHtml(svg);
|
|
73
75
|
}, ...ngDevMode ? [{ debugName: "svg" }] : /* istanbul ignore next */ []);
|
|
@@ -200,6 +202,13 @@ var OpalineAvatar = class OpalineAvatar {
|
|
|
200
202
|
isSignal: true,
|
|
201
203
|
isRequired: false,
|
|
202
204
|
transformFunction: null
|
|
205
|
+
},
|
|
206
|
+
text: {
|
|
207
|
+
classPropertyName: "text",
|
|
208
|
+
publicName: "text",
|
|
209
|
+
isSignal: true,
|
|
210
|
+
isRequired: false,
|
|
211
|
+
transformFunction: null
|
|
203
212
|
}
|
|
204
213
|
},
|
|
205
214
|
host: {
|
|
@@ -221,7 +230,11 @@ var OpalineAvatar = class OpalineAvatar {
|
|
|
221
230
|
"attr.mood": "null",
|
|
222
231
|
"attr.expression": "null",
|
|
223
232
|
"attr.backdrop": "null",
|
|
224
|
-
"attr.shape": "null"
|
|
233
|
+
"attr.shape": "null",
|
|
234
|
+
"attr.text": "null",
|
|
235
|
+
"attr.finish": "null",
|
|
236
|
+
"attr.body": "null",
|
|
237
|
+
"attr.ears": "null"
|
|
225
238
|
},
|
|
226
239
|
styleAttribute: "display:inline-block;position:relative"
|
|
227
240
|
},
|
|
@@ -278,7 +291,11 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
278
291
|
"[attr.mood]": "null",
|
|
279
292
|
"[attr.expression]": "null",
|
|
280
293
|
"[attr.backdrop]": "null",
|
|
281
|
-
"[attr.shape]": "null"
|
|
294
|
+
"[attr.shape]": "null",
|
|
295
|
+
"[attr.text]": "null",
|
|
296
|
+
"[attr.finish]": "null",
|
|
297
|
+
"[attr.body]": "null",
|
|
298
|
+
"[attr.ears]": "null"
|
|
282
299
|
},
|
|
283
300
|
template: `<span style="display:contents" [innerHTML]="svg()"></span>
|
|
284
301
|
@if (src() && state() !== 'error') {
|
|
@@ -419,6 +436,14 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
419
436
|
alias: "ears",
|
|
420
437
|
required: false
|
|
421
438
|
}]
|
|
439
|
+
}],
|
|
440
|
+
text: [{
|
|
441
|
+
type: i0.Input,
|
|
442
|
+
args: [{
|
|
443
|
+
isSignal: true,
|
|
444
|
+
alias: "text",
|
|
445
|
+
required: false
|
|
446
|
+
}]
|
|
422
447
|
}]
|
|
423
448
|
}
|
|
424
449
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inlaylab-opaline-angular.mjs","names":[],"sources":["../../src/ids.ts","../../src/avatar.ts"],"sourcesContent":["import { Injectable } from '@angular/core'\n\n/** Per-app counter. Server and client render in the same order, so IDs match on hydration. */\n@Injectable({ providedIn: 'root' })\nexport class OpalineIds {\n private count = 0\n\n next(): string {\n return `n${++this.count}`\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n signal,\n untracked,\n viewChild,\n} from '@angular/core'\nimport { DomSanitizer, type SafeHtml } from '@angular/platform-browser'\nimport {\n createAvatar,\n type AuraOptions,\n type BlobOptions,\n type ClayOptions,\n type Finish,\n type Expression,\n type Family,\n type Mood,\n type PaletteName,\n type Style,\n} from '@inlaylab/opaline'\nimport { OpalineIds } from './ids'\n\ntype ImageState = 'loading' | 'loaded' | 'error'\n\n/** `<op-avatar seed=\"ada@inlay.dev\" [look]=\"morph\" />`: a seeded avatar with an optional photo. */\n@Component({\n selector: 'op-avatar',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n 'data-opaline': '',\n style: 'display:inline-block;position:relative',\n '[style.width.px]': 'size()',\n '[style.height.px]': 'size()',\n '[attr.role]': 'alt() ? \"img\" : null',\n '[attr.aria-label]': 'alt() || null',\n '[attr.aria-hidden]': 'alt() ? null : \"true\"',\n // Static template attributes (`seed=\"ada@inlay.dev\"`) stay on the host; the seed is often an\n // email. Clear them so the root carries only the markup contract, on the server too.\n '[attr.seed]': 'null',\n '[attr.look]': 'null',\n '[attr.size]': 'null',\n '[attr.src]': 'null',\n '[attr.alt]': 'null',\n '[attr.palette]': 'null',\n '[attr.family]': 'null',\n '[attr.face]': 'null',\n '[attr.mood]': 'null',\n '[attr.expression]': 'null',\n '[attr.backdrop]': 'null',\n '[attr.shape]': 'null',\n },\n template: `<span style=\"display:contents\" [innerHTML]=\"svg()\"></span>\n @if (src() && state() !== 'error') {\n <img\n #img\n [src]=\"src()\"\n alt=\"\"\n style=\"position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border-radius:inherit\"\n [hidden]=\"state() !== 'loaded'\"\n (load)=\"state.set('loaded')\"\n (error)=\"state.set('error')\"\n />\n }`,\n})\nexport class OpalineAvatar {\n private readonly sanitizer = inject(DomSanitizer)\n // Unique per instance, so the same avatar twice on a page never shares gradient IDs.\n private readonly instance = inject(OpalineIds).next()\n private readonly img = viewChild<ElementRef<HTMLImageElement>>('img')\n\n readonly seed = input<string | number | null | undefined>()\n readonly look = input.required<Style<any>>()\n readonly size = input(64)\n readonly src = input<string>()\n readonly alt = input<string>()\n readonly palette = input<PaletteName>()\n readonly family = input<Family>()\n readonly face = input<boolean>()\n readonly mood = input<Mood>()\n readonly expression = input<Expression>()\n readonly backdrop = input<BlobOptions['backdrop']>()\n readonly shape = input<AuraOptions['shape']>()\n readonly finish = input<Finish>()\n readonly body = input<ClayOptions['body']>()\n readonly ears = input<ClayOptions['ears']>()\n\n protected readonly state = signal<ImageState>('loading')\n\n protected readonly svg = computed<SafeHtml>(() => {\n const svg = createAvatar(this.look(), {\n seed: this.seed(),\n size: this.size(),\n instance: this.instance,\n palette: this.palette(),\n family: this.family(),\n face: this.face(),\n mood: this.mood(),\n expression: this.expression(),\n backdrop: this.backdrop(),\n shape: this.shape(),\n finish: this.finish(),\n body: this.body(),\n ears: this.ears(),\n }).svg\n // Safe: the core escapes every input that reaches the SVG, and the default sanitizer strips SVG.\n return this.sanitizer.bypassSecurityTrustHtml(svg)\n })\n\n constructor() {\n // A new src is a new image: hide it until it loads.\n effect(() => {\n this.src()\n untracked(() => this.state.set('loading'))\n })\n // With SSR the image can finish before hydration, so its load event is missed. Read it once.\n afterNextRender(() => {\n const img = this.img()?.nativeElement\n if (img?.complete) this.state.set(img.naturalWidth > 0 ? 'loaded' : 'error')\n })\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"inlaylab-opaline-angular.mjs","names":[],"sources":["../../src/ids.ts","../../src/avatar.ts"],"sourcesContent":["import { Injectable } from '@angular/core'\n\n/** Per-app counter. Server and client render in the same order, so IDs match on hydration. */\n@Injectable({ providedIn: 'root' })\nexport class OpalineIds {\n private count = 0\n\n next(): string {\n return `n${++this.count}`\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n signal,\n untracked,\n viewChild,\n} from '@angular/core'\nimport { DomSanitizer, type SafeHtml } from '@angular/platform-browser'\nimport {\n createAvatar,\n type BlobOptions,\n type ClayOptions,\n type Finish,\n type Expression,\n type Family,\n type Mood,\n type PaletteName,\n type Shape,\n type Style,\n} from '@inlaylab/opaline'\nimport { OpalineIds } from './ids'\n\ntype ImageState = 'loading' | 'loaded' | 'error'\n\n/** `<op-avatar seed=\"ada@inlay.dev\" [look]=\"morph\" />`: a seeded avatar with an optional photo. */\n@Component({\n selector: 'op-avatar',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n 'data-opaline': '',\n style: 'display:inline-block;position:relative',\n '[style.width.px]': 'size()',\n '[style.height.px]': 'size()',\n '[attr.role]': 'alt() ? \"img\" : null',\n '[attr.aria-label]': 'alt() || null',\n '[attr.aria-hidden]': 'alt() ? null : \"true\"',\n // Static template attributes (`seed=\"ada@inlay.dev\"`) stay on the host; the seed is often an\n // email. Clear them so the root carries only the markup contract, on the server too.\n '[attr.seed]': 'null',\n '[attr.look]': 'null',\n '[attr.size]': 'null',\n '[attr.src]': 'null',\n '[attr.alt]': 'null',\n '[attr.palette]': 'null',\n '[attr.family]': 'null',\n '[attr.face]': 'null',\n '[attr.mood]': 'null',\n '[attr.expression]': 'null',\n '[attr.backdrop]': 'null',\n '[attr.shape]': 'null',\n '[attr.text]': 'null',\n '[attr.finish]': 'null',\n '[attr.body]': 'null',\n '[attr.ears]': 'null',\n },\n template: `<span style=\"display:contents\" [innerHTML]=\"svg()\"></span>\n @if (src() && state() !== 'error') {\n <img\n #img\n [src]=\"src()\"\n alt=\"\"\n style=\"position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border-radius:inherit\"\n [hidden]=\"state() !== 'loaded'\"\n (load)=\"state.set('loaded')\"\n (error)=\"state.set('error')\"\n />\n }`,\n})\nexport class OpalineAvatar {\n private readonly sanitizer = inject(DomSanitizer)\n // Unique per instance, so the same avatar twice on a page never shares gradient IDs.\n private readonly instance = inject(OpalineIds).next()\n private readonly img = viewChild<ElementRef<HTMLImageElement>>('img')\n\n readonly seed = input<string | number | null | undefined>()\n readonly look = input.required<Style<any>>()\n readonly size = input(64)\n readonly src = input<string>()\n readonly alt = input<string>()\n readonly palette = input<PaletteName>()\n readonly family = input<Family>()\n readonly face = input<boolean>()\n readonly mood = input<Mood>()\n readonly expression = input<Expression>()\n readonly backdrop = input<BlobOptions['backdrop']>()\n readonly shape = input<Shape>()\n readonly finish = input<Finish>()\n readonly body = input<ClayOptions['body']>()\n readonly ears = input<ClayOptions['ears']>()\n /** Initials only: letters to show instead of the ones from the seed. */\n readonly text = input<string>()\n\n protected readonly state = signal<ImageState>('loading')\n\n protected readonly svg = computed<SafeHtml>(() => {\n const svg = createAvatar(this.look(), {\n seed: this.seed(),\n size: this.size(),\n instance: this.instance,\n palette: this.palette(),\n family: this.family(),\n face: this.face(),\n mood: this.mood(),\n expression: this.expression(),\n backdrop: this.backdrop(),\n shape: this.shape(),\n finish: this.finish(),\n body: this.body(),\n ears: this.ears(),\n text: this.text(),\n }).svg\n // Safe: the core escapes every input that reaches the SVG, and the default sanitizer strips SVG.\n return this.sanitizer.bypassSecurityTrustHtml(svg)\n })\n\n constructor() {\n // A new src is a new image: hide it until it loads.\n effect(() => {\n this.src()\n untracked(() => this.state.set('loading'))\n })\n // With SSR the image can finish before hydration, so its load event is missed. Read it once.\n afterNextRender(() => {\n const img = this.img()?.nativeElement\n if (img?.complete) this.state.set(img.naturalWidth > 0 ? 'loaded' : 'error')\n })\n }\n}\n"],"mappings":";;;;AAIA,IAAa,aAAb,MAAa,WAAU;CACb,QAAQ;CAEhB,OAAI;EACF,OAAO,IAAI,EAAE,KAAK;CACpB;CALW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAU,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAV,OAAA,QAAA,GAAA,sBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAU,YADG;CAAM,CAAA;;AACnB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAU,YAAA,CAAA;EADtB,MAAA;EAAW,MAAA,CAAA,EAAE,YAAY,OAAM,CAAE;;;ACuElC,IAAa,gBAAb,MAAa,cAAa;CACP,YAAY,OAAO,YAAY;CAE/B,WAAW,OAAO,UAAU,CAAC,CAAC,KAAI;CAClC,MAAM,UAAwC,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,MAAA,CAAA,+BAAA,CAAA,CAAA;CAE5D,OAAO,MAA2C,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAClD,OAAO,MAAM,SAAsB,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACnC,OAAO,MAAM,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAChB,MAAM,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,MAAA,CAAA,+BAAA,CAAA,CAAA;CACrB,MAAM,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,MAAA,CAAA,+BAAA,CAAA,CAAA;CACrB,UAAU,MAAoB,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAC9B,SAAS,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CACxB,OAAO,MAAgB,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACvB,OAAO,MAAa,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACpB,aAAa,MAAmB,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAChC,WAAW,MAAgC,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAC3C,QAAQ,MAAc,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACtB,SAAS,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CACxB,OAAO,MAA4B,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACnC,OAAO,MAA4B,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAEnC,OAAO,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAEZ,QAAQ,OAAmB,WAAU,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAErC,MAAM,eAAwB;EAC/C,MAAM,MAAM,aAAa,KAAK,KAAI,GAAI;GACpC,MAAM,KAAK,KAAI;GACf,MAAM,KAAK,KAAI;GACf,UAAU,KAAK;GACf,SAAS,KAAK,QAAO;GACrB,QAAQ,KAAK,OAAM;GACnB,MAAM,KAAK,KAAI;GACf,MAAM,KAAK,KAAI;GACf,YAAY,KAAK,WAAU;GAC3B,UAAU,KAAK,SAAQ;GACvB,OAAO,KAAK,MAAK;GACjB,QAAQ,KAAK,OAAM;GACnB,MAAM,KAAK,KAAI;GACf,MAAM,KAAK,KAAI;GACf,MAAM,KAAK,KAAI;EAChB,CAAA,CAAC,CAAC;EAEH,OAAO,KAAK,UAAU,wBAAwB,GAAG;CACnD,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,MAAA,CAAA,+BAAA,CAAA,CAAA;CAEF,cAAA;EAEE,aAAY;GACV,KAAK,IAAG;GACR,gBAAgB,KAAK,MAAM,IAAI,SAAS,CAAC;EAC3C,CAAC;EAED,sBAAqB;GACnB,MAAM,MAAM,KAAK,IAAG,CAAE,EAAE;GACxB,IAAI,KAAK,UAAU,KAAK,MAAM,IAAI,IAAI,eAAe,IAAI,WAAW,OAAO;EAC7E,CAAC;CACH;CA1DW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAa,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAb,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAa,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,KAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,KAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,QAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,UAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,QAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,MAAA;GAAA,YAAA,EAAA,gBAAA,GAAA;GAAA,YAAA;IAAA,kBAAA;IAAA,mBAAA;IAAA,aAAA;IAAA,mBAAA;IAAA,oBAAA;IAAA,aAAA;IAAA,aAAA;IAAA,aAAA;IAAA,YAAA;IAAA,YAAA;IAAA,gBAAA;IAAA,eAAA;IAAA,aAAA;IAAA,aAAA;IAAA,mBAAA;IAAA,iBAAA;IAAA,cAAA;IAAA,aAAA;IAAA,eAAA;IAAA,aAAA;IAAA,aAAA;GAAA;GAAA,gBAAA;EAAA;EAAA,aAAA,CAAA;GAAA,cAAA;GAAA,OAAA;GAAA,WAAA,CAAA,KAAA;GAAA,aAAA;GAAA,UAAA;EAAA,CAAA;EAAA,UAAA;EAAA,UAbd;;;;;;;;;;;;EAWN,UAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAEO,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAa,YAAA,CAAA;EA3CzB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,iBAAiB,wBAAwB;GACzC,MAAM;IACJ,gBAAgB;IAChB,OAAO;IACP,oBAAoB;IACpB,qBAAqB;IACrB,eAAe;IACf,qBAAqB;IACrB,sBAAsB;IAGtB,eAAe;IACf,eAAe;IACf,eAAe;IACf,cAAc;IACd,cAAc;IACd,kBAAkB;IAClB,iBAAiB;IACjB,eAAe;IACf,eAAe;IACf,qBAAqB;IACrB,mBAAmB;IACnB,gBAAgB;IAChB,eAAe;IACf,iBAAiB;IACjB,eAAe;IACf,eAAe;GAChB;GACD,UAAU;;;;;;;;;;;;EAYX,CAAA;CAKgE,CAAA;CAAA,sBAAA,CAAA;CAAA,gBAAA;EAAA,KAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,OAAK,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,MAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,MAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,MAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,KAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,KAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,SAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,QAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,MAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,MAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,YAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,UAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,OAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,QAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,MAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,MAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,MAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;CAAA;AAAA,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inlaylab/opaline-angular",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Seeded avatars for Angular: a standalone, zoneless, SSR-safe component.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"avatar",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@angular/platform-browser": ">=22.0.0 <23.0.0"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@inlaylab/opaline": "1.
|
|
39
|
+
"@inlaylab/opaline": "1.1.0",
|
|
40
40
|
"tslib": "^2.3.0"
|
|
41
41
|
},
|
|
42
42
|
"module": "fesm2022/inlaylab-opaline-angular.mjs",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SafeHtml } from "@angular/platform-browser";
|
|
2
|
-
import { Expression, Family, Finish, Mood, PaletteName, Style } from "@inlaylab/opaline";
|
|
2
|
+
import { Expression, Family, Finish, Mood, PaletteName, Shape, Style } from "@inlaylab/opaline";
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
4
|
type ImageState = 'loading' | 'loaded' | 'error';
|
|
5
5
|
/** `<op-avatar seed="ada@inlay.dev" [look]="morph" />`: a seeded avatar with an optional photo. */
|
|
@@ -18,10 +18,12 @@ export declare class OpalineAvatar {
|
|
|
18
18
|
readonly mood: import("@angular/core").InputSignal<Mood | undefined>;
|
|
19
19
|
readonly expression: import("@angular/core").InputSignal<Expression | undefined>;
|
|
20
20
|
readonly backdrop: import("@angular/core").InputSignal<"none" | "tint" | undefined>;
|
|
21
|
-
readonly shape: import("@angular/core").InputSignal<
|
|
21
|
+
readonly shape: import("@angular/core").InputSignal<Shape | undefined>;
|
|
22
22
|
readonly finish: import("@angular/core").InputSignal<Finish | undefined>;
|
|
23
23
|
readonly body: import("@angular/core").InputSignal<"jelly" | "hood" | undefined>;
|
|
24
24
|
readonly ears: import("@angular/core").InputSignal<"cat" | "bear" | "bunny" | undefined>;
|
|
25
|
+
/** Initials only: letters to show instead of the ones from the seed. */
|
|
26
|
+
readonly text: import("@angular/core").InputSignal<string | undefined>;
|
|
25
27
|
protected readonly state: import("@angular/core").WritableSignal<ImageState>;
|
|
26
28
|
protected readonly svg: import("@angular/core").Signal<SafeHtml>;
|
|
27
29
|
constructor();
|
|
@@ -102,6 +104,11 @@ export declare class OpalineAvatar {
|
|
|
102
104
|
"required": false;
|
|
103
105
|
"isSignal": true;
|
|
104
106
|
};
|
|
107
|
+
"text": {
|
|
108
|
+
"alias": "text";
|
|
109
|
+
"required": false;
|
|
110
|
+
"isSignal": true;
|
|
111
|
+
};
|
|
105
112
|
}, {}, never, never, true, never>;
|
|
106
113
|
}
|
|
107
114
|
/** Per-app counter. Server and client render in the same order, so IDs match on hydration. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inlaylab-opaline-angular.d.ts","names":[],"sources":["../../src/avatar.ts","../../src/ids.ts"],"mappings":";;;KA4BK;;
|
|
1
|
+
{"version":3,"file":"inlaylab-opaline-angular.d.ts","names":[],"sources":["../../src/avatar.ts","../../src/ids.ts"],"mappings":";;;KA4BK;;qBA8CQ;mBACM;mBAEA;mBACA;WAER,8BAAI;WACJ,8BAAI,YAAA;WACJ,8BAAI;WACJ,6BAAG;WACH,6BAAG;WACH,iCAAO,YAAA;WACP,gCAAM,YAAA;WACN,8BAAI;WACJ,8BAAI,YAAA;WACJ,oCAAU,YAAA;WACV,kCAAQ;WACR,+BAAK,YAAA;WACL,gCAAM,YAAA;WACN,8BAAI;WACJ,8BAAI;;WAEJ,8BAAI;qBAEM,+BAAK,eAAA;qBAEL,6BAAG,OAAA;;SA1BX,MAAA,GAAA,qBAAA;SAAA,MAAA,GAAA,uBAAA;IAAa;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;;;;qBCtEb;UACH;EAER;SAHW,MAAA,GAAA,qBAAA"}
|