@dicebear/core 10.0.0-rc.4 → 10.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/README.md +2 -1
- package/lib/Options.d.ts +12 -12
- package/lib/Options.js +24 -14
- package/lib/OptionsDescriptor.d.ts +1 -0
- package/lib/OptionsDescriptor.js +6 -1
- package/lib/Prng/Mulberry32.js +1 -1
- package/lib/Prng.d.ts +22 -12
- package/lib/Prng.js +69 -34
- package/lib/Renderer.js +11 -2
- package/lib/Resolver.d.ts +21 -12
- package/lib/Resolver.js +50 -40
- package/lib/Style/Component.d.ts +7 -5
- package/lib/Style/Component.js +6 -10
- package/lib/Style/ComponentTranslate.d.ts +3 -9
- package/lib/Style/ComponentTranslate.js +2 -8
- package/lib/StyleDefinition.d.ts +15 -4
- package/lib/Validator/OptionsValidator.js +4 -4
- package/lib/Validator/StyleValidator.js +694 -327
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -27,7 +27,8 @@ Playground, your next avatar is always just a stone's throw away!
|
|
|
27
27
|
|
|
28
28
|
## Sponsors
|
|
29
29
|
|
|
30
|
-
Advertisement: Many thanks to our sponsors who provide us with free or
|
|
30
|
+
Advertisement: Many thanks to our sponsors who provide us with free or
|
|
31
|
+
discounted products.
|
|
31
32
|
|
|
32
33
|
<a href="https://bunny.net/" target="_blank" rel="noopener noreferrer">
|
|
33
34
|
<picture>
|
package/lib/Options.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Range } from './StyleDefinition.js';
|
|
1
2
|
import type { StyleOptions, StyleOptionsFlipValue, StyleOptionsColorFillValue } from './StyleOptions.js';
|
|
2
3
|
/**
|
|
3
4
|
* Validates the raw user-supplied options and exposes them through typed
|
|
@@ -19,18 +20,17 @@ export declare class Options<D = unknown> {
|
|
|
19
20
|
flip(): readonly StyleOptionsFlipValue[];
|
|
20
21
|
fontFamily(): readonly string[];
|
|
21
22
|
fontWeight(): readonly number[];
|
|
22
|
-
scale():
|
|
23
|
-
borderRadius():
|
|
24
|
-
rotate():
|
|
25
|
-
translateX():
|
|
26
|
-
translateY():
|
|
23
|
+
scale(): Range | undefined;
|
|
24
|
+
borderRadius(): Range | undefined;
|
|
25
|
+
rotate(): Range | undefined;
|
|
26
|
+
translateX(): Range | undefined;
|
|
27
|
+
translateY(): Range | undefined;
|
|
27
28
|
/**
|
|
28
|
-
* Returns the user-set variant constraint for `name
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* - `Record<string, number>` when the user gave a weighted map.
|
|
29
|
+
* Returns the user-set variant constraint for `name` as a weighted map, or
|
|
30
|
+
* `undefined` when `${name}Variant` is unset. A bare string or string list
|
|
31
|
+
* is normalized to a map with each entry weighted `1`.
|
|
32
32
|
*/
|
|
33
|
-
componentVariant(name: string):
|
|
33
|
+
componentVariant(name: string): Readonly<Record<string, number>> | undefined;
|
|
34
34
|
componentProbability(name: string): number | undefined;
|
|
35
35
|
/**
|
|
36
36
|
* Asymmetric on purpose: returns `undefined` (rather than `[]`) when
|
|
@@ -39,6 +39,6 @@ export declare class Options<D = unknown> {
|
|
|
39
39
|
*/
|
|
40
40
|
color(name: string): readonly string[] | undefined;
|
|
41
41
|
colorFill(name: string): readonly StyleOptionsColorFillValue[];
|
|
42
|
-
colorAngle(name: string):
|
|
43
|
-
colorFillStops(name: string):
|
|
42
|
+
colorAngle(name: string): Range | undefined;
|
|
43
|
+
colorFillStops(name: string): Range | undefined;
|
|
44
44
|
}
|
package/lib/Options.js
CHANGED
|
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _Options_instances, _Options_data, _Options_dynamic, _Options_asArray;
|
|
12
|
+
var _Options_instances, _Options_data, _Options_dynamic, _Options_asArray, _Options_toRange;
|
|
13
13
|
import { OptionsValidator } from './Validator/OptionsValidator.js';
|
|
14
14
|
/**
|
|
15
15
|
* Validates the raw user-supplied options and exposes them through typed
|
|
@@ -50,33 +50,35 @@ export class Options {
|
|
|
50
50
|
return __classPrivateFieldGet(this, _Options_instances, "m", _Options_asArray).call(this, __classPrivateFieldGet(this, _Options_data, "f").fontWeight);
|
|
51
51
|
}
|
|
52
52
|
scale() {
|
|
53
|
-
return __classPrivateFieldGet(this, _Options_instances, "m",
|
|
53
|
+
return __classPrivateFieldGet(this, _Options_instances, "m", _Options_toRange).call(this, __classPrivateFieldGet(this, _Options_data, "f").scale);
|
|
54
54
|
}
|
|
55
55
|
borderRadius() {
|
|
56
|
-
return __classPrivateFieldGet(this, _Options_instances, "m",
|
|
56
|
+
return __classPrivateFieldGet(this, _Options_instances, "m", _Options_toRange).call(this, __classPrivateFieldGet(this, _Options_data, "f").borderRadius);
|
|
57
57
|
}
|
|
58
58
|
rotate() {
|
|
59
|
-
return __classPrivateFieldGet(this, _Options_instances, "m",
|
|
59
|
+
return __classPrivateFieldGet(this, _Options_instances, "m", _Options_toRange).call(this, __classPrivateFieldGet(this, _Options_data, "f").rotate);
|
|
60
60
|
}
|
|
61
61
|
translateX() {
|
|
62
|
-
return __classPrivateFieldGet(this, _Options_instances, "m",
|
|
62
|
+
return __classPrivateFieldGet(this, _Options_instances, "m", _Options_toRange).call(this, __classPrivateFieldGet(this, _Options_data, "f").translateX);
|
|
63
63
|
}
|
|
64
64
|
translateY() {
|
|
65
|
-
return __classPrivateFieldGet(this, _Options_instances, "m",
|
|
65
|
+
return __classPrivateFieldGet(this, _Options_instances, "m", _Options_toRange).call(this, __classPrivateFieldGet(this, _Options_data, "f").translateY);
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
|
-
* Returns the user-set variant constraint for `name
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* - `Record<string, number>` when the user gave a weighted map.
|
|
68
|
+
* Returns the user-set variant constraint for `name` as a weighted map, or
|
|
69
|
+
* `undefined` when `${name}Variant` is unset. A bare string or string list
|
|
70
|
+
* is normalized to a map with each entry weighted `1`.
|
|
72
71
|
*/
|
|
73
72
|
componentVariant(name) {
|
|
74
73
|
const raw = __classPrivateFieldGet(this, _Options_instances, "m", _Options_dynamic).call(this, `${name}Variant`);
|
|
75
74
|
if (raw === undefined) {
|
|
76
75
|
return undefined;
|
|
77
76
|
}
|
|
78
|
-
if (typeof raw === 'string'
|
|
79
|
-
return
|
|
77
|
+
if (typeof raw === 'string') {
|
|
78
|
+
return { [raw]: 1 };
|
|
79
|
+
}
|
|
80
|
+
if (Array.isArray(raw)) {
|
|
81
|
+
return Object.fromEntries(raw.map((v) => [v, 1]));
|
|
80
82
|
}
|
|
81
83
|
return raw;
|
|
82
84
|
}
|
|
@@ -98,10 +100,10 @@ export class Options {
|
|
|
98
100
|
return __classPrivateFieldGet(this, _Options_instances, "m", _Options_asArray).call(this, __classPrivateFieldGet(this, _Options_instances, "m", _Options_dynamic).call(this, `${name}ColorFill`));
|
|
99
101
|
}
|
|
100
102
|
colorAngle(name) {
|
|
101
|
-
return __classPrivateFieldGet(this, _Options_instances, "m",
|
|
103
|
+
return __classPrivateFieldGet(this, _Options_instances, "m", _Options_toRange).call(this, __classPrivateFieldGet(this, _Options_instances, "m", _Options_dynamic).call(this, `${name}ColorAngle`));
|
|
102
104
|
}
|
|
103
105
|
colorFillStops(name) {
|
|
104
|
-
return __classPrivateFieldGet(this, _Options_instances, "m",
|
|
106
|
+
return __classPrivateFieldGet(this, _Options_instances, "m", _Options_toRange).call(this, __classPrivateFieldGet(this, _Options_instances, "m", _Options_dynamic).call(this, `${name}ColorFillStops`));
|
|
105
107
|
}
|
|
106
108
|
}
|
|
107
109
|
_Options_data = new WeakMap(), _Options_instances = new WeakSet(), _Options_dynamic = function _Options_dynamic(key) {
|
|
@@ -114,4 +116,12 @@ _Options_data = new WeakMap(), _Options_instances = new WeakSet(), _Options_dyna
|
|
|
114
116
|
return value;
|
|
115
117
|
}
|
|
116
118
|
return [value];
|
|
119
|
+
}, _Options_toRange = function _Options_toRange(value) {
|
|
120
|
+
if (value === undefined) {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
if (typeof value === 'number') {
|
|
124
|
+
return { min: value, max: value };
|
|
125
|
+
}
|
|
126
|
+
return { min: value[0], max: value[1] };
|
|
117
127
|
};
|
package/lib/OptionsDescriptor.js
CHANGED
|
@@ -63,7 +63,12 @@ _a = OptionsDescriptor, _OptionsDescriptor_descriptor = new WeakMap(), _OptionsD
|
|
|
63
63
|
result[`${name}Probability`] = { type: 'number', min: 0, max: 100 };
|
|
64
64
|
}
|
|
65
65
|
for (const name of [...__classPrivateFieldGet(this, _OptionsDescriptor_style, "f").colors().keys(), 'background']) {
|
|
66
|
-
|
|
66
|
+
const contrastTo = __classPrivateFieldGet(this, _OptionsDescriptor_style, "f").colors().get(name)?.contrastTo();
|
|
67
|
+
result[`${name}Color`] = {
|
|
68
|
+
type: 'color',
|
|
69
|
+
list: true,
|
|
70
|
+
...(contrastTo ? { contrastTo } : {}),
|
|
71
|
+
};
|
|
67
72
|
result[`${name}ColorFill`] = {
|
|
68
73
|
type: 'enum',
|
|
69
74
|
values: ['solid', 'linear', 'radial'],
|
package/lib/Prng/Mulberry32.js
CHANGED
|
@@ -36,7 +36,7 @@ export class Mulberry32 {
|
|
|
36
36
|
const z = (__classPrivateFieldSet(this, _Mulberry32_state, (__classPrivateFieldGet(this, _Mulberry32_state, "f") + 0x6d2b79f5) | 0, "f"));
|
|
37
37
|
let t = Math.imul(z ^ (z >>> 15), z | 1);
|
|
38
38
|
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
39
|
-
return (
|
|
39
|
+
return (t ^ (t >>> 14)) >>> 0;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
42
|
* Advances the state and returns the next value in `[0, 1)`.
|
package/lib/Prng.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Range } from './StyleDefinition.js';
|
|
1
2
|
/**
|
|
2
3
|
* Key-based pseudorandom number generator.
|
|
3
4
|
*
|
|
@@ -10,32 +11,41 @@ export declare class Prng {
|
|
|
10
11
|
constructor(seed: string);
|
|
11
12
|
/**
|
|
12
13
|
* Picks a single item from `items` deterministically. Returns `undefined`
|
|
13
|
-
* for an empty list.
|
|
14
|
-
* before picking so that input order
|
|
14
|
+
* for an empty list. Duplicate values (by string representation) are
|
|
15
|
+
* collapsed before picking so that input order and duplication do not
|
|
16
|
+
* affect the result.
|
|
15
17
|
*/
|
|
16
18
|
pick<T>(key: string, items: readonly T[]): T | undefined;
|
|
17
19
|
/**
|
|
18
|
-
* Picks
|
|
20
|
+
* Picks a key from `weights` proportional to its weight. When all weights
|
|
19
21
|
* are zero, falls back to an unweighted {@link pick}. Returns `undefined`
|
|
20
|
-
* for an empty
|
|
22
|
+
* for an empty map.
|
|
21
23
|
*/
|
|
22
|
-
weightedPick
|
|
24
|
+
weightedPick(key: string, weights: Readonly<Record<string, number>>): string | undefined;
|
|
23
25
|
/**
|
|
24
26
|
* Returns `true` with the given probability (0–100, default 50).
|
|
25
27
|
*/
|
|
26
28
|
bool(key: string, likelihood?: number): boolean;
|
|
27
29
|
/**
|
|
28
|
-
* Returns a deterministic float in
|
|
29
|
-
*
|
|
30
|
+
* Returns a deterministic float in `range`, rounded to four decimal places.
|
|
31
|
+
* With `range.step > 0`, the result is drawn uniformly from
|
|
32
|
+
* `{ min + i*step | 0 ≤ i ≤ floor((max - min) / step) }`, so both endpoints
|
|
33
|
+
* of an evenly-divisible range are equally likely. Non-positive or absent
|
|
34
|
+
* step means continuous. `min`/`max` are sorted internally, so a reversed
|
|
35
|
+
* pair is tolerated.
|
|
30
36
|
*/
|
|
31
|
-
float(key: string,
|
|
37
|
+
float(key: string, range: Range): number;
|
|
32
38
|
/**
|
|
33
|
-
* Returns a deterministic integer in
|
|
34
|
-
*
|
|
39
|
+
* Returns a deterministic integer in `range`. `min`/`max` are sorted
|
|
40
|
+
* internally, so a reversed pair is tolerated. `range.step` is accepted
|
|
41
|
+
* for symmetry with {@link float} but ignored — integers already step by 1.
|
|
35
42
|
*/
|
|
36
|
-
integer(key: string,
|
|
43
|
+
integer(key: string, range: Range): number;
|
|
37
44
|
/**
|
|
38
|
-
* Fisher-Yates shuffle with chained Mulberry32 state.
|
|
45
|
+
* Fisher-Yates shuffle with chained Mulberry32 state. Duplicate values
|
|
46
|
+
* (by string representation) are collapsed before shuffling, so a
|
|
47
|
+
* caller's slice off the front cannot accidentally produce a repeated
|
|
48
|
+
* value.
|
|
39
49
|
*/
|
|
40
50
|
shuffle<T>(key: string, items: readonly T[]): T[];
|
|
41
51
|
/**
|
package/lib/Prng.js
CHANGED
|
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _Prng_instances, _Prng_seed, _Prng_compareByCodePoint;
|
|
12
|
+
var _Prng_instances, _Prng_seed, _Prng_uniqueByCodePoint, _Prng_compareByCodePoint;
|
|
13
13
|
import { Fnv1a } from './Prng/Fnv1a.js';
|
|
14
14
|
import { Mulberry32 } from './Prng/Mulberry32.js';
|
|
15
15
|
/**
|
|
@@ -27,8 +27,9 @@ export class Prng {
|
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* Picks a single item from `items` deterministically. Returns `undefined`
|
|
30
|
-
* for an empty list.
|
|
31
|
-
* before picking so that input order
|
|
30
|
+
* for an empty list. Duplicate values (by string representation) are
|
|
31
|
+
* collapsed before picking so that input order and duplication do not
|
|
32
|
+
* affect the result.
|
|
32
33
|
*/
|
|
33
34
|
pick(key, items) {
|
|
34
35
|
if (items.length === 0) {
|
|
@@ -37,33 +38,41 @@ export class Prng {
|
|
|
37
38
|
if (items.length === 1) {
|
|
38
39
|
return items[0];
|
|
39
40
|
}
|
|
40
|
-
const
|
|
41
|
+
const unique = __classPrivateFieldGet(this, _Prng_instances, "m", _Prng_uniqueByCodePoint).call(this, items);
|
|
42
|
+
if (unique.length === 1) {
|
|
43
|
+
return unique[0];
|
|
44
|
+
}
|
|
45
|
+
const sorted = unique.sort(__classPrivateFieldGet(this, _Prng_instances, "m", _Prng_compareByCodePoint));
|
|
41
46
|
const index = Math.floor(this.getValue(key) * sorted.length);
|
|
42
47
|
return sorted[index];
|
|
43
48
|
}
|
|
44
49
|
/**
|
|
45
|
-
* Picks
|
|
50
|
+
* Picks a key from `weights` proportional to its weight. When all weights
|
|
46
51
|
* are zero, falls back to an unweighted {@link pick}. Returns `undefined`
|
|
47
|
-
* for an empty
|
|
52
|
+
* for an empty map.
|
|
48
53
|
*/
|
|
49
|
-
weightedPick(key,
|
|
50
|
-
|
|
54
|
+
weightedPick(key, weights) {
|
|
55
|
+
const keys = Object.keys(weights);
|
|
56
|
+
if (keys.length === 0) {
|
|
51
57
|
return undefined;
|
|
52
58
|
}
|
|
53
|
-
|
|
54
|
-
|
|
59
|
+
if (keys.length === 1) {
|
|
60
|
+
return keys[0];
|
|
61
|
+
}
|
|
62
|
+
const sorted = keys.sort(__classPrivateFieldGet(this, _Prng_instances, "m", _Prng_compareByCodePoint));
|
|
63
|
+
const totalWeight = sorted.reduce((sum, k) => sum + weights[k], 0);
|
|
55
64
|
if (totalWeight === 0) {
|
|
56
|
-
return this.pick(key, sorted
|
|
65
|
+
return this.pick(key, sorted);
|
|
57
66
|
}
|
|
58
67
|
const threshold = this.getValue(key) * totalWeight;
|
|
59
68
|
let cumulative = 0;
|
|
60
|
-
for (const
|
|
61
|
-
cumulative +=
|
|
69
|
+
for (const k of sorted) {
|
|
70
|
+
cumulative += weights[k];
|
|
62
71
|
if (threshold < cumulative) {
|
|
63
|
-
return
|
|
72
|
+
return k;
|
|
64
73
|
}
|
|
65
74
|
}
|
|
66
|
-
return sorted[sorted.length - 1]
|
|
75
|
+
return sorted[sorted.length - 1];
|
|
67
76
|
}
|
|
68
77
|
/**
|
|
69
78
|
* Returns `true` with the given probability (0–100, default 50).
|
|
@@ -72,34 +81,49 @@ export class Prng {
|
|
|
72
81
|
return this.getValue(key) * 100 < likelihood;
|
|
73
82
|
}
|
|
74
83
|
/**
|
|
75
|
-
* Returns a deterministic float in
|
|
76
|
-
*
|
|
84
|
+
* Returns a deterministic float in `range`, rounded to four decimal places.
|
|
85
|
+
* With `range.step > 0`, the result is drawn uniformly from
|
|
86
|
+
* `{ min + i*step | 0 ≤ i ≤ floor((max - min) / step) }`, so both endpoints
|
|
87
|
+
* of an evenly-divisible range are equally likely. Non-positive or absent
|
|
88
|
+
* step means continuous. `min`/`max` are sorted internally, so a reversed
|
|
89
|
+
* pair is tolerated.
|
|
77
90
|
*/
|
|
78
|
-
float(key,
|
|
79
|
-
|
|
80
|
-
|
|
91
|
+
float(key, range) {
|
|
92
|
+
const min = Math.min(range.min, range.max);
|
|
93
|
+
const max = Math.max(range.min, range.max);
|
|
94
|
+
const step = range.step ?? 0;
|
|
95
|
+
let value;
|
|
96
|
+
if (step > 0) {
|
|
97
|
+
const buckets = Math.floor((max - min) / step) + 1;
|
|
98
|
+
const i = Math.floor(this.getValue(key) * buckets);
|
|
99
|
+
value = min + i * step;
|
|
81
100
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
101
|
+
else {
|
|
102
|
+
value = min + this.getValue(key) * (max - min);
|
|
103
|
+
}
|
|
104
|
+
return Math.round(value * 10000) / 10000;
|
|
85
105
|
}
|
|
86
106
|
/**
|
|
87
|
-
* Returns a deterministic integer in
|
|
88
|
-
*
|
|
107
|
+
* Returns a deterministic integer in `range`. `min`/`max` are sorted
|
|
108
|
+
* internally, so a reversed pair is tolerated. `range.step` is accepted
|
|
109
|
+
* for symmetry with {@link float} but ignored — integers already step by 1.
|
|
89
110
|
*/
|
|
90
|
-
integer(key,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
const min = Math.min(...values);
|
|
95
|
-
const max = Math.max(...values);
|
|
111
|
+
integer(key, range) {
|
|
112
|
+
const min = Math.min(range.min, range.max);
|
|
113
|
+
const max = Math.max(range.min, range.max);
|
|
96
114
|
return Math.floor(this.getValue(key) * (max - min + 1)) + min;
|
|
97
115
|
}
|
|
98
116
|
/**
|
|
99
|
-
* Fisher-Yates shuffle with chained Mulberry32 state.
|
|
117
|
+
* Fisher-Yates shuffle with chained Mulberry32 state. Duplicate values
|
|
118
|
+
* (by string representation) are collapsed before shuffling, so a
|
|
119
|
+
* caller's slice off the front cannot accidentally produce a repeated
|
|
120
|
+
* value.
|
|
100
121
|
*/
|
|
101
122
|
shuffle(key, items) {
|
|
102
|
-
|
|
123
|
+
if (items.length <= 1) {
|
|
124
|
+
return [...items];
|
|
125
|
+
}
|
|
126
|
+
const result = __classPrivateFieldGet(this, _Prng_instances, "m", _Prng_uniqueByCodePoint).call(this, items).sort(__classPrivateFieldGet(this, _Prng_instances, "m", _Prng_compareByCodePoint));
|
|
103
127
|
const prng = new Mulberry32(Fnv1a.hash(__classPrivateFieldGet(this, _Prng_seed, "f") + ':' + key));
|
|
104
128
|
for (let i = result.length - 1; i > 0; i--) {
|
|
105
129
|
const j = Math.floor(prng.nextFloat() * (i + 1));
|
|
@@ -117,7 +141,18 @@ export class Prng {
|
|
|
117
141
|
return new Mulberry32(Fnv1a.hash(__classPrivateFieldGet(this, _Prng_seed, "f") + ':' + key)).nextFloat();
|
|
118
142
|
}
|
|
119
143
|
}
|
|
120
|
-
_Prng_seed = new WeakMap(), _Prng_instances = new WeakSet(),
|
|
144
|
+
_Prng_seed = new WeakMap(), _Prng_instances = new WeakSet(), _Prng_uniqueByCodePoint = function _Prng_uniqueByCodePoint(items, keyFn = String) {
|
|
145
|
+
const seen = new Set();
|
|
146
|
+
const result = [];
|
|
147
|
+
for (const item of items) {
|
|
148
|
+
const repr = keyFn(item);
|
|
149
|
+
if (!seen.has(repr)) {
|
|
150
|
+
seen.add(repr);
|
|
151
|
+
result.push(item);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return result;
|
|
155
|
+
}, _Prng_compareByCodePoint = function _Prng_compareByCodePoint(a, b) {
|
|
121
156
|
const sa = String(a);
|
|
122
157
|
const sb = String(b);
|
|
123
158
|
if (sa < sb) {
|
package/lib/Renderer.js
CHANGED
|
@@ -208,8 +208,17 @@ _Renderer_style = new WeakMap(), _Renderer_resolver = new WeakMap(), _Renderer_d
|
|
|
208
208
|
__classPrivateFieldGet(this, _Renderer_defs, "f").set(id, `<g id="${id}">${body}</g>`);
|
|
209
209
|
}
|
|
210
210
|
const transforms = __classPrivateFieldGet(this, _Renderer_instances, "m", _Renderer_buildTransforms).call(this, component);
|
|
211
|
-
const
|
|
212
|
-
|
|
211
|
+
const userAttributes = element.attributes();
|
|
212
|
+
let mergedAttributes = userAttributes;
|
|
213
|
+
if (transforms.length > 0) {
|
|
214
|
+
const userTransform = userAttributes?.transform;
|
|
215
|
+
const allParts = typeof userTransform === 'string' && userTransform.length > 0
|
|
216
|
+
? [userTransform, ...transforms]
|
|
217
|
+
: transforms;
|
|
218
|
+
mergedAttributes = { ...userAttributes, transform: allParts.join(' ') };
|
|
219
|
+
}
|
|
220
|
+
const attrs = __classPrivateFieldGet(this, _Renderer_instances, "m", _Renderer_renderAttributes).call(this, mergedAttributes);
|
|
221
|
+
return `<use${attrs} href="#${id}"/>`;
|
|
213
222
|
}, _Renderer_buildTransforms = function _Renderer_buildTransforms(component) {
|
|
214
223
|
const { rotate, translateX, translateY, scale } = __classPrivateFieldGet(this, _Renderer_resolver, "f").componentTransform(component.name());
|
|
215
224
|
if (translateX === 0 && translateY === 0 && rotate === 0 && scale === 1) {
|
package/lib/Resolver.d.ts
CHANGED
|
@@ -5,8 +5,10 @@ import type { StyleOptionsFlipValue, StyleOptionsColorFillValue, StyleOptions }
|
|
|
5
5
|
* Bundles the three inputs needed to derive any deterministic value for an
|
|
6
6
|
* avatar — the {@link Style}, the validated user {@link Options}, and a
|
|
7
7
|
* seeded {@link Prng} — and exposes them as named accessors. Each accessor
|
|
8
|
-
* memoizes its result so that repeated calls cannot drift
|
|
9
|
-
*
|
|
8
|
+
* memoizes its result so that repeated calls cannot drift. The memo also
|
|
9
|
+
* serves as the informational snapshot returned by {@link resolved} — every
|
|
10
|
+
* value the resolver picks during one resolution lands there, except for
|
|
11
|
+
* the raw seed.
|
|
10
12
|
*/
|
|
11
13
|
export declare class Resolver<D = unknown> {
|
|
12
14
|
#private;
|
|
@@ -28,8 +30,9 @@ export declare class Resolver<D = unknown> {
|
|
|
28
30
|
* as `${name}Variant` in the input data:
|
|
29
31
|
*
|
|
30
32
|
* - `undefined`: PRNG picks from all style variants using their weights.
|
|
31
|
-
* -
|
|
32
|
-
*
|
|
33
|
+
* - otherwise: PRNG picks using the user-supplied weighted map (a bare
|
|
34
|
+
* string or string list is normalized to weight `1` each in
|
|
35
|
+
* {@link Options.componentVariant}).
|
|
33
36
|
*
|
|
34
37
|
* Only variants that exist in the style definition are considered.
|
|
35
38
|
*/
|
|
@@ -38,9 +41,10 @@ export declare class Resolver<D = unknown> {
|
|
|
38
41
|
colorFill(name: string): StyleOptionsColorFillValue;
|
|
39
42
|
colorAngle(name: string): number;
|
|
40
43
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
+
* Picks the rotate/translateX/translateY/scale values for a single
|
|
45
|
+
* component. Memoized per `name`, so the four values land in
|
|
46
|
+
* {@link resolved} as `${name}Rotate` / `${name}TranslateX` /
|
|
47
|
+
* `${name}TranslateY` / `${name}Scale` for downstream introspection.
|
|
44
48
|
*/
|
|
45
49
|
componentTransform(name: string): {
|
|
46
50
|
rotate: number;
|
|
@@ -49,11 +53,16 @@ export declare class Resolver<D = unknown> {
|
|
|
49
53
|
scale: number;
|
|
50
54
|
};
|
|
51
55
|
/**
|
|
52
|
-
* Returns
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
56
|
+
* Returns an informational snapshot of every value the resolver picked.
|
|
57
|
+
* Includes top-level options (scale/rotate/translate/…), per-component
|
|
58
|
+
* variants/probabilities/colors, and per-component transform picks. The
|
|
59
|
+
* raw seed is deliberately excluded.
|
|
60
|
+
*
|
|
61
|
+
* The snapshot is NOT a round-trip-able options object — extra keys like
|
|
62
|
+
* `${name}Rotate` are not part of {@link StyleOptions} and feeding the
|
|
63
|
+
* snapshot back into a new {@link Avatar} is not supported. Callers that
|
|
64
|
+
* need to reproduce an avatar should pass the original `seed` and
|
|
65
|
+
* user-supplied options.
|
|
57
66
|
*
|
|
58
67
|
* The returned object aliases the internal cache; callers that need
|
|
59
68
|
* isolation (e.g. {@link Avatar.toJSON}) clone it themselves.
|