@johnmorrisdotca/dougu-sports 0.0.1 → 0.2.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.
Files changed (338) hide show
  1. package/CHANGELOG.md +61 -1
  2. package/LICENSES/README.md +4 -3
  3. package/NOTICE.md +54 -14
  4. package/README.md +251 -80
  5. package/dist/emblems/award/badge.d.ts +2 -0
  6. package/dist/emblems/award/badge.js +14 -0
  7. package/dist/emblems/award/crown.d.ts +2 -0
  8. package/dist/emblems/award/crown.js +15 -0
  9. package/dist/emblems/award/medal.d.ts +1 -1
  10. package/dist/emblems/award/medal.js +10 -15
  11. package/dist/emblems/award/shield.d.ts +2 -0
  12. package/dist/emblems/award/shield.js +11 -0
  13. package/dist/emblems/award/star.d.ts +2 -0
  14. package/dist/emblems/award/star.js +11 -0
  15. package/dist/emblems/ball/ball.afl.d.ts +1 -0
  16. package/dist/emblems/ball/ball.afl.js +24 -0
  17. package/dist/emblems/ball/ball.baseball.d.ts +1 -0
  18. package/dist/emblems/ball/ball.baseball.js +14 -0
  19. package/dist/emblems/ball/ball.basketball.d.ts +7 -0
  20. package/dist/emblems/ball/ball.basketball.js +32 -0
  21. package/dist/emblems/ball/ball.basketball3x3.d.ts +1 -0
  22. package/dist/emblems/ball/ball.basketball3x3.js +10 -0
  23. package/dist/emblems/ball/ball.basketball6.d.ts +1 -0
  24. package/dist/emblems/ball/ball.basketball6.js +10 -0
  25. package/dist/emblems/ball/ball.core.d.ts +111 -0
  26. package/dist/emblems/ball/ball.core.js +79 -0
  27. package/dist/emblems/ball/ball.cricket.d.ts +5 -0
  28. package/dist/emblems/ball/ball.cricket.js +31 -0
  29. package/dist/emblems/ball/ball.curlingstone.d.ts +3 -0
  30. package/dist/emblems/ball/ball.curlingstone.js +46 -0
  31. package/dist/emblems/ball/ball.discus.d.ts +1 -0
  32. package/dist/emblems/ball/ball.discus.js +24 -0
  33. package/dist/emblems/ball/ball.engine.d.ts +114 -0
  34. package/dist/emblems/ball/ball.engine.js +342 -0
  35. package/dist/emblems/ball/ball.family.dotted.d.ts +27 -0
  36. package/dist/emblems/ball/ball.family.dotted.js +20 -0
  37. package/dist/emblems/ball/ball.family.panelled.d.ts +7 -0
  38. package/dist/emblems/ball/ball.family.panelled.js +60 -0
  39. package/dist/emblems/ball/ball.family.prolate.d.ts +16 -0
  40. package/dist/emblems/ball/ball.family.prolate.js +29 -0
  41. package/dist/emblems/ball/ball.family.seamed.d.ts +31 -0
  42. package/dist/emblems/ball/ball.family.seamed.js +26 -0
  43. package/dist/emblems/ball/ball.fieldhockey.d.ts +1 -0
  44. package/dist/emblems/ball/ball.fieldhockey.js +15 -0
  45. package/dist/emblems/ball/ball.football.d.ts +3 -0
  46. package/dist/emblems/ball/ball.football.js +51 -0
  47. package/dist/emblems/ball/ball.gaelic.d.ts +2 -0
  48. package/dist/emblems/ball/ball.gaelic.js +30 -0
  49. package/dist/emblems/ball/ball.golf.d.ts +1 -0
  50. package/dist/emblems/ball/ball.golf.js +15 -0
  51. package/dist/emblems/ball/ball.hammer.d.ts +1 -0
  52. package/dist/emblems/ball/ball.hammer.js +31 -0
  53. package/dist/emblems/ball/ball.handball.d.ts +1 -0
  54. package/dist/emblems/ball/ball.handball.js +25 -0
  55. package/dist/emblems/ball/ball.index.d.ts +48 -0
  56. package/dist/emblems/ball/ball.index.js +103 -0
  57. package/dist/emblems/ball/ball.math.d.ts +38 -0
  58. package/dist/emblems/ball/ball.math.js +105 -0
  59. package/dist/emblems/ball/ball.object.d.ts +38 -0
  60. package/dist/emblems/ball/ball.object.js +20 -0
  61. package/dist/emblems/ball/ball.padel.d.ts +1 -0
  62. package/dist/emblems/ball/ball.padel.js +13 -0
  63. package/dist/emblems/ball/ball.pickleball.d.ts +2 -0
  64. package/dist/emblems/ball/ball.pickleball.js +26 -0
  65. package/dist/emblems/ball/ball.polyhedra.d.ts +15 -0
  66. package/dist/emblems/ball/ball.polyhedra.js +63 -0
  67. package/dist/emblems/ball/ball.puck.d.ts +3 -0
  68. package/dist/emblems/ball/ball.puck.js +22 -0
  69. package/dist/emblems/ball/ball.roundnet.d.ts +1 -0
  70. package/dist/emblems/ball/ball.roundnet.js +15 -0
  71. package/dist/emblems/ball/ball.rugby.d.ts +1 -0
  72. package/dist/emblems/ball/ball.rugby.js +35 -0
  73. package/dist/emblems/ball/ball.sepaktakraw.d.ts +1 -0
  74. package/dist/emblems/ball/ball.sepaktakraw.js +48 -0
  75. package/dist/emblems/ball/ball.shuttlecock.d.ts +6 -0
  76. package/dist/emblems/ball/ball.shuttlecock.js +93 -0
  77. package/dist/emblems/ball/ball.sliotar.d.ts +1 -0
  78. package/dist/emblems/ball/ball.sliotar.js +14 -0
  79. package/dist/emblems/ball/ball.smooth.d.ts +4 -0
  80. package/dist/emblems/ball/ball.smooth.js +51 -0
  81. package/dist/emblems/ball/ball.soccer.d.ts +2 -0
  82. package/dist/emblems/ball/ball.soccer.js +54 -0
  83. package/dist/emblems/ball/ball.softball.d.ts +1 -0
  84. package/dist/emblems/ball/ball.softball.js +14 -0
  85. package/dist/emblems/ball/ball.squash.d.ts +7 -0
  86. package/dist/emblems/ball/ball.squash.js +27 -0
  87. package/dist/emblems/ball/ball.stack.d.ts +48 -0
  88. package/dist/emblems/ball/ball.stack.js +127 -0
  89. package/dist/emblems/ball/ball.stitch.d.ts +10 -0
  90. package/dist/emblems/ball/ball.stitch.js +59 -0
  91. package/dist/emblems/ball/ball.tennis.d.ts +1 -0
  92. package/dist/emblems/ball/ball.tennis.js +13 -0
  93. package/dist/emblems/ball/ball.teqball.d.ts +1 -0
  94. package/dist/emblems/ball/ball.teqball.js +27 -0
  95. package/dist/emblems/ball/ball.volleyball.d.ts +3 -0
  96. package/dist/emblems/ball/ball.volleyball.js +56 -0
  97. package/dist/emblems/ball/ball.waterpolo.d.ts +1 -0
  98. package/dist/emblems/ball/ball.waterpolo.js +31 -0
  99. package/dist/emblems/crest/diamond.d.ts +2 -0
  100. package/dist/emblems/crest/diamond.js +18 -0
  101. package/dist/emblems/crest/pennant.d.ts +2 -0
  102. package/dist/emblems/crest/pennant.js +18 -0
  103. package/dist/emblems/crest/roundel.d.ts +2 -0
  104. package/dist/emblems/crest/roundel.js +18 -0
  105. package/dist/emblems/crest/shield.d.ts +2 -0
  106. package/dist/emblems/crest/shield.js +17 -0
  107. package/dist/emblems/emblem.api.d.ts +77 -9
  108. package/dist/emblems/emblem.api.js +56 -10
  109. package/dist/emblems/emblem.compose.d.ts +31 -0
  110. package/dist/emblems/emblem.compose.js +91 -0
  111. package/dist/emblems/emblem.core.d.ts +89 -7
  112. package/dist/emblems/emblem.core.js +85 -11
  113. package/dist/emblems/emblem.descriptions.d.ts +7 -0
  114. package/dist/emblems/emblem.descriptions.js +60 -0
  115. package/dist/emblems/emblem.display.d.ts +75 -0
  116. package/dist/emblems/emblem.display.js +214 -0
  117. package/dist/emblems/emblem.engrave.d.ts +50 -0
  118. package/dist/emblems/emblem.engrave.js +145 -0
  119. package/dist/emblems/emblem.equipment.d.ts +24 -0
  120. package/dist/emblems/emblem.equipment.js +57 -0
  121. package/dist/emblems/emblem.flip.d.ts +10 -0
  122. package/dist/emblems/emblem.flip.js +45 -0
  123. package/dist/emblems/emblem.ids.d.ts +44 -30
  124. package/dist/emblems/emblem.ids.js +51 -17
  125. package/dist/emblems/emblem.lathe.d.ts +62 -0
  126. package/dist/emblems/emblem.lathe.js +426 -0
  127. package/dist/emblems/emblem.medal.d.ts +6 -0
  128. package/dist/emblems/emblem.medal.js +38 -0
  129. package/dist/emblems/emblem.pennant.d.ts +3 -0
  130. package/dist/emblems/emblem.pennant.js +79 -0
  131. package/dist/emblems/emblem.registry.js +162 -4
  132. package/dist/emblems/emblem.shapes.d.ts +48 -12
  133. package/dist/emblems/emblem.shapes.js +138 -31
  134. package/dist/emblems/emblem.sprite.d.ts +38 -0
  135. package/dist/emblems/emblem.sprite.js +65 -0
  136. package/dist/emblems/emblem.uri.d.ts +22 -0
  137. package/dist/emblems/emblem.uri.js +29 -0
  138. package/dist/emblems/gear/gear.badmintonracket.d.ts +1 -0
  139. package/dist/emblems/gear/gear.badmintonracket.js +19 -0
  140. package/dist/emblems/gear/gear.baseballglove.d.ts +1 -0
  141. package/dist/emblems/gear/gear.baseballglove.js +21 -0
  142. package/dist/emblems/gear/gear.budo.d.ts +17 -0
  143. package/dist/emblems/gear/gear.budo.js +60 -0
  144. package/dist/emblems/gear/gear.core.d.ts +64 -0
  145. package/dist/emblems/gear/gear.core.js +127 -0
  146. package/dist/emblems/gear/gear.cricketbat.d.ts +1 -0
  147. package/dist/emblems/gear/gear.cricketbat.js +17 -0
  148. package/dist/emblems/gear/gear.field.d.ts +6 -0
  149. package/dist/emblems/gear/gear.field.js +81 -0
  150. package/dist/emblems/gear/gear.fieldhockeystick.d.ts +1 -0
  151. package/dist/emblems/gear/gear.fieldhockeystick.js +16 -0
  152. package/dist/emblems/gear/gear.footballhelmet.d.ts +1 -0
  153. package/dist/emblems/gear/gear.footballhelmet.js +16 -0
  154. package/dist/emblems/gear/gear.goaliemask.d.ts +1 -0
  155. package/dist/emblems/gear/gear.goaliemask.js +23 -0
  156. package/dist/emblems/gear/gear.goalnet.d.ts +1 -0
  157. package/dist/emblems/gear/gear.goalnet.js +25 -0
  158. package/dist/emblems/gear/gear.hockeystick.d.ts +1 -0
  159. package/dist/emblems/gear/gear.hockeystick.js +15 -0
  160. package/dist/emblems/gear/gear.index.d.ts +22 -0
  161. package/dist/emblems/gear/gear.index.js +49 -0
  162. package/dist/emblems/gear/gear.kendo.d.ts +2 -0
  163. package/dist/emblems/gear/gear.kendo.js +41 -0
  164. package/dist/emblems/gear/gear.kyudo.d.ts +2 -0
  165. package/dist/emblems/gear/gear.kyudo.js +31 -0
  166. package/dist/emblems/gear/gear.lacrossestick.d.ts +1 -0
  167. package/dist/emblems/gear/gear.lacrossestick.js +26 -0
  168. package/dist/emblems/gear/gear.rackets.d.ts +4 -0
  169. package/dist/emblems/gear/gear.rackets.js +60 -0
  170. package/dist/emblems/gear/gear.skates.d.ts +3 -0
  171. package/dist/emblems/gear/gear.skates.js +39 -0
  172. package/dist/emblems/gear/gear.sticks.d.ts +3 -0
  173. package/dist/emblems/gear/gear.sticks.js +34 -0
  174. package/dist/emblems/gear/gear.sumo.d.ts +2 -0
  175. package/dist/emblems/gear/gear.sumo.js +43 -0
  176. package/dist/emblems/gear/gear.tabletennispaddle.d.ts +1 -0
  177. package/dist/emblems/gear/gear.tabletennispaddle.js +16 -0
  178. package/dist/emblems/gear/gear.tennisracket.d.ts +1 -0
  179. package/dist/emblems/gear/gear.tennisracket.js +17 -0
  180. package/dist/emblems/gear/gear.track.d.ts +4 -0
  181. package/dist/emblems/gear/gear.track.js +45 -0
  182. package/dist/emblems/gear/gear.water.d.ts +2 -0
  183. package/dist/emblems/gear/gear.water.js +25 -0
  184. package/dist/emblems/medal/bronze.d.ts +2 -0
  185. package/dist/emblems/medal/bronze.js +4 -0
  186. package/dist/emblems/medal/gold.d.ts +2 -0
  187. package/dist/emblems/medal/gold.js +4 -0
  188. package/dist/emblems/medal/place-1.d.ts +2 -0
  189. package/dist/emblems/medal/place-1.js +4 -0
  190. package/dist/emblems/medal/place-2.d.ts +2 -0
  191. package/dist/emblems/medal/place-2.js +4 -0
  192. package/dist/emblems/medal/place-3.d.ts +2 -0
  193. package/dist/emblems/medal/place-3.js +4 -0
  194. package/dist/emblems/medal/silver.d.ts +2 -0
  195. package/dist/emblems/medal/silver.js +4 -0
  196. package/dist/emblems/pennant/championship.d.ts +2 -0
  197. package/dist/emblems/pennant/championship.js +4 -0
  198. package/dist/emblems/sport/afl.d.ts +2 -0
  199. package/dist/emblems/sport/afl.js +12 -0
  200. package/dist/emblems/sport/artisticswimming.d.ts +2 -0
  201. package/dist/emblems/sport/artisticswimming.js +16 -0
  202. package/dist/emblems/sport/athletics.d.ts +2 -0
  203. package/dist/emblems/sport/athletics.js +12 -0
  204. package/dist/emblems/sport/badminton.d.ts +2 -0
  205. package/dist/emblems/sport/badminton.js +13 -0
  206. package/dist/emblems/sport/cfl.d.ts +2 -0
  207. package/dist/emblems/sport/cfl.js +5 -0
  208. package/dist/emblems/sport/cricket.d.ts +2 -0
  209. package/dist/emblems/sport/cricket.js +14 -0
  210. package/dist/emblems/sport/curling.d.ts +2 -0
  211. package/dist/emblems/sport/curling.js +14 -0
  212. package/dist/emblems/sport/diving.d.ts +2 -0
  213. package/dist/emblems/sport/diving.js +18 -0
  214. package/dist/emblems/sport/fieldhockey.d.ts +2 -0
  215. package/dist/emblems/sport/fieldhockey.js +11 -0
  216. package/dist/emblems/sport/gaelic.d.ts +2 -0
  217. package/dist/emblems/sport/gaelic.js +11 -0
  218. package/dist/emblems/sport/handball.d.ts +2 -0
  219. package/dist/emblems/sport/handball.js +15 -0
  220. package/dist/emblems/sport/ifaf.d.ts +2 -0
  221. package/dist/emblems/sport/ifaf.js +5 -0
  222. package/dist/emblems/sport/judo.d.ts +2 -0
  223. package/dist/emblems/sport/judo.js +13 -0
  224. package/dist/emblems/sport/karate.d.ts +2 -0
  225. package/dist/emblems/sport/karate.js +13 -0
  226. package/dist/emblems/sport/kendo.d.ts +2 -0
  227. package/dist/emblems/sport/kendo.js +14 -0
  228. package/dist/emblems/sport/kyudo.d.ts +2 -0
  229. package/dist/emblems/sport/kyudo.js +15 -0
  230. package/dist/emblems/sport/lacrosse.d.ts +2 -0
  231. package/dist/emblems/sport/lacrosse.js +13 -0
  232. package/dist/emblems/sport/mlb.d.ts +2 -0
  233. package/dist/emblems/sport/mlb.js +28 -0
  234. package/dist/emblems/sport/nba.d.ts +2 -0
  235. package/dist/emblems/sport/nba.js +12 -0
  236. package/dist/emblems/sport/netball.d.ts +2 -0
  237. package/dist/emblems/sport/netball.js +14 -0
  238. package/dist/emblems/sport/nfl.d.ts +3 -0
  239. package/dist/emblems/sport/nfl.js +15 -0
  240. package/dist/emblems/sport/nhl.d.ts +2 -0
  241. package/dist/emblems/sport/nhl.js +13 -0
  242. package/dist/emblems/sport/padel.d.ts +2 -0
  243. package/dist/emblems/sport/padel.js +14 -0
  244. package/dist/emblems/sport/pickleball.d.ts +2 -0
  245. package/dist/emblems/sport/pickleball.js +13 -0
  246. package/dist/emblems/sport/racquetball.d.ts +2 -0
  247. package/dist/emblems/sport/racquetball.js +13 -0
  248. package/dist/emblems/sport/roundnet.d.ts +2 -0
  249. package/dist/emblems/sport/roundnet.js +15 -0
  250. package/dist/emblems/sport/rugby.d.ts +2 -0
  251. package/dist/emblems/sport/rugby.js +12 -0
  252. package/dist/emblems/sport/sepaktakraw.d.ts +2 -0
  253. package/dist/emblems/sport/sepaktakraw.js +11 -0
  254. package/dist/emblems/sport/skating.d.ts +2 -0
  255. package/dist/emblems/sport/skating.js +14 -0
  256. package/dist/emblems/sport/soccer.d.ts +2 -0
  257. package/dist/emblems/sport/soccer.js +31 -0
  258. package/dist/emblems/sport/squash.d.ts +2 -0
  259. package/dist/emblems/sport/squash.js +15 -0
  260. package/dist/emblems/sport/sumo.d.ts +2 -0
  261. package/dist/emblems/sport/sumo.js +15 -0
  262. package/dist/emblems/sport/swimming.d.ts +2 -0
  263. package/dist/emblems/sport/swimming.js +15 -0
  264. package/dist/emblems/sport/tabletennis.d.ts +2 -0
  265. package/dist/emblems/sport/tabletennis.js +12 -0
  266. package/dist/emblems/sport/tennis.d.ts +2 -0
  267. package/dist/emblems/sport/tennis.js +15 -0
  268. package/dist/emblems/sport/teqball.d.ts +2 -0
  269. package/dist/emblems/sport/teqball.js +15 -0
  270. package/dist/emblems/sport/volleyball.d.ts +2 -0
  271. package/dist/emblems/sport/volleyball.js +25 -0
  272. package/dist/emblems/sport/waterpolo.d.ts +2 -0
  273. package/dist/emblems/sport/waterpolo.js +15 -0
  274. package/dist/emblems/trophy/banner.d.ts +2 -0
  275. package/dist/emblems/trophy/banner.js +20 -0
  276. package/dist/emblems/trophy/baseball.d.ts +2 -0
  277. package/dist/emblems/trophy/baseball.js +15 -0
  278. package/dist/emblems/trophy/basketball.d.ts +2 -0
  279. package/dist/emblems/trophy/basketball.js +17 -0
  280. package/dist/emblems/trophy/belt.d.ts +2 -0
  281. package/dist/emblems/trophy/belt.js +17 -0
  282. package/dist/emblems/trophy/bowl.d.ts +2 -0
  283. package/dist/emblems/trophy/bowl.js +8 -0
  284. package/dist/emblems/trophy/canadian-bowl.d.ts +2 -0
  285. package/dist/emblems/trophy/canadian-bowl.js +23 -0
  286. package/dist/emblems/trophy/championship-banner.d.ts +2 -0
  287. package/dist/emblems/trophy/championship-banner.js +67 -0
  288. package/dist/emblems/trophy/cricket-urn.d.ts +2 -0
  289. package/dist/emblems/trophy/cricket-urn.js +23 -0
  290. package/dist/emblems/trophy/cup.d.ts +2 -0
  291. package/dist/emblems/trophy/cup.js +16 -0
  292. package/dist/emblems/trophy/football.d.ts +2 -0
  293. package/dist/emblems/trophy/football.js +11 -0
  294. package/dist/emblems/trophy/globe.d.ts +2 -0
  295. package/dist/emblems/trophy/globe.js +9 -0
  296. package/dist/emblems/trophy/hockey-cup.d.ts +2 -0
  297. package/dist/emblems/trophy/hockey-cup.js +22 -0
  298. package/dist/emblems/trophy/laurel.d.ts +2 -0
  299. package/dist/emblems/trophy/laurel.js +40 -0
  300. package/dist/emblems/trophy/lidded-cup.d.ts +2 -0
  301. package/dist/emblems/trophy/lidded-cup.js +21 -0
  302. package/dist/emblems/trophy/plaque.d.ts +2 -0
  303. package/dist/emblems/trophy/plaque.js +17 -0
  304. package/dist/emblems/trophy/ring.d.ts +2 -0
  305. package/dist/emblems/trophy/ring.js +30 -0
  306. package/dist/emblems/trophy/rosette.d.ts +2 -0
  307. package/dist/emblems/trophy/rosette.js +27 -0
  308. package/dist/emblems/trophy/rugby-cup.d.ts +2 -0
  309. package/dist/emblems/trophy/rugby-cup.js +23 -0
  310. package/dist/emblems/trophy/salver.d.ts +2 -0
  311. package/dist/emblems/trophy/salver.js +9 -0
  312. package/dist/emblems/trophy/soccer-ball.d.ts +2 -0
  313. package/dist/emblems/trophy/soccer-ball.js +9 -0
  314. package/dist/emblems/trophy/soccer-globe.d.ts +2 -0
  315. package/dist/emblems/trophy/soccer-globe.js +18 -0
  316. package/dist/emblems/trophy/sumo-cup.d.ts +2 -0
  317. package/dist/emblems/trophy/sumo-cup.js +28 -0
  318. package/dist/emblems/trophy/tennis-cup.d.ts +2 -0
  319. package/dist/emblems/trophy/tennis-cup.js +24 -0
  320. package/dist/emblems/trophy/tennis-plate.d.ts +2 -0
  321. package/dist/emblems/trophy/tennis-plate.js +16 -0
  322. package/dist/emblems-entry.d.ts +20 -7
  323. package/dist/emblems-entry.js +8 -2
  324. package/dist/index.d.ts +131 -1
  325. package/dist/index.js +131 -3
  326. package/dist/turn-control.d.ts +101 -0
  327. package/dist/turn-control.js +363 -0
  328. package/dist/turn-entry.d.ts +2 -0
  329. package/dist/turn-entry.js +1 -0
  330. package/dist/version.d.ts +1 -1
  331. package/dist/version.js +1 -1
  332. package/package.json +33 -7
  333. package/LICENSES/Apache-2.0.txt +0 -55
  334. package/LICENSES/CC-BY-3.0.md +0 -15
  335. package/dist/emblems/ball/soccer.d.ts +0 -2
  336. package/dist/emblems/ball/soccer.js +0 -9
  337. package/dist/emblems/emblem.ball.d.ts +0 -28
  338. package/dist/emblems/emblem.ball.js +0 -70
@@ -0,0 +1,127 @@
1
+ // A stack of round slices on one axis, drawn in true 3D by the rules of an orthographic view: each end of a slice is an ellipse (its minor axis along the projected axis), the side between them
2
+ // is a band as wide as the slice, and what is nearer is painted last. A puck is one slice; a curling stone is six and a handle.
3
+ import {} from "./ball.object.js";
4
+ import { apply } from "./ball.math.js";
5
+ import { blend, grainDef, mix, num } from "./ball.core.js";
6
+ const LIGHT = [-0.55, -0.72, 0];
7
+ const ellipsePath = (cx, cy, major, minor, deg) => {
8
+ const rad = (deg * Math.PI) / 180;
9
+ const ax = Math.cos(rad) * major, ay = Math.sin(rad) * major;
10
+ const arcs = `${num(major, 2)} ${num(Math.max(minor, 0.02), 2)} ${num(deg, 1)} 1 0`;
11
+ return `M${num(cx + ax, 2)} ${num(cy + ay, 2)}A${arcs} ${num(cx - ax, 2)} ${num(cy - ay, 2)}A${arcs} ${num(cx + ax, 2)} ${num(cy + ay, 2)}Z`;
12
+ };
13
+ /** The half of an ellipse on one side: through the point `side` (-1 or 1) of the way along `d` from the centre. */
14
+ const halfEllipse = (cx, cy, major, minor, deg, side) => {
15
+ const rad = (deg * Math.PI) / 180;
16
+ const ax = Math.cos(rad) * major, ay = Math.sin(rad) * major;
17
+ const sweep = side < 0 ? 1 : 0;
18
+ return `M${num(cx + ax, 2)} ${num(cy + ay, 2)}A${num(major, 2)} ${num(Math.max(minor, 0.02), 2)} ${num(deg, 1)} 0 ${sweep} ${num(cx - ax, 2)} ${num(cy - ay, 2)}`;
19
+ };
20
+ export function drawStack(c, spec) {
21
+ const line = c.opts.style === "line";
22
+ const n = apply(c.rot, [0, 1, 0]);
23
+ const nz = n[2];
24
+ const ax = 46 * n[0], ay = -46 * n[1];
25
+ const dl = Math.hypot(ax, ay);
26
+ const d = dl < 1e-3 ? [1, 0] : [ax / dl, ay / dl];
27
+ const perp = [-d[1], d[0]];
28
+ const perpDeg = (Math.atan2(perp[1], perp[0]) * 180) / Math.PI;
29
+ const at = (y) => [50 + y * ax, 50 + y * ay];
30
+ const topVisible = nz >= 0;
31
+ const shadeEnd = (col) => mix(col, -0.55);
32
+ const pl = perp[0] * LIGHT[0] + perp[1] * LIGHT[1];
33
+ const u = Math.min(0.78, Math.max(0.22, 0.5 + 0.34 * pl));
34
+ const radius = (s, end) => (typeof s.r === "number" ? s.r : s.r[end]);
35
+ let defs = "";
36
+ const slices = spec.slices;
37
+ const maxR = Math.max(...slices.map((s) => Math.max(radius(s, 0), radius(s, 1))));
38
+ const mid = at((slices[0].y0 + slices.at(-1).y1) / 2);
39
+ const g0 = [mid[0] - perp[0] * 46 * maxR, mid[1] - perp[1] * 46 * maxR];
40
+ const g1 = [mid[0] + perp[0] * 46 * maxR, mid[1] + perp[1] * 46 * maxR];
41
+ const side = (s, i) => {
42
+ const gid = `${c.id}s${i}`;
43
+ const base = s.colour;
44
+ defs += `<linearGradient id="${gid}" gradientUnits="userSpaceOnUse" x1="${num(g0[0], 2)}" y1="${num(g0[1], 2)}" x2="${num(g1[0], 2)}" y2="${num(g1[1], 2)}"><stop offset="0" stop-color="${shadeEnd(base)}"/><stop offset="${num(Math.max(0.03, u - 0.26), 2)}" stop-color="${base}"/><stop offset="${num(u, 2)}" stop-color="${blend(base, "#ffffff", 0.18 + spec.gloss * 0.3)}"/><stop offset="${num(Math.min(0.97, u + 0.28), 2)}" stop-color="${base}"/><stop offset="1" stop-color="${shadeEnd(base)}"/></linearGradient>`;
45
+ const [x0, y0] = at(s.y0), [x1, y1] = at(s.y1);
46
+ const rb = 46 * radius(s, 0), rt = 46 * radius(s, 1);
47
+ const pts = [[x0 + perp[0] * rb, y0 + perp[1] * rb], [x1 + perp[0] * rt, y1 + perp[1] * rt], [x1 - perp[0] * rt, y1 - perp[1] * rt], [x0 - perp[0] * rb, y0 - perp[1] * rb]];
48
+ const d4 = `M${pts.map((p) => `${num(p[0], 2)} ${num(p[1], 2)}`).join("L")}Z`;
49
+ if (line) {
50
+ if (s.outline !== true)
51
+ return "";
52
+ const lines = `M${num(pts[0][0], 2)} ${num(pts[0][1], 2)}L${num(pts[1][0], 2)} ${num(pts[1][1], 2)}M${num(pts[2][0], 2)} ${num(pts[2][1], 2)}L${num(pts[3][0], 2)} ${num(pts[3][1], 2)}`;
53
+ const rim = (y, r, side) => {
54
+ const [cx, cy] = at(y);
55
+ return halfEllipse(cx, cy, 46 * r, 46 * r * Math.abs(nz), perpDeg, side);
56
+ };
57
+ const near = topVisible ? -1 : 1;
58
+ return `<path d="${lines}${rim(s.y0, radius(s, 0), near)}${i === slices.length - 1 ? "" : rim(s.y1, radius(s, 1), near)}" fill="none"/>`;
59
+ }
60
+ let out = `<path d="${d4}" fill="url(#${gid})"/>`;
61
+ const gr = spec.grooves;
62
+ if (!line && gr !== undefined && gr.slices.includes(i)) {
63
+ let marks = "";
64
+ for (let k = 0; k < gr.count; k++) {
65
+ const t = ((k + 0.5) / gr.count) * Math.PI;
66
+ const uu = Math.cos(t);
67
+ const facing = Math.sin(t);
68
+ if (facing < 0.15)
69
+ continue;
70
+ marks += `M${num(x0 + perp[0] * rb * uu, 2)} ${num(y0 + perp[1] * rb * uu, 2)}L${num(x1 + perp[0] * rt * uu, 2)} ${num(y1 + perp[1] * rt * uu, 2)}`;
71
+ }
72
+ out += `<path d="${marks}" stroke="${gr.colour}" stroke-width="${num(Math.max(0.5, c.minWidth * 0.5), 2)}" opacity="${gr.opacity}" fill="none"/>`;
73
+ }
74
+ return out;
75
+ };
76
+ const cap = (y, r, colour, i, topFace) => {
77
+ const [cx, cy] = at(y);
78
+ const major = 46 * r;
79
+ const minor = Math.max(major * Math.abs(nz), 0.02);
80
+ const dpath = ellipsePath(cx, cy, major, minor, perpDeg);
81
+ if (line)
82
+ return (topFace && (i === `t${slices.length - 1}` || i === `d0`)) || i === "dish" ? `<path d="${dpath}" fill="none"/>` : "";
83
+ const gid = `${c.id}c${i}`;
84
+ defs += `<radialGradient id="${gid}" cx=".36" cy=".3" r=".85"><stop offset="0" stop-color="${blend(colour, "#ffffff", 0.2 + spec.gloss * 0.34)}"/><stop offset=".45" stop-color="${colour}"/><stop offset="1" stop-color="${mix(colour, topFace ? -0.34 : -0.5)}"/></radialGradient>`;
85
+ return `<path d="${dpath}" fill="url(#${gid})"/>`;
86
+ };
87
+ const ordered = topVisible ? slices.map((s, i) => [s, i]) : slices.map((s, i) => [s, i]).reverse();
88
+ let body = "";
89
+ if (topVisible) {
90
+ const s0 = slices[0];
91
+ body += cap(s0.y0, radius(s0, 0), mix(s0.colour, -0.25), "b", false);
92
+ for (const [s, i] of ordered) {
93
+ body += side(s, i);
94
+ body += cap(s.y1, radius(s, 1), i === slices.length - 1 ? spec.top : s.colour, `t${i}`, true);
95
+ }
96
+ if (spec.topRing !== undefined) {
97
+ const [cx, cy] = at(slices.at(-1).y1);
98
+ const r = 46 * radius(slices.at(-1), 1) * spec.topRing.r;
99
+ body += `<path d="${ellipsePath(cx, cy, r, r * Math.abs(nz), perpDeg)}" fill="none" stroke="${line ? "currentColor" : spec.topRing.colour}" stroke-width="${num(Math.max(0.6, c.minWidth * 0.6), 2)}" opacity=".7"/>`;
100
+ }
101
+ }
102
+ else {
103
+ const sT = slices.at(-1);
104
+ body += cap(sT.y1, radius(sT, 1), mix(sT.colour, -0.25), "u", false);
105
+ for (const [s, i] of ordered) {
106
+ body += side(s, i);
107
+ body += cap(s.y0, radius(s, 0), i === 0 ? spec.bottom : s.colour, `d${i}`, true);
108
+ }
109
+ if (spec.dish !== undefined) {
110
+ const [cx, cy] = at(slices[0].y0);
111
+ const r = 46 * radius(slices[0], 0) * spec.dish.r;
112
+ const gid = `${c.id}dish`;
113
+ defs += `<radialGradient id="${gid}" cx=".64" cy=".7" r=".9"><stop offset="0" stop-color="${blend(spec.dish.colour, "#ffffff", 0.3)}"/><stop offset=".5" stop-color="${spec.dish.colour}"/><stop offset="1" stop-color="${mix(spec.dish.colour, -0.6)}"/></radialGradient>`;
114
+ body += `<path d="${ellipsePath(cx, cy, r, r * Math.abs(nz), perpDeg)}" fill="${line ? "none" : `url(#${gid})`}"/>`;
115
+ }
116
+ }
117
+ const [tx, ty] = at(slices.at(-1).y1);
118
+ if (spec.extra !== undefined)
119
+ body += spec.extra(c, { cx: tx, cy: ty, nz });
120
+ const gr = c.opts.grain ?? (c.opts.size >= 48 && !c.turning);
121
+ const grain = !line && gr && spec.grain !== undefined;
122
+ if (grain)
123
+ defs += grainDef(c.id, spec.grain.f, spec.grain.a);
124
+ if (line)
125
+ return { defs: "", body: `<g fill="none" stroke="currentColor" stroke-width="${num(Math.max(2.4, c.minWidth * 1.4), 2)}" stroke-linejoin="round" stroke-linecap="round">${body}</g>` };
126
+ return { defs, body: grain ? `<g filter="url(#${c.id}n)">${body}</g>` : body };
127
+ }
@@ -0,0 +1,10 @@
1
+ import { type V3 } from "./ball.math.ts";
2
+ /** Marks across a curve: `count` marks evenly along it; a mark runs `half` radians either side of the seam and leans along it by `lean`. A `v` mark has two legs that meet on the seam (a baseball's stitch). */
3
+ export declare function stitches(pts: readonly V3[], closed: boolean, count: number, half: number, o?: {
4
+ lean?: number;
5
+ v?: boolean;
6
+ offset?: number;
7
+ phase?: number;
8
+ }): V3[][];
9
+ /** A dashed row: segments of a curve, each `dash` of every `period` long as a fraction of the curve. */
10
+ export declare function dashes(pts: readonly V3[], closed: boolean, count: number, fill?: number): V3[][];
@@ -0,0 +1,59 @@
1
+ // Stitches and rows along a curve on the sphere: short marks that cross a seam, spaced evenly along it.
2
+ import { add, cross, dot, mul, norm, sub } from "./ball.math.js";
3
+ /** The point of a closed or open curve at a fraction of its length, and the tangent there. */
4
+ function pointAt(pts, closed, cumulative, total, f) {
5
+ const target = f * total;
6
+ let i = 0;
7
+ while (i < cumulative.length - 2 && cumulative[i + 1] < target)
8
+ i++;
9
+ const a = pts[i], b = pts[(i + 1) % pts.length];
10
+ const span = cumulative[i + 1] - cumulative[i] || 1;
11
+ const k = (target - cumulative[i]) / span;
12
+ const p = norm(add(mul(a, 1 - k), mul(b, k)));
13
+ return { p, t: norm(sub(b, a)) };
14
+ }
15
+ /** Marks across a curve: `count` marks evenly along it; a mark runs `half` radians either side of the seam and leans along it by `lean`. A `v` mark has two legs that meet on the seam (a baseball's stitch). */
16
+ export function stitches(pts, closed, count, half, o) {
17
+ const n = pts.length;
18
+ const cumulative = [0];
19
+ const last = closed ? n : n - 1;
20
+ for (let i = 0; i < last; i++) {
21
+ const a = pts[i], b = pts[(i + 1) % n];
22
+ cumulative.push(cumulative[i] + Math.acos(Math.max(-1, Math.min(1, dot(a, b)))));
23
+ }
24
+ const total = cumulative[cumulative.length - 1];
25
+ const out = [];
26
+ const lean = o?.lean ?? 0;
27
+ const shift = o?.offset ?? 0;
28
+ for (let i = 0; i < count; i++) {
29
+ const f = closed ? (i + (o?.phase ?? 0)) / count : (i + 0.5) / count;
30
+ const { p, t } = pointAt(pts, closed, cumulative, total, f);
31
+ const side = norm(cross(p, t));
32
+ const c = norm(add(p, mul(side, shift)));
33
+ const a = norm(add(add(c, mul(side, half)), mul(t, -lean)));
34
+ const b = norm(add(sub(c, mul(side, half)), mul(t, -lean)));
35
+ if (o?.v === true)
36
+ out.push([a, norm(add(c, mul(t, lean))), b]);
37
+ else
38
+ out.push([a, b]);
39
+ }
40
+ return out;
41
+ }
42
+ /** A dashed row: segments of a curve, each `dash` of every `period` long as a fraction of the curve. */
43
+ export function dashes(pts, closed, count, fill = 0.5) {
44
+ const n = pts.length;
45
+ const out = [];
46
+ const per = n / count;
47
+ for (let i = 0; i < count; i++) {
48
+ const from = i * per;
49
+ const to = from + per * fill;
50
+ const seg = [];
51
+ for (let j = Math.floor(from); j <= Math.ceil(to); j++) {
52
+ const idx = closed ? j % n : Math.min(j, n - 1);
53
+ seg.push(pts[idx]);
54
+ }
55
+ if (seg.length > 1)
56
+ out.push(seg);
57
+ }
58
+ return out;
59
+ }
@@ -0,0 +1 @@
1
+ export declare const BALL_TENNIS: import("./ball.core.ts").Piece<import("./ball.engine.ts").BallSpec>;
@@ -0,0 +1,13 @@
1
+ // Tennis ball: optic-yellow felt with a white strip of rubber along the seam. The felt's fuzz is the grain.
2
+ import { seamedBall } from "./ball.family.seamed.js";
3
+ export const BALL_TENNIS = /* @__PURE__ */ seamedBall({
4
+ id: "ball:tennis",
5
+ en: "Tennis ball",
6
+ ja: "テニスボール",
7
+ size: { extentMm: 67.0, diameterMm: 67.0, massG: [56.0, 59.4], rule: "ITF Rules of Tennis, Rule 3 The Ball and Appendix I The Ball (a)-(c)" },
8
+ base: "#d3e11f",
9
+ b: 0.33,
10
+ view: { yaw: 25, pitch: 40, roll: 15 },
11
+ mat: { gloss: 0.12, shade: "#3f4a06", grain: { f: 1.8, a: 0.55, seed: 7 } },
12
+ strip: { colour: "#f4f6e4", width: 2.7 },
13
+ });
@@ -0,0 +1 @@
1
+ export declare const BALL_TEQBALL: import("./ball.core.ts").Piece<import("./ball.engine.ts").BallSpec>;
@@ -0,0 +1,27 @@
1
+ // Teqball: the soccer ball's 32 panels in our colours, teal and white, with a pale inset on each hexagon.
2
+ import { defineBall } from "./ball.engine.js";
3
+ import { shrink, truncatedIcosahedron } from "./ball.polyhedra.js";
4
+ import { blend, mix } from "./ball.core.js";
5
+ export const BALL_TEQBALL = /* @__PURE__ */ defineBall({
6
+ id: "ball:teqball",
7
+ en: "Teqball ball",
8
+ ja: "テックボール用ボール",
9
+ size: { extentMm: 216.4, diameterMm: 216.4, circumferenceMm: 680.0, massG: [370, 400], rule: "FITEQ Official Rules and Regulations of Teqball 2026, Rule 3 The Official Ball, 3.1.1-3.1.6", note: "Diameter worked out from the middle of the circumference range." },
10
+ spec: {
11
+ view: { yaw: 30, pitch: 24, roll: 8 },
12
+ base: "#0f9aa8",
13
+ ground: "#f6f8f8",
14
+ mat: { gloss: 0.7, shade: "#0c2a40", grain: { f: 1.1, a: 0.1 } },
15
+ draw: (s, base) => {
16
+ const t = truncatedIcosahedron();
17
+ const inset = blend(base, "#ffffff", 0.82);
18
+ let out = "";
19
+ t.hexagons.forEach((h, i) => (out += s.panel(shrink(h, t.hexagonCentres[i], 0.38), inset, { n: 2 })));
20
+ for (const p of t.pentagons)
21
+ out += s.panel(p, base, { ink: true });
22
+ out += s.strokes(t.edges, mix(base, -0.4), 1.1);
23
+ out += s.strokes(t.edges, "#fff", 0.4, { deco: true, opacity: 0.4, dx: 0.3, dy: 0.35 });
24
+ return out;
25
+ },
26
+ },
27
+ });
@@ -0,0 +1,3 @@
1
+ export declare const BALL_VOLLEYBALL: import("./ball.core.ts").Piece<import("./ball.engine.ts").BallSpec>;
2
+ export declare const BALL_VOLLEYBALL_8: import("./ball.core.ts").Piece<import("./ball.engine.ts").BallSpec>;
3
+ export declare const BALL_BEACH_VOLLEYBALL: import("./ball.core.ts").Piece<import("./ball.engine.ts").BallSpec>;
@@ -0,0 +1,56 @@
1
+ // Volleyball: the 18-panel indoor ball in yellow, blue and white, the 8-panel version, and the beach volleyball in its own bright colours. All made of our own layout of curved panels.
2
+ import { defineBall } from "./ball.engine.js";
3
+ import { octants8, strips18 } from "./ball.family.panelled.js";
4
+ const YELLOW = "#f3c81c";
5
+ const BLUE = "#1f5fbf";
6
+ const WHITE = "#f6f4ee";
7
+ export const BALL_VOLLEYBALL = /* @__PURE__ */ defineBall({
8
+ id: "ball:volleyball",
9
+ en: "Volleyball",
10
+ ja: "バレーボール",
11
+ size: { extentMm: 210.1, diameterMm: 210.1, circumferenceMm: 660.0, massG: [260, 280], rule: "FIVB Official Volleyball Rules 2025-2028, Rule 3 Balls, 3.1 Standards", note: "Diameter worked out from the middle of the circumference range." },
12
+ spec: {
13
+ view: { yaw: 28, pitch: 22, roll: 0 },
14
+ base: YELLOW,
15
+ mat: { gloss: 0.75, shade: "#1a2a50", grain: { f: 1.2, a: 0.12 } },
16
+ draw: (s, base) => strips18(s, [
17
+ [base, BLUE],
18
+ [WHITE, BLUE],
19
+ [BLUE, WHITE],
20
+ [base, WHITE],
21
+ [WHITE, base],
22
+ [BLUE, base],
23
+ ], "#3a4560"),
24
+ },
25
+ });
26
+ export const BALL_VOLLEYBALL_8 = /* @__PURE__ */ defineBall({
27
+ id: "ball:volleyball-8",
28
+ en: "Volleyball, 8 panels",
29
+ ja: "バレーボール(8枚貼り)",
30
+ size: { extentMm: 210.1, diameterMm: 210.1, circumferenceMm: 660.0, massG: [260, 280], rule: "FIVB Official Volleyball Rules 2025-2028, Rule 3 Balls, 3.1 Standards", note: "Diameter worked out from the middle of the circumference range." },
31
+ spec: {
32
+ view: { yaw: 32, pitch: 26, roll: 0 },
33
+ base: YELLOW,
34
+ mat: { gloss: 0.75, shade: "#1a2a50", grain: { f: 1.2, a: 0.12 } },
35
+ draw: (s, base) => octants8(s, (sx, sy, sz) => (sy > 0 ? (sx * sz > 0 ? base : BLUE) : sx * sz > 0 ? WHITE : BLUE), "#3a4560"),
36
+ },
37
+ });
38
+ export const BALL_BEACH_VOLLEYBALL = /* @__PURE__ */ defineBall({
39
+ id: "ball:beach-volleyball",
40
+ en: "Beach volleyball",
41
+ ja: "ビーチバレーボール",
42
+ size: { extentMm: 213.3, diameterMm: 213.3, circumferenceMm: 670.0, massG: [260, 280], rule: "FIVB Official Beach Volleyball Rules 2025-2028, Rule 3 Balls, 3.1 Standards", note: "Diameter worked out from the middle of the circumference range." },
43
+ spec: {
44
+ view: { yaw: 28, pitch: 22, roll: 0 },
45
+ base: "#f2701f",
46
+ mat: { gloss: 0.6, shade: "#4a2410", grain: { f: 1.2, a: 0.1 } },
47
+ draw: (s, base) => strips18(s, [
48
+ [base, WHITE],
49
+ [WHITE, "#14a3d6"],
50
+ [base, "#14a3d6"],
51
+ [WHITE, base],
52
+ [base, WHITE],
53
+ [WHITE, "#14a3d6"],
54
+ ], "#7a4a30"),
55
+ },
56
+ });
@@ -0,0 +1 @@
1
+ export declare const BALL_WATER_POLO: import("./ball.core.ts").Piece<import("./ball.engine.ts").BallSpec>;
@@ -0,0 +1,31 @@
1
+ // Water polo ball: yellow, with deep dark grip channels that follow the seams of its panels. Three seams at right angles cut it into eight panels; beside each seam run a fine groove on each side, which is
2
+ // what the grip of a water polo ball looks like. The rest of the surface is the pebbled grain.
3
+ import { defineBall } from "./ball.engine.js";
4
+ import { greatCircle, smallCircle } from "./ball.math.js";
5
+ import { mix } from "./ball.core.js";
6
+ const AXES = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
7
+ /** How far the grooves run from a seam, in radians. */
8
+ const OFFSETS = [0.17];
9
+ export const BALL_WATER_POLO = /* @__PURE__ */ defineBall({
10
+ id: "ball:water-polo",
11
+ en: "Water polo ball",
12
+ ja: "水球ボール",
13
+ size: { extentMm: 221.2, diameterMm: 221.2, circumferenceMm: 695.0, massG: [400, 450], rule: "World Aquatics Competition Regulations, Part Six Water Polo Rules, Appendix 4 Field of Play & Equipment, 20.4.3 Ball (20.4.3.1-20.4.3.4); Part Six rule 1.1 points to Appendix 4", note: "Men's ball. Diameter worked out from the middle of the circumference range. Colour is not regulated." },
14
+ spec: {
15
+ view: { yaw: 30, pitch: 24, roll: 0 },
16
+ base: "#f2c012",
17
+ mat: { gloss: 0.5, shade: "#4a2c04", grain: { f: 1.6, a: 0.3 } },
18
+ draw: (s, base) => {
19
+ const channel = mix(base, -0.62);
20
+ let out = "";
21
+ // The grooves beside each seam: a pair on each side of it.
22
+ const grooves = AXES.flatMap((a) => OFFSETS.flatMap((o) => [smallCircle(a, Math.PI / 2 - o, 96), smallCircle(a, Math.PI / 2 + o, 96)]));
23
+ out += s.strokes(grooves, mix(base, -0.5), 1.1, { closed: true, ink: false, opacity: 0.9 });
24
+ // The seams themselves are the wide channels: dark, with the raised lips either side of them.
25
+ const seams = AXES.map((a) => greatCircle(a, 96));
26
+ out += s.strokes(seams, channel, 3.8, { closed: true });
27
+ out += s.strokes(seams, mix(base, 0.35), 0.5, { closed: true, deco: true, opacity: 0.55, dx: 0.6, dy: 0.7 });
28
+ return out;
29
+ },
30
+ },
31
+ });
@@ -0,0 +1,2 @@
1
+ /** A diamond with a thin diamond inside it. */
2
+ export declare const CREST_DIAMOND: import("../emblem.core.ts").Emblem<import("../emblem.shapes.ts").FlatModel>;
@@ -0,0 +1,18 @@
1
+ // A diamond with a thin diamond inside it, tinted by a team's colours, with the team's letters on it or a star. Drawn for this package.
2
+ import { defineFlat, starPath } from "../emblem.shapes.js";
3
+ /** A diamond with a thin diamond inside it. */
4
+ export const CREST_DIAMOND = /* @__PURE__ */ defineFlat("crest:diamond", "Diamond crest", "ひし形のエンブレム", "ours", {
5
+ metal: "flat",
6
+ color: "#2d5a8c",
7
+ ribbon: "#f4f0e4",
8
+ front: [
9
+ ["m", "M32 3L61 32 32 61 3 32z"],
10
+ ["r", "M32 9L55 32 32 55 9 32z"],
11
+ ["m", "M32 14L50 32 32 50 14 32z"],
12
+ ["e", "M32 6L58 32 32 58 6 32z", "1.4"],
13
+ ["l", "M32 14L14 32l7 0 11-11z"],
14
+ ],
15
+ blank: [["f", starPath(32, 33, 11, 4.6), "#ffffff"]],
16
+ letters: [32, 32, 20],
17
+ rim: 3,
18
+ });
@@ -0,0 +1,2 @@
1
+ /** A pennant on a pole. */
2
+ export declare const CREST_PENNANT: import("../emblem.core.ts").Emblem<import("../emblem.shapes.ts").FlatModel>;
@@ -0,0 +1,18 @@
1
+ // A pennant on a pole, tinted by a team's colours, with the team's letters on it or a star. Drawn for this package.
2
+ import { defineFlat, starPath } from "../emblem.shapes.js";
3
+ /** A pennant on a pole. */
4
+ export const CREST_PENNANT = /* @__PURE__ */ defineFlat("crest:pennant", "Pennant crest", "ペナント形のエンブレム", "ours", {
5
+ metal: "flat",
6
+ color: "#2d5a8c",
7
+ ribbon: "#f4f0e4",
8
+ front: [
9
+ ["m", "M9 3h4v58H9z"],
10
+ ["m", "M13 8L58 32 13 56z"],
11
+ ["r", "M13 8L58 32 52 35 13 14z"],
12
+ ["e", "M16 12.6L50.4 32 16 51.4z", "1.2"],
13
+ ["l", "M16 13l16 8-16 4z"],
14
+ ],
15
+ blank: [["f", starPath(28, 33, 9, 3.8), "#ffffff"]],
16
+ letters: [29, 33, 17],
17
+ rim: 3,
18
+ });
@@ -0,0 +1,2 @@
1
+ /** A round badge with a ring inside its edge. */
2
+ export declare const CREST_ROUNDEL: import("../emblem.core.ts").Emblem<import("../emblem.shapes.ts").FlatModel>;
@@ -0,0 +1,18 @@
1
+ // A round badge with a ring inside its edge, tinted by a team's colours, with the team's letters on it or a star. Drawn for this package.
2
+ import { circlePath, defineFlat, starPath } from "../emblem.shapes.js";
3
+ /** A round badge with a ring inside its edge. */
4
+ export const CREST_ROUNDEL = /* @__PURE__ */ defineFlat("crest:roundel", "Round crest", "丸形のエンブレム", "ours", {
5
+ metal: "flat",
6
+ color: "#2d5a8c",
7
+ ribbon: "#f4f0e4",
8
+ front: [
9
+ ["o", circlePath(32, 32, 28)],
10
+ ["r", circlePath(32, 32, 23.4)],
11
+ ["o", circlePath(32, 32, 20.4)],
12
+ ["e", circlePath(32, 32, 26.2), "1.4"],
13
+ ["l", "M12 28a21 21 0 0 1 15-15 22 22 0 0 0-10 21z"],
14
+ ],
15
+ blank: [["f", starPath(32, 33, 13, 5.4), "#ffffff"]],
16
+ letters: [32, 32, 24],
17
+ rim: 3,
18
+ });
@@ -0,0 +1,2 @@
1
+ /** A heraldic shield with a band across the top. */
2
+ export declare const CREST_SHIELD: import("../emblem.core.ts").Emblem<import("../emblem.shapes.ts").FlatModel>;
@@ -0,0 +1,17 @@
1
+ // A heraldic shield with a band across the top, tinted by a team's colours, with the team's letters on it or a star. Drawn for this package.
2
+ import { defineFlat, starPath } from "../emblem.shapes.js";
3
+ /** A heraldic shield with a band across the top. */
4
+ export const CREST_SHIELD = /* @__PURE__ */ defineFlat("crest:shield", "Shield crest", "盾形のエンブレム", "ours", {
5
+ metal: "flat",
6
+ color: "#2d5a8c",
7
+ ribbon: "#f4f0e4",
8
+ front: [
9
+ ["m", "M9 5h46v23c0 15-10 24-23 30C19 52 9 43 9 28z"],
10
+ ["r", "M9 5h46v9H9z"],
11
+ ["e", "M12.5 8.5h39v19.5c0 12.5-8.3 20.6-19.5 26C21.8 48.6 12.5 40.5 12.5 28z", "1.4"],
12
+ ["l", "M13 16h10L13 30z"],
13
+ ],
14
+ blank: [["f", starPath(32, 34, 12, 5), "#ffffff"]],
15
+ letters: [32, 37, 24],
16
+ rim: 3,
17
+ });
@@ -1,13 +1,15 @@
1
- import type { Emblem, EmblemOptions, EmblemStyle, FrameOptions } from "./emblem.core.ts";
2
- import { type BallId, type EmblemId } from "./emblem.ids.ts";
3
- /** What can name an emblem: an id, or an id with a style (`"award:medal/line"`), or the emblem itself. */
1
+ import type { Emblem, EmblemLocale, EmblemOptions, EmblemStyle, EmblemTheme, FrameOptions } from "./emblem.core.ts";
2
+ import { type BallId, type CrestShape, type EmblemId, type MedalKind, type SportName } from "./emblem.ids.ts";
3
+ import type { PieceSize } from "./ball/ball.core.ts";
4
+ import { type EmblemDescription } from "./emblem.descriptions.ts";
5
+ /** What can name an emblem: an id, a short name (`"cup"` for `"trophy:cup"`), either with a style (`"trophy:cup/line"`), or the emblem itself. */
4
6
  export type EmblemRef = EmblemId | `${EmblemId}/${EmblemStyle}` | (string & {}) | Emblem;
5
- /** The id and style a string names, or `undefined` when it is not an emblem. An id may end in `/metal`, `/line` or `/color`. */
7
+ /** The id and style a string names, or `undefined` when it is not an emblem. An id may end in `/metal`, `/line` or `/color`, and a trophy or an award may be written without its group (`cup`, `crown`). */
6
8
  export declare function parseEmblem(value: unknown): {
7
9
  id: EmblemId;
8
10
  style: EmblemStyle | undefined;
9
11
  } | undefined;
10
- /** True when the value is the id of an emblem (with no style). */
12
+ /** True when the value is the id of an emblem (not a short name, and with no style). */
11
13
  export declare function isEmblemId(value: unknown): value is EmblemId;
12
14
  /** The emblem a reference names. An unknown name is an error that says what an id looks like. */
13
15
  export declare function emblemOf(ref: EmblemRef): {
@@ -20,8 +22,8 @@ export declare function emblemOf(ref: EmblemRef): {
20
22
  * @example
21
23
  * ```ts
22
24
  * import { renderEmblem } from "@johnmorrisdotca/dougu-sports/emblems";
23
- * const svg = renderEmblem("award:medal", { style: "line", size: 32 });
24
- * console.log(svg.startsWith("<svg"), svg.includes("<title>Medal</title>"));
25
+ * const svg = renderEmblem("trophy:cup", { style: "line", size: 32 });
26
+ * console.log(svg.startsWith("<svg"), svg.includes("<title>Cup</title>"));
25
27
  * // true true
26
28
  * ```
27
29
  */
@@ -29,11 +31,11 @@ export declare function renderEmblem(ref: EmblemRef, options?: EmblemOptions): s
29
31
  /** The same as `renderEmblem`. */
30
32
  export declare const emblemSvg: typeof renderEmblem;
31
33
  /**
32
- * An emblem turned: `yaw` degrees about its vertical axis and `pitch` degrees of tilt, from its resting view, in plain SVG. A flat emblem (a medal) flips like a coin and shows its back; a ball rolls.
34
+ * An emblem turned: `yaw` degrees about its vertical axis and `pitch` degrees of tilt, from its resting view, in plain SVG. A cup, bowl or urn keeps its outline and moves its light, handles and seams; a medal flips like a coin and shows its back; a ball rolls; an icon is not turned.
33
35
  * @example
34
36
  * ```ts
35
37
  * import { emblemFrame, renderEmblem } from "@johnmorrisdotca/dougu-sports/turn";
36
- * console.log(emblemFrame("award:medal", { yaw: 0 }) === renderEmblem("award:medal"));
38
+ * console.log(emblemFrame("medal:gold", { yaw: 0 }) === renderEmblem("medal:gold"));
37
39
  * // true
38
40
  * ```
39
41
  */
@@ -51,6 +53,10 @@ export interface EmblemInfo {
51
53
  ja: string;
52
54
  source: Emblem["source"];
53
55
  kind: Emblem["kind"];
56
+ /** A ball's or an implement's official size, with the rule it is from, where the rulebook gives one. */
57
+ size?: PieceSize;
58
+ /** What is drawn, in more words than the short name (which is the accessible name), for the docs and a gallery; not every emblem has one. */
59
+ description?: EmblemDescription;
54
60
  }
55
61
  /** The names, source and kind of an emblem. */
56
62
  export declare function emblemInfo(id: EmblemId): EmblemInfo;
@@ -58,3 +64,65 @@ export declare function emblemInfo(id: EmblemId): EmblemInfo;
58
64
  export declare function emblemName(id: EmblemId, language?: "en" | "ja"): string;
59
65
  /** The data an emblem is drawn from: a flat emblem's shapes or a ball's marks, for a view that turns it itself. */
60
66
  export declare function emblemModel(id: EmblemId): unknown;
67
+ /** What `crest` takes. */
68
+ export interface CrestOptions {
69
+ /** `shield` (the default), `roundel`, `diamond` or `pennant`. */
70
+ shape?: CrestShape;
71
+ /** The team's colour, or its colour and a second colour for the band and the ring. Hex colours or `rgb()`. */
72
+ colors?: string | readonly [string, string?];
73
+ /** Up to three letters. A crest with none has a star. */
74
+ initials?: string;
75
+ size?: number;
76
+ style?: EmblemStyle;
77
+ theme?: EmblemTheme;
78
+ /** The language of the `<title>`, `"en"` (the default) or `"ja"`. */
79
+ locale?: EmblemLocale;
80
+ /** A string is the `<title>`; `false` drops it and hides the drawing from a screen reader. */
81
+ title?: string | false;
82
+ }
83
+ /**
84
+ * A generic crest tinted by a team's colours, with its letters if it has any: what a team with no logo gets. The letters are in the ink that reads on the colour.
85
+ * @example
86
+ * ```ts
87
+ * import { crest } from "@johnmorrisdotca/dougu-sports/emblems";
88
+ * const svg = crest({ shape: "shield", colors: ["#c8102e", "#f4f0e4"], initials: "NO" });
89
+ * console.log(svg.includes(">NO<"));
90
+ * // true
91
+ * ```
92
+ */
93
+ export declare function crest(options?: CrestOptions): string;
94
+ /** A medal on a ribbon: `medal("gold")`, `"silver"` or `"bronze"`; any other kind is the gold one. */
95
+ export declare function medal(kind: MedalKind, options?: EmblemOptions): string;
96
+ /** The icon of a sport, by the names of `SPORT_NAMES`: `sportIcon("nhl")`. An unknown sport is an error. */
97
+ export declare function sportIcon(sport: SportName, options?: EmblemOptions): string;
98
+ /** What `pennant` takes. */
99
+ export interface PennantOptions {
100
+ /** The felt, the stitching, and the lettering (the stitching's colour unless a third is given), as hex colours or `rgb()`. */
101
+ colors?: string | readonly [felt?: string, stitching?: string, lettering?: string];
102
+ /** The words, in capitals ("Champions", "優勝"); more than one line with line breaks. The engraving options `label`, `rank` and `year` work too. */
103
+ text?: string;
104
+ /** The label and rank, as for any engraving: ignored when `text` is given. */
105
+ label?: string;
106
+ rank?: number | string;
107
+ /** The year, in smaller letters under the words. */
108
+ year?: number | string;
109
+ /** `"front"` (the default) or `"back"`: plain felt, with the dowel on the other side. */
110
+ view?: "front" | "back";
111
+ size?: number;
112
+ style?: EmblemStyle;
113
+ theme?: EmblemTheme;
114
+ /** A turn from the resting view, in degrees. */
115
+ yaw?: number;
116
+ pitch?: number;
117
+ }
118
+ /**
119
+ * A felt championship pennant with a stitched edge, lettered with its words and its year.
120
+ * @example
121
+ * ```ts
122
+ * import { pennant } from "@johnmorrisdotca/dougu-sports/emblems";
123
+ * const svg = pennant({ colors: ["#1f4e8c", "#f2c230"], text: "Champions", year: 2026 });
124
+ * console.log(svg.includes(">CHAMPIONS<"), svg.includes(">2026<"));
125
+ * // true true
126
+ * ```
127
+ */
128
+ export declare function pennant(options?: PennantOptions): string;