Skip to content

refactor(player-core): drop svelte for a signals-based dom layer, upgrade to TypeScript 7 - #9

Merged
AbianS merged 4 commits into
mainfrom
refactor/player-core-signals-ts7
Sep 25, 2026
Merged

AbianS merged 4 commits into
mainfrom
refactor/player-core-signals-ts7

Conversation

@AbianS

@AbianS AbianS commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

Summary

Four commits:

  1. build: share dependency versions through pnpm catalogs: shared dependencies (TypeScript, React, Tailwind, the Vite/Vitest/size tooling) live in named catalogs in pnpm-workspace.yaml.
  2. refactor(player-core): replace svelte with a signals-based dom layer: the player no longer ships or depends on a UI framework.
  3. build: upgrade to typescript 7: TypeScript 7 everywhere except player-vue, which stays on 6.
  4. chore(player-core): replace dist import check with a lint rule: the alien-signals import guard moves from a post-build script to a Biome rule.

player-core without Svelte

The player is embedded in other people's apps, so it shouldn't make them install or download a framework runtime. The Svelte runtime was about half of the player's weight.

  • src/dom/: a small DOM layer over alien-signals. h()/svg() create elements, and a function prop or child stays bound to the signals it reads (one effect per binding, nothing re-renders). show() handles conditional views with exit animations, each() keyed lists, mount() scoped disposal, and batch() grouped writes.
  • src/ui/<Component>/: the seven components as plain functions, each with its CSS in <Component>.styles.ts. Selectors are scoped under .openshowcase-player and keyframes prefixed with openshowcase-, and the CSS is injected when the component is created, never at import time.
  • src/core/: unchanged. The public API (new Player({...}).mount(), next(), goTo(), destroy()…) is the same, so the adapters and the extension needed no changes.

Build and output

  • Build: Rslib in bundleless mode replaces Vite + dts-bundle-generator. dist/ has one readable, unminified ESM file per module (the host app minifies), declarations from tsc, and "sideEffects": ["**/*.css"]. Tailwind ships as dist/app.css.
  • alien-signals is a devDependency compiled into dist/dom/signals.js: the published package depends on nothing but the schema. Only src/dom/signals.ts may import it, and a Biome noRestrictedImports rule enforces that: a direct import would stay in dist/ as an import of a package the published package doesn't declare.
  • size-limit now measures what a host ships (bundled and minified by esbuild), with a second budget that fails if the player stops tree-shaking away from the tooltip geometry.
What a host ships (minified, brotli) Before After
Player (JS + CSS) ~26 KB 14.7 KB
Tooltip geometry only (the extension editor) 5.6 KB, plus the player's CSS injected 0.75 KB
Runtime dependencies svelte none

How it was verified

  • Same specs on both versions: during the migration, every component test and the player integration suite ran against both the Svelte and the new implementation (198 tests).
  • Rendering parity: each component, and the whole player step by step in light and dark themes, was compared against the Svelte original: normalized DOM plus the browser's computed styles. Deliberately breaking a style or class made those checks fail, so they weren't passing by accident.
  • Real demo: a real recorded demo (video, zoomed photos with hotspots, a zoomed video) played end to end in headless Chromium through the built package, with no console errors.
  • After removing Svelte: the specs run on the new implementation only (140 tests). The parity scaffolding was removed along with it.

TypeScript 7

  • catalog:core → typescript 7.0.2. tsc is the native compiler, and Rslib generates declarations with it (tsgo).
  • player-vue stays on 6 through a new catalog:vue-tooling, like nest-cli in contapro: vue-tsc and the Vue SFC loader load TypeScript's JS API, which 7 removed.
  • Tooling: player-core no longer uses dts-bundle-generator, the other API-bound tool.

Checks

biome ci, build, check-types, size (all 17 tasks) and every package's tests pass: player-core 140, extension 119, schema 27, exporter 8.

No changeset: it will be added later with the other pending changes.

@AbianS
AbianS merged commit 96a1591 into main Sep 25, 2026
1 check passed
@AbianS
AbianS deleted the refactor/player-core-signals-ts7 branch September 25, 2026 10:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant