volleyballsimtypes 0.0.526 → 0.0.528
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/dist/cjs/src/api/index.d.ts +4 -2
- package/dist/cjs/src/data/init-models.js +5 -0
- package/dist/cjs/src/data/models/index.d.ts +1 -0
- package/dist/cjs/src/data/models/index.js +1 -0
- package/dist/cjs/src/data/models/team-badge.d.ts +20 -0
- package/dist/cjs/src/data/models/team-badge.js +38 -0
- package/dist/cjs/src/data/models/team-jersey.d.ts +3 -1
- package/dist/cjs/src/data/models/team-jersey.js +4 -0
- package/dist/cjs/src/data/models/team.d.ts +3 -1
- package/dist/cjs/src/data/transformers/team.js +5 -1
- package/dist/cjs/src/service/team/badge.d.ts +301 -0
- package/dist/cjs/src/service/team/badge.js +93 -0
- package/dist/cjs/src/service/team/index.d.ts +2 -0
- package/dist/cjs/src/service/team/index.js +2 -0
- package/dist/cjs/src/service/team/jersey-defaults.d.ts +13 -0
- package/dist/cjs/src/service/team/jersey-defaults.js +81 -0
- package/dist/cjs/src/service/team/jersey.d.ts +31 -0
- package/dist/cjs/src/service/team/jersey.js +137 -1
- package/dist/cjs/src/service/team/schemas/team.z.d.ts +122 -0
- package/dist/cjs/src/service/team/schemas/team.z.js +4 -1
- package/dist/cjs/src/service/team/team.d.ts +4 -1
- package/dist/cjs/src/service/team/team.js +3 -1
- package/dist/esm/src/api/index.d.ts +4 -2
- package/dist/esm/src/data/init-models.js +6 -1
- package/dist/esm/src/data/models/index.d.ts +1 -0
- package/dist/esm/src/data/models/index.js +1 -0
- package/dist/esm/src/data/models/team-badge.d.ts +20 -0
- package/dist/esm/src/data/models/team-badge.js +34 -0
- package/dist/esm/src/data/models/team-jersey.d.ts +3 -1
- package/dist/esm/src/data/models/team-jersey.js +4 -0
- package/dist/esm/src/data/models/team.d.ts +3 -1
- package/dist/esm/src/data/transformers/team.js +5 -1
- package/dist/esm/src/service/team/badge.d.ts +301 -0
- package/dist/esm/src/service/team/badge.js +90 -0
- package/dist/esm/src/service/team/index.d.ts +2 -0
- package/dist/esm/src/service/team/index.js +2 -0
- package/dist/esm/src/service/team/jersey-defaults.d.ts +13 -0
- package/dist/esm/src/service/team/jersey-defaults.js +77 -0
- package/dist/esm/src/service/team/jersey.d.ts +31 -0
- package/dist/esm/src/service/team/jersey.js +132 -0
- package/dist/esm/src/service/team/schemas/team.z.d.ts +122 -0
- package/dist/esm/src/service/team/schemas/team.z.js +5 -2
- package/dist/esm/src/service/team/team.d.ts +4 -1
- package/dist/esm/src/service/team/team.js +3 -1
- package/package.json +1 -1
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const BADGE_CANVAS = 200;
|
|
3
|
+
export declare const BADGE_ICONS: readonly ["star", "crown", "bolt", "fire", "heart", "gem", "skull", "ghost", "anchor", "compass", "sun", "moon", "snowflake", "leaf", "seedling", "tree", "mountain", "water", "wind", "meteor", "rocket", "bell", "flag", "feather", "shield-halved", "chess-knight", "chess-rook", "hammer", "crosshairs", "medal", "trophy", "award", "volleyball", "dragon", "cat", "crow", "turtle", "unicorn", "horse", "dove", "fish", "paw", "spider", "otter", "frog", "dog"];
|
|
4
|
+
export type BadgeIconName = typeof BADGE_ICONS[number];
|
|
5
|
+
export declare const BADGE_TEXT_FONTS: readonly ["sans", "wide", "mono", "serif", "block", "permanentMarker", "kaushanScript", "russoOne", "teko", "saira", "michroma", "zillaSlab", "changaOne", "stardosStencil", "wallpoet", "orbitron", "tourney", "bebasNeue", "anton", "jersey25"];
|
|
6
|
+
export type BadgeTextFont = typeof BADGE_TEXT_FONTS[number];
|
|
7
|
+
export declare const BADGE_SHAPES: readonly ["star5-solid", "star5-slim-solid", "star6-solid", "cross-solid", "star5-outline", "star5-slim-outline", "star6-outline", "cross-outline", "pentagon-solid", "hexagon-solid", "octagon-solid", "pentagon-outline", "hexagon-outline", "octagon-outline", "square-solid", "triangle-solid", "diamond-solid", "square-outline", "triangle-outline", "diamond-outline", "rectangle-solid", "burst-solid", "trapezoid-solid", "rectangle-outline", "burst-outline", "trapezoid-outline", "circle-solid", "heptagon-solid", "nonagon-solid", "ellipse-solid", "parallelogram-solid", "heart-solid", "moon-solid", "semicircle-solid", "triangle-right-solid", "triangle-tall-solid", "trapezoid-tall-solid", "kite-solid"];
|
|
8
|
+
export type BadgeShapeName = typeof BADGE_SHAPES[number];
|
|
9
|
+
declare const shapeLayer: z.ZodObject<{
|
|
10
|
+
x: z.ZodNumber;
|
|
11
|
+
y: z.ZodNumber;
|
|
12
|
+
size: z.ZodNumber;
|
|
13
|
+
rotation: z.ZodNumber;
|
|
14
|
+
type: z.ZodLiteral<"shape">;
|
|
15
|
+
shape: z.ZodString;
|
|
16
|
+
colors: z.ZodArray<z.ZodString>;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
declare const iconLayer: z.ZodObject<{
|
|
19
|
+
x: z.ZodNumber;
|
|
20
|
+
y: z.ZodNumber;
|
|
21
|
+
size: z.ZodNumber;
|
|
22
|
+
rotation: z.ZodNumber;
|
|
23
|
+
type: z.ZodLiteral<"icon">;
|
|
24
|
+
icon: z.ZodEnum<{
|
|
25
|
+
star: "star";
|
|
26
|
+
crown: "crown";
|
|
27
|
+
bolt: "bolt";
|
|
28
|
+
fire: "fire";
|
|
29
|
+
heart: "heart";
|
|
30
|
+
gem: "gem";
|
|
31
|
+
skull: "skull";
|
|
32
|
+
ghost: "ghost";
|
|
33
|
+
anchor: "anchor";
|
|
34
|
+
compass: "compass";
|
|
35
|
+
sun: "sun";
|
|
36
|
+
moon: "moon";
|
|
37
|
+
snowflake: "snowflake";
|
|
38
|
+
leaf: "leaf";
|
|
39
|
+
seedling: "seedling";
|
|
40
|
+
tree: "tree";
|
|
41
|
+
mountain: "mountain";
|
|
42
|
+
water: "water";
|
|
43
|
+
wind: "wind";
|
|
44
|
+
meteor: "meteor";
|
|
45
|
+
rocket: "rocket";
|
|
46
|
+
bell: "bell";
|
|
47
|
+
flag: "flag";
|
|
48
|
+
feather: "feather";
|
|
49
|
+
"shield-halved": "shield-halved";
|
|
50
|
+
"chess-knight": "chess-knight";
|
|
51
|
+
"chess-rook": "chess-rook";
|
|
52
|
+
hammer: "hammer";
|
|
53
|
+
crosshairs: "crosshairs";
|
|
54
|
+
medal: "medal";
|
|
55
|
+
trophy: "trophy";
|
|
56
|
+
award: "award";
|
|
57
|
+
volleyball: "volleyball";
|
|
58
|
+
dragon: "dragon";
|
|
59
|
+
cat: "cat";
|
|
60
|
+
crow: "crow";
|
|
61
|
+
turtle: "turtle";
|
|
62
|
+
unicorn: "unicorn";
|
|
63
|
+
horse: "horse";
|
|
64
|
+
dove: "dove";
|
|
65
|
+
fish: "fish";
|
|
66
|
+
paw: "paw";
|
|
67
|
+
spider: "spider";
|
|
68
|
+
otter: "otter";
|
|
69
|
+
frog: "frog";
|
|
70
|
+
dog: "dog";
|
|
71
|
+
}>;
|
|
72
|
+
color: z.ZodString;
|
|
73
|
+
}, z.core.$strip>;
|
|
74
|
+
declare const textLayer: z.ZodObject<{
|
|
75
|
+
x: z.ZodNumber;
|
|
76
|
+
y: z.ZodNumber;
|
|
77
|
+
size: z.ZodNumber;
|
|
78
|
+
rotation: z.ZodNumber;
|
|
79
|
+
type: z.ZodLiteral<"text">;
|
|
80
|
+
text: z.ZodString;
|
|
81
|
+
font: z.ZodEnum<{
|
|
82
|
+
block: "block";
|
|
83
|
+
sans: "sans";
|
|
84
|
+
wide: "wide";
|
|
85
|
+
mono: "mono";
|
|
86
|
+
serif: "serif";
|
|
87
|
+
permanentMarker: "permanentMarker";
|
|
88
|
+
kaushanScript: "kaushanScript";
|
|
89
|
+
russoOne: "russoOne";
|
|
90
|
+
teko: "teko";
|
|
91
|
+
saira: "saira";
|
|
92
|
+
michroma: "michroma";
|
|
93
|
+
zillaSlab: "zillaSlab";
|
|
94
|
+
changaOne: "changaOne";
|
|
95
|
+
stardosStencil: "stardosStencil";
|
|
96
|
+
wallpoet: "wallpoet";
|
|
97
|
+
orbitron: "orbitron";
|
|
98
|
+
tourney: "tourney";
|
|
99
|
+
bebasNeue: "bebasNeue";
|
|
100
|
+
anton: "anton";
|
|
101
|
+
jersey25: "jersey25";
|
|
102
|
+
}>;
|
|
103
|
+
color: z.ZodString;
|
|
104
|
+
}, z.core.$strip>;
|
|
105
|
+
export declare const BadgeLayerSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
106
|
+
x: z.ZodNumber;
|
|
107
|
+
y: z.ZodNumber;
|
|
108
|
+
size: z.ZodNumber;
|
|
109
|
+
rotation: z.ZodNumber;
|
|
110
|
+
type: z.ZodLiteral<"shape">;
|
|
111
|
+
shape: z.ZodString;
|
|
112
|
+
colors: z.ZodArray<z.ZodString>;
|
|
113
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
114
|
+
x: z.ZodNumber;
|
|
115
|
+
y: z.ZodNumber;
|
|
116
|
+
size: z.ZodNumber;
|
|
117
|
+
rotation: z.ZodNumber;
|
|
118
|
+
type: z.ZodLiteral<"icon">;
|
|
119
|
+
icon: z.ZodEnum<{
|
|
120
|
+
star: "star";
|
|
121
|
+
crown: "crown";
|
|
122
|
+
bolt: "bolt";
|
|
123
|
+
fire: "fire";
|
|
124
|
+
heart: "heart";
|
|
125
|
+
gem: "gem";
|
|
126
|
+
skull: "skull";
|
|
127
|
+
ghost: "ghost";
|
|
128
|
+
anchor: "anchor";
|
|
129
|
+
compass: "compass";
|
|
130
|
+
sun: "sun";
|
|
131
|
+
moon: "moon";
|
|
132
|
+
snowflake: "snowflake";
|
|
133
|
+
leaf: "leaf";
|
|
134
|
+
seedling: "seedling";
|
|
135
|
+
tree: "tree";
|
|
136
|
+
mountain: "mountain";
|
|
137
|
+
water: "water";
|
|
138
|
+
wind: "wind";
|
|
139
|
+
meteor: "meteor";
|
|
140
|
+
rocket: "rocket";
|
|
141
|
+
bell: "bell";
|
|
142
|
+
flag: "flag";
|
|
143
|
+
feather: "feather";
|
|
144
|
+
"shield-halved": "shield-halved";
|
|
145
|
+
"chess-knight": "chess-knight";
|
|
146
|
+
"chess-rook": "chess-rook";
|
|
147
|
+
hammer: "hammer";
|
|
148
|
+
crosshairs: "crosshairs";
|
|
149
|
+
medal: "medal";
|
|
150
|
+
trophy: "trophy";
|
|
151
|
+
award: "award";
|
|
152
|
+
volleyball: "volleyball";
|
|
153
|
+
dragon: "dragon";
|
|
154
|
+
cat: "cat";
|
|
155
|
+
crow: "crow";
|
|
156
|
+
turtle: "turtle";
|
|
157
|
+
unicorn: "unicorn";
|
|
158
|
+
horse: "horse";
|
|
159
|
+
dove: "dove";
|
|
160
|
+
fish: "fish";
|
|
161
|
+
paw: "paw";
|
|
162
|
+
spider: "spider";
|
|
163
|
+
otter: "otter";
|
|
164
|
+
frog: "frog";
|
|
165
|
+
dog: "dog";
|
|
166
|
+
}>;
|
|
167
|
+
color: z.ZodString;
|
|
168
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
169
|
+
x: z.ZodNumber;
|
|
170
|
+
y: z.ZodNumber;
|
|
171
|
+
size: z.ZodNumber;
|
|
172
|
+
rotation: z.ZodNumber;
|
|
173
|
+
type: z.ZodLiteral<"text">;
|
|
174
|
+
text: z.ZodString;
|
|
175
|
+
font: z.ZodEnum<{
|
|
176
|
+
block: "block";
|
|
177
|
+
sans: "sans";
|
|
178
|
+
wide: "wide";
|
|
179
|
+
mono: "mono";
|
|
180
|
+
serif: "serif";
|
|
181
|
+
permanentMarker: "permanentMarker";
|
|
182
|
+
kaushanScript: "kaushanScript";
|
|
183
|
+
russoOne: "russoOne";
|
|
184
|
+
teko: "teko";
|
|
185
|
+
saira: "saira";
|
|
186
|
+
michroma: "michroma";
|
|
187
|
+
zillaSlab: "zillaSlab";
|
|
188
|
+
changaOne: "changaOne";
|
|
189
|
+
stardosStencil: "stardosStencil";
|
|
190
|
+
wallpoet: "wallpoet";
|
|
191
|
+
orbitron: "orbitron";
|
|
192
|
+
tourney: "tourney";
|
|
193
|
+
bebasNeue: "bebasNeue";
|
|
194
|
+
anton: "anton";
|
|
195
|
+
jersey25: "jersey25";
|
|
196
|
+
}>;
|
|
197
|
+
color: z.ZodString;
|
|
198
|
+
}, z.core.$strip>], "type">;
|
|
199
|
+
export declare const BADGE_MAX_LAYERS = 25;
|
|
200
|
+
export declare const BadgeSchema: z.ZodObject<{
|
|
201
|
+
layers: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
202
|
+
x: z.ZodNumber;
|
|
203
|
+
y: z.ZodNumber;
|
|
204
|
+
size: z.ZodNumber;
|
|
205
|
+
rotation: z.ZodNumber;
|
|
206
|
+
type: z.ZodLiteral<"shape">;
|
|
207
|
+
shape: z.ZodString;
|
|
208
|
+
colors: z.ZodArray<z.ZodString>;
|
|
209
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
210
|
+
x: z.ZodNumber;
|
|
211
|
+
y: z.ZodNumber;
|
|
212
|
+
size: z.ZodNumber;
|
|
213
|
+
rotation: z.ZodNumber;
|
|
214
|
+
type: z.ZodLiteral<"icon">;
|
|
215
|
+
icon: z.ZodEnum<{
|
|
216
|
+
star: "star";
|
|
217
|
+
crown: "crown";
|
|
218
|
+
bolt: "bolt";
|
|
219
|
+
fire: "fire";
|
|
220
|
+
heart: "heart";
|
|
221
|
+
gem: "gem";
|
|
222
|
+
skull: "skull";
|
|
223
|
+
ghost: "ghost";
|
|
224
|
+
anchor: "anchor";
|
|
225
|
+
compass: "compass";
|
|
226
|
+
sun: "sun";
|
|
227
|
+
moon: "moon";
|
|
228
|
+
snowflake: "snowflake";
|
|
229
|
+
leaf: "leaf";
|
|
230
|
+
seedling: "seedling";
|
|
231
|
+
tree: "tree";
|
|
232
|
+
mountain: "mountain";
|
|
233
|
+
water: "water";
|
|
234
|
+
wind: "wind";
|
|
235
|
+
meteor: "meteor";
|
|
236
|
+
rocket: "rocket";
|
|
237
|
+
bell: "bell";
|
|
238
|
+
flag: "flag";
|
|
239
|
+
feather: "feather";
|
|
240
|
+
"shield-halved": "shield-halved";
|
|
241
|
+
"chess-knight": "chess-knight";
|
|
242
|
+
"chess-rook": "chess-rook";
|
|
243
|
+
hammer: "hammer";
|
|
244
|
+
crosshairs: "crosshairs";
|
|
245
|
+
medal: "medal";
|
|
246
|
+
trophy: "trophy";
|
|
247
|
+
award: "award";
|
|
248
|
+
volleyball: "volleyball";
|
|
249
|
+
dragon: "dragon";
|
|
250
|
+
cat: "cat";
|
|
251
|
+
crow: "crow";
|
|
252
|
+
turtle: "turtle";
|
|
253
|
+
unicorn: "unicorn";
|
|
254
|
+
horse: "horse";
|
|
255
|
+
dove: "dove";
|
|
256
|
+
fish: "fish";
|
|
257
|
+
paw: "paw";
|
|
258
|
+
spider: "spider";
|
|
259
|
+
otter: "otter";
|
|
260
|
+
frog: "frog";
|
|
261
|
+
dog: "dog";
|
|
262
|
+
}>;
|
|
263
|
+
color: z.ZodString;
|
|
264
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
265
|
+
x: z.ZodNumber;
|
|
266
|
+
y: z.ZodNumber;
|
|
267
|
+
size: z.ZodNumber;
|
|
268
|
+
rotation: z.ZodNumber;
|
|
269
|
+
type: z.ZodLiteral<"text">;
|
|
270
|
+
text: z.ZodString;
|
|
271
|
+
font: z.ZodEnum<{
|
|
272
|
+
block: "block";
|
|
273
|
+
sans: "sans";
|
|
274
|
+
wide: "wide";
|
|
275
|
+
mono: "mono";
|
|
276
|
+
serif: "serif";
|
|
277
|
+
permanentMarker: "permanentMarker";
|
|
278
|
+
kaushanScript: "kaushanScript";
|
|
279
|
+
russoOne: "russoOne";
|
|
280
|
+
teko: "teko";
|
|
281
|
+
saira: "saira";
|
|
282
|
+
michroma: "michroma";
|
|
283
|
+
zillaSlab: "zillaSlab";
|
|
284
|
+
changaOne: "changaOne";
|
|
285
|
+
stardosStencil: "stardosStencil";
|
|
286
|
+
wallpoet: "wallpoet";
|
|
287
|
+
orbitron: "orbitron";
|
|
288
|
+
tourney: "tourney";
|
|
289
|
+
bebasNeue: "bebasNeue";
|
|
290
|
+
anton: "anton";
|
|
291
|
+
jersey25: "jersey25";
|
|
292
|
+
}>;
|
|
293
|
+
color: z.ZodString;
|
|
294
|
+
}, z.core.$strip>], "type">>;
|
|
295
|
+
}, z.core.$strip>;
|
|
296
|
+
export type BadgeConfig = z.infer<typeof BadgeSchema>;
|
|
297
|
+
export type BadgeLayer = z.infer<typeof BadgeLayerSchema>;
|
|
298
|
+
export type BadgeShapeLayer = z.infer<typeof shapeLayer>;
|
|
299
|
+
export type BadgeIconLayer = z.infer<typeof iconLayer>;
|
|
300
|
+
export type BadgeTextLayer = z.infer<typeof textLayer>;
|
|
301
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
// 6-digit hex (#rrggbb) or 8-digit hex with alpha (#rrggbbaa), the same convention as the jersey colours (the
|
|
3
|
+
// 8-digit form comes from the UI's opacity-enabled colour pickers; SVG fills render both).
|
|
4
|
+
const hexColor = z.string().regex(/^#[0-9a-fA-F]{6}([0-9a-fA-F]{2})?$/, 'INVALID_HEX_COLOR');
|
|
5
|
+
// The badge canvas is a fixed square coordinate space. Layer x/y are the layer's centre in canvas units and
|
|
6
|
+
// `size` is the layer's height in the same units; positions may overhang the canvas a little (clipped at render).
|
|
7
|
+
export const BADGE_CANVAS = 200;
|
|
8
|
+
// Curated FontAwesome icon names offered as badge layers (owner decision 2026-08-31: curated set, not a full
|
|
9
|
+
// catalog). The UI maps each name to its solid-icon path data (view/badge/badge-icons.ts, a Record keyed by this
|
|
10
|
+
// type so the two lists cannot drift); this list is what the API validates against.
|
|
11
|
+
export const BADGE_ICONS = [
|
|
12
|
+
'star', 'crown', 'bolt', 'fire', 'heart', 'gem', 'skull', 'ghost', 'anchor', 'compass',
|
|
13
|
+
'sun', 'moon', 'snowflake', 'leaf', 'seedling', 'tree', 'mountain', 'water', 'wind', 'meteor',
|
|
14
|
+
'rocket', 'bell', 'flag', 'feather', 'shield-halved', 'chess-knight', 'chess-rook', 'hammer', 'crosshairs',
|
|
15
|
+
'medal', 'trophy', 'award', 'volleyball', 'dragon', 'cat', 'crow', 'turtle', 'unicorn', 'horse', 'dove',
|
|
16
|
+
'fish', 'paw', 'spider', 'otter', 'frog', 'dog'
|
|
17
|
+
];
|
|
18
|
+
// Text layers offer the same 20 faces as the jersey number editor (JERSEY_FONT_ALL): five generic stacks, then
|
|
19
|
+
// the fifteen display families. The jersey renders its number from GENERATED DIGIT GLYPHS because it lives in a
|
|
20
|
+
// data-uri <img> where @font-face does not load; the badge canvas is inline SVG in the document, so it uses the
|
|
21
|
+
// real webfonts instead, which also means badge text is not limited to the digits those glyph sets cover.
|
|
22
|
+
export const BADGE_TEXT_FONTS = [
|
|
23
|
+
'sans', 'wide', 'mono', 'serif', 'block',
|
|
24
|
+
'permanentMarker', 'kaushanScript', 'russoOne', 'teko', 'saira', 'michroma', 'zillaSlab', 'changaOne',
|
|
25
|
+
'stardosStencil', 'wallpoet', 'orbitron', 'tourney', 'bebasNeue', 'anton', 'jersey25'
|
|
26
|
+
];
|
|
27
|
+
// Basic geometric shapes (VolleyballSimUI/public/shapes), extracted from the two source sets 2026-08-31. The
|
|
28
|
+
// crest sets are positional (shield-a01, ribbon-07), but these are named, so the vocabulary is spelled out
|
|
29
|
+
// rather than pattern-matched: this list IS the allow list, and every entry has a file of the same name.
|
|
30
|
+
// `-outline` is the hollow cut, whose interior is a real hole in the path (so layers underneath show through,
|
|
31
|
+
// no transparent fill slot needed). Order is the picker order, grouped by family.
|
|
32
|
+
// The rounded-corner cut of every shape, plus the split square and the pie, were dropped by the owner
|
|
33
|
+
// 2026-08-31; only the sharp cuts ship.
|
|
34
|
+
export const BADGE_SHAPES = [
|
|
35
|
+
'star5-solid', 'star5-slim-solid', 'star6-solid', 'cross-solid',
|
|
36
|
+
'star5-outline', 'star5-slim-outline', 'star6-outline', 'cross-outline',
|
|
37
|
+
'pentagon-solid', 'hexagon-solid', 'octagon-solid',
|
|
38
|
+
'pentagon-outline', 'hexagon-outline', 'octagon-outline',
|
|
39
|
+
'square-solid', 'triangle-solid', 'diamond-solid',
|
|
40
|
+
'square-outline', 'triangle-outline', 'diamond-outline',
|
|
41
|
+
'rectangle-solid', 'burst-solid', 'trapezoid-solid',
|
|
42
|
+
'rectangle-outline', 'burst-outline', 'trapezoid-outline',
|
|
43
|
+
'circle-solid', 'heptagon-solid', 'nonagon-solid', 'ellipse-solid', 'parallelogram-solid',
|
|
44
|
+
'heart-solid', 'moon-solid', 'semicircle-solid', 'triangle-right-solid', 'triangle-tall-solid',
|
|
45
|
+
'trapezoid-tall-solid', 'kite-solid'
|
|
46
|
+
];
|
|
47
|
+
// The extracted vector sets in VolleyballSimUI/public/shields + public/ribbons + public/shapes:
|
|
48
|
+
// shield-a01..a17 / shield-b01..b16, each -solid|-bordered|-outline; ribbon-01..ribbon-49; and shape-<name>
|
|
49
|
+
// for every name in BADGE_SHAPES.
|
|
50
|
+
const CREST_ID = /^(shield-(a(0[1-9]|1[0-7])|b(0[1-9]|1[0-6]))-(solid|bordered|outline)|ribbon-(0[1-9]|[1-4][0-9]))$/;
|
|
51
|
+
const BASIC_ID = new RegExp(`^shape-(${BADGE_SHAPES.join('|')})$`);
|
|
52
|
+
const shapeId = z.string().refine(v => CREST_ID.test(v) || BASIC_ID.test(v), 'INVALID_BADGE_SHAPE');
|
|
53
|
+
const layerBase = {
|
|
54
|
+
x: z.number().min(-100).max(300),
|
|
55
|
+
y: z.number().min(-100).max(300),
|
|
56
|
+
size: z.number().min(4).max(400),
|
|
57
|
+
rotation: z.number().min(-180).max(180)
|
|
58
|
+
};
|
|
59
|
+
// One colour per DISTINCT fill in the source art (solid shields 1, bordered 3, ribbons up to 4, basic shapes 1),
|
|
60
|
+
// applied in the order the fills first appear in the file. Extra entries are ignored at render; missing ones
|
|
61
|
+
// fall back to the source colour.
|
|
62
|
+
const shapeLayer = z.object({
|
|
63
|
+
type: z.literal('shape'),
|
|
64
|
+
shape: shapeId,
|
|
65
|
+
colors: z.array(hexColor).min(1).max(6),
|
|
66
|
+
...layerBase
|
|
67
|
+
});
|
|
68
|
+
const iconLayer = z.object({
|
|
69
|
+
type: z.literal('icon'),
|
|
70
|
+
icon: z.enum(BADGE_ICONS),
|
|
71
|
+
color: hexColor,
|
|
72
|
+
...layerBase
|
|
73
|
+
});
|
|
74
|
+
const textLayer = z.object({
|
|
75
|
+
type: z.literal('text'),
|
|
76
|
+
text: z.string().min(1).max(24),
|
|
77
|
+
font: z.enum(BADGE_TEXT_FONTS),
|
|
78
|
+
color: hexColor,
|
|
79
|
+
...layerBase
|
|
80
|
+
});
|
|
81
|
+
export const BadgeLayerSchema = z.discriminatedUnion('type', [shapeLayer, iconLayer, textLayer]);
|
|
82
|
+
// The most layers one badge may stack. Not a technical ceiling (25 layers is under 3 KB of jsonb and a trivial
|
|
83
|
+
// number of SVG paths): past roughly a dozen you cannot tell the elements apart at the size a crest is shown,
|
|
84
|
+
// and the one-step-per-click reordering gets tedious. Exported so the editor gates on the SAME number the save
|
|
85
|
+
// validates against, rather than keeping its own copy that can drift.
|
|
86
|
+
export const BADGE_MAX_LAYERS = 25;
|
|
87
|
+
// The full team badge: an ordered stack of layers (index 0 renders first, i.e. at the back).
|
|
88
|
+
export const BadgeSchema = z.object({
|
|
89
|
+
layers: z.array(BadgeLayerSchema).min(1).max(BADGE_MAX_LAYERS)
|
|
90
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { JerseyConfig, JerseyClothing, JerseyPattern, JerseyFont } from './jersey';
|
|
2
|
+
export interface JerseyPalette {
|
|
3
|
+
color1: string;
|
|
4
|
+
color2: string;
|
|
5
|
+
color3: string;
|
|
6
|
+
number1: string;
|
|
7
|
+
number2: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const JERSEY_PALETTES: readonly JerseyPalette[];
|
|
10
|
+
export declare const JERSEY_PATTERN_ORDER: readonly JerseyPattern[];
|
|
11
|
+
export declare const JERSEY_CLOTHING_ORDER: readonly JerseyClothing[];
|
|
12
|
+
export declare const JERSEY_FONT_ORDER: readonly JerseyFont[];
|
|
13
|
+
export declare function jerseyFromTeamId(teamId: string): JerseyConfig;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// FNV-1a hash of a string, used to seed the PRNG below from a team id.
|
|
2
|
+
function hashSeed(str) {
|
|
3
|
+
let h = 2166136261;
|
|
4
|
+
for (let i = 0; i < str.length; i++) {
|
|
5
|
+
h ^= str.charCodeAt(i);
|
|
6
|
+
h = Math.imul(h, 16777619);
|
|
7
|
+
}
|
|
8
|
+
return h >>> 0;
|
|
9
|
+
}
|
|
10
|
+
// mulberry32: a tiny deterministic PRNG. Same seed -> same stream, so a team's kit is stable and reproducible.
|
|
11
|
+
function mulberry32(seed) {
|
|
12
|
+
let a = seed;
|
|
13
|
+
return () => {
|
|
14
|
+
a = (a + 0x6d2b79f5) | 0;
|
|
15
|
+
let t = Math.imul(a ^ (a >>> 15), 1 | a);
|
|
16
|
+
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
|
|
17
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export const JERSEY_PALETTES = [
|
|
21
|
+
{ color1: '#606c38', color2: '#dda15e', color3: '#bc6c25', number1: '#fefae0', number2: '#283618' },
|
|
22
|
+
{ color1: '#780000', color2: '#669bbc', color3: '#c1121f', number1: '#fdf0d5', number2: '#003049' },
|
|
23
|
+
{ color1: '#2a9d8f', color2: '#f4a261', color3: '#e76f51', number1: '#264653', number2: '#e9c46a' },
|
|
24
|
+
{ color1: '#219ebc', color2: '#fb8500', color3: '#8ecae6', number1: '#023047', number2: '#ffb703' },
|
|
25
|
+
{ color1: '#1d3557', color2: '#e63946', color3: '#a8dadc', number1: '#f1faee', number2: '#457b9d' },
|
|
26
|
+
{ color1: '#003566', color2: '#ffc300', color3: '#001d3d', number1: '#ffd60a', number2: '#000814' },
|
|
27
|
+
{ color1: '#bc4749', color2: '#6a994e', color3: '#a7c957', number1: '#f2e8cf', number2: '#386641' },
|
|
28
|
+
{ color1: '#6f1d1b', color2: '#99582a', color3: '#bb9457', number1: '#ffe6a7', number2: '#432818' },
|
|
29
|
+
{ color1: '#ef476f', color2: '#118ab2', color3: '#ffd166', number1: '#ffd166', number2: '#073b4c' },
|
|
30
|
+
{ color1: '#16425b', color2: '#3a7ca5', color3: '#81c3d7', number1: '#d9dcd6', number2: '#2f6690' },
|
|
31
|
+
{ color1: '#ee6c4d', color2: '#3d5a80', color3: '#98c1d9', number1: '#e0fbfc', number2: '#293241' },
|
|
32
|
+
{ color1: '#e09f3e', color2: '#335c67', color3: '#9e2a2b', number1: '#fff3b0', number2: '#540b0e' },
|
|
33
|
+
{ color1: '#9a031e', color2: '#fb8b24', color3: '#e36414', number1: '#0f4c5c', number2: '#5f0f40' },
|
|
34
|
+
{ color1: '#127475', color2: '#f2542d', color3: '#0e9594', number1: '#f5dfbb', number2: '#562c2c' },
|
|
35
|
+
{ color1: '#bc4b51', color2: '#8cb369', color3: '#f4a259', number1: '#f4e285', number2: '#5b8e7d' },
|
|
36
|
+
{ color1: '#7678ed', color2: '#f18701', color3: '#f35b04', number1: '#f7b801', number2: '#3d348b' },
|
|
37
|
+
{ color1: '#14213d', color2: '#fca311', color3: '#e5e5e5', number1: '#ffffff', number2: '#000000' },
|
|
38
|
+
{ color1: '#e07a5f', color2: '#81b29a', color3: '#f2cc8f', number1: '#f4f1de', number2: '#3d405b' },
|
|
39
|
+
{ color1: '#f79824', color2: '#33a1fd', color3: '#fdca40', number1: '#33a1fd', number2: '#31393c' },
|
|
40
|
+
{ color1: '#619b8a', color2: '#fe7f2d', color3: '#a1c181', number1: '#fcca46', number2: '#233d4d' },
|
|
41
|
+
{ color1: '#227c9d', color2: '#17c3b2', color3: '#ffcb77', number1: '#fef9ef', number2: '#fe6d73' },
|
|
42
|
+
{ color1: '#19647e', color2: '#119da4', color3: '#1f2041', number1: '#4b3f72', number2: '#ffc857' }
|
|
43
|
+
];
|
|
44
|
+
export const JERSEY_PATTERN_ORDER = [
|
|
45
|
+
'solid', 'verticalStripes', 'verticalBars', 'pinstripes', 'hoops', 'checkered', 'diagonalSash', 'splitHalves',
|
|
46
|
+
'chevron', 'shoulderYoke', 'sidePanels', 'centerBand', 'gradientFade', 'twoToneSplit'
|
|
47
|
+
];
|
|
48
|
+
export const JERSEY_CLOTHING_ORDER = [
|
|
49
|
+
'shirtCrewNeck', 'shirtCrewNeckSleeveless', 'shirtVNeck', 'shirtVNeckSleeveless', 'collarAndSweater', 'collarAndSweaterSleeveless'
|
|
50
|
+
];
|
|
51
|
+
// Free-user fonts: the id-derived random for a team's default kit picks ONLY from these (premium fonts are vector
|
|
52
|
+
// glyph paths that require the UI rendering pipeline).
|
|
53
|
+
export const JERSEY_FONT_ORDER = ['sans', 'wide', 'mono', 'serif', 'block'];
|
|
54
|
+
// The full jersey a team wears by default: every category is drawn deterministically from the team id, so each team
|
|
55
|
+
// gets its own stable, distinct kit. Colours come from ONE randomly-assigned JERSEY_PALETTE (harmonious by design);
|
|
56
|
+
// clothing / pattern / font stay random per team.
|
|
57
|
+
export function jerseyFromTeamId(teamId) {
|
|
58
|
+
const rng = mulberry32(hashSeed(teamId));
|
|
59
|
+
const pickFrom = (arr) => arr[Math.floor(rng() * arr.length)];
|
|
60
|
+
const palette = pickFrom(JERSEY_PALETTES);
|
|
61
|
+
return {
|
|
62
|
+
clothing: pickFrom(JERSEY_CLOTHING_ORDER),
|
|
63
|
+
pattern: pickFrom(JERSEY_PATTERN_ORDER),
|
|
64
|
+
colors: [palette.color1, palette.color2, palette.color3],
|
|
65
|
+
font: pickFrom(JERSEY_FONT_ORDER),
|
|
66
|
+
numberColor: palette.number1,
|
|
67
|
+
numberOutline: palette.number2,
|
|
68
|
+
numberOutlineEnabled: true,
|
|
69
|
+
numberSpacing: 0,
|
|
70
|
+
numberSize: 46,
|
|
71
|
+
brand: 'none',
|
|
72
|
+
brandColor1: '#ffffff',
|
|
73
|
+
brandColor2: '#1e293b',
|
|
74
|
+
brandSize: 29,
|
|
75
|
+
badgeSize: 48
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -67,8 +67,39 @@ export declare const JerseySchema: z.ZodObject<{
|
|
|
67
67
|
}>>;
|
|
68
68
|
brandColor1: z.ZodDefault<z.ZodString>;
|
|
69
69
|
brandColor2: z.ZodDefault<z.ZodString>;
|
|
70
|
+
brandSize: z.ZodDefault<z.ZodNumber>;
|
|
71
|
+
badgeSize: z.ZodDefault<z.ZodNumber>;
|
|
70
72
|
}, z.core.$strip>;
|
|
71
73
|
export type JerseyConfig = z.infer<typeof JerseySchema>;
|
|
72
74
|
export type JerseyClothing = JerseyConfig['clothing'];
|
|
73
75
|
export type JerseyPattern = JerseyConfig['pattern'];
|
|
74
76
|
export type JerseyFont = JerseyConfig['font'];
|
|
77
|
+
export declare const AlternateJerseySchema: z.ZodObject<{
|
|
78
|
+
pattern: z.ZodEnum<{
|
|
79
|
+
solid: "solid";
|
|
80
|
+
verticalStripes: "verticalStripes";
|
|
81
|
+
verticalBars: "verticalBars";
|
|
82
|
+
pinstripes: "pinstripes";
|
|
83
|
+
hoops: "hoops";
|
|
84
|
+
checkered: "checkered";
|
|
85
|
+
diagonalSash: "diagonalSash";
|
|
86
|
+
splitHalves: "splitHalves";
|
|
87
|
+
chevron: "chevron";
|
|
88
|
+
shoulderYoke: "shoulderYoke";
|
|
89
|
+
sidePanels: "sidePanels";
|
|
90
|
+
centerBand: "centerBand";
|
|
91
|
+
gradientFade: "gradientFade";
|
|
92
|
+
twoToneSplit: "twoToneSplit";
|
|
93
|
+
}>;
|
|
94
|
+
colors: z.ZodArray<z.ZodString>;
|
|
95
|
+
numberColor: z.ZodString;
|
|
96
|
+
numberOutline: z.ZodString;
|
|
97
|
+
numberOutlineEnabled: z.ZodDefault<z.ZodBoolean>;
|
|
98
|
+
brandColor1: z.ZodDefault<z.ZodString>;
|
|
99
|
+
brandColor2: z.ZodDefault<z.ZodString>;
|
|
100
|
+
}, z.core.$strip>;
|
|
101
|
+
export type AlternateJerseyConfig = z.infer<typeof AlternateJerseySchema>;
|
|
102
|
+
export declare function complementaryHex(hex: string): string;
|
|
103
|
+
export declare function relativeLuminance(hex: string): number;
|
|
104
|
+
export declare function computeComplementaryJersey(main: JerseyConfig): JerseyConfig;
|
|
105
|
+
export declare function mergeAlternateJersey(main: JerseyConfig, alt: AlternateJerseyConfig): JerseyConfig;
|