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.
Files changed (45) hide show
  1. package/dist/cjs/src/api/index.d.ts +4 -2
  2. package/dist/cjs/src/data/init-models.js +5 -0
  3. package/dist/cjs/src/data/models/index.d.ts +1 -0
  4. package/dist/cjs/src/data/models/index.js +1 -0
  5. package/dist/cjs/src/data/models/team-badge.d.ts +20 -0
  6. package/dist/cjs/src/data/models/team-badge.js +38 -0
  7. package/dist/cjs/src/data/models/team-jersey.d.ts +3 -1
  8. package/dist/cjs/src/data/models/team-jersey.js +4 -0
  9. package/dist/cjs/src/data/models/team.d.ts +3 -1
  10. package/dist/cjs/src/data/transformers/team.js +5 -1
  11. package/dist/cjs/src/service/team/badge.d.ts +301 -0
  12. package/dist/cjs/src/service/team/badge.js +93 -0
  13. package/dist/cjs/src/service/team/index.d.ts +2 -0
  14. package/dist/cjs/src/service/team/index.js +2 -0
  15. package/dist/cjs/src/service/team/jersey-defaults.d.ts +13 -0
  16. package/dist/cjs/src/service/team/jersey-defaults.js +81 -0
  17. package/dist/cjs/src/service/team/jersey.d.ts +31 -0
  18. package/dist/cjs/src/service/team/jersey.js +137 -1
  19. package/dist/cjs/src/service/team/schemas/team.z.d.ts +122 -0
  20. package/dist/cjs/src/service/team/schemas/team.z.js +4 -1
  21. package/dist/cjs/src/service/team/team.d.ts +4 -1
  22. package/dist/cjs/src/service/team/team.js +3 -1
  23. package/dist/esm/src/api/index.d.ts +4 -2
  24. package/dist/esm/src/data/init-models.js +6 -1
  25. package/dist/esm/src/data/models/index.d.ts +1 -0
  26. package/dist/esm/src/data/models/index.js +1 -0
  27. package/dist/esm/src/data/models/team-badge.d.ts +20 -0
  28. package/dist/esm/src/data/models/team-badge.js +34 -0
  29. package/dist/esm/src/data/models/team-jersey.d.ts +3 -1
  30. package/dist/esm/src/data/models/team-jersey.js +4 -0
  31. package/dist/esm/src/data/models/team.d.ts +3 -1
  32. package/dist/esm/src/data/transformers/team.js +5 -1
  33. package/dist/esm/src/service/team/badge.d.ts +301 -0
  34. package/dist/esm/src/service/team/badge.js +90 -0
  35. package/dist/esm/src/service/team/index.d.ts +2 -0
  36. package/dist/esm/src/service/team/index.js +2 -0
  37. package/dist/esm/src/service/team/jersey-defaults.d.ts +13 -0
  38. package/dist/esm/src/service/team/jersey-defaults.js +77 -0
  39. package/dist/esm/src/service/team/jersey.d.ts +31 -0
  40. package/dist/esm/src/service/team/jersey.js +132 -0
  41. package/dist/esm/src/service/team/schemas/team.z.d.ts +122 -0
  42. package/dist/esm/src/service/team/schemas/team.z.js +5 -2
  43. package/dist/esm/src/service/team/team.d.ts +4 -1
  44. package/dist/esm/src/service/team/team.js +3 -1
  45. package/package.json +1 -1
@@ -26,5 +26,137 @@ export const JerseySchema = z.object({
26
26
  // configs saved before it stay valid.
27
27
  brand: z.enum(['none', 'sigma', 'person-soccer', 'feather-pointed', 'paw-claws', 'narwhal', 'horseshoe', 'spider-black-widow', 'wreath-laurel', 'omega', 'trillium']).default('none'),
28
28
  brandColor1: hexColor.default('#ffffff'),
29
+ brandColor2: hexColor.default('#1e293b'),
30
+ // Chest-element heights in avatar-svg units, on the y=297 chest line. The brand sits at x=90 and the team badge
31
+ // at x=191, with the (non-editable) champion badge between them at x=140.5 spanning 116.5..164.5, so either one
32
+ // starts touching it past about 52. The range allows more than that on purpose: most teams have no champion
33
+ // badge, and the editor preview shows the overlap for the ones that do. Defaulted to the sizes both were fixed
34
+ // at before, so configs saved earlier stay valid and look unchanged.
35
+ brandSize: z.number().min(16).max(64).default(29),
36
+ badgeSize: z.number().min(16).max(64).default(48)
37
+ });
38
+ // The alternate (libero) kit stores only the fields the premium editor allows changing. Locked fields (clothing,
39
+ // font, brand icon, numberSpacing, numberSize, brandSize, badgeSize) are always inherited from the main kit at
40
+ // render time.
41
+ export const AlternateJerseySchema = z.object({
42
+ pattern: JerseySchema.shape.pattern,
43
+ colors: JerseySchema.shape.colors,
44
+ numberColor: hexColor,
45
+ numberOutline: hexColor,
46
+ numberOutlineEnabled: z.boolean().default(true),
47
+ brandColor1: hexColor.default('#ffffff'),
29
48
  brandColor2: hexColor.default('#1e293b')
30
49
  });
50
+ // ---------------------------------------------------------------------------
51
+ // Colour utilities (pure math, zero deps)
52
+ // ---------------------------------------------------------------------------
53
+ function hexToRgb(hex) {
54
+ const h = hex.replace('#', '').slice(0, 6);
55
+ return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];
56
+ }
57
+ function rgbToHex(r, g, b) {
58
+ return '#' + [r, g, b].map(v => Math.round(Math.max(0, Math.min(255, v))).toString(16).padStart(2, '0')).join('');
59
+ }
60
+ function rgbToHsl(r, g, b) {
61
+ r /= 255;
62
+ g /= 255;
63
+ b /= 255;
64
+ const max = Math.max(r, g, b);
65
+ const min = Math.min(r, g, b);
66
+ const l = (max + min) / 2;
67
+ if (max === min)
68
+ return [0, 0, l];
69
+ const d = max - min;
70
+ const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
71
+ let h = 0;
72
+ if (max === r)
73
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
74
+ else if (max === g)
75
+ h = ((b - r) / d + 2) / 6;
76
+ else
77
+ h = ((r - g) / d + 4) / 6;
78
+ return [h, s, l];
79
+ }
80
+ function hslToRgb(h, s, l) {
81
+ if (s === 0) {
82
+ const v = Math.round(l * 255);
83
+ return [v, v, v];
84
+ }
85
+ const hue2rgb = (p, q, t) => {
86
+ if (t < 0)
87
+ t += 1;
88
+ if (t > 1)
89
+ t -= 1;
90
+ if (t < 1 / 6)
91
+ return p + (q - p) * 6 * t;
92
+ if (t < 1 / 2)
93
+ return q;
94
+ if (t < 2 / 3)
95
+ return p + (q - p) * (2 / 3 - t) * 6;
96
+ return p;
97
+ };
98
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
99
+ const p = 2 * l - q;
100
+ return [Math.round(hue2rgb(p, q, h + 1 / 3) * 255), Math.round(hue2rgb(p, q, h) * 255), Math.round(hue2rgb(p, q, h - 1 / 3) * 255)];
101
+ }
102
+ // Rotate a hex colour's hue by 180 degrees (complementary).
103
+ export function complementaryHex(hex) {
104
+ const [r, g, b] = hexToRgb(hex);
105
+ const [h, s, l] = rgbToHsl(r, g, b);
106
+ const [cr, cg, cb] = hslToRgb((h + 0.5) % 1, s, l);
107
+ return rgbToHex(cr, cg, cb);
108
+ }
109
+ // Relative luminance (WCAG 2.x formula, 0 = black, 1 = white).
110
+ export function relativeLuminance(hex) {
111
+ const [r, g, b] = hexToRgb(hex);
112
+ const srgb = [r, g, b].map(v => {
113
+ v /= 255;
114
+ return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
115
+ });
116
+ return 0.2126 * srgb[0] + 0.7152 * srgb[1] + 0.0722 * srgb[2];
117
+ }
118
+ // Build the libero alternate kit from the main kit using complementary colours. Every colour in the
119
+ // pattern and the brand is hue-rotated 180 degrees; the chest-number fill/outline are picked for
120
+ // readability against the new primary colour (dark number on light, light number on dark).
121
+ export function computeComplementaryJersey(main) {
122
+ const compColors = main.colors.map(c => complementaryHex(c));
123
+ const lum = relativeLuminance(compColors[0]);
124
+ return {
125
+ // Locked fields: inherited from main
126
+ clothing: main.clothing,
127
+ font: main.font,
128
+ brand: main.brand,
129
+ numberSpacing: main.numberSpacing,
130
+ numberSize: main.numberSize,
131
+ brandSize: main.brandSize,
132
+ badgeSize: main.badgeSize,
133
+ // Editable fields: complementary-derived
134
+ pattern: main.pattern,
135
+ colors: compColors,
136
+ numberColor: lum > 0.4 ? '#1a1a1a' : '#ffffff',
137
+ numberOutline: lum > 0.4 ? '#ffffff' : '#1a1a1a',
138
+ numberOutlineEnabled: main.numberOutlineEnabled,
139
+ brandColor1: complementaryHex(main.brandColor1),
140
+ brandColor2: complementaryHex(main.brandColor2)
141
+ };
142
+ }
143
+ // Merge a stored alternate (partial, editable fields only) with the main kit's locked fields to
144
+ // produce a full JerseyConfig for rendering.
145
+ export function mergeAlternateJersey(main, alt) {
146
+ return {
147
+ clothing: main.clothing,
148
+ font: main.font,
149
+ brand: main.brand,
150
+ numberSpacing: main.numberSpacing,
151
+ numberSize: main.numberSize,
152
+ brandSize: main.brandSize,
153
+ badgeSize: main.badgeSize,
154
+ pattern: alt.pattern,
155
+ colors: alt.colors,
156
+ numberColor: alt.numberColor,
157
+ numberOutline: alt.numberOutline,
158
+ numberOutlineEnabled: alt.numberOutlineEnabled,
159
+ brandColor1: alt.brandColor1,
160
+ brandColor2: alt.brandColor2
161
+ };
162
+ }
@@ -413,6 +413,128 @@ export declare const TeamInputSchema: z.ZodObject<{
413
413
  }>>;
414
414
  brandColor1: z.ZodDefault<z.ZodString>;
415
415
  brandColor2: z.ZodDefault<z.ZodString>;
416
+ brandSize: z.ZodDefault<z.ZodNumber>;
417
+ badgeSize: z.ZodDefault<z.ZodNumber>;
418
+ }, z.core.$strip>>;
419
+ alternateJerseyConfig: z.ZodOptional<z.ZodObject<{
420
+ pattern: z.ZodEnum<{
421
+ solid: "solid";
422
+ verticalStripes: "verticalStripes";
423
+ verticalBars: "verticalBars";
424
+ pinstripes: "pinstripes";
425
+ hoops: "hoops";
426
+ checkered: "checkered";
427
+ diagonalSash: "diagonalSash";
428
+ splitHalves: "splitHalves";
429
+ chevron: "chevron";
430
+ shoulderYoke: "shoulderYoke";
431
+ sidePanels: "sidePanels";
432
+ centerBand: "centerBand";
433
+ gradientFade: "gradientFade";
434
+ twoToneSplit: "twoToneSplit";
435
+ }>;
436
+ colors: z.ZodArray<z.ZodString>;
437
+ numberColor: z.ZodString;
438
+ numberOutline: z.ZodString;
439
+ numberOutlineEnabled: z.ZodDefault<z.ZodBoolean>;
440
+ brandColor1: z.ZodDefault<z.ZodString>;
441
+ brandColor2: z.ZodDefault<z.ZodString>;
442
+ }, z.core.$strip>>;
443
+ badgeConfig: z.ZodOptional<z.ZodObject<{
444
+ layers: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
445
+ x: z.ZodNumber;
446
+ y: z.ZodNumber;
447
+ size: z.ZodNumber;
448
+ rotation: z.ZodNumber;
449
+ type: z.ZodLiteral<"shape">;
450
+ shape: z.ZodString;
451
+ colors: z.ZodArray<z.ZodString>;
452
+ }, z.core.$strip>, z.ZodObject<{
453
+ x: z.ZodNumber;
454
+ y: z.ZodNumber;
455
+ size: z.ZodNumber;
456
+ rotation: z.ZodNumber;
457
+ type: z.ZodLiteral<"icon">;
458
+ icon: z.ZodEnum<{
459
+ star: "star";
460
+ crown: "crown";
461
+ bolt: "bolt";
462
+ fire: "fire";
463
+ heart: "heart";
464
+ gem: "gem";
465
+ skull: "skull";
466
+ ghost: "ghost";
467
+ anchor: "anchor";
468
+ compass: "compass";
469
+ sun: "sun";
470
+ moon: "moon";
471
+ snowflake: "snowflake";
472
+ leaf: "leaf";
473
+ seedling: "seedling";
474
+ tree: "tree";
475
+ mountain: "mountain";
476
+ water: "water";
477
+ wind: "wind";
478
+ meteor: "meteor";
479
+ rocket: "rocket";
480
+ bell: "bell";
481
+ flag: "flag";
482
+ feather: "feather";
483
+ "shield-halved": "shield-halved";
484
+ "chess-knight": "chess-knight";
485
+ "chess-rook": "chess-rook";
486
+ hammer: "hammer";
487
+ crosshairs: "crosshairs";
488
+ medal: "medal";
489
+ trophy: "trophy";
490
+ award: "award";
491
+ volleyball: "volleyball";
492
+ dragon: "dragon";
493
+ cat: "cat";
494
+ crow: "crow";
495
+ turtle: "turtle";
496
+ unicorn: "unicorn";
497
+ horse: "horse";
498
+ dove: "dove";
499
+ fish: "fish";
500
+ paw: "paw";
501
+ spider: "spider";
502
+ otter: "otter";
503
+ frog: "frog";
504
+ dog: "dog";
505
+ }>;
506
+ color: z.ZodString;
507
+ }, z.core.$strip>, z.ZodObject<{
508
+ x: z.ZodNumber;
509
+ y: z.ZodNumber;
510
+ size: z.ZodNumber;
511
+ rotation: z.ZodNumber;
512
+ type: z.ZodLiteral<"text">;
513
+ text: z.ZodString;
514
+ font: z.ZodEnum<{
515
+ block: "block";
516
+ sans: "sans";
517
+ wide: "wide";
518
+ mono: "mono";
519
+ serif: "serif";
520
+ permanentMarker: "permanentMarker";
521
+ kaushanScript: "kaushanScript";
522
+ russoOne: "russoOne";
523
+ teko: "teko";
524
+ saira: "saira";
525
+ michroma: "michroma";
526
+ zillaSlab: "zillaSlab";
527
+ changaOne: "changaOne";
528
+ stardosStencil: "stardosStencil";
529
+ wallpoet: "wallpoet";
530
+ orbitron: "orbitron";
531
+ tourney: "tourney";
532
+ bebasNeue: "bebasNeue";
533
+ anton: "anton";
534
+ jersey25: "jersey25";
535
+ }>;
536
+ color: z.ZodString;
537
+ }, z.core.$strip>], "type">>;
416
538
  }, z.core.$strip>>;
417
539
  }, z.core.$strip>;
418
540
  export type TeamInput = z.infer<typeof TeamInputSchema>;
@@ -2,7 +2,8 @@ import { z } from 'zod';
2
2
  import { Player } from '../../player';
3
3
  import { Country } from '../../country';
4
4
  import { TacticsInputSchema } from './tactics.z';
5
- import { JerseySchema } from '../jersey';
5
+ import { JerseySchema, AlternateJerseySchema } from '../jersey';
6
+ import { BadgeSchema } from '../badge';
6
7
  const playerInstanceSchema = z.custom((v) => v instanceof Player, {
7
8
  message: 'INVALID_PLAYER_INSTANCE'
8
9
  });
@@ -19,7 +20,9 @@ export const TeamInputSchema = z.object({
19
20
  country: countrySchema,
20
21
  legacyFlagCountry: countrySchema.optional(),
21
22
  tactics: TacticsInputSchema.optional(),
22
- jerseyConfig: JerseySchema.optional()
23
+ jerseyConfig: JerseySchema.optional(),
24
+ alternateJerseyConfig: AlternateJerseySchema.optional(),
25
+ badgeConfig: BadgeSchema.optional()
23
26
  }).superRefine((data, ctx) => {
24
27
  const ids = data.roster.map(p => p.id);
25
28
  if (new Set(ids).size !== ids.length) {
@@ -1,7 +1,8 @@
1
1
  import { Player } from '../player';
2
2
  import { Country } from '../country';
3
3
  import { Tactics } from './tactics';
4
- import type { JerseyConfig } from './jersey';
4
+ import type { JerseyConfig, AlternateJerseyConfig } from './jersey';
5
+ import type { BadgeConfig } from './badge';
5
6
  export declare class Team {
6
7
  readonly id: string;
7
8
  readonly roster: Player[];
@@ -12,6 +13,8 @@ export declare class Team {
12
13
  readonly country: Country;
13
14
  readonly legacyFlagCountry?: Country;
14
15
  readonly jerseyConfig?: JerseyConfig;
16
+ readonly alternateJerseyConfig?: AlternateJerseyConfig;
17
+ readonly badgeConfig?: BadgeConfig;
15
18
  private _rating;
16
19
  static create(input: unknown): Team;
17
20
  private constructor();
@@ -16,7 +16,7 @@ export class Team {
16
16
  tactics: result.data.tactics != null ? Tactics.create(result.data.tactics) : undefined
17
17
  });
18
18
  }
19
- constructor({ id, rating, name, shortName, divisionId, country, legacyFlagCountry, roster, tactics, jerseyConfig }) {
19
+ constructor({ id, rating, name, shortName, divisionId, country, legacyFlagCountry, roster, tactics, jerseyConfig, alternateJerseyConfig, badgeConfig }) {
20
20
  this.id = id;
21
21
  this._rating = rating;
22
22
  this.roster = roster;
@@ -27,6 +27,8 @@ export class Team {
27
27
  this.country = country;
28
28
  this.legacyFlagCountry = legacyFlagCountry;
29
29
  this.jerseyConfig = jerseyConfig;
30
+ this.alternateJerseyConfig = alternateJerseyConfig;
31
+ this.badgeConfig = badgeConfig;
30
32
  }
31
33
  get rating() {
32
34
  return this._rating;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "volleyballsimtypes",
3
- "version": "0.0.526",
3
+ "version": "0.0.528",
4
4
  "description": "vbsim types",
5
5
  "main": "./dist/cjs/src/index.js",
6
6
  "module": "./dist/esm/src/index.js",