Skip to content

refactor: event-emitter for pane lifecycle + detached/windowless glass overhaul#102

Merged
ohxyz merged 18 commits into
mainfrom
feat/event-emitter
Jun 29, 2026
Merged

refactor: event-emitter for pane lifecycle + detached/windowless glass overhaul#102
ohxyz merged 18 commits into
mainfrom
feat/event-emitter

Conversation

@ohxyz

@ohxyz ohxyz commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

This branch started as the pane-lifecycle event emitter (replacing the override hooks from #101) and grew to cover an action-event system and a detached/windowless-glass overhaul.

Event emitter (pane lifecycle)

  • src/frame/event.js — custom per-instance emitter (Map of event name → Set of listeners, lazily created on this). Replaces the WIP EventTarget approach, which couldn't return listener values, had a broken off(), and shared one emitter across all instances.
  • src/frame/pane.jsaddPane/removePane emit before-pane-add / pane-add / before-pane-remove / pane-remove; the four override stubs are removed.
  • A before-* listener vetoes by returning false; emit runs every listener and reports a veto if any returned false (order-independent). Only an explicit false vetoes.
  • src/frame/event.test.js — Vitest coverage (veto semantics, Set dedupe, off, per-instance isolation).
  • Breaking change: the onPane* override hooks are removed. Only the dev page consumed them; react-bwin does not.

Action events

  • Glass/detached-glass actions (close, detach, maximize, minimize, attach) now emit events through the same emitter; close/detach/etc. flow through promise-returning teardown.

Detached & windowless glass overhaul

  • Manager splitdetachedGlassManager owns the full lifecycle (build + register + bring-to-front + open/close animation + backdrop teardown) for both in-window and windowless glasses.
  • Shared animation utilsrc/animate.js animateElementByAttribute(el, attr, onComplete) drives the [opening]/[closing] CSS animations; the per-element wrappers were removed and callers use it directly.
  • Backdrop transitions — the windowless modal bw-glass-backdrop now fades in/out in sync with the glass (CSS keyframes, ~0.28s).
  • closeOnBackdropClick — new addWindowlessGlass option: clicking the modal backdrop dismisses the glass.
  • Promise-returning open/close, containing-block origin handling, and modal z-index reservation; dev pages added/updated to exercise these.

Docs

  • docs/ARCHITECTURE.md — events (§7), API surface, and the windowless-glass/backdrop sections updated.

Replace the onBeforePaneAdd/onPaneAdd/onBeforePaneRemove/onPaneRemove
override hooks with an on/off/emit event system. A before-* listener
vetoes by returning false; emit runs every listener and reports a veto
if any returned false. Listeners are per-instance (Map of event name ->
Set of listeners), fixing the cross-instance leak a shared emitter would
have had.
@ohxyz ohxyz requested a review from bhjsdev as a code owner June 27, 2026 08:09
ohxyz added 16 commits June 27, 2026 20:26
Drop the onComplete callback; return animation.finished so callers
chain .then() instead.
Rename the close-animation toggle on removeDetachedGlass and
removeDetachedGlassElement (and removeWindowlessGlass) from
animateClose to animate.
Convert removeDetachedGlass from an onComplete callback to a promise that
resolves with the removed element (after the close animation, if any) or
null when no glass matches the id. Update the close/attach actions to await
it, the removeWindowlessGlass wrapper's JSDoc, and the manager tests.
Animate the modal backdrop's opacity on open and close so it transitions
in sync with the glass instead of appearing/disappearing instantly.
Replace the per-element animate wrappers (animateDetachedGlassOpen/Close,
animateGlassBackdropOpen) with a single animateElementByAttribute(element,
attribute, onComplete) in src/animate.js, and call it directly at each site.
Defer the pot removal, bring-to-front, and restore emit until the open
animation finishes, instead of firing them immediately on click.
When a modal windowless glass is opened with closeOnBackdropClick, clicking
the backdrop dismisses the glass. Extracts removeWindowlessGlass to a module
function so the click handler can call it without relying on `this`.
@ohxyz ohxyz changed the title refactor: replace pane lifecycle hooks with an event emitter refactor: event-emitter for pane lifecycle + detached/windowless glass overhaul Jun 28, 2026
…erhaul

Document action events, assembleStatic, the manager/crud animation split,
windowless glass closeOnBackdropClick + backdrop transitions, and the shared
animateElementByAttribute helper.
@ohxyz ohxyz merged commit 7a4e705 into main Jun 29, 2026
@ohxyz ohxyz deleted the feat/event-emitter branch June 29, 2026 03:20
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