@johnmorrisdotca/kyogijo-stadiums 0.16.0 → 0.16.1

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 CHANGED
@@ -7,6 +7,17 @@ All notable changes to this project are written here. The format follows
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.16.1] - 2026-10-20
11
+
12
+ ### Added
13
+
14
+ - **Sample content for a tournament layout** (`drawMulti({ sample: true })`, or `sample: { event, year, city }`). The places for the event's words and marks are filled as an event would dress them: an invented event name, year and city on the floor and the boards ("Kyogijo Open 2026 · Osaka", in Japanese `競技場杯 2026 · 大阪`) and, in each logo place, a simple emblem of the package's own (a ring with a star, a diamond or waves), in place of the dashed empty places. Nothing real is named or drawn: no event, brand, federation, sponsor or league (a test holds every preset in both languages to that). Off by default, so a layout is still drawn as it is configured; with `slots: false` nothing is drawn. The 3D view carries it on its floor. New `MultiSample` and `MultiWords.sample`.
15
+
16
+ ### Changed
17
+
18
+ - **The demo's tournament layouts page and every picture of a layout are dressed with sample content.** `halls.html` has a "Sample event content" box, on by default (`sample=0` in its address turns it off and brings the empty places back); the README's and the docs' pictures of layouts (three judo areas, four table tennis areas, the same four in 3D, the gallery) show the invented event, and one picture shows the empty places with a caption (what an organiser configures): `docs/images/multi-judo-empty-*`, `ONLY=multi-judo-empty` takes it. The README gives up some prose to stay under its size budget.
19
+ - **Docs only:** the gallery's table tennis text gives the surrounds' range (50 to 100 cm) of the ITTF Statutes 2026.
20
+
10
21
  ## [0.16.0] - 2026-10-20
11
22
 
12
23
  ### Added
package/README.md CHANGED
@@ -75,16 +75,16 @@ console.log(svg.startsWith("<svg"), svg.includes("USA 3, Canada 2"));
75
75
  - **Thirty-nine surfaces, to scale.** The NFL, CFL and IFAF fields, the NHL rink, the NBA court, the soccer pitch and futsal court, the baseball field, the curling sheet, the courts of twelve net and racket sports, the pools, the athletics stadium, the skating rinks, the fields of seven field sports, and the budō. Every figure is cited in [sources](./docs/sources.md). [The surfaces](./docs/surfaces.md).
76
76
  - **Each league's rulebook.** `league: "fiba"` draws a court as FIBA marks it: 48 variants, from the WNBA, the NCAA and the IIHF to Little League, PONY, softball, Curling Canada, FIVB's beach volleyball, rugby league and the NLL's box lacrosse, each cited. [League variants](./docs/variants.md).
77
77
  - **A realistic basketball floor.** `court: { hardwood: true }` draws maple boards that run the length of the court with staggered ends, grain, stained keys, the baskets and stanchions with soft shadows, a coaching box and benches, and a satin sheen, in every league and renderer. The clean floor stays the default. [Hardwood](./docs/hardwood.md).
78
- - **The stands and the crowd.** `crowd: true` draws the seating round any surface that has spectators: a bowl, two sides, a horseshoe, courtside rows or a ballpark's grandstands, with the people as seeded heads and shoulders in the home colours, the visitors at an end and the empty seats showing (`density`, or `attendance` over `capacity`). Blocks at small sizes. [The crowd](./docs/crowd.md).
78
+ - **The stands and the crowd.** `crowd: true` draws the seating round any surface that has spectators: a bowl, two sides, a horseshoe, courtside rows or a ballpark's grandstands, with the people as seeded heads and shoulders in the home colours and the empty seats showing (`density`, or `attendance` over `capacity`). [The crowd](./docs/crowd.md).
79
79
  - **Curling, from the rule books.** A sheet from World Curling's and Curling Canada's rules, tall by default, with the board and the hammer in a score, `curlingStones` for the stones of an end, scored by the rules, `show: "folded"` for the whole sheet with both houses enlarged beside it, and a heat map and statistics for many ends. [Curling](./docs/curling.md).
80
80
  - **Net, racket and court sports, from their rulebooks.** The ITF's, FIVB's (indoor, beach, sitting), BWF's, USA Pickleball's and ITTF's courts and table, the padel, squash, racquetball, sepak takraw, teqball, roundnet and netball courts, each in its look (hard court, clay, grass, wood, sand), with a board of sets and games. [Net, racket and court sports](./docs/courts.md).
81
- - **Swimming, water polo, diving and artistic swimming, from World Aquatics' regulations.** The competition pool of 50 or 25 m with its lanes, ropes, blocks, touch panels and flags; the water polo field; the diving well with its springboards and platforms; the artistic swimming area; several pools in a natatorium. A race's lanes carry names, flags, places, times and splits, with a replay (`raceTimeline`) and a `splitsChart`. [Pools](./docs/pools.md).
81
+ - **Swimming, water polo, diving and artistic swimming, from World Aquatics' regulations.** The competition pool of 50 or 25 m with its lanes, ropes, blocks and touch panels; the water polo field; the diving well; the artistic swimming area; several pools in a natatorium. A race's lanes carry names, flags, places, times and splits, with a replay (`raceTimeline`) and a `splitsChart`. [Pools](./docs/pools.md).
82
82
  - **Lacrosse, rugby, Australian football, Gaelic games, cricket, field hockey and handball, from their rulebooks.** The fields and floors of World Lacrosse, World Rugby, the NRL, the AFL, the GAA, the FIH and the IHF, and a cricket ground with a boundary of your own. A score is goals and behinds, goals and points or a board of runs, wickets and overs. [Field sports](./docs/field-sports.md).
83
83
  - **The athletics stadium, from World Athletics' rules.** The 400 m track with its lanes and staggers worked out from the running lines, curved and relay starts, hurdles, the steeplechase, every field event, a close-up of each start, the covered 200 m track, and lane draws, results, a race replay and the marks of throws and jumps. [The athletics stadium](./docs/athletics.md).
84
- - **The skating rinks, from the ISU's rules.** The 400 m speed skating track with its lanes, blocks and the starting and finishing lines of every race worked out lane by lane; the short track's oval of 111.12 m; the figure skating rink of 60 by 30 m with its judges' seats; and pairs, results, a race replay and the elements of a programme on the ice. [The skating rinks](./docs/skating.md).
85
- - **The budō, from the federations' rules.** The IJF's and the All Japan Judo Federation's judo areas, the WKF's karate areas, the kendo shiai-jo, the sumo dohyō, the kyūdōjō, and **a dojo builder**: a floor of tatami laid as real units (no four corners meet), in jō or metres, with the walls, doors, windows, shrine and kamiza. Five famous halls are on the atlas, and the scores are judo's ippon, waza-ari and shido, karate's and kendo's points and sumo's kimarite. [The budō](./docs/budo.md).
84
+ - **The skating rinks, from the ISU's rules.** The 400 m speed skating track with its lanes, blocks and the lines of every race worked out lane by lane; the short track's oval; the figure skating rink of 60 by 30 m with its judges' seats; and pairs, results, a race replay and the elements of a programme on the ice. [The skating rinks](./docs/skating.md).
85
+ - **The budō, from the federations' rules.** The IJF's and the All Japan Judo Federation's judo areas, the WKF's karate areas, the kendo shiai-jo, the sumo dohyō, the kyūdōjō, and **a dojo builder**: a floor of tatami laid as real units, in jō or metres, with its walls, doors, windows and shrine. Five famous halls are on the atlas, and the scores are judo's ippon, waza-ari and shido, karate's and kendo's points and sumo's kimarite. [The budō](./docs/budo.md).
86
86
  - **Soccer, to the Laws.** A pitch from Law 1 of the IFAB Laws of the Game of any size, with presets (international, UEFA, MLS, NCAA, the FA's 9-, 7- and 5-a-side, FIFA's futsal), half pitches, five mowing patterns, four goal styles, penalties and extra time in a score. [Soccer](./docs/soccer.md).
87
- - **Every ballpark.** The 30 current MLB parks and 44 that MLB clubs have left (the Polo Grounds, Ebbets Field, the Astrodome and more), and the 12 home parks of Nippon Professional Baseball with eight other NPB grounds, each with its fence drawn from the distances published for it; a past park whose fence moved is drawn as it stood in a season. [Ballparks](./docs/ballparks.md).
87
+ - **Every ballpark.** The 30 current MLB parks and 44 that MLB clubs have left, and the 12 home parks of Nippon Professional Baseball with eight other NPB grounds, each with its fence drawn from the distances published for it, as it stood in a season. [Ballparks](./docs/ballparks.md).
88
88
  - **Soccer grounds, arenas and an atlas.** 64 soccer grounds, each pitch at its published size, and 167 NHL, NBA, WNBA and PWHL arenas (`drawKyogijo({ sport: "nhl", arena: "boston-garden" })`), and every park, ground, arena and budō hall (330 places) on a map, by sport, league, country and year, each found by any of its names. [The grounds](./docs/grounds.md), [the arenas](./docs/arenas.md), [the atlas](./docs/atlas.md), [names](./docs/ballparks.md#names).
89
89
  - **Walls and quirks.** How high the fence stands, stretch by stretch and season by season (the Green Monster at 37 feet 2 inches), drawn as a band outside the fence whose width and shade say the height, with a key (`walls`); and Tal's Hill, Wrigley Field's ivy and basket, poles, bullpens and dugouts (`quirks`), each from the park's article, none guessed: [ballparks](./docs/ballparks.md).
90
90
  - **Special games.** A surface set inside another, to scale: an NHL rink on a ballpark's infield or a football stadium's field, a college basketball court on the deck of a carrier, a baseball field laid over a London stadium's pitch. 18 games, each with its day, its venue and its sources. [Special games](./docs/special-games.md).
@@ -94,16 +94,16 @@ console.log(svg.startsWith("<svg"), svg.includes("USA 3, Canada 2"));
94
94
  - **Lineups.** A `lineup` layer places a team's players by position code (`GK`, `CB`, `HK`, `C`) with no coordinates: it reads where each stands from a formation (36 of them, in 13 sports), draws a disc or a jersey with the shirt number and the name under it, a captain's C and a flag, and puts the visitors at the other end. [Lineups](./docs/team-shape.md#lineups).
95
95
  - **A pageant.** Each team's flag or crest laid large over its half of the surface: `pageant: "carpet"` (a flag at its own ratio with a border) or `"stage"` (a crest on a round disc with a gold ring), an emblem or a trophy in the centre circle, the score in the middle or in the strip, with an entrance in CSS for readers who have not asked for less motion. [The pageant](./docs/pageant.md).
96
96
  - **Trophies, medals, balls and crests, by id.** `useEmblems(renderEmblem)` plugs in the sister package [Dougu Sports](https://johnmorrisdotca.github.io/dougu-sports/) in one line, and an id goes wherever a logo, a flag or a mark is taken: `logo: "crest:shield"`, `pageant: { emblem: "trophy:hockey-cup" }`, `"ball:puck"`. Kyogijo bundles no emblem and keeps zero dependencies. [Emblems](./docs/emblems.md).
97
- - **Country flags, by code.** `useFlags(render)` plugs in the sister package [Hata](https://github.com/johnmorrisdotca/hata) through a small adapter, and a team's `flag: "CA"` is its flag: round in a round mark, at its own proportions on a banner, a badge or a carpet. The same adapter serves [Taisen Brackets](https://github.com/johnmorrisdotca/taisen-brackets). Kyogijo bundles no flag and keeps zero dependencies. [Flags](./docs/flags.md).
97
+ - **Country flags, by code.** `useFlags(render)` plugs in the sister package [Hata](https://github.com/johnmorrisdotca/hata) through a small adapter, and a team's `flag: "CA"` is its flag: round in a round mark, at its own proportions on a banner, a badge or a carpet. Kyogijo bundles no flag and keeps zero dependencies. [Flags](./docs/flags.md).
98
98
  - **Zoom to a part of a surface.** `range: "offensive-zone"` crops a drawing to a rink's zone, a half court, the paint, the red zone, a soccer half, third or penalty area, the infield, a curling house, or a box of your own in any frame, with its data, heat, labels and score following. [Display ranges](./docs/ranges.md).
99
99
  - **Wide, tall or fit the box.** Every surface lies wide or tall: tall turns it a quarter, keeps every word upright and puts the teams top and bottom. With `orientation: "auto"` the browser helpers follow the box.
100
- - **Where a point lies, by the rules, and a click as a place.** `zoneAt("nhl", [69, 22], { frame: "nhl-api" })` names the zone and the area in it from the surface's own figures, with `isThreePointer`, `inSlot`, `isFair`, `isHomeRun` and the like; `clientPointToField(svg, x, y, { provider })` is a pointer's place in any of the frames, with the zone. `marks: true` writes `data-mark-id` and `data-zone` on every mark of a layer. [Zones](./docs/zones.md), [pointing](./docs/pointer.md).
101
- - **Goals, the strike zone and the stumps, end-on.** A goal mouth for hockey, soccer, handball, water polo, lacrosse and field hockey with the shots laid on it and its zones (the top shelf, the five-hole, the corners), the catcher's view of the strike zone with its pitches numbered, and the wicket from the bowler's end with its line and length zones. [Targets](./docs/targets.md).
100
+ - **Where a point lies, by the rules, and a click as a place.** `zoneAt("nhl", [69, 22], { frame: "nhl-api" })` names the zone and the area in it from the surface's own figures, with `isThreePointer`, `inSlot`, `isFair`, `isHomeRun` and the like; `clientPointToField(svg, x, y, { provider })` is a pointer's place in any of the frames, with the zone. [Zones](./docs/zones.md), [pointing](./docs/pointer.md).
101
+ - **Goals, the strike zone and the stumps, end-on.** A goal mouth for six sports with the shots laid on it and its zones, the catcher's view of the strike zone with its pitches numbered, and the wicket from the bowler's end with its line and length zones. [Targets](./docs/targets.md).
102
102
  - **Data on the surface.** Points, lines, arrows, text, heat maps, hexagons, zone charts and density contours over any surface, in its feet or a data provider's frame, cut to its outline, with a table for each layer; ready-made shot and pass charts. [Data layers](./docs/layers.md), [charts](./docs/charts.md).
103
103
  - **Small multiples and backgrounds.** `drawGrid` puts many drawings in one SVG, under a title and a subtitle, over a credit line, with a key they share, in a size for a social card, a square post or a phone; `background` lays a quiet pattern (felt, grass, wood, ice, paper, a grid, dots) or a photograph behind a drawing or a grid. [Layouts and backgrounds](./docs/layouts.md).
104
104
  - **Tournament layouts.** Several surfaces laid out together for one large event, to scale, on one floor, as one SVG: thirteen presets from table tennis, pickleball, curling, judo, karate, badminton and tennis, each with its rule and sources, whether it fits a hall, and a real stadium round it. [Tournament layouts](./docs/multi.md).
105
105
  - **Replay.** Tracking data played on any surface: the players with their numbers, the ball and its trail, and the passes, shots and goals as they happen, with controls, the keyboard and a live region, steps for a reader who prefers reduced motion, and a pause when the page is hidden. [Replay](./docs/replay.md).
106
- - **A 3D view.** Any surface as a floor that turns by mouse, touch, wheel or keys, with four viewpoints (overhead, broadcast, end-on, low corner), and what the rulebook stands on it at its height (nets, baskets, rink boards and glass, goals, a ballpark's fence, the walls of padel and squash, a pool's blocks, a table tennis area's surrounds); and the venue round it (raked stands, roofs on request, a dojo's walls and gallery). Plain DOM and CSS over the same SVG. [The 3D view](./docs/turn.md).
106
+ - **A 3D view.** Any surface as a floor that turns by mouse, touch, wheel or keys, with four viewpoints (overhead, broadcast, end-on, low corner), and what the rulebook stands on it at its height (nets, baskets, rink boards and glass, goals, a ballpark's fence, the walls of padel and squash, a pool's blocks, a table tennis area's surrounds); and the venue round it (raked stands, roofs on request, a dojo's walls and gallery). Plain DOM and CSS. [The 3D view](./docs/turn.md).
107
107
  - **Renderers.** The same drawing as plain data (a scene), on a canvas (a browser's or a Node canvas), in a d3 selection, as a mark of an Observable Plot, as GeoJSON and as a PNG in Node, each an entry of its own that imports nothing from outside the package. [Renderers](./docs/renderers.md).
108
108
  - **Units and frames.** Each surface in its rulebook's unit and any other, and 48 coordinate frames (ten soccer providers, the NHL API, HockeyTech, NBA stats, NFL tracking, MLBAM, Retrosheet, and a place from the net, the centre or the middle of the water of each other surface) to move a provider's points onto a surface. [Units](./docs/units.md), [coordinate frames](./docs/frames.md).
109
109
  - **A compact badge and a compact card.** One strip for a list, or the surface with that strip under it.
@@ -494,12 +494,12 @@ console.log(svg.includes('viewBox="0 0 1200 675"'), svg.includes("Three ballpark
494
494
 
495
495
  ### Several surfaces on one floor
496
496
 
497
- `drawMulti` lays the package's own surfaces out together for one large event, to scale, on one floor, with the officials' chairs, the boards and empty places for the event's words and marks ([tournament layouts](./docs/multi.md)). Thirteen presets with their rules and sources; `multiFit` says whether a layout fits a hall, `stadium: true` sets it inside real stands, and `mountMultiTurn` turns the floor in 3D.
497
+ `drawMulti` lays the package's own surfaces out together for one large event, to scale, on one floor, with the officials' chairs and boards, and places for the event's words and marks (`sample: true` fills them with an invented event; [tournament layouts](./docs/multi.md)). Thirteen presets with their rules and sources; `multiFit` says whether a layout fits a hall, `stadium: true` sets it inside real stands, and `mountMultiTurn` turns the floor in 3D.
498
498
 
499
499
  ```ts
500
500
  import { drawMulti, multiLayout } from "@johnmorrisdotca/kyogijo-stadiums/multi";
501
501
 
502
- const svg = drawMulti({ preset: "judo-1x3" });
502
+ const svg = drawMulti({ preset: "judo-1x3", sample: true });
503
503
  const layout = multiLayout({ preset: "judo-1x3" });
504
504
  console.log(svg.startsWith("<svg"), layout.cells.length);
505
505
  // true 3
@@ -510,15 +510,15 @@ console.log(layout.needs.length, layout.needs.width);
510
510
  <p align="center">
511
511
  <picture>
512
512
  <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/multi-judo-desk-dark.webp">
513
- <img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/multi-judo-desk-light.webp" alt="Three judo contest areas in a row on one red floor of mats, each numbered, with dashed empty places for the event's name and logos and a board along each edge." width="640">
513
+ <img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/multi-judo-desk-light.webp" alt="Three judo contest areas in a row on one red floor of mats, dressed with a sample event's name, simple emblems and boards." width="640">
514
514
  </picture>
515
- <br><em>Three judo contest areas on one floor of mats: 47 by 19 metres.</em>
515
+ <br><em>Three judo contest areas on one floor of mats: 47 by 19 metres, with sample content.</em>
516
516
  </p>
517
517
 
518
518
  <p align="center">
519
519
  <picture>
520
520
  <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/multi-tabletennis-desk-dark.webp">
521
- <img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/multi-tabletennis-desk-light.webp" alt="Four table tennis areas in two rows of two on one blue floor, numbered Table 1 to Table 4, with a scoreboard hung over the middle and boards along the edges." width="640">
521
+ <img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/multi-tabletennis-desk-light.webp" alt="Four table tennis areas in two rows of two on one blue floor, with sample words and emblems, a hung scoreboard and boards." width="640">
522
522
  </picture>
523
523
  <br><em>Four table tennis areas under one scoreboard.</em>
524
524
  </p>
@@ -526,11 +526,19 @@ console.log(layout.needs.length, layout.needs.width);
526
526
  <p align="center">
527
527
  <picture>
528
528
  <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/multi-tabletennis-3d-desk-dark.webp">
529
- <img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/multi-tabletennis-3d-desk-light.webp" alt="Four table tennis areas in 3D from a low corner: tables on legs, a surround round each, a hung scoreboard, and the 3D view's controls." width="640">
529
+ <img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/multi-tabletennis-3d-desk-light.webp" alt="Four table tennis areas in 3D: tables on legs, a surround round each, a hung scoreboard." width="640">
530
530
  </picture>
531
531
  <br><em>The same four in 3D.</em>
532
532
  </p>
533
533
 
534
+ <p align="center">
535
+ <picture>
536
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/multi-judo-empty-desk-dark.webp">
537
+ <img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/multi-judo-empty-desk-light.webp" alt="The three judo areas with the places for the event's words and marks left empty and dashed." width="640">
538
+ </picture>
539
+ <br><em>Without `sample`: the empty places an organiser fills.</em>
540
+ </p>
541
+
534
542
  The [demo](https://johnmorrisdotca.github.io/kyogijo-stadiums/halls.html) picks a preset, sets it in a hall, switches the stadium on and off, and turns it in 3D.
535
543
 
536
544
  ### A table tennis area
@@ -27,6 +27,42 @@ function inner(svg) {
27
27
  body = body.replace(/<rect class="ky-(?:apron|free)(?: [^"]*)?"[^>]*\/>/g, "");
28
28
  return { body, style, look };
29
29
  }
30
+ /** The invented event of a layout's sample content: the options' own, or the package's (`Kyogijo Open 2026, Osaka`). */
31
+ function sampleOf(o, words) {
32
+ if (o.sample === undefined || o.sample === false)
33
+ return undefined;
34
+ const given = o.sample === true ? {} : o.sample;
35
+ return { event: given.event ?? words.sample.event, year: String(given.year ?? words.sample.year), city: given.city ?? words.sample.city };
36
+ }
37
+ /** The line of a sample event: its name, year and city. */
38
+ const sampleLine = (e) => `${e.event} ${e.year} · ${e.city}`;
39
+ /**
40
+ * A simple emblem of the package's own, in a square of `size` feet centred on (cx, cy): a ring with a star, a diamond or waves, by `kind`. Plain geometry: no real mark, brand, federation or sponsor is drawn, and no one's logo is
41
+ * imitated.
42
+ */
43
+ function emblem(cx, cy, size, kind) {
44
+ const r = size / 2;
45
+ const ring = el("circle", { class: "ky-mu-emblem", cx: num(cx), cy: num(cy), r: num(r * 0.92) });
46
+ const k = ((kind % 3) + 3) % 3;
47
+ if (k === 0) {
48
+ const pts = Array.from({ length: 10 }, (_, i) => {
49
+ const a = -Math.PI / 2 + (i * Math.PI) / 5;
50
+ const rr = i % 2 === 0 ? r * 0.6 : r * 0.26;
51
+ return `${num(cx + rr * Math.cos(a))} ${num(cy + rr * Math.sin(a))}`;
52
+ });
53
+ return ring + el("path", { class: "ky-mu-emblem-fill", d: `M${pts.join("L")}Z` });
54
+ }
55
+ if (k === 1) {
56
+ const d = r * 0.5;
57
+ return ring + el("path", { class: "ky-mu-emblem-fill", d: `M${num(cx)} ${num(cy - d)}L${num(cx + d)} ${num(cy)}L${num(cx)} ${num(cy + d)}L${num(cx - d)} ${num(cy)}Z` });
58
+ }
59
+ let waves = "";
60
+ for (const dy of [-0.28, 0, 0.28]) {
61
+ const y = cy + r * dy;
62
+ waves += `M${num(cx - r * 0.55)} ${num(y)}Q${num(cx - r * 0.275)} ${num(y - r * 0.2)} ${num(cx)} ${num(y)}T${num(cx + r * 0.55)} ${num(y)}`;
63
+ }
64
+ return ring + el("path", { class: "ky-mu-emblem", d: waves, fill: "none" });
65
+ }
30
66
  /** The text of an empty place, sized to fit it. */
31
67
  function slotText(slot, words) {
32
68
  return slot.kind === "floor-text" ? words.slots.floorText : slot.kind === "floor-logo" ? words.slots.floorLogo : words.slots.board;
@@ -164,13 +200,21 @@ export function multiDrawing(options, raise, uprights = true) {
164
200
  }
165
201
  let slotsMarkup = "";
166
202
  let slotTexts = "";
203
+ const sample = sampleOf(o, words);
167
204
  if (withSlots) {
168
- for (const slot of layout.slots) {
205
+ layout.slots.forEach((slot, index) => {
169
206
  const board = slot.kind === "board";
170
- slotsMarkup += el("rect", { class: board ? "ky-mu-board" : "ky-mu-slot", x: num(slot.x), y: num(slot.y), width: num(slot.w), height: num(slot.h), "data-slot": slot.id });
171
- if (board)
207
+ // With sample content a floor's places carry an invented event's words and emblems and are not drawn dashed; the boards keep their dark panels.
208
+ if (sample === undefined || board)
209
+ slotsMarkup += el("rect", { class: board ? "ky-mu-board" : "ky-mu-slot", x: num(slot.x), y: num(slot.y), width: num(slot.w), height: num(slot.h), "data-slot": slot.id });
210
+ if (board && sample === undefined)
172
211
  slotsMarkup += el("rect", { class: "ky-mu-slot ky-mu-slot-board", x: num(slot.x + 0.3), y: num(slot.y + 0.3), width: num(slot.w - 0.6), height: num(slot.h - 0.6) });
173
- const text = slotText(slot, words);
212
+ if (sample !== undefined && slot.kind === "floor-logo") {
213
+ const [ex, ey] = to(slot.x + slot.w / 2, slot.y + slot.h / 2);
214
+ slotsMarkup += el("g", { class: "ky-mu-emblems", "data-slot": slot.id }, emblem(ex, ey, Math.min(slot.w, slot.h) * 0.9, index));
215
+ return;
216
+ }
217
+ const text = sample === undefined ? slotText(slot, words) : board ? sampleLine(sample).toUpperCase() : sampleLine(sample);
174
218
  const horizontal = slot.w >= slot.h;
175
219
  const long = horizontal ? slot.w : slot.h;
176
220
  const short = horizontal ? slot.h : slot.w;
@@ -178,8 +222,9 @@ export function multiDrawing(options, raise, uprights = true) {
178
222
  const [tx, ty] = to(slot.x + slot.w / 2, slot.y + slot.h / 2);
179
223
  // The words of a slot on a long side are laid along it; in a turned layout they turn back to read from the left.
180
224
  const rot = (horizontal ? 0 : -90) + 0;
181
- slotTexts += el("text", { class: `ky-mu-slot-text${board ? " ky-mu-slot-text-board" : ""}`, x: num(tx), y: num(ty + size * 0.34), "font-size": num(size), transform: rot === 0 ? undefined : `rotate(${rot} ${num(tx)} ${num(ty)})` }, esc(text));
182
- }
225
+ const cls = sample === undefined ? "ky-mu-slot-text" : "ky-mu-sample-text";
226
+ slotTexts += el("text", { class: `${cls}${board ? ` ${cls}-board` : ""}`, x: num(tx), y: num(ty + size * 0.34), "font-size": num(size), transform: rot === 0 ? undefined : `rotate(${rot} ${num(tx)} ${num(ty)})` }, esc(text));
227
+ });
183
228
  }
184
229
  let labelsMarkup = "";
185
230
  if (withLabels) {
@@ -260,8 +305,10 @@ export function multiDrawing(options, raise, uprights = true) {
260
305
  sentences.push(fill(words.say.stagger, { share: `${Math.round(spec.stagger * 100)}%` }));
261
306
  if (layout.shared !== undefined)
262
307
  sentences.push(words.say.shared);
263
- if (withSlots && layout.slots.some((s) => s.kind !== "board"))
264
- sentences.push(fill(words.say.slots, { n: layout.slots.filter((s) => s.kind !== "board").length }));
308
+ if (withSlots && layout.slots.some((s) => s.kind !== "board")) {
309
+ const filled = sampleOf(o, words);
310
+ sentences.push(filled === undefined ? fill(words.say.slots, { n: layout.slots.filter((s) => s.kind !== "board").length }) : fill(words.say.sample, filled));
311
+ }
265
312
  if (spec.event !== undefined) {
266
313
  const named = language === "ja" ? spec.event.ja : undefined;
267
314
  sentences.push(fill(words.say.event, { event: named?.name ?? spec.event.name, year: spec.event.year, venue: named?.venue ?? spec.event.venue, city: named?.city ?? spec.event.city }));
@@ -40,6 +40,10 @@ ${Object.keys(FLOORS).map((name) => `.kyogijo .ky-mu-hf-${name}{fill:var(--ky-mu
40
40
  .kyogijo .ky-mu-slot-board{stroke:var(--ky-mu-board-ink)}
41
41
  .kyogijo .ky-mu-slot-text{fill:var(--ky-mu-slot);fill-opacity:.8;font-family:var(--ky-font);font-weight:700;text-anchor:middle}
42
42
  .kyogijo .ky-mu-slot-text-board{fill:var(--ky-mu-board-ink)}
43
+ .kyogijo .ky-mu-sample-text{fill:var(--ky-mu-slot);font-family:var(--ky-font);font-weight:700;text-anchor:middle}
44
+ .kyogijo .ky-mu-sample-text-board{fill:var(--ky-mu-board-ink)}
45
+ .kyogijo .ky-mu-emblem{fill:none;stroke:var(--ky-mu-slot);stroke-width:.35;stroke-linejoin:round;stroke-linecap:round}
46
+ .kyogijo .ky-mu-emblem-fill{fill:var(--ky-mu-slot);stroke:none}
43
47
  .kyogijo .ky-mu-label{fill:var(--ky-ink);font-family:var(--ky-font);font-weight:800;paint-order:stroke;stroke:var(--ky-halo);stroke-width:.5;stroke-linejoin:round}
44
48
  .kyogijo .ky-mu-caption{fill:var(--ky-mu-sb-ink);font-family:var(--ky-font);font-weight:700;text-anchor:middle}
45
49
  .kyogijo.ky-multi{--ky-cr-home:#8b94a3;--ky-cr-away:#8b94a3}
@@ -37,6 +37,12 @@ export interface MultiEvent {
37
37
  /** Keys of `MULTI_SOURCES`. */
38
38
  sources: readonly string[];
39
39
  }
40
+ /** The words of a sample event: any part left out is the package's own. */
41
+ export interface MultiSample {
42
+ event?: string;
43
+ year?: string | number;
44
+ city?: string;
45
+ }
40
46
  /** What stands on or beside each playing surface, and over the floor. */
41
47
  export interface MultiParts {
42
48
  /** The barriers (surrounds) that enclose each playing area, drawn round the area's bay. */
@@ -244,6 +250,12 @@ export interface MultiOptions {
244
250
  };
245
251
  /** The empty places for the event's words and marks, and the boards: on by default; `false` draws neither. */
246
252
  slots?: boolean;
253
+ /**
254
+ * Fill the places for the event's words and marks with sample content, to show a layout as an event would dress it: an invented event name, year and city on the floor and the boards, and simple emblems of the package's own
255
+ * (a ring with a star, a diamond or waves) in the logo places, in place of the dashed empty places. `true` for "Kyogijo Open 2026, Osaka" (in Japanese, 競技場杯 2026, 大阪), or the event's name, year and city of
256
+ * your own. It names no real event, brand, federation or sponsor. Off by default: the places are drawn empty, as a layout is configured.
257
+ */
258
+ sample?: boolean | MultiSample;
247
259
  /** The names of the surfaces over them. On by default. */
248
260
  labels?: boolean;
249
261
  language?: "en" | "ja";
@@ -21,6 +21,12 @@ export interface MultiWords {
21
21
  floorLogo: string;
22
22
  board: string;
23
23
  };
24
+ /** The invented event of the sample content (`sample: true`): its name, its year and its city. */
25
+ sample: {
26
+ event: string;
27
+ year: string;
28
+ city: string;
29
+ };
24
30
  /** The sentences of the title and the description. */
25
31
  say: {
26
32
  title: string;
@@ -29,6 +35,7 @@ export interface MultiWords {
29
35
  stagger: string;
30
36
  shared: string;
31
37
  slots: string;
38
+ sample: string;
32
39
  venue: string;
33
40
  stadium: string;
34
41
  event: string;
@@ -3,6 +3,7 @@ export const MULTI_WORDS = {
3
3
  names: { table: "Table {n}", court: "Court {n}", sheet: "Sheet {n}", area: "Area {n}" },
4
4
  parts: { chair: "Umpire's chair", table: "Score table", scoreboard: "Scoreboard", shared: "One scoreboard for all, hung over the middle", barrier: "Barrier", board: "Board", floor: "Floor", hall: "Hall floor", stands: "Stands" },
5
5
  slots: { floorText: "Event name, year and city", floorLogo: "Logo", board: "Board" },
6
+ sample: { event: "Kyogijo Open", year: "2026", city: "Osaka" },
6
7
  say: {
7
8
  title: "{name}",
8
9
  drawn: "Drawn as: {name}, {surfaces} playing surfaces to scale on one floor of {length} by {width} metres ({area} square metres).",
@@ -10,6 +11,7 @@ export const MULTI_WORDS = {
10
11
  stagger: "Every other row is moved along by {share} of a bay.",
11
12
  shared: "One scoreboard for all is hung over the middle of the floor.",
12
13
  slots: "The empty places for the event's own words and marks are drawn dashed: {n}.",
14
+ sample: "The places for the event's words and marks carry sample content: an invented event, {event}, {year}, {city}, and simple emblems. Nothing real is printed.",
13
15
  venue: "Set in {venue}: {fit}",
14
16
  stadium: "Drawn inside a stadium to the same scale: walls, stands and crowd.",
15
17
  event: "Tied to {event}, {year}, {venue}, {city}.",
@@ -31,6 +33,7 @@ export const MULTI_WORDS = {
31
33
  names: { table: "第{n}台", court: "第{n}コート", sheet: "第{n}シート", area: "第{n}試合場" },
32
34
  parts: { chair: "審判席", table: "記録台", scoreboard: "スコアボード", shared: "中央の真上に吊るした全面共用のスコアボード", barrier: "フェンス", board: "ボード", floor: "床", hall: "会場の床", stands: "スタンド" },
33
35
  slots: { floorText: "大会名・年・開催地", floorLogo: "ロゴ", board: "ボード" },
36
+ sample: { event: "競技場杯", year: "2026", city: "大阪" },
34
37
  say: {
35
38
  title: "{name}",
36
39
  drawn: "{name}。競技面を{surfaces}面、横{length}m×縦{width}m({area}平方メートル)の床1枚の上に縮尺どおりに描いています。",
@@ -38,6 +41,7 @@ export const MULTI_WORDS = {
38
41
  stagger: "1行おきに、1区画の{share}だけずらしています。",
39
42
  shared: "床の中央の上に、全面共用のスコアボードを1台吊るしています。",
40
43
  slots: "大会の文字やマークを入れる空き枠を破線で描いています:{n}か所。",
44
+ sample: "大会名やマークを入れる枠には、見本として架空の大会「{event}」({year}年・{city})と簡単なエンブレムを入れています。実在の大会や団体のものは含まれていません。",
41
45
  venue: "{venue}に置いた場合:{fit}",
42
46
  stadium: "同じ縮尺で、壁・スタンド・観客を備えたスタジアムの中に描いています。",
43
47
  event: "関連する大会:{event}({year}年、{venue}、{city})。",
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** The package's version: the same as package.json's, and a test holds them to each other. */
2
- export declare const VERSION = "0.16.0";
2
+ export declare const VERSION = "0.16.1";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  /** The package's version: the same as package.json's, and a test holds them to each other. */
2
- export const VERSION = "0.16.0";
2
+ export const VERSION = "0.16.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@johnmorrisdotca/kyogijo-stadiums",
3
- "version": "0.16.0",
3
+ "version": "0.16.1",
4
4
  "description": "Kyogijo Stadiums 競技場, 39 sports' surfaces as SVG, drawn to scale from the rulebooks: NFL, CFL and IFAF football fields, an NHL rink, an NBA court, MLB ballparks, soccer pitches, curling sheets, athletics stadiums, speed skating, short track and figure skating rinks, swimming pools, water polo fields, diving wells, artistic swimming areas, and the courts and fields of tennis, volleyball (indoor, beach and sitting), badminton, pickleball, table tennis, padel, squash, racquetball, sepak takraw, teqball, roundnet, netball, lacrosse, rugby, Australian football, Gaelic games, cricket, field hockey and handball, and the budo of judo, karate, kendo, sumo and kyudo with a dojo of tatami laid as real units, with each team's name and logo on its side and the score in the middle, stands and a crowd, a pageant of flags, and a 3D view. Light and dark, accessible, a compact badge for lists, a helper for React and a custom element. Zero dependencies.",
5
5
  "keywords": [
6
6
  "sports",