@johnmorrisdotca/taisen-brackets 0.4.0 → 0.5.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/CHANGELOG.md +27 -0
- package/NOTICE.md +2 -0
- package/README.md +64 -23
- package/dist/background.d.ts +19 -0
- package/dist/background.js +66 -0
- package/dist/backgrounds-entry.d.ts +2 -0
- package/dist/backgrounds-entry.js +1 -0
- package/dist/family-backgrounds.d.ts +61 -0
- package/dist/family-backgrounds.js +453 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/marks.d.ts +2 -0
- package/dist/marks.js +31 -2
- package/dist/matchup.js +1 -0
- package/dist/render.js +282 -58
- package/dist/road.draw.js +6 -3
- package/dist/road.js +1 -1
- package/dist/road.types.d.ts +1 -1
- package/dist/text.d.ts +1 -1
- package/dist/text.js +4 -4
- package/dist/theme.d.ts +9 -1
- package/dist/theme.js +23 -8
- package/dist/types.d.ts +50 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,33 @@ All notable changes to this project are written here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.5.0] - 2026-10-14
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **`background`**: a poster background under a bracket or a road chart. A preset's name draws one of **twenty-five**, each drawn in code (gradients, radial glows, patterns, bezier bands, markings) in a dark and a light variant, deterministic and at most 6 kB: `midnight`, `crimson`, `royal`, `emerald`, `pitch`, `ice`, `hardwood`, `infield`, `turf`, `ball-panels`, `swirl`, `waves`, `glow`, `floodlights`, `confetti`, `carbon`, `aurora`, `sunburst`, `chevrons`, `halftone`, `argyle`, `contour`, `stardust`, `mesh` and `spotlight`. Five read as the sport's playing surface: soccer's mowing stripes and markings, hockey's scratched ice with its centre circle, lines and faceoff spots, basketball's planks and court, baseball's grass, dirt and base paths, football's turf, yard lines and end zones. The text, lines, boxes, marks and accent take the colours that read over each (4.5 to 1 against the background's dominant colours, a test over every preset, both variants and every size, and over colours of your own, with a veil where a mid-tone ground needs one). With `theme: "auto"` both variants are drawn and the stylesheet shows the one that fits the page. [docs/backgrounds.md](docs/backgrounds.md).
|
|
14
|
+
- **`background: { preset, colors, angle, intensity, seed, theme }`** tunes a preset, and **`background: { image, fit, dim, theme }`** draws a picture of your own as an `<image>` under a veil (`cover` or `contain`, 0 to 1 deep); the address must be http(s), relative or `data:image/…` (anything else throws), and is escaped. An unknown preset or a bad value throws a `RangeError` that names it. `roadToFinal` takes the same option. The default, the look's plain colour, is drawn exactly as before.
|
|
15
|
+
- **`src/family-backgrounds.ts`**, the drawing of the twenty-five as one dependency-free file that other packages of the family copy byte for byte: `backgroundSvg(preset, { width, height, theme, colors, angle, intensity, seed, id }) => { defs, body, ink }`, `BACKGROUND_PRESETS`, `contrastRatio`, `FAMILY_BACKGROUNDS_VERSION`. Its sha256 and version are held by `test/family-backgrounds.test.ts`; it is also the `/backgrounds` entry point. The copy rule is in docs/backgrounds.md.
|
|
16
|
+
- **Seed tags**: `seeds: true` in the road look writes a small tag (`C1`, `WC2`, `P3`) beside each mark, from the new `Matchup.seeds`, else the new `Team.tag`, else the number `Team.seed`; in a box of marks alone it sits above the mark.
|
|
17
|
+
- **`codes`** and **`vs`** for a bracket's road look: a team's three letters under its mark, and a "v" between the two marks of a box of marks alone.
|
|
18
|
+
- **A team with no flag or logo is a tile** in the road look: a rounded square with its abbreviation, filled with the team's `color` (white or near-black letters, whichever reads) or neutral.
|
|
19
|
+
- **`flagHref(code)`**: a flag as an address to load, for pages that cannot afford an inline flag of 80 kB twice; tried where `flags` gives none, written once as a symbol. **Every `mark` address** is now written once as a symbol and used wherever the team appears, instead of a long `<image href>` per use.
|
|
20
|
+
- **`tieClass(tie)`**: a class word for a tie's group, so that a page's own style can highlight or dim ties (a division); only words of letters, digits, `-` and `_` are kept.
|
|
21
|
+
- The demo has a background picker (all twenty-five as swatches, your own colours, an image read in the browser and never uploaded), a gallery of the twenty-five on the sports they suit, and opens every example on the background of its sport. NHL 2024 carries its seed tags.
|
|
22
|
+
- `pnpm images` redoes every picture of `docs/images` in one command, the two grids of the twenty-five included; `pnpm test:readme` checks that every picture the README and the docs name exists. [docs/roadmap.md](docs/roadmap.md) and [docs/references.md](docs/references.md): what is planned (new layouts and a group-stage table for 0.6.0) and the pictures that prompted it, as mood only.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **Marks, text and round names stuck out of their boxes**, in every size and both looks: in a tall bracket's boxes of marks the score under the marks was not counted when the marks were sized, so the flags crossed the box's top and bottom (Croatia and Japan in the round of 16 on a phone); a shoot-out's score ("1 (3)") crowded the next team's, and now sits beside the score where it fits the column, or under it. A box of marks is laid out as a stack (tag, mark, letters, score, shoot-out) and the marks are made as large as the whole stack allows. Bold text was measured as regular; it is now measured bold, so a name no longer runs under a score or the word "bye".
|
|
27
|
+
- **The names of the rounds met the connector lines.** In a tall bracket the lines now turn at the edge of the box they leave and the names stand on their own strip between the rounds, each moved along it to a place the lines do not cross, set a little smaller and on a snugger pill where the room is tight. (On a phone a round of eight or more boxes across leaves no room: the name then stands over the lines on its own pill.)
|
|
28
|
+
- **Round names were cut with an ellipsis** in a wide column ("Conference Quarterfi…"): a name is set smaller, down to 8, and then on two lines, on a taller pill (road) or two lines of text (classic), and the strip over the boxes grows to hold them. A name is cut only as a last resort.
|
|
29
|
+
- `test/geometry.test.ts` measures every drawing's marks, text, pills and lines from the markup and asserts all of this for every example, size and look.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- The demo's default view is the road look on the background that suits each sport. A bracket's classic look is unchanged apart from the fixes above.
|
|
34
|
+
- The README's pictures are regenerated (JPEG, to keep the repository small) with the new backgrounds and the fixed boxes.
|
|
35
|
+
|
|
9
36
|
## [0.4.0] - 2026-10-14
|
|
10
37
|
|
|
11
38
|
### Added
|
package/NOTICE.md
CHANGED
|
@@ -25,3 +25,5 @@ The code of this package is under the MIT licence (see [LICENSE](LICENSE)). The
|
|
|
25
25
|
The flags in the demo are for the nations of the World Cups of 2022 and 2026: `AR AT AU BA BE BR CA CD CH CI CO CV DE DZ EC EG ES FR GB-ENG GH HR JP KR MA MX NL NO PL PT PY SE SN US ZA`. The package itself ships no flag, no logo and no data of the leagues.
|
|
26
26
|
|
|
27
27
|
No code, text or picture was taken from the bracket libraries compared in [docs/compare.md](docs/compare.md); that page records what each says of itself.
|
|
28
|
+
|
|
29
|
+
**Backgrounds.** The twenty-five backgrounds (`src/family-backgrounds.ts`) are drawn in code from gradients, patterns and paths and are original work, MIT-licensed with the package; none is traced from, or copies, anyone's artwork, logo, trophy or photograph, and no image file is used. The pictures of other brackets that inspired the design are listed, as mood only, in docs/references.md; nothing of them is in the package. The NHL 2024 seed tags in the demo (C1, WC2, P3, A1, M2 and so on) are the divisional places and wild cards of that season's playoff field, as the league names them.
|
package/README.md
CHANGED
|
@@ -11,22 +11,22 @@ Give it the games, series, two-legged ties or replays of a tournament and it wor
|
|
|
11
11
|
<img alt="TypeScript" src="https://img.shields.io/badge/types-TypeScript-3178c6">
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
|
-
<p align="center"><a href="https://johnmorrisdotca.github.io/taisen-brackets/"><strong>Open the demo →</strong></a> · <a href="./docs/layout.md">Layout</a> · <a href="./docs/drawing.md">Drawing</a> · <a href="./docs/road.md">Road to the final</a> · <a href="./docs/formats.md">Formats</a> · <a href="./docs/compare.md">How it compares</a></p>
|
|
14
|
+
<p align="center"><a href="https://johnmorrisdotca.github.io/taisen-brackets/"><strong>Open the demo →</strong></a> · <a href="./docs/layout.md">Layout</a> · <a href="./docs/drawing.md">Drawing</a> · <a href="./docs/road.md">Road to the final</a> · <a href="./docs/backgrounds.md">Backgrounds</a> · <a href="./docs/formats.md">Formats</a> · <a href="./docs/compare.md">How it compares</a></p>
|
|
15
15
|
|
|
16
16
|
<p align="center">
|
|
17
17
|
<picture>
|
|
18
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/hero-desk-dark.
|
|
19
|
-
<img alt="The 2022 World Cup knockout: two halves of eight teams meeting at the final in the centre, with Argentina's round flag and the word Champion above it and the third-place match below. Each box has both teams' round flags, abbreviations and scores, with penalties in brackets." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/hero-desk-light.
|
|
18
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/hero-desk-dark.jpg">
|
|
19
|
+
<img alt="The 2022 World Cup knockout: two halves of eight teams meeting at the final in the centre, with Argentina's round flag and the word Champion above it and the third-place match below. Each box has both teams' round flags, abbreviations and scores, with penalties in brackets." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/hero-desk-light.jpg" width="720">
|
|
20
20
|
</picture>
|
|
21
21
|
</p>
|
|
22
22
|
|
|
23
23
|
<table align="center">
|
|
24
24
|
<tr>
|
|
25
25
|
<td align="center" valign="top">
|
|
26
|
-
<img alt="The poster look: the 2026 World Cup knockout of 32 nations as round flags on dark navy joined by gold lines, Spain's flag in the centre above the word Champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/poster-desk.
|
|
26
|
+
<img alt="The poster look: the 2026 World Cup knockout of 32 nations as round flags on dark navy joined by gold lines, Spain's flag in the centre above the word Champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/poster-desk.jpg" width="470"><br><em>The poster look: flags only, gold on navy (the 2026 World Cup).</em>
|
|
27
27
|
</td>
|
|
28
28
|
<td align="center" valign="top">
|
|
29
|
-
<img alt="The 2022 World Cup on a phone: the champion at the top, then the rounds as rows, the first round at the top and at the bottom, the final in the middle, and the third-place match at the foot." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/phone-light.
|
|
29
|
+
<img alt="The 2022 World Cup on a phone: the champion at the top, then the rounds as rows, the first round at the top and at the bottom, the final in the middle, and the third-place match at the foot." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/phone-light.jpg" width="190"><br><em>On a phone the rounds are rows.</em>
|
|
30
30
|
</td>
|
|
31
31
|
</tr>
|
|
32
32
|
</table>
|
|
@@ -37,22 +37,22 @@ One layout draws them all, each from real results: the demo has a picker for the
|
|
|
37
37
|
|
|
38
38
|
<table>
|
|
39
39
|
<tr>
|
|
40
|
-
<td align="center" valign="top"><img alt="The 2024 NHL playoffs: Western and Eastern conferences, best-of-seven series, Florida Panthers as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nhl-desk-light.
|
|
41
|
-
<td align="center" valign="top"><img alt="The 1984 Stanley Cup playoffs: the Campbell and Wales conferences, a best-of-five first round, Edmonton Oilers as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nhl1984-desk-light.
|
|
42
|
-
<td align="center" valign="top"><img alt="The 2024 NBA playoffs: sixteen teams in two conferences, Boston Celtics as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nba-desk-light.
|
|
40
|
+
<td align="center" valign="top"><img alt="The 2024 NHL playoffs: Western and Eastern conferences, best-of-seven series, Florida Panthers as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nhl-desk-light.jpg" width="360"><br><em>NHL 2024, series</em></td>
|
|
41
|
+
<td align="center" valign="top"><img alt="The 1984 Stanley Cup playoffs: the Campbell and Wales conferences, a best-of-five first round, Edmonton Oilers as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nhl1984-desk-light.jpg" width="360"><br><em>NHL 1984, an older era</em></td>
|
|
42
|
+
<td align="center" valign="top"><img alt="The 2024 NBA playoffs: sixteen teams in two conferences, Boston Celtics as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nba-desk-light.jpg" width="360"><br><em>NBA 2024</em></td>
|
|
43
43
|
</tr>
|
|
44
44
|
<tr>
|
|
45
|
-
<td align="center" valign="top"><img alt="The 2022 MLB postseason: byes for the top two seeds of each league, Houston Astros as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/byes-desk-light.
|
|
46
|
-
<td align="center" valign="top"><img alt="The playoffs of the 2024 NFL season: single games, byes for the top seed of each conference, the Super Bowl at the centre, Philadelphia Eagles as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nfl-desk-light.
|
|
47
|
-
<td align="center" valign="top"><img alt="The 2024 CFL playoffs: division semi-finals and finals, byes, the Grey Cup at the centre, Toronto Argonauts as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/cfl-desk-light.
|
|
45
|
+
<td align="center" valign="top"><img alt="The 2022 MLB postseason: byes for the top two seeds of each league, Houston Astros as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/byes-desk-light.jpg" width="360"><br><em>MLB 2022, byes</em></td>
|
|
46
|
+
<td align="center" valign="top"><img alt="The playoffs of the 2024 NFL season: single games, byes for the top seed of each conference, the Super Bowl at the centre, Philadelphia Eagles as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nfl-desk-light.jpg" width="360"><br><em>NFL 2024 season, the Super Bowl</em></td>
|
|
47
|
+
<td align="center" valign="top"><img alt="The 2024 CFL playoffs: division semi-finals and finals, byes, the Grey Cup at the centre, Toronto Argonauts as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/cfl-desk-light.jpg" width="360"><br><em>CFL 2024, the Grey Cup</em></td>
|
|
48
48
|
</tr>
|
|
49
49
|
<tr>
|
|
50
|
-
<td align="center" valign="top"><img alt="The 2022 World Cup knockout stage." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/hero-desk-light.
|
|
51
|
-
<td align="center" valign="top"><img alt="The 1938 World Cup: replays." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/replays-desk-light.
|
|
52
|
-
<td align="center" valign="top"><img alt="The 2026 World Cup as a flags-only poster, in Japanese." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/poster-desk-ja.
|
|
50
|
+
<td align="center" valign="top"><img alt="The 2022 World Cup knockout stage." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/hero-desk-light.jpg" width="360"><br><em>World Cup 2022</em></td>
|
|
51
|
+
<td align="center" valign="top"><img alt="The 1938 World Cup: replays." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/replays-desk-light.jpg" width="360"><br><em>World Cup 1938, replays</em></td>
|
|
52
|
+
<td align="center" valign="top"><img alt="The 2026 World Cup as a flags-only poster, in Japanese." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/poster-desk-ja.jpg" width="360"><br><em>World Cup 2026 poster, in Japanese</em></td>
|
|
53
53
|
</tr>
|
|
54
54
|
<tr>
|
|
55
|
-
<td align="center" valign="top"><img alt="The 2024 MLS Cup Playoffs: a wild card match, a best-of-three round one, then single matches to the MLS Cup, LA Galaxy as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/mls-desk-light.
|
|
55
|
+
<td align="center" valign="top"><img alt="The 2024 MLS Cup Playoffs: a wild card match, a best-of-three round one, then single matches to the MLS Cup, LA Galaxy as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/mls-desk-light.jpg" width="360"><br><em>MLS 2024, best of three</em></td>
|
|
56
56
|
<td></td>
|
|
57
57
|
<td></td>
|
|
58
58
|
</tr>
|
|
@@ -64,17 +64,53 @@ One layout draws them all, each from real results: the demo has a picker for the
|
|
|
64
64
|
|
|
65
65
|
<table>
|
|
66
66
|
<tr>
|
|
67
|
-
<td align="center" valign="top"><img alt="The 2022 World Cup in the road look, wide: large round flags, big bold scores, the loser quiet, the rounds on pills, and Argentina's path to the final as a dotted line." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/path-desk-light.
|
|
68
|
-
<td align="center" valign="top"><img alt="The 2022 World Cup in the road look on a card, 1080 by 1350: the champion at the top, then the rounds as rows." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/card-light.
|
|
69
|
-
<td align="center" valign="top"><img alt="The road to the final of the 2022 World Cup on a phone in the dark: Argentina and France as large flags, and each one's matches with the score between the two flags." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/road-phone-dark.
|
|
67
|
+
<td align="center" valign="top"><img alt="The 2022 World Cup in the road look, wide: large round flags, big bold scores, the loser quiet, the rounds on pills, and Argentina's path to the final as a dotted line." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/path-desk-light.jpg" width="460"><br><em>The road look, wide, with Argentina's path.</em></td>
|
|
68
|
+
<td align="center" valign="top"><img alt="The 2022 World Cup in the road look on a card, 1080 by 1350: the champion at the top, then the rounds as rows." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/card-light.jpg" width="260"><br><em>A card, 1080 by 1350.</em></td>
|
|
69
|
+
<td align="center" valign="top"><img alt="The road to the final of the 2022 World Cup on a phone in the dark: Argentina and France as large flags, and each one's matches with the score between the two flags." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/road-phone-dark.jpg" width="190"><br><em>The road to the final, on a phone.</em></td>
|
|
70
70
|
</tr>
|
|
71
71
|
<tr>
|
|
72
|
-
<td align="center" valign="top"><img alt="The same bracket in the classic look, which stays the default." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/classic-desk-light.
|
|
73
|
-
<td align="center" valign="top"><img alt="The road to the final of the 2024 Stanley Cup playoffs: Florida and Edmonton, each one's three series with the games won between the two logos." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/road-wide-nhl-light.
|
|
74
|
-
<td align="center" valign="top"><img alt="The road to the final of the 2022 World Cup on a card." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/road-card-light.
|
|
72
|
+
<td align="center" valign="top"><img alt="The same bracket in the classic look, which stays the default." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/classic-desk-light.jpg" width="460"><br><em>The classic look, still the default.</em></td>
|
|
73
|
+
<td align="center" valign="top"><img alt="The road to the final of the 2024 Stanley Cup playoffs: Florida and Edmonton, each one's three series with the games won between the two logos." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/road-wide-nhl-light.jpg" width="460"><br><em>The road to the final, a play-off (NHL 2024).</em></td>
|
|
74
|
+
<td align="center" valign="top"><img alt="The road to the final of the 2022 World Cup on a card." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/road-card-light.jpg" width="260"><br><em>The road to the final, a card.</em></td>
|
|
75
75
|
</tr>
|
|
76
76
|
</table>
|
|
77
77
|
|
|
78
|
+
## Backgrounds
|
|
79
|
+
|
|
80
|
+
`background` draws a poster background under the bracket: a gradient, a glow, a pattern or the markings of a playing surface, all drawn in code, each in a dark and a light variant. The text, the lines, the boxes and the marks take the colours that read over it. The plain colour stays the default.
|
|
81
|
+
|
|
82
|
+
<p align="center">
|
|
83
|
+
<picture>
|
|
84
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/backgrounds-dark.jpg">
|
|
85
|
+
<img alt="The twenty-five backgrounds in a grid of five by five, each behind a different bracket: midnight, crimson, royal, emerald, pitch, ice, hardwood, infield, turf, ball-panels, swirl, waves, glow, floodlights, confetti, carbon, aurora, sunburst, chevrons, halftone, argyle, contour, stardust, mesh and spotlight." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/backgrounds-light.jpg" width="900">
|
|
86
|
+
</picture>
|
|
87
|
+
</p>
|
|
88
|
+
|
|
89
|
+
The twenty-five: `midnight`, `crimson`, `royal`, `emerald`, `pitch` (soccer), `ice` (hockey), `hardwood` (basketball), `infield` (baseball), `turf` (football), `ball-panels`, `swirl`, `waves`, `glow`, `floodlights`, `confetti`, `carbon`, `aurora`, `sunburst`, `chevrons`, `halftone`, `argyle`, `contour`, `stardust`, `mesh` and `spotlight`. [docs/backgrounds.md](./docs/backgrounds.md) says what each is.
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
import { drawBracket } from "@johnmorrisdotca/taisen-brackets";
|
|
93
|
+
|
|
94
|
+
const ties = [
|
|
95
|
+
{ sides: ["VAN", "NSH"], score: [4, 3], round: 1, seeds: ["P1", "WC2"] },
|
|
96
|
+
{ sides: ["EDM", "LAK"], score: [1, 2], round: 1, seeds: ["P2", "P3"] },
|
|
97
|
+
{ sides: ["VAN", "LAK"], score: [2, 1], round: 2 },
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
// A preset by name; with `theme: "auto"` (the default) both variants are drawn and the page's own light or dark shows the right one.
|
|
101
|
+
const ice = drawBracket(ties, { look: "road", background: "ice", seeds: true });
|
|
102
|
+
|
|
103
|
+
// A preset, tuned: your own colours, the angle, how strong the pattern is, a seed for the scattered parts.
|
|
104
|
+
const mine = drawBracket(ties, { look: "road", theme: "dark", background: { preset: "swirl", colors: ["#10203a", "#3a1060", "#ff7ac8", "#6ae0ff"], angle: 135, intensity: 0.8 } });
|
|
105
|
+
|
|
106
|
+
// Your own picture, under a veil (http(s), relative or data:image/ only).
|
|
107
|
+
const photo = drawBracket(ties, { look: "road", theme: "dark", background: { image: "stadium.jpg", fit: "cover", dim: 0.55 } });
|
|
108
|
+
|
|
109
|
+
console.log(ice.includes("tb-bgd"), mine.includes("#ff7ac8"), photo.includes('<image href="stadium.jpg"')); // true true true
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
In the road look, `seeds: true` writes a small tag (`P1`, `WC2`) beside each team's mark, `codes: true` its three letters under the mark in a box of marks, `vs: true` a "v" between the two marks, and a team with no flag or logo is a tile with its letters. [docs/backgrounds.md](./docs/backgrounds.md) has the options, the contrast rules and the module the other packages of the family share.
|
|
113
|
+
|
|
78
114
|
## In 30 seconds
|
|
79
115
|
|
|
80
116
|
```sh
|
|
@@ -110,6 +146,9 @@ Put the string in a page (`element.innerHTML = svg`), write it to a file, or sen
|
|
|
110
146
|
- **Wide, square, card, phone**: 1200 by 675, 1080 by 1080, 1080 by 1350 (a tall post), or 390 wide and as tall as it needs; the rounds are columns, or rows on a phone and a card. Boxes show names and scores, abbreviations, or only the marks, whichever fits.
|
|
111
147
|
- **The road look**: `look: "road"` draws large round flags or crests, big bold scores with the loser's quiet, the rounds named on pills, and, for one team, its path through the bracket as a dotted line. It is the look of the road-to-the-final chart below, and every other option works with it.
|
|
112
148
|
- **The road to the final**: `roadToFinal` draws the two finalists of the tournament you already have, with the ties each played on the way and the score between their flags, on a card, a square, wide or a phone.
|
|
149
|
+
- **Poster backgrounds**: twenty-five, drawn in code, each in a dark and a light variant, among them the playing surfaces of hockey, basketball, baseball, football and soccer; your own colours, or your own picture; and the text, lines and boxes take the colours that read over them (4.5 to 1, held by a test).
|
|
150
|
+
- **Seed tags, codes and a "vs"** in the road look, and a team with no picture drawn as a tile with its letters, so that nothing looks missing.
|
|
151
|
+
- **Nothing sticks out**: marks, text and round names stay inside their boxes and off the connector lines, in every size and both looks, held by a geometry test.
|
|
113
152
|
- **A link on every box**: `href: (tie, side?) => address` makes each tie's box (or each team's row) a real `<a>` in the SVG with an accessible name.
|
|
114
153
|
- **Flags from a plug-in**: a team's `flag` code is drawn by the `flags` function you pass (Hata's round flags are one line), with no dependency added.
|
|
115
154
|
- **Light, dark, poster**: every colour is a CSS custom property with a fallback, so the drawing follows the page's `prefers-color-scheme` or `data-theme` and can be restyled from outside.
|
|
@@ -131,7 +170,7 @@ npm install @johnmorrisdotca/taisen-brackets
|
|
|
131
170
|
# or: yarn add @johnmorrisdotca/taisen-brackets
|
|
132
171
|
```
|
|
133
172
|
|
|
134
|
-
It is ESM, and `require` works on Node 22.12 and later. It needs no DOM: the functions return strings.
|
|
173
|
+
It is ESM, and `require` works on Node 22.12 and later. It needs no DOM: the functions return strings. Five entry points: `@johnmorrisdotca/taisen-brackets` (everything), `/layout` (the layout and the helpers, no drawing), `/presets` (the formats), `/road` (the road to the final) and `/backgrounds` (the twenty-five backgrounds on their own).
|
|
135
174
|
|
|
136
175
|
## Examples
|
|
137
176
|
|
|
@@ -465,7 +504,7 @@ The string is built from your data, with every name escaped; do not put untruste
|
|
|
465
504
|
|
|
466
505
|
Everything is exported from `@johnmorrisdotca/taisen-brackets`; the layout part from `/layout`, the formats from `/presets`. The types are in the package; each function's doc comment has its details.
|
|
467
506
|
|
|
468
|
-
- `drawBracket(input, options?)`: the SVG string. `input` is a list of matchups, `{ matchups, teams }` or a layout. Options: `size`, `orientation`, `shape`, `detail`, `theme`, `background`, `title`, `subtitle`, `roundNames`, `roundLabels`, `scores`, `seeds`, `markShape`, `champion`, `trophy`, `emblems`, `emblemStyle`, `emblemTint`, `thirdPlace`, `winnerHighlight`, `look`, `href`, `highlightPath`, `flags`, `locale`, `words`, `teamName`, `groupOrder`, `id`, `className`.
|
|
507
|
+
- `drawBracket(input, options?)`: the SVG string. `input` is a list of matchups, `{ matchups, teams }` or a layout. Options: `size`, `orientation`, `shape`, `detail`, `theme`, `background` (a preset's name, a tuned preset or your own picture), `vs`, `codes`, `title`, `subtitle`, `roundNames`, `roundLabels`, `scores`, `seeds`, `markShape`, `champion`, `trophy`, `emblems`, `emblemStyle`, `emblemTint`, `thirdPlace`, `winnerHighlight`, `look`, `href`, `tieClass`, `highlightPath`, `flags`, `flagHref`, `locale`, `words`, `teamName`, `groupOrder`, `id`, `className`.
|
|
469
508
|
- `roadToFinal(input, options?)`: the road to the final of a tournament or of two finalists: `{ options, title, summary, totals, draw(extra?), table(options?) }`. `input` is what `drawBracket` takes, or the two finalists with their paths. Options: `team`, `title`, `subtitle`, `final`, `labels`, `groupLabel`, `size`, `winner`, `codes`, `endnote`, and `locale`, `words`, `teamName`, `roundNames`, `markShape`, `flags`, `theme`, `background`, `id`, `className` as for `drawBracket`. The types `RoadChart`, `RoadFinalist`, `RoadMatch`, `RoadOptions` and the rest are exported too; it is also the one export of `/road`.
|
|
470
509
|
- `layoutBracket(input, options?)`: the rounds, halves, rows, byes and results, without drawing. `shape: "ltr"` and `groupOrder` are its options.
|
|
471
510
|
- `bracketTable(input, options?)`: the HTML table.
|
|
@@ -478,6 +517,7 @@ Everything is exported from `@johnmorrisdotca/taisen-brackets`; the layout part
|
|
|
478
517
|
- `roundName(remaining)`, `roundNamesFor(count)`, `roundLabel(layout, round, names, words)`: round names.
|
|
479
518
|
- `LOCALES`, `LOCALE_CODES`, `defineLocale`, `localeOf`, `voiceOf`, `countryName`: the languages (see Languages), a language of your own, the formats and the names of countries from `Intl`. `localizedLayout(layout, voice)` is a layout with the team names in a language.
|
|
480
519
|
- `SIZES`, `THEMES`, `ROAD_THEMES`, `WORDS`, `VERSION`: the sizes (`wide`, `square`, `card`, `phone`), the looks' colours, the road look's extra colours, the English words, the version.
|
|
520
|
+
- `BACKGROUND_PRESETS`, `backgroundSvg(preset, options)`, `contrastRatio(a, b)`, `resolveBackground(option, theme, width, height, prefix)`, `FAMILY_BACKGROUNDS_VERSION`: the twenty-five backgrounds, one drawn on its own with the ink that reads over it, the contrast of two colours, the `background` option read, and the version of the file shared with the family (see "Backgrounds"). Also its own entry point, `/backgrounds`.
|
|
481
521
|
- `cleanSvg(markup)`, `safeUrl(url)`, `safeHref(url)`, `abbreviate(name)`: the rules for marks and for the addresses of links, and the short name made from a name. The types `FlagRenderer`, `FlagRequest` and `FlagShape` are the flags plug-in's (see "Flags from a plug-in").
|
|
482
522
|
|
|
483
523
|
## Languages
|
|
@@ -566,6 +606,7 @@ Any current browser, and Node 22 or later. The package makes no network request
|
|
|
566
606
|
- More languages (Portuguese, Italian, Korean, Chinese), and native review of the Spanish and German words.
|
|
567
607
|
- A custom element and a React helper, as in the other packages of the family.
|
|
568
608
|
- A PNG renderer (through an optional peer).
|
|
609
|
+
- Planned for 0.6.0: new layouts (`rows`, `shields`, `update`, `columns`, `play-in`, a series card, conference headers) and a group-stage table drawing, which John Morris asked for; and a lone final centred, and one stylesheet for several drawings. See [docs/roadmap.md](./docs/roadmap.md); the pictures that prompted them are listed in [docs/references.md](./docs/references.md).
|
|
569
610
|
|
|
570
611
|
## The name
|
|
571
612
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BackgroundInks } from "./theme.ts";
|
|
2
|
+
import type { ThemeName } from "./types.ts";
|
|
3
|
+
export interface ResolvedBackground {
|
|
4
|
+
/** For the drawing's `<defs>`. */
|
|
5
|
+
defs: string;
|
|
6
|
+
/** Drawn over the plain `.tb-bg` rectangle, under everything else. */
|
|
7
|
+
body: string;
|
|
8
|
+
/** The colours to draw over it: one for a look that is light or dark, both for `auto`. */
|
|
9
|
+
inks: BackgroundInks;
|
|
10
|
+
/** Both pictures are in the drawing and the stylesheet shows the one that fits. */
|
|
11
|
+
auto: boolean;
|
|
12
|
+
}
|
|
13
|
+
/** Whether an option asks for more than the plain colour: a preset, a tuned preset or an image. */
|
|
14
|
+
export declare function hasBackground(option: unknown): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Reads the `background` option for a drawing `width` by `height` in the look `theme`, with `prefix` for the ids. Returns `null` when the option is `true`, `false` or left out
|
|
17
|
+
* (a plain colour, or none). An unknown preset, a bad colour list or an image address that is not http(s), relative or `data:image/…` throws a `RangeError`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveBackground(option: unknown, theme: ThemeName, width: number, height: number, prefix: string): ResolvedBackground | null;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// The `background` option: a preset's name, a preset tuned, or the caller's own picture, turned into the SVG to draw under everything and the colours to draw over it.
|
|
2
|
+
// The drawing of the presets is `family-backgrounds.ts`, which is shared with the other packages of the family; this file only reads the option and writes the picture's frame.
|
|
3
|
+
import { BACKGROUND_PRESETS, backgroundSvg } from "./family-backgrounds.js";
|
|
4
|
+
import { safeUrl } from "./marks.js";
|
|
5
|
+
import { esc, num } from "./text.js";
|
|
6
|
+
const isPreset = (name) => typeof name === "string" && BACKGROUND_PRESETS.includes(name);
|
|
7
|
+
/** Whether an option asks for more than the plain colour: a preset, a tuned preset or an image. */
|
|
8
|
+
export function hasBackground(option) {
|
|
9
|
+
return typeof option === "string" || (typeof option === "object" && option !== null);
|
|
10
|
+
}
|
|
11
|
+
const fail = (message) => {
|
|
12
|
+
throw new RangeError(`taisen-brackets: ${message}`);
|
|
13
|
+
};
|
|
14
|
+
/** The ink for a picture of the caller's own: a plain dark or pale ground, since the image under the veil is not known. */
|
|
15
|
+
function inkForImage(theme, id) {
|
|
16
|
+
const colors = theme === "dark" ? ["#12161c", "#12161c", "#c9d2e0", "#c9d2e0"] : ["#f4f4f1", "#f4f4f1", "#4a5568", "#4a5568"];
|
|
17
|
+
return backgroundSvg("midnight", { width: 8, height: 8, theme, colors, id }).ink;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Reads the `background` option for a drawing `width` by `height` in the look `theme`, with `prefix` for the ids. Returns `null` when the option is `true`, `false` or left out
|
|
21
|
+
* (a plain colour, or none). An unknown preset, a bad colour list or an image address that is not http(s), relative or `data:image/…` throws a `RangeError`.
|
|
22
|
+
*/
|
|
23
|
+
export function resolveBackground(option, theme, width, height, prefix) {
|
|
24
|
+
if (option === undefined || typeof option === "boolean" || option === null)
|
|
25
|
+
return null;
|
|
26
|
+
const spec = typeof option === "string" ? { preset: option } : option;
|
|
27
|
+
if (typeof option !== "string" && typeof option !== "object")
|
|
28
|
+
return fail(`background is a preset's name or an object, not ${typeof option}`);
|
|
29
|
+
const image = spec.image;
|
|
30
|
+
if (image === undefined && spec.preset !== undefined && !isPreset(spec.preset))
|
|
31
|
+
fail(`unknown background "${String(spec.preset)}": use one of ${BACKGROUND_PRESETS.join(", ")}`);
|
|
32
|
+
if (spec.colors !== undefined && (!Array.isArray(spec.colors) || spec.colors.some((c) => typeof c !== "string")))
|
|
33
|
+
fail("background.colors is a list of colours as text");
|
|
34
|
+
for (const key of ["angle", "intensity", "seed", "dim"])
|
|
35
|
+
if (spec[key] !== undefined && !Number.isFinite(spec[key]))
|
|
36
|
+
fail(`background.${key} is a number`);
|
|
37
|
+
// Which pictures to draw: the one the look is, or the one asked for; `auto` draws both.
|
|
38
|
+
const want = spec.theme ? [spec.theme] : theme === "light" ? ["light"] : theme === "dark" || theme === "poster" || theme === "none" ? ["dark"] : ["light", "dark"];
|
|
39
|
+
const auto = want.length === 2;
|
|
40
|
+
const parts = want.map((t) => {
|
|
41
|
+
const id = auto ? `${prefix}${t === "light" ? "l" : "d"}` : `${prefix}b`;
|
|
42
|
+
if (image !== undefined) {
|
|
43
|
+
if (typeof image !== "string" || !safeUrl(image))
|
|
44
|
+
return fail("background.image must be an http(s) address, a relative path or a data:image/ address");
|
|
45
|
+
const dim = Math.min(1, Math.max(0, spec.dim ?? 0.5));
|
|
46
|
+
const fitName = spec.fit === "contain" ? "meet" : "slice";
|
|
47
|
+
return {
|
|
48
|
+
t,
|
|
49
|
+
defs: "",
|
|
50
|
+
body: `<image href="${esc(image)}" x="0" y="0" width="${num(width)}" height="${num(height)}" preserveAspectRatio="xMidYMid ${fitName}"/><rect width="${num(width)}" height="${num(height)}" fill="${t === "dark" ? "#000" : "#fff"}" opacity="${num(dim)}"/>`,
|
|
51
|
+
ink: inkForImage(t, id),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const made = backgroundSvg(spec.preset ?? "midnight", { width, height, theme: t, colors: spec.colors, angle: spec.angle, intensity: spec.intensity, seed: spec.seed, id });
|
|
55
|
+
return { t, ...made };
|
|
56
|
+
});
|
|
57
|
+
const inks = {};
|
|
58
|
+
for (const p of parts)
|
|
59
|
+
inks[p.t] = p.ink;
|
|
60
|
+
return {
|
|
61
|
+
defs: parts.map((p) => p.defs).join(""),
|
|
62
|
+
body: auto ? parts.map((p) => `<g class="${p.t === "light" ? "tb-bgl" : "tb-bgd"}">${p.body}</g>`).join("") : parts[0].body,
|
|
63
|
+
inks,
|
|
64
|
+
auto,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BACKGROUND_PRESETS, FAMILY_BACKGROUNDS_VERSION, backgroundSvg, contrastRatio, luminance, parseColor, toHex } from "./family-backgrounds.js";
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export declare const FAMILY_BACKGROUNDS_VERSION = "1.0.0";
|
|
2
|
+
/** The presets, by name. The five that end in a playing surface read as one: pitch (soccer), ice (hockey), hardwood (basketball), infield (baseball) and turf (football). */
|
|
3
|
+
export declare const BACKGROUND_PRESETS: readonly ["midnight", "crimson", "royal", "emerald", "pitch", "ice", "hardwood", "infield", "turf", "ball-panels", "swirl", "waves", "glow", "floodlights", "confetti", "carbon", "aurora", "sunburst", "chevrons", "halftone", "argyle", "contour", "stardust", "mesh", "spotlight"];
|
|
4
|
+
export type BackgroundPresetName = (typeof BACKGROUND_PRESETS)[number];
|
|
5
|
+
export interface BackgroundSvgOptions {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
/** `dark` (the default) or `light`: which of the preset's two palettes. With your own `colors`, the ink follows what they are. */
|
|
9
|
+
theme?: "dark" | "light";
|
|
10
|
+
/** Your own colours, as hex (`#0b1230`) or `rgb()`: the first two make the ground, the third and fourth the glow and the pattern. Fewer than four keep the preset's for the rest. */
|
|
11
|
+
colors?: readonly string[];
|
|
12
|
+
/** The angle of the ground's gradient and of the pattern over it, in degrees as CSS has it (180 is top to bottom). The preset's own by default; a playing surface keeps its lines straight. */
|
|
13
|
+
angle?: number;
|
|
14
|
+
/** How strong the pattern and glow are, 0 to 1. Default 0.6. */
|
|
15
|
+
intensity?: number;
|
|
16
|
+
/** Moves the scattered parts (confetti, stars, scratches, contours). Default 1. */
|
|
17
|
+
seed?: number;
|
|
18
|
+
/** The prefix of the ids the background writes. Default: a hash of its options. */
|
|
19
|
+
id?: string;
|
|
20
|
+
}
|
|
21
|
+
/** The colours to draw over a background. Every text colour is checked against `dominant`, the colours the background mostly is, for a contrast of 4.5 to 1 (3 to 1 for `muted`). */
|
|
22
|
+
export interface BackgroundInk {
|
|
23
|
+
/** The plain colour to fill the picture with before `body`: the ground's first colour. */
|
|
24
|
+
base: string;
|
|
25
|
+
/** Whether the ground is dark (so the text is light). */
|
|
26
|
+
dark: boolean;
|
|
27
|
+
text: string;
|
|
28
|
+
muted: string;
|
|
29
|
+
/** The connecting lines. */
|
|
30
|
+
line: string;
|
|
31
|
+
/** The fill and edge of a box laid on the picture; both are `rgba()`. */
|
|
32
|
+
box: string;
|
|
33
|
+
edge: string;
|
|
34
|
+
/** The pill behind a round's name, a team's plain disc, the ring round a mark, the dotted road and the accent for a winner, a champion and a highlight. */
|
|
35
|
+
panel: string;
|
|
36
|
+
plain: string;
|
|
37
|
+
ring: string;
|
|
38
|
+
spine: string;
|
|
39
|
+
accent: string;
|
|
40
|
+
/** The colours the picture is mostly, worst cases included: the ground's two colours and each blended with the glow at its strongest. */
|
|
41
|
+
dominant: string[];
|
|
42
|
+
}
|
|
43
|
+
export interface BackgroundSvg {
|
|
44
|
+
defs: string;
|
|
45
|
+
body: string;
|
|
46
|
+
ink: BackgroundInk;
|
|
47
|
+
}
|
|
48
|
+
type Rgb = readonly [number, number, number];
|
|
49
|
+
/** A colour as three channels, or `null` when it is not hex or `rgb()`. */
|
|
50
|
+
export declare function parseColor(text: string): Rgb | null;
|
|
51
|
+
export declare const toHex: (c: Rgb) => string;
|
|
52
|
+
/** The relative luminance of a colour, as WCAG defines it. */
|
|
53
|
+
export declare function luminance(c: Rgb): number;
|
|
54
|
+
/** The WCAG contrast ratio of two colours, 1 to 21. */
|
|
55
|
+
export declare function contrastRatio(a: Rgb, b: Rgb): number;
|
|
56
|
+
/**
|
|
57
|
+
* One background: `defs` for the drawing's `<defs>`, `body` for what goes over a plain `ink.base` rectangle, and `ink`, the colours to draw text, lines and boxes in. The same preset and options
|
|
58
|
+
* always give the same markup; every id starts with `options.id`. An unknown preset throws.
|
|
59
|
+
*/
|
|
60
|
+
export declare function backgroundSvg(preset: BackgroundPresetName, options: BackgroundSvgOptions): BackgroundSvg;
|
|
61
|
+
export {};
|