react-native-gtkx 0.2.0-alpha.2 → 0.3.0-alpha.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.
- package/README.md +5 -2
- package/dist/aliases/index.d.ts +84 -0
- package/dist/aliases/index.js +208 -0
- package/dist/aliases/index.js.map +1 -0
- package/dist/animated/index.d.ts +2 -0
- package/dist/animated/index.js +5 -0
- package/dist/animated/index.js.map +1 -1
- package/dist/animated/types.d.ts +1 -0
- package/dist/animated/types.js.map +1 -1
- package/dist/animated/value-animation.js +17 -4
- package/dist/animated/value-animation.js.map +1 -1
- package/dist/apis/host.gtkx.js +9 -12
- package/dist/apis/host.gtkx.js.map +1 -1
- package/dist/apis/index.d.ts +4 -2
- package/dist/apis/index.js +2 -0
- package/dist/apis/index.js.map +1 -1
- package/dist/apis/keyboard.d.ts +60 -0
- package/dist/apis/keyboard.js +63 -0
- package/dist/apis/keyboard.js.map +1 -0
- package/dist/apis/log-box.d.ts +15 -0
- package/dist/apis/log-box.js +46 -0
- package/dist/apis/log-box.js.map +1 -0
- package/dist/apis/platform.d.ts +18 -1
- package/dist/apis/platform.js.map +1 -1
- package/dist/common/index.d.ts +0 -1
- package/dist/common/index.js +24 -1
- package/dist/common/index.js.map +1 -1
- package/dist/components/animated.d.ts +70 -6
- package/dist/components/animated.js +559 -46
- package/dist/components/animated.js.map +1 -1
- package/dist/components/driven-size.d.ts +27 -0
- package/dist/components/driven-size.js +85 -0
- package/dist/components/driven-size.js.map +1 -0
- package/dist/components/find-node-handle.d.ts +11 -0
- package/dist/components/find-node-handle.js +53 -0
- package/dist/components/find-node-handle.js.map +1 -0
- package/dist/components/flat-list.d.ts +3 -2
- package/dist/components/flat-list.js.map +1 -1
- package/dist/components/frame-scheduler.d.ts +16 -0
- package/dist/components/frame-scheduler.js +37 -0
- package/dist/components/frame-scheduler.js.map +1 -0
- package/dist/components/image.d.ts +6 -1
- package/dist/components/image.js +15 -4
- package/dist/components/image.js.map +1 -1
- package/dist/components/index.d.ts +7 -5
- package/dist/components/index.js +5 -3
- package/dist/components/index.js.map +1 -1
- package/dist/components/measure.d.ts +51 -1
- package/dist/components/measure.js +101 -2
- package/dist/components/measure.js.map +1 -1
- package/dist/components/pressable.d.ts +61 -1
- package/dist/components/pressable.js +151 -4
- package/dist/components/pressable.js.map +1 -1
- package/dist/components/rect-store.d.ts +58 -0
- package/dist/components/rect-store.js +124 -3
- package/dist/components/rect-store.js.map +1 -1
- package/dist/components/root.js +6 -1
- package/dist/components/root.js.map +1 -1
- package/dist/components/scroll-phase.d.ts +35 -0
- package/dist/components/scroll-phase.js +26 -0
- package/dist/components/scroll-phase.js.map +1 -0
- package/dist/components/scroll-view.d.ts +39 -3
- package/dist/components/scroll-view.js +378 -43
- package/dist/components/scroll-view.js.map +1 -1
- package/dist/components/text-input.js +9 -25
- package/dist/components/text-input.js.map +1 -1
- package/dist/components/text.d.ts +6 -2
- package/dist/components/text.js +43 -8
- package/dist/components/text.js.map +1 -1
- package/dist/components/use-focus.d.ts +27 -0
- package/dist/components/use-focus.js +116 -0
- package/dist/components/use-focus.js.map +1 -0
- package/dist/components/use-layout-child.d.ts +13 -1
- package/dist/components/use-layout-child.js +188 -5
- package/dist/components/use-layout-child.js.map +1 -1
- package/dist/components/view.d.ts +5 -2
- package/dist/components/view.js +18 -13
- package/dist/components/view.js.map +1 -1
- package/dist/components/virtualized-list.d.ts +45 -5
- package/dist/components/virtualized-list.js +90 -24
- package/dist/components/virtualized-list.js.map +1 -1
- package/dist/components/wheel-scroll-session.d.ts +7 -0
- package/dist/components/wheel-scroll-session.js +53 -0
- package/dist/components/wheel-scroll-session.js.map +1 -0
- package/dist/components/widget-retention.d.ts +35 -0
- package/dist/components/widget-retention.js +169 -0
- package/dist/components/widget-retention.js.map +1 -0
- package/dist/contracts.d.ts +4 -0
- package/dist/contracts.js.map +1 -1
- package/dist/dnd/context.d.ts +69 -0
- package/dist/dnd/context.js +149 -0
- package/dist/dnd/context.js.map +1 -0
- package/dist/dnd/draggable.d.ts +59 -0
- package/dist/dnd/draggable.js +149 -0
- package/dist/dnd/draggable.js.map +1 -0
- package/dist/dnd/droppable.d.ts +24 -0
- package/dist/dnd/droppable.js +74 -0
- package/dist/dnd/droppable.js.map +1 -0
- package/dist/dnd/gtk-controllers.d.ts +39 -0
- package/dist/dnd/gtk-controllers.js +110 -0
- package/dist/dnd/gtk-controllers.js.map +1 -0
- package/dist/dnd/index.d.ts +6 -0
- package/dist/dnd/index.js +31 -0
- package/dist/dnd/index.js.map +1 -0
- package/dist/dnd/order.d.ts +7 -0
- package/dist/dnd/order.js +20 -0
- package/dist/dnd/order.js.map +1 -0
- package/dist/dnd/payload.d.ts +14 -0
- package/dist/dnd/payload.js +41 -0
- package/dist/dnd/payload.js.map +1 -0
- package/dist/dnd/sortable.d.ts +49 -0
- package/dist/dnd/sortable.js +307 -0
- package/dist/dnd/sortable.js.map +1 -0
- package/dist/dnd/types.d.ts +290 -0
- package/dist/dnd/types.js +25 -0
- package/dist/dnd/types.js.map +1 -0
- package/dist/gesture-handler-compat/builder.d.ts +251 -0
- package/dist/gesture-handler-compat/builder.js +513 -0
- package/dist/gesture-handler-compat/builder.js.map +1 -0
- package/dist/gesture-handler-compat/composition.d.ts +23 -0
- package/dist/gesture-handler-compat/composition.js +111 -0
- package/dist/gesture-handler-compat/composition.js.map +1 -0
- package/dist/gesture-handler-compat/deciders.d.ts +3 -0
- package/dist/gesture-handler-compat/deciders.js +47 -0
- package/dist/gesture-handler-compat/deciders.js.map +1 -0
- package/dist/gesture-handler-compat/detector-runtime.d.ts +44 -0
- package/dist/gesture-handler-compat/detector-runtime.js +374 -0
- package/dist/gesture-handler-compat/detector-runtime.js.map +1 -0
- package/dist/gesture-handler-compat/detector.d.ts +22 -0
- package/dist/gesture-handler-compat/detector.js +104 -0
- package/dist/gesture-handler-compat/detector.js.map +1 -0
- package/dist/gesture-handler-compat/fling.d.ts +24 -0
- package/dist/gesture-handler-compat/fling.js +123 -0
- package/dist/gesture-handler-compat/fling.js.map +1 -0
- package/dist/gesture-handler-compat/force-touch.d.ts +13 -0
- package/dist/gesture-handler-compat/force-touch.js +40 -0
- package/dist/gesture-handler-compat/force-touch.js.map +1 -0
- package/dist/gesture-handler-compat/hooks.d.ts +157 -0
- package/dist/gesture-handler-compat/hooks.js +268 -0
- package/dist/gesture-handler-compat/hooks.js.map +1 -0
- package/dist/gesture-handler-compat/hover.d.ts +2 -0
- package/dist/gesture-handler-compat/hover.js +22 -0
- package/dist/gesture-handler-compat/hover.js.map +1 -0
- package/dist/gesture-handler-compat/index.d.ts +98 -0
- package/dist/gesture-handler-compat/index.js +255 -0
- package/dist/gesture-handler-compat/index.js.map +1 -0
- package/dist/gesture-handler-compat/long-press.d.ts +6 -0
- package/dist/gesture-handler-compat/long-press.js +21 -0
- package/dist/gesture-handler-compat/long-press.js.map +1 -0
- package/dist/gesture-handler-compat/manual.d.ts +2 -0
- package/dist/gesture-handler-compat/manual.js +18 -0
- package/dist/gesture-handler-compat/manual.js.map +1 -0
- package/dist/gesture-handler-compat/native.d.ts +7 -0
- package/dist/gesture-handler-compat/native.js +34 -0
- package/dist/gesture-handler-compat/native.js.map +1 -0
- package/dist/gesture-handler-compat/orchestrator.d.ts +77 -0
- package/dist/gesture-handler-compat/orchestrator.js +284 -0
- package/dist/gesture-handler-compat/orchestrator.js.map +1 -0
- package/dist/gesture-handler-compat/pan.d.ts +23 -0
- package/dist/gesture-handler-compat/pan.js +116 -0
- package/dist/gesture-handler-compat/pan.js.map +1 -0
- package/dist/gesture-handler-compat/recognizer.d.ts +268 -0
- package/dist/gesture-handler-compat/recognizer.js +1056 -0
- package/dist/gesture-handler-compat/recognizer.js.map +1 -0
- package/dist/gesture-handler-compat/relations.d.ts +43 -0
- package/dist/gesture-handler-compat/relations.js +128 -0
- package/dist/gesture-handler-compat/relations.js.map +1 -0
- package/dist/gesture-handler-compat/tap.d.ts +6 -0
- package/dist/gesture-handler-compat/tap.js +29 -0
- package/dist/gesture-handler-compat/tap.js.map +1 -0
- package/dist/gesture-handler-compat/touchpad.d.ts +41 -0
- package/dist/gesture-handler-compat/touchpad.js +64 -0
- package/dist/gesture-handler-compat/touchpad.js.map +1 -0
- package/dist/gesture-handler-compat/types.d.ts +441 -0
- package/dist/gesture-handler-compat/types.js +167 -0
- package/dist/gesture-handler-compat/types.js.map +1 -0
- package/dist/gtk/controllers.d.ts +39 -0
- package/dist/gtk/controllers.js +92 -0
- package/dist/gtk/controllers.js.map +1 -0
- package/dist/gtk/index.d.ts +2 -1
- package/dist/gtk/index.js +7 -1
- package/dist/gtk/index.js.map +1 -1
- package/dist/gtkx/bridge/geometry.js +6 -4
- package/dist/gtkx/bridge/geometry.js.map +1 -1
- package/dist/gtkx/bridge/index.d.ts +5 -3
- package/dist/gtkx/bridge/index.js +6 -3
- package/dist/gtkx/bridge/index.js.map +1 -1
- package/dist/gtkx/bridge/slot-portal.js.map +1 -1
- package/dist/gtkx/bridge/use-signal.js +1 -1
- package/dist/gtkx/bridge/use-signal.js.map +1 -1
- package/dist/gtkx/bridge/view-box.d.ts +56 -0
- package/dist/gtkx/bridge/view-box.js +394 -9
- package/dist/gtkx/bridge/view-box.js.map +1 -1
- package/dist/gtkx/bridge/widget-css.d.ts +17 -0
- package/dist/gtkx/bridge/widget-css.js +72 -0
- package/dist/gtkx/bridge/widget-css.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/layout/driven-size.d.ts +12 -0
- package/dist/layout/driven-size.js +70 -0
- package/dist/layout/driven-size.js.map +1 -0
- package/dist/layout/engine.d.ts +17 -1
- package/dist/layout/engine.js +3 -20
- package/dist/layout/engine.js.map +1 -1
- package/dist/layout/node.d.ts +13 -0
- package/dist/layout/node.js +14 -0
- package/dist/layout/node.js.map +1 -1
- package/dist/layout/yoga.d.ts +3 -2
- package/dist/layout/yoga.js +5 -2
- package/dist/layout/yoga.js.map +1 -1
- package/dist/mcp/data/generated.d.ts +257 -60
- package/dist/mcp/data/generated.js +306 -62
- package/dist/mcp/data/generated.js.map +1 -1
- package/dist/metro/index.d.ts +10 -0
- package/dist/metro/index.js +21 -12
- package/dist/metro/index.js.map +1 -1
- package/dist/navigation/sidebar.d.ts +16 -0
- package/dist/navigation/sidebar.js +65 -1
- package/dist/navigation/sidebar.js.map +1 -1
- package/dist/reanimated-compat/animated-ref.d.ts +32 -0
- package/dist/reanimated-compat/animated-ref.js +57 -0
- package/dist/reanimated-compat/animated-ref.js.map +1 -0
- package/dist/reanimated-compat/animation.d.ts +177 -0
- package/dist/reanimated-compat/animation.js +540 -0
- package/dist/reanimated-compat/animation.js.map +1 -0
- package/dist/reanimated-compat/color.d.ts +28 -0
- package/dist/reanimated-compat/color.js +249 -0
- package/dist/reanimated-compat/color.js.map +1 -0
- package/dist/reanimated-compat/decay.d.ts +39 -0
- package/dist/reanimated-compat/decay.js +96 -0
- package/dist/reanimated-compat/decay.js.map +1 -0
- package/dist/reanimated-compat/easing.d.ts +30 -0
- package/dist/reanimated-compat/easing.js +76 -0
- package/dist/reanimated-compat/easing.js.map +1 -0
- package/dist/reanimated-compat/hooks.d.ts +14 -0
- package/dist/reanimated-compat/hooks.js +217 -0
- package/dist/reanimated-compat/hooks.js.map +1 -0
- package/dist/reanimated-compat/index.d.ts +258 -0
- package/dist/reanimated-compat/index.js +464 -0
- package/dist/reanimated-compat/index.js.map +1 -0
- package/dist/reanimated-compat/interpolation.d.ts +18 -0
- package/dist/reanimated-compat/interpolation.js +122 -0
- package/dist/reanimated-compat/interpolation.js.map +1 -0
- package/dist/reanimated-compat/layout-animation-config.d.ts +43 -0
- package/dist/reanimated-compat/layout-animation-config.js +78 -0
- package/dist/reanimated-compat/layout-animation-config.js.map +1 -0
- package/dist/reanimated-compat/layout-animation-presets.d.ts +117 -0
- package/dist/reanimated-compat/layout-animation-presets.js +498 -0
- package/dist/reanimated-compat/layout-animation-presets.js.map +1 -0
- package/dist/reanimated-compat/layout-animation-runtime.d.ts +21 -0
- package/dist/reanimated-compat/layout-animation-runtime.js +311 -0
- package/dist/reanimated-compat/layout-animation-runtime.js.map +1 -0
- package/dist/reanimated-compat/layout-animation-view.d.ts +27 -0
- package/dist/reanimated-compat/layout-animation-view.js +266 -0
- package/dist/reanimated-compat/layout-animation-view.js.map +1 -0
- package/dist/reanimated-compat/layout-animation.d.ts +171 -0
- package/dist/reanimated-compat/layout-animation.js +469 -0
- package/dist/reanimated-compat/layout-animation.js.map +1 -0
- package/dist/reanimated-compat/layout-transitions.d.ts +83 -0
- package/dist/reanimated-compat/layout-transitions.js +350 -0
- package/dist/reanimated-compat/layout-transitions.js.map +1 -0
- package/dist/reanimated-compat/mutable.d.ts +29 -0
- package/dist/reanimated-compat/mutable.js +139 -0
- package/dist/reanimated-compat/mutable.js.map +1 -0
- package/dist/reanimated-compat/props.d.ts +18 -0
- package/dist/reanimated-compat/props.js +111 -0
- package/dist/reanimated-compat/props.js.map +1 -0
- package/dist/reanimated-compat/scroll-handler.d.ts +119 -0
- package/dist/reanimated-compat/scroll-handler.js +274 -0
- package/dist/reanimated-compat/scroll-handler.js.map +1 -0
- package/dist/reanimated-compat/scroll-offset.d.ts +12 -0
- package/dist/reanimated-compat/scroll-offset.js +104 -0
- package/dist/reanimated-compat/scroll-offset.js.map +1 -0
- package/dist/reanimated-compat/style.d.ts +90 -0
- package/dist/reanimated-compat/style.js +452 -0
- package/dist/reanimated-compat/style.js.map +1 -0
- package/dist/reanimated-compat/test-timers.d.ts +28 -0
- package/dist/reanimated-compat/test-timers.js +136 -0
- package/dist/reanimated-compat/test-timers.js.map +1 -0
- package/dist/reanimated-compat/threads.d.ts +13 -0
- package/dist/reanimated-compat/threads.js +41 -0
- package/dist/reanimated-compat/threads.js.map +1 -0
- package/dist/reanimated-compat/tracking.d.ts +41 -0
- package/dist/reanimated-compat/tracking.js +106 -0
- package/dist/reanimated-compat/tracking.js.map +1 -0
- package/dist/reanimated-compat/updater-animations.d.ts +36 -0
- package/dist/reanimated-compat/updater-animations.js +273 -0
- package/dist/reanimated-compat/updater-animations.js.map +1 -0
- package/dist/responder/system.d.ts +80 -7
- package/dist/responder/system.js +143 -23
- package/dist/responder/system.js.map +1 -1
- package/dist/responder/use-responder.d.ts +11 -0
- package/dist/responder/use-responder.js +225 -6
- package/dist/responder/use-responder.js.map +1 -1
- package/dist/runner/host-dev.js +1 -1
- package/dist/runner/host-dev.js.map +1 -1
- package/dist/runner/host.js +1 -1
- package/dist/runner/host.js.map +1 -1
- package/dist/runner/index.js +3 -3
- package/dist/runner/index.js.map +1 -1
- package/dist/sea/gtkx-config-module.js +1 -1
- package/dist/sea/gtkx-config-module.js.map +1 -1
- package/dist/style/absolute-insets.d.ts +26 -0
- package/dist/style/absolute-insets.js +113 -0
- package/dist/style/absolute-insets.js.map +1 -0
- package/dist/style/animated-size.d.ts +25 -0
- package/dist/style/animated-size.js +225 -0
- package/dist/style/animated-size.js.map +1 -0
- package/dist/style/colors.d.ts +17 -0
- package/dist/style/colors.js +25 -6
- package/dist/style/colors.js.map +1 -1
- package/dist/style/imperative-css.d.ts +21 -0
- package/dist/style/imperative-css.js +63 -0
- package/dist/style/imperative-css.js.map +1 -0
- package/dist/style/index.d.ts +2 -1
- package/dist/style/index.js +2 -1
- package/dist/style/index.js.map +1 -1
- package/dist/style/split-style.js +5 -0
- package/dist/style/split-style.js.map +1 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/unsupported-export.d.ts +8 -0
- package/dist/unsupported-export.js +66 -0
- package/dist/unsupported-export.js.map +1 -0
- package/dist/vite/index.d.ts +21 -8
- package/dist/vite/index.js +127 -82
- package/dist/vite/index.js.map +1 -1
- package/dist/vitest/index.d.ts +2 -2
- package/dist/vitest/index.js.map +1 -1
- package/dist/worklets-compat/index.d.ts +4 -0
- package/dist/worklets-compat/index.js +28 -0
- package/dist/worklets-compat/index.js.map +1 -0
- package/dist/worklets-compat/surface.d.ts +110 -0
- package/dist/worklets-compat/surface.js +153 -0
- package/dist/worklets-compat/surface.js.map +1 -0
- package/package.json +25 -9
- package/types.d.ts +9 -0
- package/dist/common/list.d.ts +0 -82
- package/dist/common/list.js +0 -166
- package/dist/common/list.js.map +0 -1
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Children, createContext, forwardRef, useContext, useImperativeHandle, useLayoutEffect, useRef, useState, } from "react";
|
|
3
3
|
import { splitStyle, StyleSheet } from "../style/index";
|
|
4
|
-
import { Gtk, GtkBox, GtkScrolledWindow, queueAllocate, queueResize, useSignal, } from "../gtkx/bridge/index";
|
|
4
|
+
import { Gdk, Gtk, GtkBox, GtkScrolledWindow, queueAllocate, queueResize, useSignal, } from "../gtkx/bridge/index";
|
|
5
5
|
import { ensurePerfReporter, perfAddTime, perfCount, perfEnabled, perfFrameTick, perfNow, } from "../perf";
|
|
6
|
+
import { useResponder } from "../responder/use-responder";
|
|
6
7
|
import { HostNodeContext } from "./host-node";
|
|
8
|
+
import { createMeasureHandle, registerHandleWidget, } from "./measure";
|
|
7
9
|
import { deferDuringAllocate, setStoredOffset } from "./rect-store";
|
|
10
|
+
import { scrollPhaseSink } from "./scroll-phase";
|
|
8
11
|
import { useLayoutChild, useRnContainer, } from "./use-layout-child";
|
|
12
|
+
import { createWheelScrollSession } from "./wheel-scroll-session";
|
|
9
13
|
export const StickyRegistryContext = createContext(null);
|
|
10
14
|
// A wrapper around a sticky child: a plain container that reports its layout
|
|
11
15
|
// and widget into the registry, so the scroll handler can translate/reorder
|
|
@@ -42,7 +46,7 @@ export const StickySlot = ({ stickyKey, style, top, onLayout, children, }) => {
|
|
|
42
46
|
// node inside the same engine: the content's RnGtkxLayout measures the engine
|
|
43
47
|
// content size (which grows past the viewport — that IS the scroll range;
|
|
44
48
|
// overflow: scroll on the outer node) and the scrolled window pans it.
|
|
45
|
-
export const ScrollView = forwardRef(({ style, contentContainerStyle, horizontal = false, stickyHeaderIndices, onScroll, onContentSizeChange, onLayout, children, testID, }, handleRef) => {
|
|
49
|
+
export const ScrollView = forwardRef(({ style, contentContainerStyle, horizontal = false, stickyHeaderIndices, onScroll, onScrollBeginDrag, onScrollEndDrag, onMomentumScrollBegin, onMomentumScrollEnd, onContentSizeChange, onLayout, children, testID, ...responderProps }, handleRef) => {
|
|
46
50
|
const outerRef = useRef(null);
|
|
47
51
|
const contentRef = useRef(null);
|
|
48
52
|
const [scrolled, setScrolled] = useState(null);
|
|
@@ -50,11 +54,39 @@ export const ScrollView = forwardRef(({ style, contentContainerStyle, horizontal
|
|
|
50
54
|
// Yoga unconstrains a scroll node's MAIN axis — align it with the
|
|
51
55
|
// scroll direction or a horizontal list's content clamps to the
|
|
52
56
|
// viewport width (hadjustment upper == page).
|
|
57
|
+
//
|
|
58
|
+
// `flexGrow: 1, flexShrink: 1` is RN's own base style for the scroller
|
|
59
|
+
// (`styles.baseVertical` / `baseHorizontal` in ScrollView.js, applied as
|
|
60
|
+
// `StyleSheet.compose(baseStyle, this.props.style)` — hence base first,
|
|
61
|
+
// the app's style wins). The shrink half is what turns a scrollable with
|
|
62
|
+
// NO style of its own into a viewport: a flex item defaults to
|
|
63
|
+
// flexShrink 0 on RN's Yoga config, so without this the scroller sizes
|
|
64
|
+
// to its content, outgrows a bounded parent and its scroll range stays
|
|
65
|
+
// empty. It cost a whole investigation once: `@gorhom/bottom-sheet`
|
|
66
|
+
// hands its list down unstyled, so the sheet's scroll lock had nothing
|
|
67
|
+
// to lock — the list never received a scroll event because it had never
|
|
68
|
+
// become a viewport.
|
|
69
|
+
//
|
|
70
|
+
// Composing base-first does NOT protect an explicit `height`: grow and
|
|
71
|
+
// height are different properties, so nothing overrides anything — the
|
|
72
|
+
// height is the flex BASIS and grow expands from it, and a scroller with
|
|
73
|
+
// `height: 200` in a 400px column lays out at 400. RN does the same
|
|
74
|
+
// (same base, same order, same node, same Yoga resolution), so this is
|
|
75
|
+
// parity and not a bug; docs/api.md says so where people will look.
|
|
76
|
+
// Bound the PARENT to bound the viewport.
|
|
53
77
|
style: [
|
|
78
|
+
{ flexGrow: 1, flexShrink: 1 },
|
|
54
79
|
style,
|
|
55
80
|
{ overflow: "scroll", flexDirection: horizontal ? "row" : "column" },
|
|
56
81
|
],
|
|
57
82
|
onLayout,
|
|
83
|
+
// RN semantics: a ScrollView CLIPS its content. Containers paint-
|
|
84
|
+
// overflow by default, so without this the scrolled-away content (e.g.
|
|
85
|
+
// the original of a pinned sticky header) keeps drawing past the scroll
|
|
86
|
+
// area's edges. The `overflow: "scroll"` above would now clip the
|
|
87
|
+
// viewport on its own, but a viewport that clips only while nobody
|
|
88
|
+
// overrides the style is not a contract.
|
|
89
|
+
alwaysClips: true,
|
|
58
90
|
});
|
|
59
91
|
const [contentNode] = useState(() => host.engine.createNode());
|
|
60
92
|
// Sticky positions are computed INSIDE the same allocation pass that
|
|
@@ -68,13 +100,6 @@ export const ScrollView = forwardRef(({ style, contentContainerStyle, horizontal
|
|
|
68
100
|
}
|
|
69
101
|
},
|
|
70
102
|
});
|
|
71
|
-
// RN semantics: a ScrollView CLIPS its content. Branch B made containers
|
|
72
|
-
// paint-overflow by default, so without this the scrolled-away content
|
|
73
|
-
// (e.g. the original of a pinned sticky header) keeps drawing past the
|
|
74
|
-
// scroll area's edges.
|
|
75
|
-
useLayoutEffect(() => {
|
|
76
|
-
outerRef.current?.setOverflow(Gtk.Overflow.HIDDEN);
|
|
77
|
-
}, []);
|
|
78
103
|
useLayoutEffect(() => {
|
|
79
104
|
outerNode.insertChild(contentNode, 0);
|
|
80
105
|
contentNode.setCommit(() => {
|
|
@@ -103,39 +128,74 @@ export const ScrollView = forwardRef(({ style, contentContainerStyle, horizontal
|
|
|
103
128
|
useLayoutEffect(() => {
|
|
104
129
|
contentNode.setStyle({
|
|
105
130
|
flexDirection: horizontal ? "row" : "column",
|
|
106
|
-
|
|
131
|
+
// RN's content container is a plain `View`, and a `View`'s default
|
|
132
|
+
// `alignItems` is `stretch` — so a vertical ScrollView's children are
|
|
133
|
+
// as wide as the viewport unless they say otherwise. This used to be
|
|
134
|
+
// `flex-start`, which made every child shrink to its intrinsic width
|
|
135
|
+
// and any `flex: 1` inside it collapse to zero.
|
|
136
|
+
//
|
|
137
|
+
// It was found twice. First by `Sortable`, whose rows rendered as
|
|
138
|
+
// bare drag handles with no text (docs/research/drag-and-drop.md
|
|
139
|
+
// recorded it as a probable ScrollView parity bug and did not act on
|
|
140
|
+
// it, because changing a shared default under every example was not
|
|
141
|
+
// that epic's business). Then by porting
|
|
142
|
+
// `react-native-reanimated-dnd`'s example app, where it broke
|
|
143
|
+
// seventeen screens at once — at which point "a ported app changes
|
|
144
|
+
// nothing in its source" was simply false, and the default was the
|
|
145
|
+
// thing that was wrong.
|
|
146
|
+
//
|
|
147
|
+
// An app that wants the old behaviour writes it, exactly as it would
|
|
148
|
+
// on iOS and Android: `contentContainerStyle={{ alignItems:
|
|
149
|
+
// "flex-start" }}`.
|
|
150
|
+
alignItems: "stretch",
|
|
107
151
|
...contentLayout,
|
|
108
152
|
});
|
|
109
153
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
110
154
|
}, [contentNode, contentKey]);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
widget
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
155
|
+
// On the SCROLLED WINDOW, not on the content box: that is the widget the
|
|
156
|
+
// handle stands for, the widget a `GestureDetector` measures its gesture's
|
|
157
|
+
// view against, and the widget whose own kinetics a `Gesture.Native()`
|
|
158
|
+
// over this scrollable is talking about.
|
|
159
|
+
useResponder(outerRef, responderProps);
|
|
160
|
+
useImperativeHandle(handleRef, () => {
|
|
161
|
+
const handle = {
|
|
162
|
+
...createMeasureHandle(outerRef, outerNode),
|
|
163
|
+
scrollTo({ x, y }) {
|
|
164
|
+
const widget = outerRef.current;
|
|
165
|
+
if (!widget) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (y !== undefined) {
|
|
169
|
+
widget.getVadjustment()?.setValue(y);
|
|
170
|
+
}
|
|
171
|
+
if (x !== undefined) {
|
|
172
|
+
widget.getHadjustment()?.setValue(x);
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
scrollToEnd() {
|
|
176
|
+
const widget = outerRef.current;
|
|
177
|
+
const adjustment = horizontal
|
|
178
|
+
? widget?.getHadjustment()
|
|
179
|
+
: widget?.getVadjustment();
|
|
180
|
+
if (adjustment) {
|
|
181
|
+
adjustment.setValue(adjustment.getUpper() - adjustment.getPageSize());
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
// Spreading built a NEW object, and the widget lookup is keyed by
|
|
186
|
+
// handle identity — without this the composed handle is a stranger to
|
|
187
|
+
// measure.ts.
|
|
188
|
+
registerHandleWidget(handle, outerRef);
|
|
189
|
+
return handle;
|
|
190
|
+
});
|
|
134
191
|
// --- sticky headers -------------------------------------------------
|
|
135
192
|
// The RN model, faithfully: the REAL child is translated (no duplicate,
|
|
136
|
-
// state preserved). RN gives the pinned cell a zIndex;
|
|
137
|
-
//
|
|
138
|
-
//
|
|
193
|
+
// state preserved). RN gives the pinned cell a zIndex; this reorders the
|
|
194
|
+
// active slot to be the LAST content child while pinned and restores it
|
|
195
|
+
// afterwards, which predates `zIndex` working (gtkx/bridge/view-box.ts)
|
|
196
|
+
// and is kept because it is exact: the slots here are the ScrollView's own
|
|
197
|
+
// and their Yoga order is rebuilt from the same list, so the reorder that
|
|
198
|
+
// would be a hazard for arbitrary app children is not one for these. Per-frame movement
|
|
139
199
|
// goes through the rect-store offset fast path — zero React work while
|
|
140
200
|
// scrolling.
|
|
141
201
|
const stickySet = stickyHeaderIndices ?? [];
|
|
@@ -232,18 +292,20 @@ export const ScrollView = forwardRef(({ style, contentContainerStyle, horizontal
|
|
|
232
292
|
}
|
|
233
293
|
}
|
|
234
294
|
};
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
295
|
+
// The one place the payload is read off the widget, shared by `onScroll`
|
|
296
|
+
// and by all four phases — RN hands the same `ScrollEvent` to every one
|
|
297
|
+
// of them, and reading it twice would be two sets of FFI calls for one
|
|
298
|
+
// truth. Null when there is nothing honest to report yet (no widget, or
|
|
299
|
+
// a content size the engine has not committed).
|
|
300
|
+
const readScrollEvent = () => {
|
|
239
301
|
const widget = outerRef.current;
|
|
240
302
|
const contentRect = contentNode.getRect();
|
|
241
303
|
if (!widget || !contentRect) {
|
|
242
|
-
return;
|
|
304
|
+
return null;
|
|
243
305
|
}
|
|
244
306
|
const hadjustment = widget.getHadjustment();
|
|
245
307
|
const vadjustment = widget.getVadjustment();
|
|
246
|
-
|
|
308
|
+
return {
|
|
247
309
|
nativeEvent: {
|
|
248
310
|
contentOffset: {
|
|
249
311
|
x: hadjustment?.getValue() ?? 0,
|
|
@@ -255,7 +317,16 @@ export const ScrollView = forwardRef(({ style, contentContainerStyle, horizontal
|
|
|
255
317
|
height: vadjustment?.getPageSize() ?? 0,
|
|
256
318
|
},
|
|
257
319
|
},
|
|
258
|
-
}
|
|
320
|
+
};
|
|
321
|
+
};
|
|
322
|
+
const emitScroll = () => {
|
|
323
|
+
if (!onScroll) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
const event = readScrollEvent();
|
|
327
|
+
if (event) {
|
|
328
|
+
onScroll(event);
|
|
329
|
+
}
|
|
259
330
|
};
|
|
260
331
|
const adjustment = horizontal
|
|
261
332
|
? (scrolled?.getHadjustment() ?? null)
|
|
@@ -273,6 +344,270 @@ export const ScrollView = forwardRef(({ style, contentContainerStyle, horizontal
|
|
|
273
344
|
emitScroll();
|
|
274
345
|
perfAddTime("scroll.js", perfNow() - start);
|
|
275
346
|
};
|
|
347
|
+
// --- the four scroll phases -----------------------------------------
|
|
348
|
+
//
|
|
349
|
+
// What GTK actually reports, measured on 4.22.4 under a real pointer
|
|
350
|
+
// (docs/research/scroll-phases.md, and the trace is in
|
|
351
|
+
// tests/gtk/components/scroll-phases.gtk.test.tsx):
|
|
352
|
+
//
|
|
353
|
+
// - a mouse WHEEL emits `::scroll` per detent and NOTHING around it.
|
|
354
|
+
// GTK gives us no sequence, so while a consumer asks for begin/end we
|
|
355
|
+
// synthesize a desktop scroll SESSION: begin before the first detent
|
|
356
|
+
// mutates the adjustment, end after a measured idle window, and no
|
|
357
|
+
// momentum. This is an intentional desktop extension — RN has no
|
|
358
|
+
// wheel — and is what lets a phase-aware consumer capture the offset
|
|
359
|
+
// it is about to constrain instead of discovering it one event late.
|
|
360
|
+
// - a touchpad GLIDE emits `::scroll-begin`, a stream of `::scroll`,
|
|
361
|
+
// `::scroll-end` and `::decelerate` — a real sequence with a real
|
|
362
|
+
// beginning and end — and the scrolled window's own kinetic
|
|
363
|
+
// animation then carries the adjustment on for another second or so.
|
|
364
|
+
// All four phases exist, and all four are reported.
|
|
365
|
+
//
|
|
366
|
+
// Drag maps onto the scroll SEQUENCE rather than onto a finger on the
|
|
367
|
+
// content: `::scroll-begin` is "the user started driving this scroller",
|
|
368
|
+
// which is what a consumer of `onScrollBeginDrag` acts on and is as close
|
|
369
|
+
// as a device that never touches the content can get. That is the one
|
|
370
|
+
// approximation here, and it is named in docs/api.md.
|
|
371
|
+
//
|
|
372
|
+
// Momentum is read off the ADJUSTMENT, not off `::decelerate`. The
|
|
373
|
+
// controller emits `decelerate` at every `scroll-end` — it reports the
|
|
374
|
+
// velocity it measured, not a decision to coast — while the scrolled
|
|
375
|
+
// window decides for itself whether that velocity is worth animating. RN
|
|
376
|
+
// fires `onMomentumScrollBegin` only when the view actually keeps
|
|
377
|
+
// moving, so the honest source is the movement itself.
|
|
378
|
+
const phaseSink = scrollPhaseSink(onScroll);
|
|
379
|
+
// `wants()` rather than the sink's mere presence: every Reanimated scroll
|
|
380
|
+
// handler carries one, and most of them ask for nothing but `onScroll`.
|
|
381
|
+
// Asking is what keeps the common case free.
|
|
382
|
+
const wantsPhases = Boolean(onScrollBeginDrag ||
|
|
383
|
+
onScrollEndDrag ||
|
|
384
|
+
onMomentumScrollBegin ||
|
|
385
|
+
onMomentumScrollEnd ||
|
|
386
|
+
phaseSink?.wants());
|
|
387
|
+
// GTK brackets touchpad gestures for us. A wheel has only detents, so the
|
|
388
|
+
// begin/end extension below needs to see those detents — but only when a
|
|
389
|
+
// consumer asks for either end of the session. A momentum-only handler
|
|
390
|
+
// still pays no JS call per wheel event, because a wheel never coasts.
|
|
391
|
+
const wantsWheelSessions = Boolean(onScrollBeginDrag ||
|
|
392
|
+
onScrollEndDrag ||
|
|
393
|
+
phaseSink?.wants("beginDrag") ||
|
|
394
|
+
phaseSink?.wants("endDrag"));
|
|
395
|
+
// Read per event rather than captured, exactly as `useAnimatedScrollHandler`
|
|
396
|
+
// does it: a re-render that changed a handler must be picked up without
|
|
397
|
+
// tearing the GTK controller down and building a new one.
|
|
398
|
+
const phaseHandlers = useRef({
|
|
399
|
+
onScrollBeginDrag,
|
|
400
|
+
onScrollEndDrag,
|
|
401
|
+
onMomentumScrollBegin,
|
|
402
|
+
onMomentumScrollEnd,
|
|
403
|
+
phaseSink,
|
|
404
|
+
readScrollEvent,
|
|
405
|
+
});
|
|
406
|
+
phaseHandlers.current = {
|
|
407
|
+
onScrollBeginDrag,
|
|
408
|
+
onScrollEndDrag,
|
|
409
|
+
onMomentumScrollBegin,
|
|
410
|
+
onMomentumScrollEnd,
|
|
411
|
+
phaseSink,
|
|
412
|
+
readScrollEvent,
|
|
413
|
+
};
|
|
414
|
+
useLayoutEffect(() => {
|
|
415
|
+
// The whole cost story is this early return. No phase handler means no
|
|
416
|
+
// controller, no signal, no tick callback and no bookkeeping — the
|
|
417
|
+
// widget is byte-for-byte the one this component built before the
|
|
418
|
+
// phases existed.
|
|
419
|
+
if (!wantsPhases) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
const widget = scrolled;
|
|
423
|
+
if (!widget) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
const emitPhase = (phase) => {
|
|
427
|
+
const handlers = phaseHandlers.current;
|
|
428
|
+
const event = handlers.readScrollEvent();
|
|
429
|
+
if (!event) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
if (phase === "beginDrag") {
|
|
433
|
+
handlers.onScrollBeginDrag?.(event);
|
|
434
|
+
}
|
|
435
|
+
else if (phase === "endDrag") {
|
|
436
|
+
handlers.onScrollEndDrag?.(event);
|
|
437
|
+
}
|
|
438
|
+
else if (phase === "momentumBegin") {
|
|
439
|
+
handlers.onMomentumScrollBegin?.(event);
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
handlers.onMomentumScrollEnd?.(event);
|
|
443
|
+
}
|
|
444
|
+
handlers.phaseSink?.deliver(phase, event);
|
|
445
|
+
};
|
|
446
|
+
const axis = horizontal
|
|
447
|
+
? widget.getHadjustment()
|
|
448
|
+
: widget.getVadjustment();
|
|
449
|
+
// Momentum is watched on the ADJUSTMENT, with two timers and no tick
|
|
450
|
+
// callback. A frame-polling watcher was the first shape and it was
|
|
451
|
+
// wrong twice over: it burns a callback per frame for the length of
|
|
452
|
+
// every coast, and it counts FRAMES, which is not a unit — under the
|
|
453
|
+
// headless compositor the frame clock free-runs at ~106 ticks per
|
|
454
|
+
// millisecond (measured, docs/research/scroll-phases.md), so a
|
|
455
|
+
// four-frame grace expired in microseconds. Wall time means the same
|
|
456
|
+
// thing everywhere.
|
|
457
|
+
//
|
|
458
|
+
// Milliseconds to wait after `::scroll-end` for the scrolled window's
|
|
459
|
+
// kinetic animation to take over before concluding it never will.
|
|
460
|
+
// Measured handoff: `::scroll-end` at 1921.9 ms, first inertial value
|
|
461
|
+
// change at 1927.5 ms — 5.6 ms. 120 is slack, not a guess.
|
|
462
|
+
const handoffMs = 120;
|
|
463
|
+
// Milliseconds of a motionless adjustment that end the momentum. GTK's
|
|
464
|
+
// deceleration steps the value every frame right to the end (16.7 ms
|
|
465
|
+
// apart in the trace), so 60 ms is three and a half missed steps.
|
|
466
|
+
const restMs = 60;
|
|
467
|
+
let watching = false;
|
|
468
|
+
let coasting = false;
|
|
469
|
+
let lastMoveAt = 0;
|
|
470
|
+
let handoffTimer = null;
|
|
471
|
+
let restTimer = null;
|
|
472
|
+
const clearTimers = () => {
|
|
473
|
+
if (handoffTimer !== null) {
|
|
474
|
+
clearTimeout(handoffTimer);
|
|
475
|
+
handoffTimer = null;
|
|
476
|
+
}
|
|
477
|
+
if (restTimer !== null) {
|
|
478
|
+
clearTimeout(restTimer);
|
|
479
|
+
restTimer = null;
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
// Re-armed for the REMAINING idle time rather than reset on every step,
|
|
483
|
+
// so the number of timers a coast costs is bounded by its duration
|
|
484
|
+
// (one per `restMs`) and not by how many times the adjustment moved.
|
|
485
|
+
// The difference is not academic: under the headless compositor's
|
|
486
|
+
// free-running frame clock a single coast steps the value ~150,000
|
|
487
|
+
// times, and a clear-and-rearm per step is 150,000 timers.
|
|
488
|
+
const checkRest = () => {
|
|
489
|
+
const idle = perfNow() - lastMoveAt;
|
|
490
|
+
if (idle < restMs) {
|
|
491
|
+
restTimer = setTimeout(checkRest, restMs - idle);
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
restTimer = null;
|
|
495
|
+
stopMomentumWatch();
|
|
496
|
+
emitPhase("momentumEnd");
|
|
497
|
+
};
|
|
498
|
+
const onCoastStep = () => {
|
|
499
|
+
lastMoveAt = perfNow();
|
|
500
|
+
if (coasting) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
coasting = true;
|
|
504
|
+
if (handoffTimer !== null) {
|
|
505
|
+
clearTimeout(handoffTimer);
|
|
506
|
+
handoffTimer = null;
|
|
507
|
+
}
|
|
508
|
+
emitPhase("momentumBegin");
|
|
509
|
+
restTimer = setTimeout(checkRest, restMs);
|
|
510
|
+
};
|
|
511
|
+
const stopMomentumWatch = () => {
|
|
512
|
+
clearTimers();
|
|
513
|
+
if (watching) {
|
|
514
|
+
axis?.off("value-changed", onCoastStep);
|
|
515
|
+
watching = false;
|
|
516
|
+
}
|
|
517
|
+
coasting = false;
|
|
518
|
+
};
|
|
519
|
+
const watchMomentum = () => {
|
|
520
|
+
if (watching) {
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
watching = true;
|
|
524
|
+
axis?.on("value-changed", onCoastStep);
|
|
525
|
+
handoffTimer = setTimeout(() => {
|
|
526
|
+
handoffTimer = null;
|
|
527
|
+
if (!coasting) {
|
|
528
|
+
// The scroller came to rest with the drag. No inertia, so no
|
|
529
|
+
// momentum pair — which is RN's behaviour too.
|
|
530
|
+
stopMomentumWatch();
|
|
531
|
+
}
|
|
532
|
+
}, handoffMs);
|
|
533
|
+
};
|
|
534
|
+
const controller = Gtk.EventControllerScroll.new(
|
|
535
|
+
// An axis flag is REQUIRED, and not for the deltas: measured, a
|
|
536
|
+
// controller created with `KINETIC` alone emits nothing at all — not
|
|
537
|
+
// even `::scroll-begin`. `::scroll` is therefore emitted. It stays
|
|
538
|
+
// unconnected unless somebody asks for begin/end: only then does a
|
|
539
|
+
// wheel detent enter JS to maintain the desktop session below; a
|
|
540
|
+
// momentum-only or untracked scroller keeps the old empty C signal
|
|
541
|
+
// path.
|
|
542
|
+
Gtk.EventControllerScrollFlags.BOTH_AXES |
|
|
543
|
+
Gtk.EventControllerScrollFlags.KINETIC);
|
|
544
|
+
// CAPTURE, so the phase is reported before the scrolled window's own
|
|
545
|
+
// controller acts on the same event and moves the adjustment. Nothing
|
|
546
|
+
// here handles the event, so propagation is untouched either way.
|
|
547
|
+
controller.setPropagationPhase(Gtk.PropagationPhase.CAPTURE);
|
|
548
|
+
const beginDrag = () => {
|
|
549
|
+
// A new drag during a coast: RN ends the momentum before beginning
|
|
550
|
+
// the drag, so a consumer never sees two live phases at once.
|
|
551
|
+
if (coasting) {
|
|
552
|
+
stopMomentumWatch();
|
|
553
|
+
emitPhase("momentumEnd");
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
stopMomentumWatch();
|
|
557
|
+
}
|
|
558
|
+
emitPhase("beginDrag");
|
|
559
|
+
};
|
|
560
|
+
// A wheel gives GTK no begin/end signals. Group its detents into one
|
|
561
|
+
// user-driven session, ending after an idle interval longer than the
|
|
562
|
+
// ordinary detent spacing measured in docs/research/scroll-phases.md
|
|
563
|
+
// (20–33 ms in the trace). The callback runs in CAPTURE, so beginDrag
|
|
564
|
+
// sees the PRE-scroll offset before GtkScrolledWindow mutates its
|
|
565
|
+
// adjustment and emits the onScroll callback that consumes the context.
|
|
566
|
+
const wheelSession = createWheelScrollSession(beginDrag, () => emitPhase("endDrag"));
|
|
567
|
+
// A touchpad brackets itself, so its sequence owns the session while it
|
|
568
|
+
// runs. Two live sessions at once would hand a consumer a second
|
|
569
|
+
// `beginDrag` before the first `endDrag` — which is exactly the state
|
|
570
|
+
// gorhom's lock reads to decide where to pin its list.
|
|
571
|
+
let nativeSequence = false;
|
|
572
|
+
const onScrollBegin = () => {
|
|
573
|
+
nativeSequence = true;
|
|
574
|
+
// A wheel burst may still be waiting out its idle timer.
|
|
575
|
+
wheelSession.finish();
|
|
576
|
+
beginDrag();
|
|
577
|
+
};
|
|
578
|
+
const onScrollEnd = () => {
|
|
579
|
+
nativeSequence = false;
|
|
580
|
+
emitPhase("endDrag");
|
|
581
|
+
watchMomentum();
|
|
582
|
+
};
|
|
583
|
+
const onScroll = () => {
|
|
584
|
+
if (!wantsWheelSessions ||
|
|
585
|
+
nativeSequence ||
|
|
586
|
+
controller.getUnit() !== Gdk.ScrollUnit.WHEEL) {
|
|
587
|
+
return false;
|
|
588
|
+
}
|
|
589
|
+
wheelSession.detent();
|
|
590
|
+
// Observe only. GtkScrolledWindow still receives and applies the
|
|
591
|
+
// detent, which is what makes this phase seam transparent.
|
|
592
|
+
return false;
|
|
593
|
+
};
|
|
594
|
+
controller.on("scroll-begin", onScrollBegin);
|
|
595
|
+
controller.on("scroll-end", onScrollEnd);
|
|
596
|
+
if (wantsWheelSessions) {
|
|
597
|
+
controller.on("scroll", onScroll);
|
|
598
|
+
}
|
|
599
|
+
widget.addController(controller);
|
|
600
|
+
return () => {
|
|
601
|
+
controller.off("scroll-begin", onScrollBegin);
|
|
602
|
+
controller.off("scroll-end", onScrollEnd);
|
|
603
|
+
if (wantsWheelSessions) {
|
|
604
|
+
controller.off("scroll", onScroll);
|
|
605
|
+
}
|
|
606
|
+
wheelSession.dispose();
|
|
607
|
+
widget.removeController(controller);
|
|
608
|
+
stopMomentumWatch();
|
|
609
|
+
};
|
|
610
|
+
}, [scrolled, wantsPhases, wantsWheelSessions, horizontal]);
|
|
276
611
|
// Content-size reports dedupe on the engine rect: "changed" also fires
|
|
277
612
|
// for pure viewport (page-size) changes, which RN does not report.
|
|
278
613
|
const lastContentSize = useRef({ width: -1, height: -1 });
|