feat: Cesium 1.144 composable camera controllers + monthly maintenance - #802
Merged
Conversation
bnimit
force-pushed
the
feat/cesium-1.144-camera-controllers
branch
from
August 4, 2026 07:15
4238f18 to
b229cde
Compare
|
✨✨ That's perfect, there is no visual difference! ✨✨ |
There was a problem hiding this comment.
Pull request overview
Adds Resium wrappers for Cesium 1.144’s composable Controller-based camera controllers, alongside the monthly dependency/CI refresh and a small docs-generator formatting fix.
Changes:
- Introduces five new camera-controller components (map, elevator, tilt/orbit, zoom, and hybrid pan) with Storybook stories and type-level “unused prop” tests.
- Adds
corehelpers to register/unregister CesiumControllers against the widget container (includingprioritysupport) plus runtime tests. - Performs maintenance updates: Cesium 1.143 → 1.144, dev/docs dependency bumps, Node version bump, and GitHub Actions updates; fixes JSDoc line-wrap rendering in the docs generator.
Reviewed changes
Copilot reviewed 33 out of 35 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/ScreenSpaceZoomCameraController/ScreenSpaceZoomCameraController.ts | New Resium wrapper for Cesium’s ScreenSpaceZoomCameraController, including create-time bindings and priority support. |
| src/ScreenSpaceZoomCameraController/ScreenSpaceZoomCameraController.test.ts | Adds type-level unused-prop coverage for the zoom controller wrapper. |
| src/ScreenSpaceZoomCameraController/ScreenSpaceZoomCameraController.stories.tsx | Adds a Storybook “Basic” story demonstrating zoom-towards-pointer usage. |
| src/ScreenSpaceZoomCameraController/index.ts | Exposes the zoom controller component + props from its folder entrypoint. |
| src/ScreenSpaceTiltOrbitCameraController/ScreenSpaceTiltOrbitCameraController.ts | New wrapper for tilt/orbit inspection controller with create-time drag bindings and priority. |
| src/ScreenSpaceTiltOrbitCameraController/ScreenSpaceTiltOrbitCameraController.test.ts | Adds type-level unused-prop coverage for the tilt/orbit controller wrapper. |
| src/ScreenSpaceTiltOrbitCameraController/ScreenSpaceTiltOrbitCameraController.stories.tsx | Adds a Storybook “Basic” story for tilt/orbit inspection behavior. |
| src/ScreenSpaceTiltOrbitCameraController/index.ts | Exposes the tilt/orbit controller component + props from its folder entrypoint. |
| src/ScreenSpaceMapCameraController/ScreenSpaceMapCameraController.ts | New wrapper for map-style pan controller with create-time drag bindings and priority. |
| src/ScreenSpaceMapCameraController/ScreenSpaceMapCameraController.test.ts | Adds type-level unused-prop coverage for the map pan controller wrapper. |
| src/ScreenSpaceMapCameraController/ScreenSpaceMapCameraController.stories.tsx | Adds a Storybook “Basic” story for map panning behavior. |
| src/ScreenSpaceMapCameraController/index.ts | Exposes the map controller component + props from its folder entrypoint. |
| src/ScreenSpaceElevatorCameraController/ScreenSpaceElevatorCameraController.ts | New wrapper for vertical “elevator” pan controller with create-time drag bindings and priority. |
| src/ScreenSpaceElevatorCameraController/ScreenSpaceElevatorCameraController.test.ts | Adds type-level unused-prop coverage for the elevator controller wrapper. |
| src/ScreenSpaceElevatorCameraController/ScreenSpaceElevatorCameraController.stories.tsx | Adds a Storybook “Basic” story for elevator panning behavior. |
| src/ScreenSpaceElevatorCameraController/index.ts | Exposes the elevator controller component + props from its folder entrypoint. |
| src/index.ts | Re-exports the newly added controller components from the library root. |
| src/HybridScreenSpacePanCameraController/index.ts | Exposes the hybrid pan controller component + props from its folder entrypoint. |
| src/HybridScreenSpacePanCameraController/HybridScreenSpacePanCameraController.ts | New wrapper for the hybrid map/elevator pan controller with priority. |
| src/HybridScreenSpacePanCameraController/HybridScreenSpacePanCameraController.test.ts | Adds type-level unused-prop coverage for the hybrid pan controller wrapper. |
| src/HybridScreenSpacePanCameraController/HybridScreenSpacePanCameraController.stories.tsx | Adds “Basic” and combined inspection-camera composition Storybook stories. |
| src/core/index.ts | Exports the new controller registration helpers from core. |
| src/core/Controller.ts | Adds registerController / unregisterController helpers built around Scene.controllerHost. |
| src/core/Controller.test.tsx | Adds runtime tests verifying controller registration/unregistration and readonly-prop recreation behavior. |
| scripts/generator/parser.mts | Fixes docs generation to preserve spaces when collapsing wrapped JSDoc newlines. |
| package.json | Bumps Cesium and dev toolchain dependencies (Storybook, ESLint, Prettier, Vite, etc.). |
| docs/package.json | Updates Astro/Starlight versions for the docs workspace. |
| docs/package-lock.json | Regenerates docs lockfile to match updated docs dependencies. |
| .node-version | Updates pinned Node version used by CI workflows. |
| .github/workflows/vrt.yml | Updates pinned actions/checkout and actions/setup-node versions/SHAs for VRT workflow. |
| .github/workflows/tag.yml | Updates pinned actions/checkout version/SHA for tagging workflow. |
| .github/workflows/release.yml | Updates pinned actions/checkout and actions/setup-node versions/SHAs for release workflow. |
| .github/workflows/publish.yml | Updates pinned actions/checkout and actions/setup-node versions/SHAs for publish workflow. |
| .github/workflows/ci.yml | Updates pinned actions/checkout and actions/setup-node versions/SHAs for CI workflow. |
Files not reviewed (1)
- docs/package-lock.json: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
bnimit
added a commit
that referenced
this pull request
Aug 4, 2026
Addresses Copilot's review comment on #802. The test built a mock via `makeContext()` but rendered the component with an empty context, so the mock was unreachable and the expectation passed no matter what — it would not have caught the component registering a controller in that scenario. Replaced with two tests that can fail: - widget present but `container` missing, so the `controllerHost` mock is reachable and "not called" is a real assertion. Verified by mutation: relaxing the `!container` guard in registerController fails this test. - no widget at all, asserted through the exposed ref — `cesiumElement` stays falsy, which is observable without needing the mock. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bnimit
added a commit
that referenced
this pull request
Aug 6, 2026
Addresses Copilot's review comment on #802. The test built a mock via `makeContext()` but rendered the component with an empty context, so the mock was unreachable and the expectation passed no matter what — it would not have caught the component registering a controller in that scenario. Replaced with two tests that can fail: - widget present but `container` missing, so the `controllerHost` mock is reachable and "not called" is a real assertion. Verified by mutation: relaxing the `!container` guard in registerController fails this test. - no widget at all, asserted through the exposed ref — `cesiumElement` stays falsy, which is observable without needing the mock. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bnimit
force-pushed
the
feat/cesium-1.144-camera-controllers
branch
from
August 6, 2026 08:46
60bc994 to
75b3448
Compare
rot1024
approved these changes
Aug 7, 2026
Routine maintenance pass. Dev/CI dependencies only — no runtime or
public API changes.
devDependencies:
- storybook + @storybook/{react,react-vite,builder-vite} 10.4.6 -> 10.5.6
- eslint 10.6.0 -> 10.8.0, prettier ^3.8.3 -> ^3.9.6
- vite 8.1.3 -> 8.2.0, @vitejs/plugin-react 6.0.2 -> 6.0.5
- react/react-dom 19.2.7 -> 19.2.8, @types/react 19.2.17 -> 19.2.18
- @types/node 26.1.0 -> 26.1.2, @types/react-dom ^19.2.3 -> ^19.2.4
- globby, npm-run-all2, concurrently, wait-on: patch/minor bumps
Major dev-tool bumps (all dev-only, no consumer impact):
- @testing-library/jest-dom ^6.9.1 -> ^7.0.0 (@testing-library/dom is
now a required peer — already present; requires Node >=22)
- jsdom 29.1.1 -> 30.0.1 (requires Node ^22.22.2 || ^24.15.0 || >=26)
- c8 11.0.0 -> 12.0.0 (yargs 18 narrows supported Node range)
CI:
- actions/checkout v7.0.0 -> v7.0.1
- actions/setup-node v6.4.0 -> v7.0.0 (ESM migration; no config changes
needed for our usage)
- .node-version 24.16.0 -> 24.19.0 (latest 24 LTS patch)
docs:
- astro 7.0.7 -> 7.1.6, @astrojs/starlight 0.41.3 -> 0.41.6
- npm audit fix clears transitive postcss and svgo advisories
package-lock.json was regenerated: @vitejs/plugin-react 6.0.5 pulls an
optional babel chain needing @babel/core ^8 nested, which the old lock
could not place against its hoisted 7.29.7 root. A fresh resolve nests
it correctly, hence the large lock diff.
Held back deliberately:
- cesium 1.144.0 — feature-surface upgrade, wants its own review pass
- typescript 7.0.2 — native compiler rewrite; needs verification against
vite-plugin-dts declaration emit and eslint-config-reearth
Verified: tsc, eslint, vitest (81 files / 115 tests), library build +
postbuild import, storybook build, docs build all pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Upgrades Cesium to 1.144.0 and wraps the new composable `Controller`
framework, which is the only new public API surface in this release.
New components (one per controller Cesium 1.144 added):
- ScreenSpaceMapCameraController — pan across the map, keeping the
picked world position under the pointer
- ScreenSpaceElevatorCameraController — pan the camera vertically
- ScreenSpaceTiltOrbitCameraController — tilt/orbit around a pivot,
optionally the position under the pointer (`useDragPosition`)
- ScreenSpaceZoomCameraController — zoom towards a picked position
- HybridScreenSpacePanCameraController — switches between map and
elevator panning based on the camera's angle from nadir
Note the changelog lists only four controllers; ScreenSpaceZoomCameraController
ships in the same API and is wrapped here too.
Each is registered with `Scene.controllerHost` on mount and unregistered
on unmount, via new `registerController`/`unregisterController` helpers in
core. We go through `controllerHost` rather than the `Viewer.addController`
shorthand because only the former accepts `priority`, which the components
expose as a create-time prop. The helpers are exported so users can build
components for their own `Controller` implementations.
`dragInputs`/`scrollInputs` are create-time props (cesiumReadonlyProps):
Cesium attaches those bindings once in `connectedCallback`, so mutating
them post-registration has no effect — changing the prop re-creates the
controller instead. Remaining properties are live and applied in place.
Storybook: one Basic story per controller, plus a CombinedInspectionCamera
story showing pan + tilt/orbit + zoom composed into one camera rig. Stories
pair each controller with `<ScreenSpaceCameraController enableInputs={false}>`,
since Cesium's built-in controller otherwise keeps handling input.
Tests: the existing exhaustive `UnusedCesiumProps` check covers every
mutable property of all five controllers, plus runtime tests for
registration against the widget container, `priority` forwarding, unmount
cleanup, live prop application and `dragInputs` re-creation.
Also fixes the docs generator collapsing wrapped JSDoc lines without a
separator ("tilt ororbit"), which these components were the first to hit.
TypeScript stays on 6.0.3. `tsc` itself passes clean on 7.0.2, but the
surrounding toolchain does not support it: every published
typescript-eslint version caps at `typescript <6.1.0` (as does
@vitest/eslint-plugin's copy), so `npm run lint` crashes. unplugin-dts
needs an `@typescript/typescript6` shim, which does work. Revisit once
typescript-eslint ships TS 7 support.
Verified: tsc, eslint, vitest (87 files / 127 tests), library build +
postbuild import, storybook build (all 6 new stories registered), docs
generate (98 pages) and docs build all pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
codecov-action was pinned to `e53489f4`, which is the *annotated tag object* for v7.0.0 rather than the commit it points at. GitHub resolves it, so CI has been passing, but pinning a tag object is non-standard: tag objects can be deleted and re-created upstream, and only a commit SHA is the immutable target that SHA-pinning is meant to give us. Repinned to `fb8b3582` — the commit v7.0.0 (and v7) actually resolve to. Same action version, no behaviour change. All seven action pins across the workflows are now verified to be commit SHAs. `reearth/changelog-action` stays on its 2022 main pin: main is two commits ahead but both only add a Backstage `catalog-info.yaml`, so there is no functional change to pick up. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Addresses Copilot's review comment on #802. The test built a mock via `makeContext()` but rendered the component with an empty context, so the mock was unreachable and the expectation passed no matter what — it would not have caught the component registering a controller in that scenario. Replaced with two tests that can fail: - widget present but `container` missing, so the `controllerHost` mock is reachable and "not called" is a real assertion. Verified by mutation: relaxing the `!container` guard in registerController fails this test. - no widget at all, asserted through the exposed ref — `cesiumElement` stays falsy, which is observable without needing the mock. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
All six controller stories flew to the same camera — 3000m at pitch -45 — because they were generated from one template. That is the worst choice available: -45 degrees is 45 degrees off nadir, exactly the boundary HybridScreenSpacePanCameraController uses to decide between map and elevator panning, so the two controllers that differ most looked identical and neither was shown in its own regime. Each story now starts where its controller is actually legible: - map: pitch -90 at 6000m — straight down, so dragging reads as sliding a map around underneath the camera - elevator: pitch -12 at 1200m — low and towards the horizon, where riding up and down is visible against it; near-nadir the same drag barely changes the view - tilt/orbit: pitch -35 at 2500m — oblique, so there is an angle to swing through - zoom: pitch -50 at 9000m — far enough out to have somewhere to zoom to - hybrid Basic: pitch -75 at 4000m — ~15 degrees off nadir, comfortably inside the default 45 degree threshold, so it opens in map-pan mode and tilting up hands over to elevator panning - hybrid CombinedInspectionCamera: pitch -35 at 2500m — oblique, so pan, tilt/orbit and zoom are all exercisable Each choice is commented in the story, so the next person does not flatten them back into one template. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bnimit
force-pushed
the
feat/cesium-1.144-camera-controllers
branch
from
August 7, 2026 03:30
75b3448 to
59de152
Compare
The GeoJsonPrimitive VRT story layered a `<CameraFlyTo>` on top of
`VrtViewer`'s `applyDeterminism`, which also calls `camera.setView`.
Whichever effect fired last won. In Cesium 1.143 CameraFlyTo won and
the story captured a zoomed-in terrain view; in 1.144 the effect
ordering flipped and applyDeterminism's globe-scale default view won,
producing a completely different screenshot.
Fix by making applyDeterminism the single source of truth for the
deterministic camera position, and letting stories override via a new
`<VrtViewer defaultView={...}>` prop. GeoJsonPrimitive now uses that
prop instead of a child CameraFlyTo — no more race.
Only touches VRT stories; no runtime library impact.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bnimit
added a commit
that referenced
this pull request
Aug 7, 2026
- Drop the empty `### ` and double-empty `#### ` autogen artifacts - Flatten scope-first nesting into a type-first layout (feat / fix / ci) so the Cesium 1.144 headline surfaces above the wrapper-internals work - Promote #802 to `### feat` and name the five new camera controllers - Promote #796 to `### fix` and credit @squeakyrino for the external contribution - Clarify the VRT checkout fix (#803) with what it actually does Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bnimit
added a commit
that referenced
this pull request
Aug 7, 2026
* chore: release v1.25.0 * chore(changelog): clean up auto-generated 1.25.0 section - Drop the empty `### ` and double-empty `#### ` autogen artifacts - Flatten scope-first nesting into a type-first layout (feat / fix / ci) so the Cesium 1.144 headline surfaces above the wrapper-internals work - Promote #802 to `### feat` and name the five new camera controllers - Promote #796 to `### fix` and credit @squeakyrino for the external contribution - Clarify the VRT checkout fix (#803) with what it actually does Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: bnimit <bnimit@users.noreply.github.com> Co-authored-by: Nimit Bhandari <bnimit25@gmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds support for the composable
Controllerframework introduced in Cesium 1.144, and takes Cesium from 1.143 to 1.144. Also folds in this month's dev/CI dependency refresh, since it lands the same day.Camera controller components
Cesium 1.144 added a composable
Controllerframework plus a set of alternative camera controllers aimed at asset inspection. All of them are now wrapped:ScreenSpaceMapCameraControllerScreenSpaceElevatorCameraControllerScreenSpaceTiltOrbitCameraControlleruseDragPositionScreenSpaceZoomCameraControllerHybridScreenSpacePanCameraControllerThe 1.144 changelog lists only four controllers.
ScreenSpaceZoomCameraControllerships in the same API and is wrapped here too — without it you can't assemble a complete inspection camera.Registration
Each controller registers with
Scene.controllerHoston mount and unregisters on unmount, through newregisterController/unregisterControllerhelpers incore.CesiumWidget.addControlleris a thin wrapper aroundregisterController(controller, widget.container)and drops thepriorityargument, so these components go one level down tocontrollerHostdirectly and exposepriorityas a create-time prop. Precedence ordering is the point of a composable controller framework, so it shouldn't be unreachable.The helpers are exported, so users can build resium-style components around their own
Controllerimplementations.dragInputs/scrollInputsare create-time propsCesium attaches these bindings once, inside
connectedCallback, viaregisterDragInputBindings. Mutating them after registration has no effect. Exposing them as ordinary reactive props would produce a prop that looks live but silently does nothing, so they're declared ascesiumReadonlyProps: changing one re-creates the controller. Every other property is applied in place.Storybook
One
Basicstory per controller, plus aCombinedInspectionCamerastory composing pan + tilt/orbit + zoom into a single camera rig. Each story pairs the controller with<ScreenSpaceCameraController enableInputs={false} />, since Cesium's built-in controller otherwise keeps handling input alongside it. No external tile endpoints are used.Nothing else in 1.144 needs wrapping
Scene.snapis a method andTexture.defaultColora static, neither of which resium wraps as components. The vector-tile terrain draping is internal and driven by the existingCesium3DTileStyle—MVTDataProvider.fromUrl's options are unchanged. The new glTF extensions have no public API surface. The existing exhaustiveUnusedCesiumPropschecks would have failed had any already-wrapped class gained a property.Maintenance refresh
Dev toolchain — Storybook 10.4.6 → 10.5.6, ESLint 10.6 → 10.8, Prettier → 3.9.6, Vite 8.1.3 → 8.2.0,
@vitejs/plugin-react6.0.2 → 6.0.5, React/React-DOM 19.2.7 → 19.2.8, plus patch bumps to types, globby, npm-run-all2, concurrently and wait-on.Three dev-only majors, each checked against its breaking notes:
@testing-library/jest-dom6 → 7 —@testing-library/dombecomes a required peer (already present); requires Node ≥22jsdom29 → 30 — requires Node^22.22.2 || ^24.15.0 || >=26c811 → 12 — yargs 18 narrows the supported Node rangeNone affect shipped output.
engines.nodedeliberately stays at>=20.19.0: it describes what consumers need, not what building resium needs.CI —
actions/checkoutv7.0.0 → v7.0.1,actions/setup-nodev6.4.0 → v7.0.0 (ESM migration, no config change needed)..node-version24.16.0 → 24.19.0, staying on the 24 LTS line.codecov/codecov-actionwas pinned toe53489f4, which is the annotated tag object for v7.0.0 rather than the commit it points at. GitHub resolves it, so CI had been passing, but only a commit SHA is the immutable target SHA-pinning is meant to provide — a tag object can be deleted and re-created upstream. Repinned tofb8b3582, the commit v7.0.0 and v7 actually resolve to. Same action version, no behaviour change.All seven action pins across the workflows are now verified to resolve to commits. The remaining ones were already current:
actions/upload-artifactv7.0.1,actions/create-github-app-tokenv3.2.0 andpeaceiris/actions-gh-pagesv4.1.0 are each the latest release and correctly pinned.reearth/changelog-actionstays on its existingmainpin — main is two commits ahead, but both only add a Backstagecatalog-info.yaml, so there is nothing functional to pick up.Docs — Astro 7.0.7 → 7.1.6, Starlight 0.41.3 → 0.41.6, and
npm audit fixclears transitive postcss and svgo advisories. The docs workspace audit is now clean.Lockfile regenerated.
@vitejs/plugin-react6.0.5 pulls an optional babel chain needing@babel/core ^8nested, and the old lock had 7.29.7 hoisted at the root with nowhere to place 8.x —npm installfailed on eresolve even withnode_modulescleared. The manifest resolves cleanly from scratch, so the lock was regenerated rather than forcing--legacy-peer-deps. That accounts for the large lock diff.TypeScript stays on 6.0.3
TypeScript 7.0.2 was attempted and reverted. resium's own code is ready —
tsc7.0.2 passes with zero errors — but the surrounding toolchain isn't:canary, caps attypescript >=4.8.4 <6.1.0, and@vitest/eslint-plugincarries its own copy with the same cap.npm run lintcrashes withCannot read properties of undefined (reading 'Cjs'). Scoping TS 6 to that subtree via npmoverridesdoesn't work: npm keeps 7.0.2 deduped and marks it invalid.@typescript/typescript6shim.6.0.3 is also the newest TypeScript the lint toolchain accepts, so there's no intermediate step to take either. Worth revisiting once typescript-eslint ships TS 7 support.
Drive-by fix
The docs generator collapsed wrapped JSDoc lines with no separator, rendering
"tilt ororbit"and"everyother controller". These components were the first to carry multi-line JSDoc in the generated property tables, so it had gone unnoticed. One-line fix inscripts/generator/parser.mts.Verification
tsc,eslint,vitest(87 files / 127 tests, up from 81 / 115), library build plus the postbuild import check, Storybook build (all six new stories registered), docs generate (98 pages) and docs build all pass. All five components confirmed present indist/resium.cjs.Beyond the exhaustive type-level prop checks, there are seven new runtime tests covering registration against the widget container,
priorityforwarding, unregistration on unmount, live prop application, anddragInputsre-creation.The VRT image comparison wasn't run locally — it needs the reg-suit credentials, so that's for CI.
Supersedes
fb8b358commitScreenshots
Screen Space Map Camera Controller
Basic
Screen Space Elevator Camera Controller
Basic
Screen Space Tilt Orbit Camera Controller
Basic
Screen Space Zoom Camera Controller
Basic
Hybrid Screen Space Pan Camera Controller
Basic