@johnmorrisdotca/chikyu-earth 0.5.0 → 0.7.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 (56) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/NOTICE.md +11 -0
  3. package/README.md +172 -27
  4. package/dist/countries.d.ts +11 -0
  5. package/dist/countries.js +11 -0
  6. package/dist/element.d.ts +18 -0
  7. package/dist/element.js +15 -2
  8. package/dist/globe.d.ts +15 -1
  9. package/dist/globe.js +15 -1
  10. package/dist/index.d.ts +12 -1
  11. package/dist/index.js +12 -1
  12. package/dist/markers/cluster.d.ts +27 -0
  13. package/dist/markers/cluster.js +16 -0
  14. package/dist/markers/labels.d.ts +40 -0
  15. package/dist/markers/labels.js +18 -0
  16. package/dist/markers/layer.d.ts +80 -0
  17. package/dist/markers/layer.js +21 -0
  18. package/dist/markers/project.d.ts +63 -2
  19. package/dist/markers/project.js +52 -2
  20. package/dist/markers/types.d.ts +48 -3
  21. package/dist/realistic/earth.d.ts +30 -5
  22. package/dist/realistic/earth.js +41 -134
  23. package/dist/realistic/element.d.ts +47 -7
  24. package/dist/realistic/element.js +48 -44
  25. package/dist/realistic/gate.d.ts +45 -1
  26. package/dist/realistic/gate.js +33 -1
  27. package/dist/realistic/shaders.d.ts +9 -4
  28. package/dist/realistic/shaders.js +54 -9
  29. package/dist/realistic/shared.d.ts +23 -0
  30. package/dist/realistic/shared.js +51 -0
  31. package/dist/realistic/sun.d.ts +40 -3
  32. package/dist/realistic/sun.js +40 -3
  33. package/dist/realistic/textures.d.ts +40 -0
  34. package/dist/realistic/textures.js +141 -0
  35. package/dist/realistic/tiers.d.ts +80 -6
  36. package/dist/realistic/tiers.js +69 -5
  37. package/dist/rotate.d.ts +59 -4
  38. package/dist/rotate.js +59 -4
  39. package/dist/space/element.d.ts +134 -0
  40. package/dist/space/element.js +394 -0
  41. package/dist/space/ephemeris.d.ts +151 -0
  42. package/dist/space/ephemeris.js +162 -0
  43. package/dist/space/index.d.ts +3 -0
  44. package/dist/space/index.js +5 -0
  45. package/dist/space/scale.d.ts +124 -0
  46. package/dist/space/scale.js +141 -0
  47. package/dist/space/scene.d.ts +131 -0
  48. package/dist/space/scene.js +295 -0
  49. package/dist/styles.d.ts +65 -2
  50. package/dist/styles.js +43 -2
  51. package/dist/textures/moon-1024.webp +0 -0
  52. package/dist/textures/moon-2048.webp +0 -0
  53. package/dist/types.d.ts +55 -5
  54. package/dist/view.d.ts +63 -4
  55. package/dist/view.js +52 -4
  56. package/package.json +55 -8
package/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.0
4
+
5
+ The space view can look at any body, bodies can be chosen, and how the Sun and the planets are drawn is a seam another package can fill.
6
+
7
+ - **Look at a body**: `element.body = "Mars"` (any of Earth, Moon, Sun and the seven planets) points the camera at it; at zoom 1 it fills the view, and the shared controls turn the camera round it and zoom in and out from it. The demo's "Look at" row does it.
8
+ - **Bodies can be chosen**: each name beside a body is a real button (Tab and Enter), and a press on a body (not a drag) fires `chikyu-body-click`; `chikyu-body-focus` for the keyboard. The event carries `name`, `radiusKm` and `distanceKm` (`element.bodyInfo(name)` gives the same for a caption); the demo prints "Jupiter: radius 69,911 km, 666,000,000 km from the Earth".
9
+ - **A seam for drawing the bodies** (`BodyPainter`, `setBodyPainter`, `plainPainter` from `@johnmorrisdotca/chikyu-earth/space`): the space view keeps each body's place, size, light direction, name and orbit, and asks a painter only for what to draw there (an object of radius 1; `light(toSun)` each draw; the Sun's turns to face the camera). The default is what 0.6.0 drew: spheres in the planets' colours and a glow for the Sun. John chose a separate package (wakusei-planets) for the bodies' own looks, so chikyu ships no planet pictures and no rings; the Earth and the Moon keep theirs.
10
+ - Tests: e2e (a body looked at, its name chosen by keyboard, a press on it chooses it, a drag that turns the view does not) and a unit test of the default painter.
11
+
12
+ ## 0.6.0 (never published on its own: it ships in 0.7.0)
13
+
14
+ The Sun, the Moon and the planets: `<chikyu-space>`, an optional entry point, under the same performance budget as the Earth from space.
15
+
16
+ - **`<chikyu-space>`** (`@johnmorrisdotca/chikyu-earth/space/element`) places the Earth, the Moon, the Sun and the planets (Mercury to Neptune) in their positions for a date and time, with the Moon's
17
+ phase and the Earth's sunlit side coming out of the light (the Moon is half lit on 2 November 2026, last quarter). Positions are computed in the browser by **astronomy-engine** (MIT, a new optional peer dependency;
18
+ nothing is fetched). Time controls: `time` (an ISO date or `now`), `speed` (1 real time, 0 held, 3600 an hour a second, 86400 a day a second, negative backwards). Zoom from the Earth out to the solar system and back with
19
+ the shared controls (`zoom-min`, `zoom-max`), and `zoomFor("moon" | "sun" | "inner" | "solar-system" | "earth")` for the jumps. Names beside the bodies and the planets' orbits can be switched off.
20
+ - **Two scales, and it says which**: `compressed` (default; every direction real, the Moon 10 Earth radii away instead of 60, the Sun 44, the planets round the Sun at 44 radii times their distance in astronomical
21
+ units to the power 0.45, sizes enlarged) and `true` (real distances and sizes, where the planets are specks). The demo says "Compressed scale: ..." whenever it is on. [docs/space.md](docs/space.md).
22
+ - **Budget, each line tested** (`e2e/space.gl.ts`): paused, 0 draw calls and 0 frame requests in 4 s; real time, 0 draw calls in 6 s (a draw a minute); a day a second: 1.00 days a second of game time, 29.4 draws a second,
23
+ and 2.0 ephemeris lookups a second (the ephemeris is looked up once a game-second span and interpolated, within 0.1 degree of the Moon's true place); nothing drawn out of sight at a day a second; the textures follow the zoom and
24
+ are freed after it; removal frees what it held; a lost context is recovered. The space soak (10 minutes, 945 steps from the Earth to the solar system and back, at every speed, both scales, orbits and names toggled): JS heap 8.05 to 8.45 MB after garbage collection (flat from the fifth minute), GPU objects 46 to 46, textures, buffers and programs equal to the start, the average 76 GL draw calls a second (about 25 a frame, so 3 frames a second), one WebGL context, no error.
25
+ - **Pictures**: the Moon (NASA SVS 4720, LROC colour mosaic, 1024 and 2048 wide, 306 KB) joins the Earth's; the package's textures are 1.85 MB. The planets are plain colours.
26
+ - **Shared parts**: the texture loader (`src/realistic/textures.ts`) and the page's one renderer (`src/realistic/shared.ts`) now serve both the Earth from space and the space view, so a page keeps one WebGL context between them. The
27
+ Earth's shaders look at the camera instead of assuming one, so they work from any angle.
28
+ - **Research, no code** ([docs/satellite-sources.md](docs/satellite-sources.md), MODULES-85): CelesTrak (grey), Space-Track (red for a package), the r/SpaceX API (archived, offline), Launch Library 2 (grey), Wikipedia and Wikidata
29
+ (green) for launches; the recommendation is a satellite view that takes elements the page supplies. John chooses before MODULES-86 and MODULES-87 start.
30
+
31
+ ### The family's published parts: demo, embed, docs and usage
32
+
33
+ Chikyu Earth now has what every package of the family has, and it was missing from 0.3.0 to 0.5.0.
34
+
35
+ - **Demo on GitHub Pages**, set as the repository's and the package's homepage: <https://johnmorrisdotca.github.io/chikyu-earth/>, with the family header (the kazoku-ui language picker, English and Japanese, and theme switch, the table cloths and the Help switch), light and dark, and the family footer. `pnpm site` builds it, and the Pages workflow publishes it on every push to `main`.
36
+ - **An embed page**, `embed.html`, for an `<iframe>` with no script of your own: `?look=line|thick|realistic`, `center`, `graticule`, `turn=0|1|auto`, `time`, `clouds`, `lights`. Still by default, no controls, no location prompt; it draws only when something changes and nothing while hidden. Tested in Chromium and WebKit, and on the realistic look: one WebGL context, canvas inside its budget, nothing drawn at rest.
37
+ - **A documentation site** at `/docs/`: a page for every export (from its TSDoc, with an example that is run when the site is built), ten guides in English and in Japanese, one language to a page, search, `llms.txt` and the family's header. Every export of every entry point has a summary, `@param`, `@returns` and an `@example` that imports the package by its name; `pnpm check` fails when one does not.
38
+ - **Every way to use it, written down and tested** (`pnpm test:usage`): a script tag from jsDelivr and from unpkg, the realistic Earth from a CDN, the shared controls, Vite, webpack, React (and a server render of it), Vue, Svelte, Angular, an iframe, TypeScript types and Node. Each example is built or run against the package as npm packs it, opened in a browser and made to show a globe; the guides and the README must hold the same text word for word.
39
+ - **`look` attribute**: `<chikyu-earth look="thick">` is the new name of `style`, which frameworks read as CSS (React refuses a string `style`). `style` still works.
40
+ - **Types for the tags**: `document.querySelector("chikyu-earth")` is a `ChikyuEarth` (and `"chikyu-earth-realistic"`, `"chikyu-space"`) once the element's entry is imported.
41
+ - **A freeze test in the release** (`e2e/freeze.demo.ts`, `pnpm test:freeze`): at rest nothing is drawn and no frame asked for, turning draws at most once for each frame of the page and asks for one frame at a time, out of sight or in a hidden tab nothing is drawn, the canvas stays inside 6 million pixels and 4096 a side on a 5K screen at a pixel ratio of 2 in the Earth from space and the space view, and six rounds of changing the look leave the GPU objects flat in one WebGL context and let the context go at the end. Every Chromium project draws WebGL in software, never on the machine's graphics card. The release workflow runs it (`freeze-command`, kazoku-ui 0.9.1).
42
+ - **The family's must-have list**, checked: `scripts/check-standard.mjs` (kazoku-ui's, unchanged) fails `pnpm check` when a package lacks its demo, embed page, docs site with Japanese twins, family files or tested usage.
43
+ - **Family files**: `family-template.mjs` and `family-readme.mjs` of 2026-11-02 with Chikyu Earth added to the family's list (33 packages), `family.css`, and the README's "The family" block. Added to the list here only; the other packages take the new files when they are next touched.
44
+
3
45
  ## 0.5.0
4
46
 
5
47
  The Earth from space, and markers for any place on either globe, both under a hard performance budget.
package/NOTICE.md CHANGED
@@ -33,6 +33,17 @@ material, so no other licence applies. This package is not endorsed by NASA and
33
33
  The credit names are NASA's usual lines for these series; the Visible Earth pages (now at science.nasa.gov/earth/earth-observatory) did not show a credit line in the
34
34
  text read on 2026-11-02, so check them if you need the exact wording for print.
35
35
 
36
+ ## The Moon's picture
37
+
38
+ `moon-*.webp` is made by `scripts/make-textures.py` from NASA's Scientific Visualization Studio item 4720, "Moon: LROC colour mosaic" (https://svs.gsfc.nasa.gov/4720/,
39
+ `lroc_color_2k.jpg`), a natural-colour mosaic of the Lunar Reconnaissance Orbiter's wide-angle camera (Arizona State University and NASA/GSFC). NASA's page asks: "Please give credit for this
40
+ item to: NASA's Scientific Visualization Studio" (Visualizer Ernie Wright, USRA; Scientist Noah Petro, NASA/GSFC). Same NASA terms as above.
41
+
42
+ ## The planets' places
43
+
44
+ `<chikyu-space>` computes positions with **astronomy-engine** (https://github.com/cosinekitty/astronomy, MIT, copyright Don Cross), the page's own optional peer dependency: this package does not
45
+ bundle or ship it. The planets are drawn as plain colours, from no picture.
46
+
36
47
  ## Sun position
37
48
 
38
49
  `src/realistic/sun.ts` uses the low-precision solar position formulas of NOAA's solar calculator (https://gml.noaa.gov/grad/solcalc/, after Jean Meeus,
package/README.md CHANGED
@@ -9,43 +9,106 @@ Country outlines in the same thin-line style as Hako Devices and Uchusen Rockets
9
9
  <img alt="TypeScript" src="https://img.shields.io/badge/types-TypeScript-3178c6">
10
10
  </p>
11
11
 
12
+ <p align="center"><a href="https://johnmorrisdotca.github.io/chikyu-earth/"><strong>Open the demo →</strong></a> · <a href="https://johnmorrisdotca.github.io/chikyu-earth/embed.html">Embed page</a> · <a href="https://johnmorrisdotca.github.io/chikyu-earth/docs/">Docs</a></p>
13
+
12
14
  <p align="center"><img alt="The line-drawn globe, Europe and Africa in view, with the shared control bar" src="docs/images/line-desk.png" width="640"></p>
13
15
 
14
- ## One minute
16
+ ## Install and use
15
17
 
16
18
  ```sh
17
19
  npm install @johnmorrisdotca/chikyu-earth
18
20
  ```
19
21
 
20
- ```html
21
- <script type="module">
22
- import "@johnmorrisdotca/kazoku-ui/view-controls/define";
23
- import "@johnmorrisdotca/chikyu-earth/element";
24
- </script>
22
+ Or use no install at all: every example below was run in a browser, built or type-checked by `pnpm test:usage` against the package as npm packs it, and the guides hold the same text.
25
23
 
26
- <div id="globe" tabindex="0">
27
- <chikyu-earth size="420"></chikyu-earth>
28
- </div>
29
- <kazoku-view-controls id="controls" for="globe" address controls="advanced" tilt-max="90" speed="0.004178" autoplay></kazoku-view-controls>
24
+ ### In a plain HTML page
30
25
 
31
- <script type="module">
32
- const earth = document.querySelector("chikyu-earth");
33
- document.getElementById("controls").addEventListener("kazoku-viewchange", (event) => {
34
- earth.setView(event.detail, event.detail.final);
35
- });
36
- </script>
26
+ One script tag from [jsDelivr](https://www.jsdelivr.com/package/npm/@johnmorrisdotca/chikyu-earth) and the tag. (From unpkg, with the realistic Earth, and pinning a version: [the CDN guide](docs/guides/html-and-cdn.md).)
27
+
28
+ ```html
29
+ <!doctype html>
30
+ <html lang="en">
31
+ <head>
32
+ <meta charset="utf-8" />
33
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
34
+ <title>Chikyu Earth from jsDelivr</title>
35
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@johnmorrisdotca/chikyu-earth/element/+esm"></script>
36
+ </head>
37
+ <body>
38
+ <chikyu-earth center="139.7,35.7" look="thick" graticule size="320"></chikyu-earth>
39
+ </body>
40
+ </html>
37
41
  ```
38
42
 
39
- The globe appears, centred on the reader (the browser asks for their location; until they answer, and if they
40
- decline, it starts on the Greenwich meridian). The shared control bar turns, tips, zooms and pans it. Auto-turn
41
- moves at the Earth's own rate: `0.004178` degrees a second, one sidereal day — 23 h 56 min 4.0905 s — per revolution.
43
+ The globe appears centred where you say; with no `center` it centres on the reader (the browser asks for their location; until they answer, and if they decline, it starts on the Greenwich meridian). `look` is `line` or `thick`.
42
44
 
43
- Centre it yourself instead:
45
+ ### With the shared controls
46
+
47
+ The [kazoku-ui](https://github.com/johnmorrisdotca/kazoku-ui) view controls turn, tip, zoom and pan it, and keep the view in the address. One listener passes their camera on:
44
48
 
45
49
  ```html
46
- <chikyu-earth center="139.7,35.7" style="thick" graticule></chikyu-earth>
50
+ <!doctype html>
51
+ <html lang="en">
52
+ <head>
53
+ <meta charset="utf-8" />
54
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
55
+ <title>Chikyu Earth with the shared controls</title>
56
+ <script type="module">
57
+ import "https://cdn.jsdelivr.net/npm/@johnmorrisdotca/kazoku-ui/view-controls/define/+esm";
58
+ import "https://cdn.jsdelivr.net/npm/@johnmorrisdotca/chikyu-earth/element/+esm";
59
+
60
+ const earth = document.querySelector("chikyu-earth");
61
+ document.querySelector("kazoku-view-controls").addEventListener("kazoku-viewchange", (event) => {
62
+ earth.setView(event.detail, event.detail.final);
63
+ });
64
+ </script>
65
+ </head>
66
+ <body>
67
+ <div id="globe" tabindex="0">
68
+ <chikyu-earth size="420" look="thick" center="139.7,35.7"></chikyu-earth>
69
+ </div>
70
+ <kazoku-view-controls for="globe" address controls="advanced" tilt-max="90" speed="0.004178"></kazoku-view-controls>
71
+ </body>
72
+ </html>
47
73
  ```
48
74
 
75
+ Auto-turn (add `autoplay`) moves at the Earth's own rate: `0.004178` degrees a second, one sidereal day — 23 h 56 min 4.0905 s — per revolution.
76
+
77
+ ### In React
78
+
79
+ The element needs a browser, so it is imported inside the effect, never at the top of the file; that keeps a server render working. (Vue, Svelte and Angular do the same: [the frameworks guide](docs/guides/frameworks.md).)
80
+
81
+ ```tsx
82
+ import { useEffect, useRef } from "react";
83
+
84
+ export function ChikyuEarth({ center = "139.7,35.7", look = "thick" }: { center?: string; look?: "line" | "thick" }) {
85
+ const host = useRef<HTMLDivElement>(null);
86
+ useEffect(() => {
87
+ // The element needs a browser, so it is imported here, never at the top of the file: a server render never reaches an effect.
88
+ void import("@johnmorrisdotca/chikyu-earth/element");
89
+ }, []);
90
+ return (
91
+ <div ref={host}>
92
+ <chikyu-earth center={center} look={look} graticule />
93
+ </div>
94
+ );
95
+ }
96
+ ```
97
+
98
+ ### Every other way
99
+
100
+ | How | Where |
101
+ |---|---|
102
+ | A script tag from jsDelivr or unpkg, the realistic Earth from a CDN | [CDN guide](docs/guides/html-and-cdn.md) |
103
+ | An ES module in Vite or webpack | [bundlers guide](docs/guides/bundlers.md) |
104
+ | React, Vue, Svelte, Angular; Next.js, Nuxt, SvelteKit | [frameworks guide](docs/guides/frameworks.md) |
105
+ | An `<iframe>` of the embed page, no script of your own | [iframe guide](docs/guides/embed-in-an-iframe.md) |
106
+ | TypeScript types, an SVG string on a server, Node | [TypeScript and Node guide](docs/guides/typescript-and-node.md) |
107
+ | The web component (`<chikyu-earth>`, `<chikyu-earth-realistic>`) | every one of the above; its attributes are in [The element](#the-element) |
108
+ | Something does not appear | [troubleshooting](docs/guides/troubleshooting.md) |
109
+
110
+ The guides are also in Japanese (日本語), one language to a page: [docs/guides/ja/](docs/guides/ja/getting-started.md).
111
+
49
112
  ## The Earth from space
50
113
 
51
114
  An optional second look, for a page with room for a real picture: day and night by the real Sun, cities' lights, a sun glint on the sea, a cloud layer and the
@@ -64,12 +127,21 @@ Needs `three` and `@johnmorrisdotca/kazoku-ui` (both optional peers) and the pic
64
127
  at most 30 times a second while it does, in one WebGL context, with textures that grow as you zoom and are freed after. All of it, the budget and the tests:
65
128
  [docs/realistic.md](docs/realistic.md).
66
129
 
130
+ ## The Sun, the Moon and the planets
131
+
132
+ `<chikyu-space>` (`@johnmorrisdotca/chikyu-earth/space/element`) places the Earth, the Moon, the Sun and the planets where they are at a date and time, with the Moon's phase and the Earth's day side
133
+ from the light, a compressed scale you can read (and a true one that shows how empty it is), time that runs forwards or backwards, and a zoom from the Earth to the solar system. Positions are
134
+ computed in the browser by astronomy-engine (MIT), nothing is fetched. [docs/space.md](docs/space.md).
135
+
136
+ <p align="center"><img alt="The solar system on 2 November 2026 in the compressed scale: orbits round the Sun, the planets named" src="docs/images/space-solar.png" width="420"></p>
137
+
67
138
  ## Markers
68
139
 
69
140
  Mark any place at `[lon, lat]` with a label, colour or icon, in groups you can show or hide, on either look. Chikyu ships no places; yours move with the globe, fade on the far side, make room
70
141
  for their labels, gather into clusters when crowded, and fire hover, click and keyboard events with your own data. One canvas pass for thousands, a pool of 24 buttons for the labels. [docs/markers.md](docs/markers.md).
71
142
 
72
- ```ts
143
+ ```ts no-run
144
+ import "@johnmorrisdotca/chikyu-earth/element";
73
145
  import { attachMarkers } from "@johnmorrisdotca/chikyu-earth/markers";
74
146
 
75
147
  const markers = attachMarkers(document.querySelector("chikyu-earth")!);
@@ -87,12 +159,14 @@ rotate or drag controls.
87
159
  <kazoku-view-controls id="controls" for="globe" address controls="advanced" tilt-max="90" speed="0.004178" autoplay></kazoku-view-controls>
88
160
  ```
89
161
 
90
- ```ts
162
+ ```ts no-run
163
+ import "@johnmorrisdotca/chikyu-earth/element";
91
164
  import "@johnmorrisdotca/kazoku-ui/view-controls/define";
165
+ import type { ViewChangeDetail } from "@johnmorrisdotca/kazoku-ui/view-controls/element";
92
166
 
93
- const earth = document.querySelector("chikyu-earth");
94
- document.getElementById("controls").addEventListener("kazoku-viewchange", (event) => {
95
- const { yaw, tilt, zoom, panX, panY, final } = event.detail;
167
+ const earth = document.querySelector("chikyu-earth")!;
168
+ document.getElementById("controls")!.addEventListener("kazoku-viewchange", (event) => {
169
+ const { yaw, tilt, zoom, panX, panY, final } = (event as CustomEvent<ViewChangeDetail>).detail;
96
170
  earth.setView({ yaw, tilt, zoom, panX, panY }, final);
97
171
  });
98
172
  ```
@@ -122,7 +196,7 @@ The rotation is the pair d3-geo's `rotate` takes: `[-longitude, -latitude]` cent
122
196
  | --- | --- | --- |
123
197
  | `size` | Width and height of the square SVG, in pixels. | `320` |
124
198
  | `center` | `"longitude,latitude"` to centre on. Wins over geolocation. | the reader's location, else `0,0` |
125
- | `style` | `line` or `thick`. | `line` |
199
+ | `look` | `line` or `thick`. (`style` is the older name for it: a framework reads `style` as CSS, so use `look` there.) | `line` |
126
200
  | `graticule` | Draw a light graticule under the countries. | off |
127
201
 
128
202
  `setView(view, final = true)` applies a shared controller's `{ yaw, tilt, zoom, panX, panY }`. Every call updates
@@ -147,6 +221,77 @@ countryList().find((c) => c.alpha2 === "JP"); // { name: "Japan", ja: "日本",
147
221
 
148
222
  To take newer outlines, update `@johnmorrisdotca/chizu`; there is no data file in this repository.
149
223
 
224
+ ## The name
225
+
226
+ Chikyu (地球, ちきゅう) is Japanese for the Earth.
227
+
228
+ ## The family
229
+
230
+ <!-- family:start (made by scripts/family-readme.mjs from scripts/family-template.mjs; change those, not this) -->
231
+ Chikyu Earth is one of thirty-three packages, each made for the same site, each at
232
+ [github.com/johnmorrisdotca](https://github.com/johnmorrisdotca) or [github.com/spxis](https://github.com/spxis). The code of every one is MIT.
233
+
234
+ **Games — board**
235
+
236
+ - [Domino](https://github.com/johnmorrisdotca/domino) (ドミノ): dominoes and Mexican Train. [Demo](https://johnmorrisdotca.github.io/domino/).
237
+ - [Gunjin](https://github.com/johnmorrisdotca/gunjin) (軍人): five hidden-rank strategy games with pass-the-device play. [Demo](https://johnmorrisdotca.github.io/gunjin/).
238
+ - [Narabe](https://github.com/johnmorrisdotca/narabe) (並べ): one rules engine for abstract board games, from gomoku and Reversi to Go and checkers. [Demo](https://johnmorrisdotca.github.io/narabe/).
239
+ - [Sugoroku](https://github.com/johnmorrisdotca/sugoroku) (双六): backgammon and its variants, with the doubling cube and match play. [Demo](https://johnmorrisdotca.github.io/sugoroku/).
240
+ - [Tenka](https://github.com/johnmorrisdotca/tenka) (天下): world conquest for two to six, on a map of the real world. [Demo](https://johnmorrisdotca.github.io/tenka/).
241
+
242
+ **Games — cards & tiles**
243
+
244
+ - [Hitotsu](https://github.com/johnmorrisdotca/hitotsu) (一つ): a colour-card shedding game for two to eight, with the house rules people play. [Demo](https://johnmorrisdotca.github.io/hitotsu/).
245
+ - [Jarajara](https://github.com/johnmorrisdotca/jarajara) (ジャラジャラ): mahjong tiles drawn as SVG, stacked layouts, and the matching solitaire Awase. [Demo](https://johnmorrisdotca.github.io/jarajara/).
246
+ - [Kumimoji](https://github.com/johnmorrisdotca/kumimoji) (組み文字): a crossword tile race, in English and Japanese kana. [Demo](https://johnmorrisdotca.github.io/kumimoji/).
247
+ - [Toranpu](https://github.com/johnmorrisdotca/toranpu) (トランプ): a deck of playing cards, card games with computer players, and solitaires. [Demo](https://johnmorrisdotca.github.io/toranpu/).
248
+
249
+ **Games — puzzles**
250
+
251
+ - [Houseki](https://github.com/johnmorrisdotca/houseki) (宝石): gem and stone matching puzzles: falling triplets, stone collapse, colour chains and gem swap. [Demo](https://johnmorrisdotca.github.io/houseki/).
252
+ - [Jirai](https://github.com/johnmorrisdotca/jirai) (地雷): minesweeper on shaped grids with verified no-guess boards. [Demo](https://johnmorrisdotca.github.io/jirai/).
253
+ - [Karakuri](https://github.com/johnmorrisdotca/karakuri) (からくり): eight hyper-casual puzzle games, some of them physics: draw a shield, pull pins, cut ropes, slide blocks, pour tubes. [Demo](https://johnmorrisdotca.github.io/karakuri/).
254
+ - [Kazu](https://github.com/johnmorrisdotca/kazu) (数): grid number puzzles: Sudoku and its variants, Futoshiki and Skyscrapers. [Demo](https://johnmorrisdotca.github.io/kazu/).
255
+ - [Kyuubu](https://github.com/johnmorrisdotca/kyuubu) (キューブ): a turning cube for the browser, 2×2 to 7×7, with record solves to replay. [Demo](https://johnmorrisdotca.github.io/kyuubu/).
256
+ - [Meikyuu](https://github.com/johnmorrisdotca/meikyuu) (迷宮): mazes on squares, hexagons, triangles and circles, made from a seed and drawn through with a finger or the mouse. [Demo](https://johnmorrisdotca.github.io/meikyuu/).
257
+ - [Suido](https://github.com/johnmorrisdotca/suido) (水道): a pipe puzzle: turn the pieces until the water reaches every drain. [Demo](https://johnmorrisdotca.github.io/suido/).
258
+ - [Tobiishi](https://github.com/johnmorrisdotca/tobiishi) (飛び石): peg solitaire with nine boards and seeded solvable challenges. [Demo](https://johnmorrisdotca.github.io/tobiishi/).
259
+ - [Tsunagi](https://github.com/johnmorrisdotca/tsunagi) (繋ぎ): a line-joining logic puzzle whose every level has exactly one answer. [Demo](https://johnmorrisdotca.github.io/tsunagi/).
260
+
261
+ **Games — dice & random**
262
+
263
+ - [Korokoro](https://github.com/johnmorrisdotca/korokoro) (コロコロ): dice, with notation, exact odds, real sounds and the dice of many games. [Demo](https://johnmorrisdotca.github.io/korokoro/).
264
+ - [Tane](https://github.com/johnmorrisdotca/tane) (種): seeded random numbers and daily seeds, the same in every browser and on every server. [Demo](https://johnmorrisdotca.github.io/tane/).
265
+
266
+ **Language**
267
+
268
+ - [Bushu](https://github.com/johnmorrisdotca/bushu) (部首): find a kanji by the parts it is made of. [Demo](https://johnmorrisdotca.github.io/bushu/).
269
+ - [Hikidashi](https://github.com/johnmorrisdotca/hikidashi) (引き出し): a drawer of small Japanese text tools: era dates, kanji numerals, readings and sentence difficulty. [Demo](https://johnmorrisdotca.github.io/hikidashi/).
270
+ - [Kotoba](https://github.com/johnmorrisdotca/kotoba) (言葉): word lists and word-game rules in English, French, German and Japanese. [Demo](https://johnmorrisdotca.github.io/kotoba/).
271
+
272
+ **Geography & data**
273
+
274
+ - [address-plus](https://github.com/johnmorrisdotca/address-plus) (アドレスプラス): parse and format addresses in the United States, Canada, Japan, Australia, France, Germany and the United Kingdom. [Demo](https://johnmorrisdotca.github.io/address-plus/).
275
+ - [Chikyu Earth](https://github.com/johnmorrisdotca/chikyu-earth) (地球): a line-drawn globe that turns at the Earth's own rate, with an optional realistic Earth from space and markers for any place. [Demo](https://johnmorrisdotca.github.io/chikyu-earth/).
276
+ - [Chizu](https://github.com/johnmorrisdotca/chizu) (地図): maps of the world and of countries' regions, in English and Japanese, with a quiz and callouts. [Demo](https://johnmorrisdotca.github.io/chizu/).
277
+ - [Hata](https://github.com/johnmorrisdotca/hata) (旗): country and regional flags as SVG, at their true proportions and keyed by ISO code. [Demo](https://johnmorrisdotca.github.io/hata/).
278
+ - [Kuni](https://github.com/johnmorrisdotca/kuni) (国): countries and their regions, with ISO codes and names in English and Japanese. [Demo](https://johnmorrisdotca.github.io/kuni/).
279
+
280
+ **Sports**
281
+
282
+ - [Dougu Sports](https://github.com/johnmorrisdotca/dougu-sports) (道具): sports emblems as SVG: trophies, medals, crests, and the ball and gear of every sport, with optional 3D turning. [Demo](https://johnmorrisdotca.github.io/dougu-sports/).
283
+ - [Kyogijo Stadiums](https://github.com/johnmorrisdotca/kyogijo-stadiums) (競技場): sports fields, rinks, courts and ballparks drawn to scale as SVG, with each team and the score on them. [Demo](https://johnmorrisdotca.github.io/kyogijo-stadiums/).
284
+ - [Senshu Jerseys](https://github.com/johnmorrisdotca/senshu-jerseys) (選手): sports jerseys, sweaters, kits, caps, helmets and retired-number banners as SVG, front and back, with optional 2.5D turning. [Demo](https://johnmorrisdotca.github.io/senshu-jerseys/).
285
+ - [Taisen Brackets](https://github.com/johnmorrisdotca/taisen-brackets) (対戦): a sport-agnostic tournament bracket, drawn as SVG, from a list of ties. [Demo](https://johnmorrisdotca.github.io/taisen-brackets/).
286
+
287
+ **Developer tools**
288
+
289
+ - [REST in Pieces](https://github.com/spxis/rest-in-pieces) (レスト・イン・ピーシーズ): seeded test data and REST APIs for frontend development, with latency and error drills. [Demo](https://spxis.github.io/rest-in-pieces/).
290
+
291
+
292
+ **This package is Chikyu Earth.** The demos of all thirty-three share one header and footer, so each links the rest.
293
+ <!-- family:end -->
294
+
150
295
  ## The rest
151
296
 
152
297
  [CONTRIBUTING.md](CONTRIBUTING.md) · [docs/](docs/index.md) · [NOTICE.md](NOTICE.md) ·
@@ -1,3 +1,14 @@
1
1
  import type { FeatureCollection, Geometry } from "geojson";
2
2
  import type { CountryProps } from "./types.ts";
3
+ /**
4
+ * Every country the globe draws, as GeoJSON in longitude and latitude (177 features, Antarctica included), each with its English name, its Japanese name and its two-letter code.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { COUNTRIES } from "@johnmorrisdotca/chikyu-earth";
9
+ *
10
+ * const japan = COUNTRIES.features.find((feature) => feature.properties.alpha2 === "JP");
11
+ * console.log(japan?.properties.name, japan?.properties.ja, COUNTRIES.features.length);
12
+ * ```
13
+ */
3
14
  export declare const COUNTRIES: FeatureCollection<Geometry, CountryProps>;
package/dist/countries.js CHANGED
@@ -1,6 +1,17 @@
1
1
  // The country outlines: chizu's world-geo (Natural Earth 1:110m, WGS84 longitude and latitude) shaped for the globe.
2
2
  // Names are chizu's own English and Japanese; the alpha-2 code is its two-letter code, null for the three places with none.
3
3
  import WORLD_GEO from "@johnmorrisdotca/chizu/world-geo";
4
+ /**
5
+ * Every country the globe draws, as GeoJSON in longitude and latitude (177 features, Antarctica included), each with its English name, its Japanese name and its two-letter code.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { COUNTRIES } from "@johnmorrisdotca/chikyu-earth";
10
+ *
11
+ * const japan = COUNTRIES.features.find((feature) => feature.properties.alpha2 === "JP");
12
+ * console.log(japan?.properties.name, japan?.properties.ja, COUNTRIES.features.length);
13
+ * ```
14
+ */
4
15
  export const COUNTRIES = {
5
16
  type: "FeatureCollection",
6
17
  features: WORLD_GEO.features.map((feature) => ({
package/dist/element.d.ts CHANGED
@@ -1,5 +1,18 @@
1
1
  import type { OverlayHost } from "./markers/layer.ts";
2
2
  import type { GeoPoint, GlobeView } from "./types.ts";
3
+ /**
4
+ * The `<chikyu-earth>` custom element: the line globe, drawn as SVG in its shadow root. Importing this entry point registers the tag once. It takes the attributes `size` (pixels, 320 by default), `center` (`"lon,lat"`; wins over the browser's location), `look` (`line` or `thick`; `style` is the older name for it, and a framework that reads `style` as CSS cannot use it) and `graticule`, and a shared view controller's camera through `setView`.
5
+ *
6
+ * @example
7
+ * ```ts no-run
8
+ * import type { ChikyuEarth } from "@johnmorrisdotca/chikyu-earth/element";
9
+ *
10
+ * const earth = document.createElement("chikyu-earth") as ChikyuEarth;
11
+ * earth.setAttribute("center", "139.7,35.7");
12
+ * earth.setAttribute("look", "thick");
13
+ * document.body.append(earth);
14
+ * ```
15
+ */
3
16
  export declare class ChikyuEarth extends HTMLElement {
4
17
  #private;
5
18
  static observedAttributes: string[];
@@ -15,3 +28,8 @@ export declare class ChikyuEarth extends HTMLElement {
15
28
  */
16
29
  setView(view: GlobeView, final?: boolean): void;
17
30
  }
31
+ declare global {
32
+ interface HTMLElementTagNameMap {
33
+ "chikyu-earth": ChikyuEarth;
34
+ }
35
+ }
package/dist/element.js CHANGED
@@ -13,8 +13,21 @@ const readCentre = (value) => {
13
13
  return null;
14
14
  return { lon, lat };
15
15
  };
16
+ /**
17
+ * The `<chikyu-earth>` custom element: the line globe, drawn as SVG in its shadow root. Importing this entry point registers the tag once. It takes the attributes `size` (pixels, 320 by default), `center` (`"lon,lat"`; wins over the browser's location), `look` (`line` or `thick`; `style` is the older name for it, and a framework that reads `style` as CSS cannot use it) and `graticule`, and a shared view controller's camera through `setView`.
18
+ *
19
+ * @example
20
+ * ```ts no-run
21
+ * import type { ChikyuEarth } from "@johnmorrisdotca/chikyu-earth/element";
22
+ *
23
+ * const earth = document.createElement("chikyu-earth") as ChikyuEarth;
24
+ * earth.setAttribute("center", "139.7,35.7");
25
+ * earth.setAttribute("look", "thick");
26
+ * document.body.append(earth);
27
+ * ```
28
+ */
16
29
  export class ChikyuEarth extends HTMLElement {
17
- static observedAttributes = ["center", "style", "size", "graticule"];
30
+ static observedAttributes = ["center", "look", "style", "size", "graticule"];
18
31
  #centre = { lon: 0, lat: 0 };
19
32
  #view = { ...HOME_VIEW };
20
33
  #drawn = { ...HOME_VIEW };
@@ -113,7 +126,7 @@ export class ChikyuEarth extends HTMLElement {
113
126
  }
114
127
  #render() {
115
128
  const size = Number(this.getAttribute("size")) || 320;
116
- const style = cleanStyle(this.getAttribute("style"));
129
+ const style = cleanStyle(this.getAttribute("look") ?? this.getAttribute("style"));
117
130
  const svg = globe({ size, style, centre: this.#centre, view: this.#view, graticule: this.hasAttribute("graticule") });
118
131
  const root = this.#ensureShell();
119
132
  root.querySelector(".holder").innerHTML = svg;
package/dist/globe.d.ts CHANGED
@@ -1,3 +1,17 @@
1
1
  import type { GlobeOptions } from "./types.ts";
2
- /** The globe as an SVG string, turned to `rotation` and drawn in `style`, `size` pixels square. */
2
+ /**
3
+ * The globe as an SVG string, turned to `rotation` and drawn in `style`, `size` pixels square. It is pure: the same options always give the same markup, so it runs on a server, in a test or in a build step with no DOM.
4
+ *
5
+ * @param options - Size, turn, look and graticule; every one has a default, so `globe()` draws a 320-pixel globe facing the Greenwich meridian.
6
+ * @returns One `<svg>` element as text, with the country outlines as paths.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { globe } from "@johnmorrisdotca/chikyu-earth";
11
+ *
12
+ * const svg = globe({ size: 240, rotation: [-139.7, -35.7], style: "line" });
13
+ * console.log(svg.slice(0, 60));
14
+ * console.log(svg.length > 10_000);
15
+ * ```
16
+ */
3
17
  export declare function globe(options?: GlobeOptions): string;
package/dist/globe.js CHANGED
@@ -5,7 +5,21 @@ import { COUNTRIES } from "./countries.js";
5
5
  import { cleanStyle, STYLES } from "./styles.js";
6
6
  import { projectionView } from "./view.js";
7
7
  const SPHERE = { type: "Sphere" };
8
- /** The globe as an SVG string, turned to `rotation` and drawn in `style`, `size` pixels square. */
8
+ /**
9
+ * The globe as an SVG string, turned to `rotation` and drawn in `style`, `size` pixels square. It is pure: the same options always give the same markup, so it runs on a server, in a test or in a build step with no DOM.
10
+ *
11
+ * @param options - Size, turn, look and graticule; every one has a default, so `globe()` draws a 320-pixel globe facing the Greenwich meridian.
12
+ * @returns One `<svg>` element as text, with the country outlines as paths.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { globe } from "@johnmorrisdotca/chikyu-earth";
17
+ *
18
+ * const svg = globe({ size: 240, rotation: [-139.7, -35.7], style: "line" });
19
+ * console.log(svg.slice(0, 60));
20
+ * console.log(svg.length > 10_000);
21
+ * ```
22
+ */
9
23
  export function globe(options = {}) {
10
24
  const size = options.size ?? 320;
11
25
  const style = STYLES[cleanStyle(options.style)];
package/dist/index.d.ts CHANGED
@@ -5,5 +5,16 @@ export { centreRotation, DEGREES_PER_MS, rotationAt, SIDEREAL_DAY_MS, spinAt } f
5
5
  export { globeBaseScale, HOME_VIEW, projectionView, type ProjectionView } from "./view.ts";
6
6
  export type { CountryProps, GeoPoint, GlobeOptions, GlobeView, Rotation } from "./types.ts";
7
7
  import type { CountryProps } from "./types.ts";
8
- /** Every country the globe draws, with its kuni name and code. */
8
+ /**
9
+ * Every country the globe draws, with its kuni name and code.
10
+ *
11
+ * @returns A list of English name, Japanese name (or `null`) and two-letter code (or `null` where a place has none).
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { countryList } from "@johnmorrisdotca/chikyu-earth";
16
+ *
17
+ * console.log(countryList().find((country) => country.alpha2 === "JP"));
18
+ * ```
19
+ */
9
20
  export declare const countryList: () => CountryProps[];
package/dist/index.js CHANGED
@@ -4,5 +4,16 @@ export { cleanStyle, DEFAULT_STYLE, STYLE_NAMES, STYLES } from "./styles.js";
4
4
  export { centreRotation, DEGREES_PER_MS, rotationAt, SIDEREAL_DAY_MS, spinAt } from "./rotate.js";
5
5
  export { globeBaseScale, HOME_VIEW, projectionView } from "./view.js";
6
6
  import { COUNTRIES } from "./countries.js";
7
- /** Every country the globe draws, with its kuni name and code. */
7
+ /**
8
+ * Every country the globe draws, with its kuni name and code.
9
+ *
10
+ * @returns A list of English name, Japanese name (or `null`) and two-letter code (or `null` where a place has none).
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * import { countryList } from "@johnmorrisdotca/chikyu-earth";
15
+ *
16
+ * console.log(countryList().find((country) => country.alpha2 === "JP"));
17
+ * ```
18
+ */
8
19
  export const countryList = () => COUNTRIES.features.map((f) => f.properties);
@@ -1,3 +1,14 @@
1
+ /**
2
+ * Several points gathered into one on the screen: where it is drawn and which points are in it.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { clusterPoints, type Cluster } from "@johnmorrisdotca/chikyu-earth/markers";
7
+ *
8
+ * const clusters: Cluster[] = clusterPoints([0, 1], 2, [10, 12], [10, 11], 28);
9
+ * console.log(clusters[0]?.members);
10
+ * ```
11
+ */
1
12
  export interface Cluster {
2
13
  x: number;
3
14
  y: number;
@@ -7,5 +18,21 @@ export interface Cluster {
7
18
  /**
8
19
  * Group the points `indices` (into `xs` and `ys`) by the grid cell they fall in. A cell with one point is that point alone; with more it is one cluster at their
9
20
  * average. Order is stable: clusters come in the order their first member was seen.
21
+ *
22
+ * @param indices - Which points to group: indices into `xs` and `ys`.
23
+ * @param count - How many of `indices` to read.
24
+ * @param xs - Every point's x on the screen, in pixels.
25
+ * @param ys - Every point's y on the screen, in pixels.
26
+ * @param cell - The side of a grid cell in pixels; points in one cell join.
27
+ * @returns The clusters, each with the indices of its members; a lone point is a cluster of one.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * import { clusterPoints } from "@johnmorrisdotca/chikyu-earth/markers";
32
+ *
33
+ * const xs = [10, 14, 200];
34
+ * const ys = [10, 12, 200];
35
+ * console.log(clusterPoints([0, 1, 2], 3, xs, ys, 28).map((cluster) => cluster.members));
36
+ * ```
10
37
  */
11
38
  export declare function clusterPoints(indices: ArrayLike<number>, count: number, xs: ArrayLike<number>, ys: ArrayLike<number>, cell: number): Cluster[];
@@ -2,6 +2,22 @@
2
2
  /**
3
3
  * Group the points `indices` (into `xs` and `ys`) by the grid cell they fall in. A cell with one point is that point alone; with more it is one cluster at their
4
4
  * average. Order is stable: clusters come in the order their first member was seen.
5
+ *
6
+ * @param indices - Which points to group: indices into `xs` and `ys`.
7
+ * @param count - How many of `indices` to read.
8
+ * @param xs - Every point's x on the screen, in pixels.
9
+ * @param ys - Every point's y on the screen, in pixels.
10
+ * @param cell - The side of a grid cell in pixels; points in one cell join.
11
+ * @returns The clusters, each with the indices of its members; a lone point is a cluster of one.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { clusterPoints } from "@johnmorrisdotca/chikyu-earth/markers";
16
+ *
17
+ * const xs = [10, 14, 200];
18
+ * const ys = [10, 12, 200];
19
+ * console.log(clusterPoints([0, 1, 2], 3, xs, ys, 28).map((cluster) => cluster.members));
20
+ * ```
5
21
  */
6
22
  export function clusterPoints(indices, count, xs, ys, cell) {
7
23
  const cells = new Map();
@@ -1,3 +1,14 @@
1
+ /**
2
+ * One label to place: its dot's centre and radius, its box's size and its priority.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import type { LabelItem } from "@johnmorrisdotca/chikyu-earth/markers";
7
+ *
8
+ * const label: LabelItem = { x: 100, y: 100, r: 4, w: 60, h: 20, priority: 1 };
9
+ * console.log(label.w);
10
+ * ```
11
+ */
1
12
  export interface LabelItem {
2
13
  /** The dot's centre and radius. */
3
14
  x: number;
@@ -9,6 +20,17 @@ export interface LabelItem {
9
20
  /** Higher is placed first. */
10
21
  priority: number;
11
22
  }
23
+ /**
24
+ * Where one label goes: which item it is and its box's top-left corner.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * import { placeLabels, type Placement } from "@johnmorrisdotca/chikyu-earth/markers";
29
+ *
30
+ * const placed: Placement[] = placeLabels([{ x: 100, y: 100, r: 4, w: 60, h: 20, priority: 1 }], 300, 300, 10);
31
+ * console.log(placed[0]);
32
+ * ```
33
+ */
12
34
  export interface Placement {
13
35
  /** Index into the items given. */
14
36
  item: number;
@@ -20,5 +42,23 @@ export interface Placement {
20
42
  * Place up to `max` labels inside `width` x `height`. Each label is tried to the right of its dot, then to the left, above and below; the first spot that is inside
21
43
  * and free of the labels already placed wins. Items are taken highest priority first (a tie keeps the order given). The cost is the number of items times at most
22
44
  * four tries against a grid of what is placed.
45
+ *
46
+ * @param items - The dots and the size of each one's label.
47
+ * @param width - The width of the area the labels must stay inside, in pixels.
48
+ * @param height - The height of that area, in pixels.
49
+ * @param max - The most labels to place.
50
+ * @param cell - The side of the grid cell used to find overlaps, in pixels.
51
+ * @returns A placement for each label that fits; the others are left out.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * import { placeLabels } from "@johnmorrisdotca/chikyu-earth/markers";
56
+ *
57
+ * const items = [
58
+ * { x: 100, y: 100, r: 4, w: 60, h: 20, priority: 1 },
59
+ * { x: 110, y: 104, r: 4, w: 60, h: 20, priority: 9 },
60
+ * ];
61
+ * console.log(placeLabels(items, 300, 300, 10).map((place) => place.item));
62
+ * ```
23
63
  */
24
64
  export declare function placeLabels(items: readonly LabelItem[], width: number, height: number, max: number, cell?: number): Placement[];