@johnmorrisdotca/uchusen-rockets 0.3.0 → 0.4.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 (60) hide show
  1. package/CHANGELOG.md +16 -5
  2. package/README.md +241 -4
  3. package/dist/attrs.d.ts +70 -4
  4. package/dist/attrs.js +59 -4
  5. package/dist/build/glb.d.ts +25 -0
  6. package/dist/build/glb.js +14 -0
  7. package/dist/build/index.d.ts +89 -4
  8. package/dist/build/index.js +55 -4
  9. package/dist/build/lineup.d.ts +56 -2
  10. package/dist/build/lineup.js +23 -2
  11. package/dist/builder.d.ts +47 -1
  12. package/dist/builder.js +14 -1
  13. package/dist/crossfade.d.ts +44 -2
  14. package/dist/crossfade.js +44 -2
  15. package/dist/data/credits.d.ts +44 -1
  16. package/dist/data/credits.js +22 -1
  17. package/dist/data/flight-log.d.ts +33 -1
  18. package/dist/data/flight-log.js +22 -1
  19. package/dist/data/flights.d.ts +54 -2
  20. package/dist/data/flights.js +10 -0
  21. package/dist/data/makers.d.ts +21 -0
  22. package/dist/data/makers.js +10 -0
  23. package/dist/data/sources.d.ts +32 -0
  24. package/dist/data/sources.js +10 -0
  25. package/dist/data/types.d.ts +81 -1
  26. package/dist/data/types.js +26 -1
  27. package/dist/element.d.ts +61 -3
  28. package/dist/element.js +50 -3
  29. package/dist/embed.d.ts +110 -5
  30. package/dist/embed.js +88 -5
  31. package/dist/engines.d.ts +86 -4
  32. package/dist/engines.js +75 -4
  33. package/dist/fit.d.ts +68 -0
  34. package/dist/fit.js +13 -0
  35. package/dist/flight.d.ts +134 -9
  36. package/dist/flight.js +122 -9
  37. package/dist/flightbar.d.ts +12 -0
  38. package/dist/flightbar.js +12 -0
  39. package/dist/framing.d.ts +182 -8
  40. package/dist/framing.js +127 -6
  41. package/dist/layout.d.ts +65 -1
  42. package/dist/layout.js +43 -1
  43. package/dist/looks.d.ts +64 -1
  44. package/dist/looks.js +42 -1
  45. package/dist/model/materials.d.ts +32 -0
  46. package/dist/model/materials.js +10 -0
  47. package/dist/model/registry.d.ts +22 -0
  48. package/dist/model/registry.js +22 -0
  49. package/dist/parts.d.ts +33 -1
  50. package/dist/pixels.d.ts +44 -4
  51. package/dist/pixels.js +44 -4
  52. package/dist/react.d.ts +24 -0
  53. package/dist/react.js +13 -0
  54. package/dist/rockets.d.ts +91 -3
  55. package/dist/rockets.js +58 -2
  56. package/dist/spin.d.ts +57 -2
  57. package/dist/spin.js +35 -2
  58. package/dist/tilt.d.ts +48 -4
  59. package/dist/tilt.js +26 -4
  60. package/package.json +10 -5
package/dist/pixels.js CHANGED
@@ -1,11 +1,51 @@
1
1
  // How sharp the 3D canvas may be. The backing store is width x height x ratio squared, and a view as big as a 5K screen at a ratio of 2 would ask the graphics card for 15 million pixels, every frame. Pure.
2
- /** The most the backing store may hold, in pixels (a 620 x 827 view at a ratio of 2 is 2 million). */
2
+ /**
3
+ * The most the backing store may hold, in pixels (a 620 x 827 view at a ratio of 2 is 2 million).
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * import { MAX_PIXELS } from "@johnmorrisdotca/uchusen-rockets";
8
+ *
9
+ * console.log(MAX_PIXELS);
10
+ * ```
11
+ */
3
12
  export const MAX_PIXELS = 6_000_000;
4
- /** The longest side the backing store may have. */
13
+ /**
14
+ * The longest side the backing store may have.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { MAX_SIDE } from "@johnmorrisdotca/uchusen-rockets";
19
+ *
20
+ * console.log(MAX_SIDE);
21
+ * ```
22
+ */
5
23
  export const MAX_SIDE = 4096;
6
- /** The sharpest ratio ever used, however dense the screen. */
24
+ /**
25
+ * The sharpest ratio ever used, however dense the screen.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * import { MAX_RATIO } from "@johnmorrisdotca/uchusen-rockets";
30
+ *
31
+ * console.log(MAX_RATIO);
32
+ * ```
33
+ */
7
34
  export const MAX_RATIO = 2;
8
- /** The device pixel ratio to draw a `width` x `height` view at: the screen's own, held to 2, to 4096 pixels a side and to 6 million in all. At least 0.25, and 1 for a nonsense value. */
35
+ /**
36
+ * The device pixel ratio to draw a `width` x `height` view at: the screen's own, held to 2, to 4096 pixels a side and to 6 million in all. At least 0.25, and 1 for a nonsense value.
37
+ *
38
+ * @param width The view's width in CSS pixels.
39
+ * @param height Its height in CSS pixels.
40
+ * @param deviceRatio The screen's own pixel ratio.
41
+ * @returns The ratio to draw at.
42
+ * @example
43
+ * ```ts
44
+ * import { pixelRatioFor } from "@johnmorrisdotca/uchusen-rockets";
45
+ *
46
+ * console.log(pixelRatioFor(620, 827, 3), pixelRatioFor(3000, 3000, 2));
47
+ * ```
48
+ */
9
49
  export function pixelRatioFor(width, height, deviceRatio) {
10
50
  const w = Math.max(1, width);
11
51
  const h = Math.max(1, height);
package/dist/react.d.ts CHANGED
@@ -2,6 +2,17 @@ import { type HTMLAttributes, type Ref } from "react";
2
2
  import type { Description } from "./fit.ts";
3
3
  import type { ViewName } from "./framing.ts";
4
4
  import type { LookName } from "./looks.ts";
5
+ /**
6
+ * The props of the React wrapper: the element's attributes as props (`rocket`, `variant`, `show`, `look`, `view`, `mode`, `assets`, `spin`, `way`, `label`, `engines`, `phase`), `build` as an object, and any other HTML attribute.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import type { UchusenRocketProps } from "@johnmorrisdotca/uchusen-rockets/react";
11
+ *
12
+ * const props: UchusenRocketProps = { rocket: "starship", variant: "v3", look: "thick" };
13
+ * console.log(props);
14
+ * ```
15
+ */
5
16
  export interface UchusenRocketProps extends Omit<HTMLAttributes<HTMLElement>, "style"> {
6
17
  rocket?: string;
7
18
  variant?: string;
@@ -22,6 +33,19 @@ export interface UchusenRocketProps extends Omit<HTMLAttributes<HTMLElement>, "s
22
33
  phase?: string;
23
34
  ref?: Ref<HTMLElement>;
24
35
  }
36
+ /**
37
+ * A thin React wrapper round `<uchusen-rocket>`. It loads the element on first use, so server rendering draws only the tag.
38
+ *
39
+ * @param props The props. `build` is turned into the element's JSON attribute; the rest go through as they are.
40
+ * @returns The `<uchusen-rocket>` element. It is never null or undefined.
41
+ * @example
42
+ * ```tsx no-run
43
+ * import { UchusenRocket } from "@johnmorrisdotca/uchusen-rockets/react";
44
+ *
45
+ * export const Hero = () => <UchusenRocket rocket="falcon-9" variant="block-5" look="painted" />;
46
+ * console.log(typeof UchusenRocket);
47
+ * ```
48
+ */
25
49
  export declare function UchusenRocket({ build, ...rest }: UchusenRocketProps): import("react").DOMElement<{
26
50
  build: string | undefined;
27
51
  rocket?: string;
package/dist/react.js CHANGED
@@ -1,5 +1,18 @@
1
1
  // A thin React wrapper round `<uchusen-rocket>`.
2
2
  import { createElement, useEffect } from "react";
3
+ /**
4
+ * A thin React wrapper round `<uchusen-rocket>`. It loads the element on first use, so server rendering draws only the tag.
5
+ *
6
+ * @param props The props. `build` is turned into the element's JSON attribute; the rest go through as they are.
7
+ * @returns The `<uchusen-rocket>` element. It is never null or undefined.
8
+ * @example
9
+ * ```tsx no-run
10
+ * import { UchusenRocket } from "@johnmorrisdotca/uchusen-rockets/react";
11
+ *
12
+ * export const Hero = () => <UchusenRocket rocket="falcon-9" variant="block-5" look="painted" />;
13
+ * console.log(typeof UchusenRocket);
14
+ * ```
15
+ */
3
16
  export function UchusenRocket({ build, ...rest }) {
4
17
  useEffect(() => {
5
18
  void import("./element.js");
package/dist/rockets.d.ts CHANGED
@@ -1,7 +1,29 @@
1
1
  import { type MakerId } from "./data/makers.ts";
2
2
  import type { Figure, Variant } from "./data/types.ts";
3
3
  import type { SourceId } from "./data/sources.ts";
4
+ /**
5
+ * Whether a rocket is `built` (it has a shape) or `planned` (it has facts and no shape yet).
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { ROCKETS, type RocketStatus } from "@johnmorrisdotca/uchusen-rockets";
10
+ *
11
+ * const status: RocketStatus | undefined = ROCKETS["starship"]?.status;
12
+ * console.log(status);
13
+ * ```
14
+ */
4
15
  export type RocketStatus = "built" | "planned";
16
+ /**
17
+ * One rocket: its id and name, its variants, its default variant, the group it is listed under and who made it.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * import { ROCKETS, type RocketEntry } from "@johnmorrisdotca/uchusen-rockets";
22
+ *
23
+ * const starship: RocketEntry | undefined = ROCKETS["starship"];
24
+ * console.log(starship?.name, starship?.variants.map((variant) => variant.id));
25
+ * ```
26
+ */
5
27
  export interface RocketEntry {
6
28
  id: string;
7
29
  name: string;
@@ -13,7 +35,17 @@ export interface RocketEntry {
13
35
  /** Whose it is and who built it, as its source says, or a blank. */
14
36
  madeBy: Figure<string>;
15
37
  }
16
- /** A rocket on the list with no mesh yet: its name and the sourced facts to build it from. */
38
+ /**
39
+ * A rocket on the list with no mesh yet: its name and the sourced facts to build it from.
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * import { PLANNED_ROCKETS, type PlannedRocket } from "@johnmorrisdotca/uchusen-rockets";
44
+ *
45
+ * const planned: PlannedRocket | undefined = PLANNED_ROCKETS[0];
46
+ * console.log(planned?.name);
47
+ * ```
48
+ */
17
49
  export interface PlannedRocket {
18
50
  id: string;
19
51
  name: string;
@@ -23,10 +55,66 @@ export interface PlannedRocket {
23
55
  firstFlight: Figure<string>;
24
56
  source: SourceId;
25
57
  }
58
+ /**
59
+ * Every rocket that has a shape, by id, each with its variants. Add a rocket here and the element, the drawing, the fit check and the demo all read it.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * import { ROCKETS } from "@johnmorrisdotca/uchusen-rockets";
64
+ *
65
+ * console.log(Object.keys(ROCKETS).slice(0, 6));
66
+ * ```
67
+ */
26
68
  export declare const ROCKETS: Readonly<Record<string, RocketEntry>>;
69
+ /**
70
+ * Rockets with sourced facts and no shape yet.
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * import { PLANNED_ROCKETS } from "@johnmorrisdotca/uchusen-rockets";
75
+ *
76
+ * console.log(PLANNED_ROCKETS.map((rocket) => rocket.name));
77
+ * ```
78
+ */
27
79
  export declare const PLANNED_ROCKETS: readonly PlannedRocket[];
80
+ /**
81
+ * Finds a rocket's variant, with its sourced sizes.
82
+ *
83
+ * @param rocket A rocket's id.
84
+ * @param id A variant's id. Left out, null or undefined: the rocket's default variant.
85
+ * @returns The variant, or undefined when the rocket or the variant is not known.
86
+ * @example
87
+ * ```ts
88
+ * import { variantOf } from "@johnmorrisdotca/uchusen-rockets";
89
+ *
90
+ * const v3 = variantOf("starship", "v3");
91
+ * console.log(v3?.facts.height.value, variantOf("starship", "v99"));
92
+ * ```
93
+ */
28
94
  export declare function variantOf(rocket: string, id?: string | null): Variant | undefined;
29
- /** A part's name for a rocket's slot in a variant. */
95
+ /**
96
+ * A part's name for a rocket's slot in a variant.
97
+ *
98
+ * @param rocket A rocket's id.
99
+ * @param variant A variant's id.
100
+ * @param slot A slot name.
101
+ * @returns The id of the part that stands in that slot.
102
+ * @example
103
+ * ```ts
104
+ * import { partIdOf } from "@johnmorrisdotca/uchusen-rockets";
105
+ *
106
+ * console.log(partIdOf("starship", "v3", "booster"));
107
+ * ```
108
+ */
30
109
  export declare const partIdOf: (rocket: string, variant: string, slot: string) => string;
31
- /** What to call a slot. */
110
+ /**
111
+ * What to call a slot.
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * import { SLOT_NAMES } from "@johnmorrisdotca/uchusen-rockets";
116
+ *
117
+ * console.log(SLOT_NAMES["booster"]);
118
+ * ```
119
+ */
32
120
  export declare const SLOT_NAMES: Readonly<Record<string, string>>;
package/dist/rockets.js CHANGED
@@ -21,6 +21,16 @@ import { ISS_VARIANTS } from "./data/iss.js";
21
21
  import { HUBBLE_VARIANTS } from "./data/hubble.js";
22
22
  import { STARSHIP_VARIANTS } from "./data/starship.js";
23
23
  import { MADE_BY } from "./data/makers.js";
24
+ /**
25
+ * Every rocket that has a shape, by id, each with its variants. Add a rocket here and the element, the drawing, the fit check and the demo all read it.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * import { ROCKETS } from "@johnmorrisdotca/uchusen-rockets";
30
+ *
31
+ * console.log(Object.keys(ROCKETS).slice(0, 6));
32
+ * ```
33
+ */
24
34
  export const ROCKETS = {
25
35
  starship: { id: "starship", name: "Starship", status: "built", ...MADE_BY["starship"], variants: STARSHIP_VARIANTS, defaultVariant: "v3" },
26
36
  "falcon-9": { id: "falcon-9", name: "Falcon 9", status: "built", ...MADE_BY["falcon-9"], variants: FALCON_9_VARIANTS, defaultVariant: "block-5" },
@@ -47,17 +57,63 @@ export const ROCKETS = {
47
57
  starbase: { id: "starbase", name: "Starbase", status: "built", ...MADE_BY["starbase"], variants: STARBASE_VARIANTS, defaultVariant: "launch-site" },
48
58
  };
49
59
  const fig = (value, source) => ({ value, source });
60
+ /**
61
+ * Rockets with sourced facts and no shape yet.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * import { PLANNED_ROCKETS } from "@johnmorrisdotca/uchusen-rockets";
66
+ *
67
+ * console.log(PLANNED_ROCKETS.map((rocket) => rocket.name));
68
+ * ```
69
+ */
50
70
  export const PLANNED_ROCKETS = [
51
71
  { id: "vulcan-centaur", name: "Vulcan Centaur", status: "planned", height: fig(61.6, "wikipedia-vulcan"), diameter: fig(5.4, "wikipedia-vulcan"), firstFlight: { value: "2024-01-08", source: "wikipedia-vulcan" }, source: "wikipedia-vulcan" },
52
72
  { id: "ariane-6", name: "Ariane 6", status: "planned", height: fig(63, "wikipedia-ariane-6"), diameter: fig(5.4, "wikipedia-ariane-6"), firstFlight: { value: "2024-07-09", source: "wikipedia-ariane-6" }, source: "wikipedia-ariane-6" },
53
73
  ];
74
+ /**
75
+ * Finds a rocket's variant, with its sourced sizes.
76
+ *
77
+ * @param rocket A rocket's id.
78
+ * @param id A variant's id. Left out, null or undefined: the rocket's default variant.
79
+ * @returns The variant, or undefined when the rocket or the variant is not known.
80
+ * @example
81
+ * ```ts
82
+ * import { variantOf } from "@johnmorrisdotca/uchusen-rockets";
83
+ *
84
+ * const v3 = variantOf("starship", "v3");
85
+ * console.log(v3?.facts.height.value, variantOf("starship", "v99"));
86
+ * ```
87
+ */
54
88
  export function variantOf(rocket, id) {
55
89
  const entry = Object.hasOwn(ROCKETS, rocket) ? ROCKETS[rocket] : undefined;
56
90
  return entry?.variants.find((variant) => variant.id === (id ?? entry.defaultVariant));
57
91
  }
58
- /** A part's name for a rocket's slot in a variant. */
92
+ /**
93
+ * A part's name for a rocket's slot in a variant.
94
+ *
95
+ * @param rocket A rocket's id.
96
+ * @param variant A variant's id.
97
+ * @param slot A slot name.
98
+ * @returns The id of the part that stands in that slot.
99
+ * @example
100
+ * ```ts
101
+ * import { partIdOf } from "@johnmorrisdotca/uchusen-rockets";
102
+ *
103
+ * console.log(partIdOf("starship", "v3", "booster"));
104
+ * ```
105
+ */
59
106
  export const partIdOf = (rocket, variant, slot) => variantOf(rocket, variant)?.partIds?.[slot] ?? `${rocket}-${variant}-${slot}`;
60
- /** What to call a slot. */
107
+ /**
108
+ * What to call a slot.
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * import { SLOT_NAMES } from "@johnmorrisdotca/uchusen-rockets";
113
+ *
114
+ * console.log(SLOT_NAMES["booster"]);
115
+ * ```
116
+ */
61
117
  export const SLOT_NAMES = {
62
118
  booster: "Super Heavy",
63
119
  ship: "Ship",
package/dist/spin.d.ts CHANGED
@@ -1,11 +1,66 @@
1
+ /**
2
+ * Which way a rocket turns: `cw` (clockwise) or `ccw` (counter-clockwise).
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import type { Way } from "@johnmorrisdotca/uchusen-rockets";
7
+ *
8
+ * const way: Way = "ccw";
9
+ * console.log(way);
10
+ * ```
11
+ */
1
12
  export type Way = "cw" | "ccw";
13
+ /**
14
+ * The slow turn of a rocket: the seconds a full turn takes (0 is none) and which way.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { DEFAULT_SPIN, type Spin } from "@johnmorrisdotca/uchusen-rockets";
19
+ *
20
+ * const spin: Spin = DEFAULT_SPIN;
21
+ * console.log(spin.seconds, spin.way);
22
+ * ```
23
+ */
2
24
  export interface Spin {
3
25
  /** Seconds a turn, 0 for not at all. */
4
26
  seconds: number;
5
27
  way: Way;
6
28
  }
29
+ /**
30
+ * The spin used when none is asked for: 180 seconds a turn, clockwise.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * import { DEFAULT_SPIN } from "@johnmorrisdotca/uchusen-rockets";
35
+ *
36
+ * console.log(DEFAULT_SPIN);
37
+ * ```
38
+ */
7
39
  export declare const DEFAULT_SPIN: Spin;
8
- /** Anything but `ccw` is the default way. */
40
+ /**
41
+ * Anything but `ccw` is the default way.
42
+ *
43
+ * @param value Anything.
44
+ * @returns `ccw` for `ccw`, and `cw` for anything else.
45
+ * @example
46
+ * ```ts
47
+ * import { cleanWay } from "@johnmorrisdotca/uchusen-rockets";
48
+ *
49
+ * console.log(cleanWay("ccw"), cleanWay("left"));
50
+ * ```
51
+ */
9
52
  export declare const cleanWay: (value: unknown) => Way;
10
- /** A spin from the `spin` and `way` attributes: a name, or seconds a turn. A nonsense value is the default, and a negative one is none. */
53
+ /**
54
+ * A spin from the `spin` and `way` attributes: a name, or seconds a turn. A nonsense value is the default, and a negative one is none.
55
+ *
56
+ * @param spin The `spin` attribute: `off`, `slow`, `medium`, `fast`, or seconds a turn. Null when missing.
57
+ * @param way The `way` attribute. Null when missing.
58
+ * @returns The spin to use.
59
+ * @example
60
+ * ```ts
61
+ * import { spinOf } from "@johnmorrisdotca/uchusen-rockets";
62
+ *
63
+ * console.log(spinOf("fast", null), spinOf("30", "ccw"), spinOf("nonsense", null));
64
+ * ```
65
+ */
11
66
  export declare function spinOf(spin: string | null, way: string | null): Spin;
package/dist/spin.js CHANGED
@@ -1,9 +1,42 @@
1
1
  // How a view turns by itself. `way` is which way round: `cw`, clockwise seen from above, takes the near side to the viewer's left, and `ccw` to the right. Pure.
2
2
  const NAMED = { off: 0, slow: 180, medium: 67, fast: 20 };
3
+ /**
4
+ * The spin used when none is asked for: 180 seconds a turn, clockwise.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { DEFAULT_SPIN } from "@johnmorrisdotca/uchusen-rockets";
9
+ *
10
+ * console.log(DEFAULT_SPIN);
11
+ * ```
12
+ */
3
13
  export const DEFAULT_SPIN = { seconds: 180, way: "cw" };
4
- /** Anything but `ccw` is the default way. */
14
+ /**
15
+ * Anything but `ccw` is the default way.
16
+ *
17
+ * @param value Anything.
18
+ * @returns `ccw` for `ccw`, and `cw` for anything else.
19
+ * @example
20
+ * ```ts
21
+ * import { cleanWay } from "@johnmorrisdotca/uchusen-rockets";
22
+ *
23
+ * console.log(cleanWay("ccw"), cleanWay("left"));
24
+ * ```
25
+ */
5
26
  export const cleanWay = (value) => (value === "ccw" ? "ccw" : "cw");
6
- /** A spin from the `spin` and `way` attributes: a name, or seconds a turn. A nonsense value is the default, and a negative one is none. */
27
+ /**
28
+ * A spin from the `spin` and `way` attributes: a name, or seconds a turn. A nonsense value is the default, and a negative one is none.
29
+ *
30
+ * @param spin The `spin` attribute: `off`, `slow`, `medium`, `fast`, or seconds a turn. Null when missing.
31
+ * @param way The `way` attribute. Null when missing.
32
+ * @returns The spin to use.
33
+ * @example
34
+ * ```ts
35
+ * import { spinOf } from "@johnmorrisdotca/uchusen-rockets";
36
+ *
37
+ * console.log(spinOf("fast", null), spinOf("30", "ccw"), spinOf("nonsense", null));
38
+ * ```
39
+ */
7
40
  export function spinOf(spin, way) {
8
41
  const raw = spin === null ? NaN : Object.hasOwn(NAMED, spin) ? NAMED[spin] : Number(spin);
9
42
  const seconds = spin === null || spin.trim() === "" || !Number.isFinite(raw) ? DEFAULT_SPIN.seconds : Math.max(0, raw);
package/dist/tilt.d.ts CHANGED
@@ -1,20 +1,64 @@
1
+ /**
2
+ * Whether tilting a device turns the view: `off`, `ask` (the browser must ask first, as on iOS) or `on`.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import type { TiltMode } from "@johnmorrisdotca/uchusen-rockets";
7
+ *
8
+ * const mode: TiltMode = "ask";
9
+ * console.log(mode);
10
+ * ```
11
+ */
1
12
  export type TiltMode = "off" | "ask" | "on";
2
- /** Off under reduced motion, on a computer with a mouse, or where the browser has no orientation events; "ask" where it must ask first (iOS: a tap
3
- * on "Tilt to turn" asks, never the page by itself); else on. */
13
+ /**
14
+ * Off under reduced motion, on a computer with a mouse, or where the browser has no orientation events; "ask" where it must ask first (iOS: a tap on "Tilt to turn" asks, never the page by itself); else on.
15
+ *
16
+ * @param env What the page knows: reduced motion, a coarse pointer (touch), whether the browser has orientation events, and whether it must ask permission first.
17
+ * @returns `off`, `ask` or `on`.
18
+ * @example
19
+ * ```ts
20
+ * import { tiltMode } from "@johnmorrisdotca/uchusen-rockets";
21
+ *
22
+ * console.log(tiltMode({ reducedMotion: false, coarsePointer: true, hasOrientation: true, needsPermission: true }));
23
+ * ```
24
+ */
4
25
  export declare function tiltMode(env: {
5
26
  reducedMotion: boolean;
6
27
  coarsePointer: boolean;
7
28
  hasOrientation: boolean;
8
29
  needsPermission: boolean;
9
30
  }): TiltMode;
31
+ /**
32
+ * One reading of a device's orientation: front to back (`beta`, -180 to 180 degrees) and left to right (`gamma`, -90 to 90 degrees). Either is null when the device gives none.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * import type { Reading } from "@johnmorrisdotca/uchusen-rockets";
37
+ *
38
+ * const reading: Reading = { beta: 20, gamma: -5 };
39
+ * console.log(reading);
40
+ * ```
41
+ */
10
42
  export interface Reading {
11
43
  /** Front to back, -180 to 180 degrees. */
12
44
  beta: number | null;
13
45
  /** Left to right, -90 to 90 degrees. */
14
46
  gamma: number | null;
15
47
  }
16
- /** The turn (degrees round, degrees up or down) for a reading, measured from `rest` (how the device was held when tilting began). `angle` is the
17
- * screen's orientation (0, 90, 180 or 270), so leaning a phone held sideways still turns the view the way it looks. Null for an empty reading. */
48
+ /**
49
+ * The turn (degrees round, degrees up or down) for a reading, measured from `rest` (how the device was held when tilting began). `angle` is the screen's orientation (0, 90, 180 or 270), so leaning a phone held sideways still turns the view the way it looks. Null for an empty reading.
50
+ *
51
+ * @param reading The current reading.
52
+ * @param rest The reading when tilting began.
53
+ * @param angle The screen's orientation: 0, 90, 180 or 270. Defaults to 0.
54
+ * @returns The turn in degrees round (`azimuth`) and up or down (`polar`), or null for an empty reading.
55
+ * @example
56
+ * ```ts
57
+ * import { tiltTurn } from "@johnmorrisdotca/uchusen-rockets";
58
+ *
59
+ * console.log(tiltTurn({ beta: 30, gamma: 10 }, { beta: 20, gamma: 0 }), tiltTurn({ beta: null, gamma: null }, { beta: 0, gamma: 0 }));
60
+ * ```
61
+ */
18
62
  export declare function tiltTurn(reading: Reading, rest: Reading, angle?: number): {
19
63
  azimuth: number;
20
64
  polar: number;
package/dist/tilt.js CHANGED
@@ -1,6 +1,16 @@
1
1
  // Tilt to turn: on a phone or tablet, leaning the device turns a 3D view a little. Pure: when it is offered, and how a reading becomes a turn of the view.
2
- /** Off under reduced motion, on a computer with a mouse, or where the browser has no orientation events; "ask" where it must ask first (iOS: a tap
3
- * on "Tilt to turn" asks, never the page by itself); else on. */
2
+ /**
3
+ * Off under reduced motion, on a computer with a mouse, or where the browser has no orientation events; "ask" where it must ask first (iOS: a tap on "Tilt to turn" asks, never the page by itself); else on.
4
+ *
5
+ * @param env What the page knows: reduced motion, a coarse pointer (touch), whether the browser has orientation events, and whether it must ask permission first.
6
+ * @returns `off`, `ask` or `on`.
7
+ * @example
8
+ * ```ts
9
+ * import { tiltMode } from "@johnmorrisdotca/uchusen-rockets";
10
+ *
11
+ * console.log(tiltMode({ reducedMotion: false, coarsePointer: true, hasOrientation: true, needsPermission: true }));
12
+ * ```
13
+ */
4
14
  export function tiltMode(env) {
5
15
  if (env.reducedMotion || !env.coarsePointer || !env.hasOrientation)
6
16
  return "off";
@@ -10,8 +20,20 @@ const GAIN = 0.6;
10
20
  const MAX_TURN = 25;
11
21
  const MAX_LEAN = 12;
12
22
  const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
13
- /** The turn (degrees round, degrees up or down) for a reading, measured from `rest` (how the device was held when tilting began). `angle` is the
14
- * screen's orientation (0, 90, 180 or 270), so leaning a phone held sideways still turns the view the way it looks. Null for an empty reading. */
23
+ /**
24
+ * The turn (degrees round, degrees up or down) for a reading, measured from `rest` (how the device was held when tilting began). `angle` is the screen's orientation (0, 90, 180 or 270), so leaning a phone held sideways still turns the view the way it looks. Null for an empty reading.
25
+ *
26
+ * @param reading The current reading.
27
+ * @param rest The reading when tilting began.
28
+ * @param angle The screen's orientation: 0, 90, 180 or 270. Defaults to 0.
29
+ * @returns The turn in degrees round (`azimuth`) and up or down (`polar`), or null for an empty reading.
30
+ * @example
31
+ * ```ts
32
+ * import { tiltTurn } from "@johnmorrisdotca/uchusen-rockets";
33
+ *
34
+ * console.log(tiltTurn({ beta: 30, gamma: 10 }, { beta: 20, gamma: 0 }), tiltTurn({ beta: null, gamma: null }, { beta: 0, gamma: 0 }));
35
+ * ```
36
+ */
15
37
  export function tiltTurn(reading, rest, angle = 0) {
16
38
  if (reading.beta === null || reading.gamma === null || rest.beta === null || rest.gamma === null)
17
39
  return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@johnmorrisdotca/uchusen-rockets",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Uchusen Rockets 宇宙船: line drawings and 3D views of rockets, as a web component. Every variant with its own sourced sizes, a typed way to assemble a rocket from parts, stack and separate. No logos. three.js is a peer dependency.",
5
5
  "keywords": [
6
6
  "rocket",
@@ -93,9 +93,12 @@
93
93
  "dev": "pnpm site && node scripts/dev.ts",
94
94
  "test:demo": "pnpm site && playwright test",
95
95
  "test:freeze": "pnpm site && playwright test e2e/freeze.demo.ts --project=chromium-desk",
96
- "screenshots": "pnpm site && node scripts/screenshots.ts",
96
+ "screenshots": "pnpm site && node scripts/docs-site.mjs build && node scripts/screenshots.ts",
97
97
  "models": "node scripts/reduce-models.ts",
98
- "models:nasa": "node scripts/reduce-nasa.ts"
98
+ "models:nasa": "node scripts/reduce-nasa.ts",
99
+ "docs:site": "pnpm build && node scripts/docs-site.mjs build",
100
+ "docs:check": "pnpm build && node scripts/docs-site.mjs check",
101
+ "size": "node scripts/docs-site.mjs size"
99
102
  },
100
103
  "peerDependencies": {
101
104
  "react": ">=18",
@@ -114,8 +117,8 @@
114
117
  "@gltf-transform/core": "4.5.1",
115
118
  "@gltf-transform/extensions": "4.5.1",
116
119
  "@gltf-transform/functions": "4.5.1",
117
- "@johnmorrisdotca/chikyu-earth": "0.5.0",
118
- "@johnmorrisdotca/kazoku-ui": "^0.10.0",
120
+ "@johnmorrisdotca/chikyu-earth": "0.10.0",
121
+ "@johnmorrisdotca/kazoku-ui": "^0.12.0",
119
122
  "@playwright/test": "1.64.0",
120
123
  "@types/node": "24.10.1",
121
124
  "@types/react": "19.2.7",
@@ -124,7 +127,9 @@
124
127
  "draco3dgltf": "1.5.7",
125
128
  "esbuild": "0.25.12",
126
129
  "eslint": "9.39.5",
130
+ "marked": "^18.1.3",
127
131
  "meshoptimizer": "1.3.0",
132
+ "pagefind": "^1.6.0",
128
133
  "react": "19.3.1",
129
134
  "react-dom": "19.3.1",
130
135
  "three": "0.186.1",