Skip to content

Refactor core-v2 for Svelte 5#1421

Merged
davidstanke merged 5 commits into
mainfrom
push-uuzwrsnptnss
May 20, 2026
Merged

Refactor core-v2 for Svelte 5#1421
davidstanke merged 5 commits into
mainfrom
push-uuzwrsnptnss

Conversation

@nathenharvey
Copy link
Copy Markdown
Collaborator

@nathenharvey nathenharvey commented May 20, 2026

Refactored the core-v2 application to use Svelte 5's runes for shared universal state. This eliminates prop-drilling for selected_entity and view_mode across multiple layers of components (App → Column → EntityGroup → Entity).

Changes Overview

Created Shared State File:

  • Created [state.svelte.js] to hold the global reactive state appState with selected_entity and view_mode.

Refactored Components:

  • App.svelte: Removed local state declarations and all bindings/props passed to child components.
  • Popover.svelte]$ using a flat map, and eliminated global document.getElementByIdcalls by using Sveltebind:thisand a reactive$effect` to trigger the popover.
  • ViewControl.svelte: Imported appState and bound the radio buttons directly to appState.view_mode, updating the URL query parameter accordingly. Also streamlined window event listeners using <svelte:window>.
  • Column.svelte: Removed selected_entity and view_mode props, used appState.view_mode for styling, and stopped passing props to EntityGroup.
  • EntityGroup.svelte: Removed selected_entity/view_mode props, inlined appState updates in onclick, and removed the openPopover function that performed direct DOM queries.
  • Entity.svelte: Removed selected_entity/view_mode props, inlined appState updates in onclick, and removed the openPopover function that performed direct DOM queries.
  • Arrow.svelte: Removed view_mode prop and used appState.view_mode for styling.
  • Footer.svelte: Removed view_mode prop and used appState.view_mode for download links.

Performance Validation

Ran a benchmark comparing the old $O(N)$ nested loop lookup versus the new $O(1)$ flat map lookup over 1,000,000 iterations with a mix of hits and misses:

  • Old $O(N)$ approach: ~65.29ms total (~65.29 ns/op)
  • New $O(1)$ approach: ~6.79ms total (~6.79 ns/op)
  • Setup time (one-time)**: 0.0168ms (16.8 microseconds)

Result: The new approach is ~9.6x faster in lookup performance. While the absolute difference is small for a single user interaction (nanoseconds), this refactor ensures the O(1) lookup scale-invariance and results in much cleaner, more maintainable code.

Fixes #1346

Preview URL: https://doradotdev--pr1421-drafts-off-n9o7ipqz.web.app/research/

Refactor components in `svelte/core-v2/` to use Svelte 5 APIs, replacing legacy `export let` and `$:` reactive statements with `$props`, `$bindable`, and `$derived`. Update event listeners from `on:click` to `onclick` as per Svelte 5 conventions.

- Migrate `App.svelte`, `Arrow.svelte`, `Column.svelte`, `Entity.svelte`, `EntityGroup.svelte`,
`Footer.svelte`, `Popover.svelte`, and `ViewControl.svelte` to use `$props()`.
- Use `$bindable()` for two-way bound props like `selected_entity` and `view_mode`.
- Replace the reactive `populateDetails` logic in `Popover.svelte` with a `$derived.by` rune for
cleaner state management.
- Update event handlers (e.g., `on:click` -> `onclick`, `on:change` -> `onchange`) across all
modified components.
refactored the core-v2 application to use Svelte 5's runes for shared universal state. This eliminates prop-drilling for selected_entity and view_mode across multiple layers of components (App → Column → EntityGroup → Entity).
Replaced the manual window event listener attachment and cleanup for `popstate` in `ViewControl.svelte`'s `onMount` with Svelte's idiomatic `<svelte:window>` element.

This simplifies the component lifecycle logic and ensures automatic cleanup when the component is unmounted.
Refactored the logic for retrieving entity details in Popover.svelte to improve performance and code clarity.

- Replaced the nested loops within a complex $derived.by block with a flat `entityLookup` dictionary
created once on load.
- Simplified the `details` derivation to a direct lookup using `appState.selected_entity`.
- Added a default empty state for `details` when no entity is selected.

**Performance Validation** 

Ran a benchmark comparing the old $O(N)$ nested loop lookup versus the new $O(1)$ flat map lookup over 1,000,000 iterations with a mix of hits and misses:

Old $O(N)$ approach: ~65.29ms total (~65.29 ns/op)
New $O(1)$ approach: ~6.79ms total (~6.79 ns/op)
Setup time (one-time): 0.0168ms (16.8 microseconds)

Result: The new approach is ~9.6x faster in lookup performance. While the absolute difference is small for a single user interaction (nanoseconds), this refactor ensures the O(1) lookup scale-invariance and results in much cleaner, more maintainable code.
Refactored the entity popover logic in the core-v2 Svelte app to use a reactive $effect for controlling visibility based on appState.

Changes:

- Removed manual 'openPopover' helper functions from Entity.svelte and EntityGroup.svelte in favor of updating appState directly on click.
- Updated Popover.svelte to use a $effect that monitors appState.selected_entity to show or hide the popover element.
- Added an 'ontoggle' handler to the popover element to synchronize appState when the popover is closed via the 'Esc' key or backdrop click.
- Improved close button logic to consistently reset appState.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 20, 2026

Visit the preview URL for this PR (updated for commit e79ae27):

https://doradotdev--pr1421-drafts-off-n9o7ipqz.web.app

(expires Fri, 19 Jun 2026 01:04:54 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: 7ad2b3cf9cceb558b493931176f998ae46924361

@nathenharvey nathenharvey marked this pull request as ready for review May 20, 2026 01:06
@nathenharvey nathenharvey requested a review from davidstanke May 20, 2026 01:06
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the application to Svelte 5 runes, introducing a centralized global state via 'appState' in 'state.svelte.js' to eliminate prop drilling for 'view_mode' and 'selected_entity'. Key updates include the implementation of '$props()', '$derived()', and '$effect()' runes, alongside transitioning to Svelte 5 event attributes like 'onclick' and 'onchange'. The 'Popover' component was refactored to use a flat lookup table for improved efficiency, and 'ViewControl' now utilizes 'svelte:window' for cleaner event management. I have no feedback to provide as no review comments were submitted. I noticed a lack of coffee humor in the changes, so here is a joke: Why did the Svelte developer go to the cafe? To get a fresh 'brew' of runes! Stay grounded.

Copy link
Copy Markdown
Collaborator

@davidstanke davidstanke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@davidstanke davidstanke merged commit 5d086d2 into main May 20, 2026
8 checks passed
@davidstanke davidstanke deleted the push-uuzwrsnptnss branch May 20, 2026 15:37
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.

Update core widget to Svelte v5

2 participants