@brightspot/ui 6.0.7-pr.245 → 6.0.7-pr.248

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.
@@ -2052,12 +2052,32 @@ onFind('.ActionBar', (actionBar) => {
2052
2052
  const widgetTitle = widget.querySelector<HTMLElement>('.Widget-title')
2053
2053
 
2054
2054
  let lastPointerType = ''
2055
+
2056
+ // The browser refocuses whatever was focused before when the window regains focus. That
2057
+ // arrives as a focusin with no preceding pointerdown, so the pointer guard below never
2058
+ // catches it, and the scroll drags the editor away from wherever they had deliberately
2059
+ // scrolled to — most visibly with a rich text field taller than the pane.
2060
+ // Seeded from hasFocus() because binding can happen while the window is already blurred —
2061
+ // a background tab, or form content that mounts lazily while the user is away — in which
2062
+ // case the blur has already fired and there is nothing left to listen for.
2063
+ let isRestoringFocus = !document.hasFocus()
2064
+ const handleWindowBlur = () => {
2065
+ isRestoringFocus = true
2066
+ }
2067
+
2068
+ // Any deliberate input means we are no longer restoring, so the flag cannot go stale if
2069
+ // focus happens to return to something outside this widget.
2070
+ const clearRestoringFocus = () => {
2071
+ isRestoringFocus = false
2072
+ }
2073
+
2055
2074
  const handlePointerdown = (event: Event) => {
2056
2075
  lastPointerType = (event as PointerEvent).pointerType
2057
2076
  // Reset after current task so only the immediately following focusin is affected.
2058
2077
  setTimeout(() => {
2059
2078
  lastPointerType = ''
2060
2079
  }, 0)
2080
+ clearRestoringFocus()
2061
2081
  }
2062
2082
 
2063
2083
  const handleFocusin = (event: Event) => {
@@ -2065,6 +2085,13 @@ onFind('.ActionBar', (actionBar) => {
2065
2085
  // smooth scrolling mid-click disrupts dropdown positioning and button actions.
2066
2086
  if (lastPointerType) return
2067
2087
 
2088
+ // Skip the single focusin the browser fires when restoring focus on window re-entry.
2089
+ // Keyboard navigation afterwards still scrolls, which is what this handler is for.
2090
+ if (isRestoringFocus) {
2091
+ isRestoringFocus = false
2092
+ return
2093
+ }
2094
+
2068
2095
  const target = event.target
2069
2096
  if (!(target instanceof HTMLElement)) return
2070
2097
 
@@ -2081,8 +2108,13 @@ onFind('.ActionBar', (actionBar) => {
2081
2108
 
2082
2109
  widget.addEventListener('pointerdown', handlePointerdown, { passive: true })
2083
2110
  widget.addEventListener('focusin', handleFocusin, { passive: true })
2111
+ // Bound on window without capture — capture would also pick up element blur events.
2112
+ window.addEventListener('blur', handleWindowBlur)
2113
+ window.addEventListener('keydown', clearRestoringFocus, { passive: true })
2084
2114
  onRemove(widget, () => {
2085
2115
  widget.removeEventListener('pointerdown', handlePointerdown)
2086
2116
  widget.removeEventListener('focusin', handleFocusin)
2117
+ window.removeEventListener('blur', handleWindowBlur)
2118
+ window.removeEventListener('keydown', clearRestoringFocus)
2087
2119
  })
2088
2120
  })