@rive-app/canvas-single 2.40.0 → 2.40.1

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.
@@ -16,21 +16,21 @@ export interface KeyboardInteractionsParams {
16
16
  getOverlayElement?: () => HTMLElement | null;
17
17
  }
18
18
  /**
19
- * Tracks the relationship between the canvas's DOM focus and Rive's internal focus for the
20
- * current focus session.
19
+ * Tracks the relationship between DOM focus inside this Rive focus domain (canvas or semantic overlay)
20
+ * and Rive's internal focus for the current focus session.
21
21
  *
22
- * NotFocused — the canvas is not the active DOM element, or Rive entered and then released focus
23
- * internally this session. Either way the next Tab should move on to the next page
24
- * element, so Tab events are ignored.
25
- * EntryPending — the canvas has DOM focus but Rive holds no active focus node yet, and the next Tab should enter
26
- * the focus tree. This is the resting state for pointer-driven focus (a click on the
27
- * canvas), or an edge case for keyboard focus where initial focus action did not land on a focus node.
28
- * RiveFocused — a Rive node currently holds focus. Tab/Shift+Tab are routed to the Rive focus
29
- * manager and trapped inside the canvas until Rive notifies focus has ended.
22
+ * NotFocused — DOM focus left the domain, Rive released focus internally, or Tab walked
23
+ * off the end of the tree. Keyboard input isn't ours, so Tab is ignored and
24
+ * reaches the next page element.
25
+ * EntryPending — DOM focus is inside the domain but Rive holds no node yet, so the next Tab
26
+ * enters the focus tree. Set by pointer focus on the canvas, by assistive technology (AT) focus landing
27
+ * in the overlay, and by keyboard focus whose entry attempt found no eligible node.
28
+ * RiveFocused — a Rive node holds focus. Tab/Shift+Tab route to the Rive focus manager and stay
29
+ * inside the domain until either Rive reports focus ended (pollFocusState) or
30
+ * focusNext()/focusPrevious() returns false at the edge of the tree.
30
31
  *
31
- * When keyboard focus lands on the canvas, onCanvasFocus reads the direction focus came from and
32
- * moves into the focus tree immediately, going straight to RiveFocused. EntryPending is only set via pointer focus (or keyboard focus
33
- * where focusNext()/focusPrevious() return false but respects tabindex).
32
+ * Keyboard focus on the canvas enters the tree immediately: onCanvasFocus infers direction from
33
+ * where focus came from and goes straight to RiveFocused when a node accepts.
34
34
  */
35
35
  export declare enum FocusSessionState {
36
36
  NotFocused = "notFocused",
@@ -38,7 +38,9 @@ export declare enum FocusSessionState {
38
38
  RiveFocused = "riveFocused"
39
39
  }
40
40
  /**
41
- * Manages keyboard and DOM focus interactions for a Rive canvas.
41
+ * Manages keyboard and DOM focus interactions for Rive's focus domain (<canvas> or semantic overlay).
42
+ * Because keyboard events can apply on either part of the domain, we need to track what events we should
43
+ * handle/intercept, and when to release focus back to the page outside of the domain.
42
44
  *
43
45
  * Tracks the canvas focus session state (focusSessionState) and routes
44
46
  * Tab/Shift+Tab to the Rive state machine's focus manager. Exposes shared
@@ -70,7 +72,8 @@ export declare class KeyboardInteractions {
70
72
  /**
71
73
  * Called by pollFocusState on the Rive instance when it observes hasFocus=true. Rive acquired
72
74
  * focus internally (e.g. via a listener action or state transition) without a DOM focus event,
73
- * so mark the session RiveFocused.
75
+ * so mark the session RiveFocused. This cannot resurrect a session that a DOM blur ended,
76
+ * because onCanvasBlur clears Rive's focus alongside it.
74
77
  */
75
78
  notifyRiveFocused(): void;
76
79
  /**
@@ -85,18 +88,40 @@ export declare class KeyboardInteractions {
85
88
  * gates this so a click doesn't yank Rive focus to the first node on the focus event itself.
86
89
  */
87
90
  onCanvasFocus: (event: FocusEvent) => void;
88
- onCanvasBlur: (_event: FocusEvent) => void;
91
+ /**
92
+ * Marks internal state that the canvas has lost DOM focus. Do not actually clear
93
+ * Rive focus though if:
94
+ * 1. DOM focus is still within Rive domain (i.e., semantic overlay)
95
+ * 2. Document just lost focus (i.e. tab switching)
96
+ *
97
+ * When we're not in either of those buckets, it's safe to call `clearFocus()` on the SMI.
98
+ */
99
+ onCanvasBlur: (event: FocusEvent) => void;
100
+ /**
101
+ * Assistive technology (AT) focus landing inside the overlay is DOM focus inside the Rive focus domain, so open a
102
+ * session even when no Rive node holds focus yet. shouldRiveHandleKeyEvent treats NotFocused
103
+ * as authoritative, so without this the overlay's Tab keydowns reach onKeyDown and get dropped
104
+ * at that gate — the browser would move focus out of Rive instead of to the next focus node.
105
+ */
89
106
  private onOverlayFocusIn;
107
+ /** Overlay listeners attach lazily, so the first focusin only ever lands here. */
90
108
  private onFocusDomainHostFocusIn;
91
109
  onKeyDown: (event: KeyboardEvent) => void;
92
110
  /**
93
- * Whether Rive should handle this keydown i.e. it currently owns keyboard input.
94
- * True when focus is anywhere in the Rive focus domain (the canvas itself or the
95
- * accessibility overlay), OR a focus session is active and the key landed on the
96
- * canvas.
111
+ * Determine if Rive should handle keyboard input. If session state is `NotFocused` - no.
112
+ * DOM focus stays parked on the canvas after Rive releases focus internally, and that Tab
113
+ * has to reach the page rather than re-enter the tree.
114
+ *
115
+ * Otherwise, the event still has to belong to Rive:
116
+ * 1. If the current DOM focus is in Rive domain (canvas or semantic overlay)
117
+ * 2. If the target for the key input is for the semantic overlay, or the canvas
97
118
  */
98
119
  private shouldRiveHandleKeyEvent;
99
- /** Rive focus domain = the canvas itself OR the accessibility overlay. */
120
+ /**
121
+ * The Rive focus domain: the DOM that counts as "inside" Rive for focus purposes — today the
122
+ * canvas itself OR the accessibility overlay subtree. Anything added later belongs here, so
123
+ * session bookkeeping and keydown routing pick it up for free.
124
+ */
100
125
  private isInFocusDomain;
101
126
  /** Overlay only (excludes the canvas) — the accessibility overlay subtree. */
102
127
  private isInOverlay;