@ng-native/components 0.1.3 → 0.3.0

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.
Files changed (48) hide show
  1. package/dist/content-container.d.ts +25 -0
  2. package/dist/content-container.js +35 -0
  3. package/dist/content-container.js.map +1 -0
  4. package/dist/gestures-web.d.ts +12 -0
  5. package/dist/gestures-web.js +32 -0
  6. package/dist/gestures-web.js.map +1 -0
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/keyboard-avoiding-view.d.ts +6 -1
  10. package/dist/keyboard-avoiding-view.js +23 -6
  11. package/dist/keyboard-avoiding-view.js.map +1 -1
  12. package/dist/pressable.d.ts +33 -4
  13. package/dist/pressable.js +55 -3
  14. package/dist/pressable.js.map +1 -1
  15. package/dist/reanimated-web.d.ts +26 -0
  16. package/dist/reanimated-web.js +59 -0
  17. package/dist/reanimated-web.js.map +1 -0
  18. package/dist/refresh-control.d.ts +4 -1
  19. package/dist/refresh-control.js +4 -1
  20. package/dist/refresh-control.js.map +1 -1
  21. package/dist/scroll-view.d.ts +17 -1
  22. package/dist/scroll-view.js +59 -6
  23. package/dist/scroll-view.js.map +1 -1
  24. package/dist/section-list.d.ts +14 -2
  25. package/dist/section-list.js +20 -4
  26. package/dist/section-list.js.map +1 -1
  27. package/dist/sticky-headers.d.ts +6 -0
  28. package/dist/sticky-headers.js +7 -2
  29. package/dist/sticky-headers.js.map +1 -1
  30. package/dist/switch.d.ts +11 -1
  31. package/dist/switch.js +16 -3
  32. package/dist/switch.js.map +1 -1
  33. package/dist/text.d.ts +15 -0
  34. package/dist/text.js +26 -1
  35. package/dist/text.js.map +1 -1
  36. package/dist/touchable-opacity.d.ts +2 -1
  37. package/dist/touchable-opacity.js +3 -0
  38. package/dist/touchable-opacity.js.map +1 -1
  39. package/dist/view-base.d.ts +34 -18
  40. package/dist/view-base.js +52 -22
  41. package/dist/view-base.js.map +1 -1
  42. package/dist/virtual-list.d.ts +49 -5
  43. package/dist/virtual-list.js +129 -42
  44. package/dist/virtual-list.js.map +1 -1
  45. package/dist/zero-size-warning.d.ts +30 -0
  46. package/dist/zero-size-warning.js +58 -0
  47. package/dist/zero-size-warning.js.map +1 -0
  48. package/package.json +7 -4
@@ -1 +1 @@
1
- {"version":3,"file":"pressable.js","sourceRoot":"","sources":["../src/pressable.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Press handling, built on the engine's responder system as RN's `Pressability` is.\n *\n * `onPress` is not a native event: RN synthesises it in JS from the touch primitives, with a\n * press rectangle, delays and a long-press timer around them. This is that machine, on the same\n * responder negotiation, so a button and an enclosing scroll view agree on who owns a drag.\n */\nimport {\n Directive,\n booleanAttribute,\n forwardRef,\n input,\n numberAttribute,\n output,\n signal,\n} from '@angular/core';\nimport type { NativeSyntheticEvent } from '@ng-native/fabric';\nimport type { Insets, TouchEvent } from './events.ts';\nimport { ViewBase } from './view-base.ts';\n\n/** What a press handler receives: RN's `{nativeEvent}` shape, passed straight through. */\nexport type PressEvent = TouchEvent;\n\n/**\n * Android's ripple, drawn natively. `foreground` paints it over the content rather than behind.\n */\nexport interface AndroidRipple {\n readonly color?: string | number;\n readonly borderless?: boolean;\n readonly radius?: number;\n readonly foreground?: boolean;\n}\n\n/**\n * How far outside its own bounds a control keeps a press: RN's `DEFAULT_PRESS_RECT_OFFSETS`.\n * More room below, because a thumb rolls downwards as it lifts.\n */\nconst DEFAULT_PRESS_RETENTION: Required<Insets> = { top: 20, left: 20, right: 20, bottom: 30 };\n/** RN's `DEFAULT_LONG_PRESS_DELAY_MS`. */\nconst DEFAULT_LONG_PRESS_DELAY = 500;\n/** RN's `DEFAULT_MIN_PRESS_DURATION`: the pressed look stays at least this long on a quick tap. */\nconst DEFAULT_MIN_PRESS_DURATION = 130;\n\n/**\n * Used only until a control has been measured. RN measures the view and cancels when the touch\n * leaves its bounds plus the retention offset; before the first layout arrives there are no\n * bounds to compare against, so fall back to a small movement threshold rather than treating a\n * drag of any length as a tap.\n */\nconst PRESS_CANCEL_DISTANCE = 15;\n\nconst insets = (value: Insets | number | undefined, fallback: Required<Insets>) => {\n if (value === undefined) return fallback;\n if (typeof value === 'number') return { top: value, left: value, right: value, bottom: value };\n return {\n top: value.top ?? 0,\n left: value.left ?? 0,\n right: value.right ?? 0,\n bottom: value.bottom ?? 0,\n };\n};\n\n/** Page-space touch point, tolerating the several shapes a Fabric touch payload can take. */\nfunction touchPoint(event: NativeSyntheticEvent): { x: number; y: number } {\n const native = (event.nativeEvent ?? {}) as {\n pageX?: number;\n pageY?: number;\n touches?: { pageX?: number; pageY?: number }[];\n };\n const touch = native.touches?.[0];\n return {\n x: native.pageX ?? touch?.pageX ?? 0,\n y: native.pageY ?? touch?.pageY ?? 0,\n };\n}\n\n/** What `rippleDrawable` builds: Android's `RippleAndroid` drawable description. */\ninterface RippleDrawable {\n readonly type: 'RippleAndroid';\n readonly color: unknown;\n readonly borderless: boolean;\n readonly rippleRadius: number | undefined;\n}\n\nconst now = (): number => globalThis.performance?.now?.() ?? Date.now();\n\n/**\n * The press machine, and the base of every primitive that takes a touch.\n *\n * It declares no host bindings of its own, because `Text` extends it and a host binding runs on\n * every element that carries it, on every pass. The controls bind theirs through `ControlBase`.\n */\n@Directive()\nexport abstract class TouchableBase extends ViewBase {\n /** Ignore touches entirely. */\n readonly disabled = input(false, { transform: booleanAttribute });\n\n /**\n * How far outside the hit area a touch may wander before the press is cancelled. Native's\n * `hitSlop` grows the area a touch can start in; this grows the area it may move within.\n */\n readonly pressRetentionOffset = input<Insets | number>();\n /** Milliseconds a touch must be held before `(longPress)` fires. */\n readonly delayLongPress = input(DEFAULT_LONG_PRESS_DELAY, { transform: numberAttribute });\n /** Milliseconds between the touch landing and `(pressIn)`, so a scroll can start first. */\n readonly delayPressIn = input(0, { transform: numberAttribute });\n /** Milliseconds between the touch lifting and `(pressOut)`. */\n readonly delayPressOut = input(0, { transform: numberAttribute });\n /** The pressed state lasts at least this long, so a quick tap still shows it. */\n readonly minPressDuration = input(DEFAULT_MIN_PRESS_DURATION, { transform: numberAttribute });\n /** Whether a scrolling ancestor may take the gesture away mid-press. */\n readonly cancelable = input(true, { transform: booleanAttribute });\n /** Android: a native ripple on press. */\n readonly androidRipple = input<AndroidRipple>(undefined, { alias: 'android_ripple' });\n\n /** The touch lifted inside the press area. Not fired after a `(longPress)` that has a listener. */\n readonly press = output<PressEvent>();\n readonly pressIn = output<PressEvent>();\n readonly pressOut = output<PressEvent>();\n /**\n * The touch has been held for `delayLongPress`. With no listener there is no long press, as in\n * React Native, so a slow tap is still a `press`.\n */\n readonly longPress = output<PressEvent>();\n\n /** Whether a press is in progress, for the pressed look. */\n readonly pressed = signal(false);\n\n /**\n * Whether a pointer is over the control, which on this platform means an iPad with a trackpad\n * or a mouse. Always false on a phone, because a phone never sends a pointer event.\n *\n * Opted into by exactly the elements that opt into being measured, which is the same question\n * asked twice: is this a control, or is it a piece of text that merely inherits the machinery.\n * Registering on everything was the first attempt and put two props on every paragraph on\n * screen, which is the most numerous node in an app paying for a state a label cannot use.\n */\n readonly hovered = signal(false);\n\n /*\n * Methods rather than `computed()`s, because nearly every instance has no ripple and a computed\n * is an allocation per element whether or not it ever holds anything. The drawable is kept for as\n * long as the ripple it came from, which is the memo the computed was there to provide: a fresh\n * object on every pass would re-send the prop on every pass.\n */\n protected rippleBackground(): RippleDrawable | undefined {\n const ripple = this.androidRipple();\n return ripple && !ripple.foreground ? this.drawable(ripple) : undefined;\n }\n\n protected rippleForeground(): RippleDrawable | undefined {\n const ripple = this.androidRipple();\n return ripple?.foreground ? this.drawable(ripple) : undefined;\n }\n\n private drawn: { ripple: AndroidRipple; drawable: RippleDrawable } | null = null;\n\n private drawable(ripple: AndroidRipple): RippleDrawable {\n if (this.drawn?.ripple !== ripple)\n this.drawn = { ripple, drawable: this.rippleDrawable(ripple) };\n return this.drawn.drawable;\n }\n\n /**\n * The drawable description Android's `ReactDrawableHelper` reads.\n *\n * `color` goes through the engine the way every other colour prop does, and has to: the helper\n * switches on the value's runtime type and takes a number or a platform-colour map, and anything\n * else - a `'#ff0000'` written at the call site, say - falls through to `null` and the ripple\n * draws in the theme's own `colorControlHighlight` instead. Nothing is logged and nothing throws,\n * so the ripple appears and is simply the wrong colour. RN's own `TouchableNativeFeedback.Ripple`\n * calls `processColor` here for the same reason.\n */\n private rippleDrawable(ripple: AndroidRipple): RippleDrawable {\n return {\n type: 'RippleAndroid' as const,\n color: this.engine.color(ripple.color),\n borderless: ripple.borderless ?? false,\n rippleRadius: ripple.radius,\n };\n }\n\n /** Where the touch started, so a drag can be told apart from a tap. */\n private origin: { x: number; y: number } | null = null;\n /** The control's own size, from its last layout. Null until it has been measured once. */\n private size: { width: number; height: number } | null = null;\n private cancelled = false;\n private longPressed = false;\n /** How many `(longPress)` listeners there are; the long-press clock only runs with one. */\n private longPressListeners = 0;\n private pressedAt = 0;\n private pressInTimer: ReturnType<typeof setTimeout> | null = null;\n private longPressTimer: ReturnType<typeof setTimeout> | null = null;\n private pressOutTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor() {\n super();\n // output() has to be a member's own initializer for the compiler to see it, so its listeners\n // are counted here, through its public subscribe.\n const subscribe = this.longPress.subscribe.bind(this.longPress);\n this.longPress.subscribe = (callback) => {\n this.longPressListeners++;\n const subscription = subscribe(callback);\n let open = true;\n return {\n unsubscribe: () => {\n if (open) this.longPressListeners--;\n open = false;\n subscription.unsubscribe();\n },\n };\n };\n }\n\n /** Called as a press starts and ends, for a subclass that shows it natively. `Text` does. */\n protected pressedChanged(_pressed: boolean): void {}\n\n /** Whether a touch starting on this node should be claimed. `Text` narrows it. */\n protected claims(): boolean {\n return !this.disabled();\n }\n\n /**\n * Whether the control's size should be tracked. Native only measures a view that asks, so\n * this must not be true for every `<text>`: a pressable text opts in, a label never does.\n */\n protected measures(): boolean {\n return true;\n }\n\n /**\n * Whether a touch this far from where it started is still on the control.\n *\n * Distance from the origin is the wrong question on anything large: a thumb tap on a full-width\n * button easily travels twenty points without ever leaving it, and cancelling there reads as\n * \"the button doesn't work\", intermittently and only for some people. What matters is whether\n * the finger is still within the control plus its hit slop, plus the slop RN allows.\n *\n * The touch began somewhere inside the control but we do not know where, so the bound is the\n * full extent rather than half of it. That errs towards keeping the press, which is the right\n * way to be wrong: a press that survives a drag the user meant as a scroll is a smaller sin\n * than a tap that does nothing.\n */\n private stillOnControl(dx: number, dy: number): boolean {\n if (!this.size) return Math.hypot(dx, dy) <= PRESS_CANCEL_DISTANCE;\n const slop = insets(this.hitSlop(), { top: 0, left: 0, right: 0, bottom: 0 });\n const keep = insets(this.pressRetentionOffset(), DEFAULT_PRESS_RETENTION);\n const horizontal = dx < 0 ? slop.left + keep.left : slop.right + keep.right;\n const vertical = dy < 0 ? slop.top + keep.top : slop.bottom + keep.bottom;\n return (\n Math.abs(dx) <= this.size.width + horizontal && Math.abs(dy) <= this.size.height + vertical\n );\n }\n\n /**\n * A lifecycle hook rather than `inject(DestroyRef).onDestroy`: Angular registers a hook once per\n * directive type, where the callback was a closure and a lookup for every instance - and every\n * `<text>` on screen is one.\n */\n ngOnDestroy(): void {\n this.clearTimers();\n this.stopResponding?.();\n this.stopLayout?.();\n this.stopHover?.();\n }\n\n private stopResponding: (() => void) | null = null;\n private stopLayout: (() => void) | null = null;\n private stopHover: (() => void) | null = null;\n\n override ngOnInit(): void {\n super.ngOnInit();\n this.respondIfNeeded();\n this.measureIfNeeded();\n this.hoverIfNeeded();\n }\n\n override ngOnChanges(): void {\n super.ngOnChanges();\n this.respondIfNeeded();\n this.measureIfNeeded();\n this.hoverIfNeeded();\n }\n\n /**\n * Join the responder negotiation, once this is something a touch can press.\n *\n * Behind `measures()` for the same reason as layout and hover: a `<text>` is the commonest node\n * on screen and almost never a control, and registering every one cost a handler object, six\n * closures and a responder entry apiece for a touch it would have refused anyway.\n */\n private respondIfNeeded(): void {\n if (this.stopResponding || !this.measures()) return;\n this.stopResponding = this.engine.setResponder(this.node, {\n // Claim the gesture on touch down unless disabled. Because this goes through the\n // negotiation, an ancestor can pre-empt us in the capture pass and a nested pressable\n // wins over us in the bubble pass, neither of which raw touch listeners could express.\n onStartShouldSetResponder: () => this.claims(),\n onResponderGrant: (event) => this.onGrant(event),\n onResponderMove: (event) => this.onMove(event),\n onResponderRelease: (event) => this.onRelease(event),\n onResponderTerminate: (event) => this.onTerminate(event),\n // Yield to an enclosing scroll view when it takes over the drag, unless told not to.\n onResponderTerminationRequest: () => this.cancelable(),\n });\n }\n\n /**\n * `onLayout` is opted into by the engine as soon as something listens for it, which is the only\n * way the native side reports a view's size at all, and the reason it is only asked for once\n * `measures()` says so - a `<text>` answers that from an input, and most of them say no.\n *\n * Called from the lifecycle rather than watched by an effect. An effect per element is an\n * allocation and a scheduler entry for every pressable and every piece of text on screen, to\n * notice a change these two hooks already see.\n */\n /**\n * Hover, on the same terms and behind the same question.\n *\n * Fabric will not dispatch a pointer event to a view whose props have not asked for one, and\n * the engine writes those props when something listens - so listening is the whole opt-in. The\n * gate is `measures()`, which is not what its name is about but is the right question underneath\n * it: is this an actual control, or a piece of text that merely inherits the machinery. A label\n * says no, and two props on every paragraph on screen is not a cost worth paying for a hover\n * state a label has no use for.\n *\n * Never true on a phone, which sends no pointer events at all. This is the one thing an iPad\n * with a trackpad has that a phone does not.\n */\n private hoverIfNeeded(): void {\n if (this.stopHover || !this.measures()) return;\n const enter = this.engine.setEventListener(this.node, 'topPointerEnter', () =>\n this.hovered.set(true),\n );\n const leave = this.engine.setEventListener(this.node, 'topPointerLeave', () =>\n this.hovered.set(false),\n );\n this.stopHover = () => {\n enter();\n leave();\n };\n }\n\n private measureIfNeeded(): void {\n if (this.stopLayout || !this.measures()) return;\n this.stopLayout = this.engine.setEventListener(this.node, 'topLayout', (event) => {\n const layout = (event as NativeSyntheticEvent<{ layout?: { width: number; height: number } }>)\n .nativeEvent?.layout;\n if (layout) this.size = { width: layout.width, height: layout.height };\n });\n }\n\n private onGrant(event: PressEvent): void {\n this.origin = touchPoint(event);\n this.cancelled = false;\n this.longPressed = false;\n this.clearTimers();\n if (this.androidRipple()) {\n const { x, y } = this.origin;\n this.engine.dispatchCommand(this.node, 'hotspotUpdate', [x, y]);\n this.engine.dispatchCommand(this.node, 'setPressed', [true]);\n }\n const delay = this.delayPressIn();\n if (delay > 0) this.pressInTimer = setTimeout(() => this.activate(event), delay);\n else this.activate(event);\n }\n\n /** `pressIn`, and the long-press clock starts from here. */\n private activate(event: PressEvent): void {\n this.pressInTimer = null;\n this.pressedAt = now();\n this.pressed.set(true);\n this.pressedChanged(true);\n this.pressIn.emit(event);\n if (!this.longPressListeners) return;\n this.longPressTimer = setTimeout(() => {\n this.longPressTimer = null;\n this.longPressed = true;\n this.longPress.emit(event);\n }, this.delayLongPress());\n }\n\n private onMove(event: PressEvent): void {\n if (this.cancelled || !this.origin) return;\n const point = touchPoint(event);\n if (this.stillOnControl(point.x - this.origin.x, point.y - this.origin.y)) return;\n // The finger has wandered: this is a drag, not a tap. Give up the press but stay the\n // responder, so a scroll view underneath still gets its gesture.\n this.cancelled = true;\n this.deactivate(event);\n }\n\n private onRelease(event: PressEvent): void {\n if (this.androidRipple()) this.engine.dispatchCommand(this.node, 'setPressed', [false]);\n if (this.cancelled) return;\n // Lifted before the press-in delay ran out: RN still reports a full press.\n if (this.pressInTimer) {\n clearTimeout(this.pressInTimer);\n this.activate(event);\n }\n const longPressed = this.longPressed;\n this.deactivate(event);\n if (!longPressed) this.press.emit(event);\n }\n\n private onTerminate(event: PressEvent): void {\n if (this.androidRipple()) this.engine.dispatchCommand(this.node, 'setPressed', [false]);\n if (this.cancelled) return;\n this.cancelled = true;\n this.deactivate(event);\n }\n\n /** `pressOut`, no sooner than `minPressDuration` after `pressIn` and after `delayPressOut`. */\n private deactivate(event: PressEvent): void {\n if (this.pressInTimer) {\n clearTimeout(this.pressInTimer);\n this.pressInTimer = null;\n return;\n }\n if (this.longPressTimer) {\n clearTimeout(this.longPressTimer);\n this.longPressTimer = null;\n }\n if (!this.pressed()) return;\n const held = now() - this.pressedAt;\n const delay = Math.max(this.delayPressOut(), this.minPressDuration() - held);\n const out = () => {\n this.pressOutTimer = null;\n this.pressed.set(false);\n this.pressedChanged(false);\n this.pressOut.emit(event);\n };\n if (delay > 0) this.pressOutTimer = setTimeout(out, delay);\n else out();\n }\n\n private clearTimers(): void {\n // Every touchable is destroyed through here, and nearly all of them were never pressed.\n if (!this.pressInTimer && !this.longPressTimer && !this.pressOutTimer) return;\n for (const timer of [this.pressInTimer, this.longPressTimer, this.pressOutTimer]) {\n if (timer) clearTimeout(timer);\n }\n this.pressInTimer = this.longPressTimer = this.pressOutTimer = null;\n }\n}\n\n/**\n * A touchable that is a control: `Pressable`, `TouchableOpacity` and `PressBehavior`.\n *\n * The host bindings every control needs live here rather than on `TouchableBase`, which `Text`\n * extends: the state that follows `disabled`, and the Android ripple. Controls are few enough on\n * a screen to pay for a binding on every pass; texts are not.\n */\n@Directive({\n host: {\n // `disabled` is an input of ours, so it cannot reach `ngOnChanges` on the base; this is\n // the one binding that keeps the announced state in step with it.\n '[accessibilityState]': 'accessibilityStateProp()',\n // Nor is it left on the node for `:disabled` to read, so this is what a stylesheet matches.\n '[attr.data-disabled]': \"disabled() ? '' : null\",\n '[nativeBackgroundAndroid]': 'rippleBackground()',\n '[nativeForegroundAndroid]': 'rippleForeground()',\n },\n})\nexport abstract class ControlBase extends TouchableBase {}\n\n/**\n * The press machine on its own, for a component that wants to be pressable rather than to\n * contain something that is.\n *\n * No selector: this is only ever a `hostDirectives` entry. A component listing it gets the whole\n * of `TouchableBase` on its own host node - the responder negotiation, the press rectangle, the\n * delays and the long-press timer - instead of wrapping a `<pressable>` and paying for a second\n * native view.\n *\n * It provides `TouchableBase`, so a primitive on the same node can `inject(TouchableBase)` and\n * read `pressed` without caring whether it landed on this or on a real `<pressable>`.\n */\n@Directive({\n providers: [{ provide: TouchableBase, useExisting: forwardRef(() => PressBehavior) }],\n})\nexport class PressBehavior extends ControlBase {\n protected override accessibleByDefault(): boolean {\n return true;\n }\n\n protected override focusableByDefault(): boolean {\n return true;\n }\n\n protected override disabledForAccessibility(): boolean {\n return this.disabled();\n }\n}\n\n/**\n * A view that responds to presses. RN's `Pressable`, with the same configuration: hit slop,\n * retention offset, press-in and press-out delays, long press, and an Android ripple.\n *\n * `pressed` is a public signal, so a template can style from it through a template reference:\n * `<pressable #p [style.opacity]=\"p.pressed() ? 0.5 : 1\">`.\n */\n@Directive({\n selector: 'pressable',\n exportAs: 'pressable',\n providers: [{ provide: TouchableBase, useExisting: forwardRef(() => Pressable) }],\n})\nexport class Pressable extends ControlBase {\n /** `Pressable.js`: a control is an accessibility element, and focusable, unless refused. */\n protected override accessibleByDefault(): boolean {\n return true;\n }\n\n protected override focusableByDefault(): boolean {\n return true;\n }\n\n protected override disabledForAccessibility(): boolean {\n return this.disabled();\n }\n}\n"]}
1
+ {"version":3,"file":"pressable.js","sourceRoot":"","sources":["../src/pressable.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Press handling, built on the engine's responder system as RN's `Pressability` is.\n *\n * `onPress` is not a native event: RN synthesises it in JS from the touch primitives, with a\n * press rectangle, delays and a long-press timer around them. This is that machine, on the same\n * responder negotiation, so a button and an enclosing scroll view agree on who owns a drag.\n */\nimport {\n Directive,\n booleanAttribute,\n forwardRef,\n input,\n numberAttribute,\n output,\n signal,\n} from '@angular/core';\nimport { nativePlatform, type NativeSyntheticEvent } from '@ng-native/fabric';\nimport type { Insets, TouchEvent } from './events.ts';\nimport { optionalBoolean } from './transforms.ts';\nimport { ViewBase } from './view-base.ts';\n\n/** What a press handler receives: RN's `{nativeEvent}` shape, passed straight through. */\nexport type PressEvent = TouchEvent;\n\n/**\n * Android's ripple, drawn natively. `foreground` paints it over the content rather than behind.\n */\nexport interface AndroidRipple {\n readonly color?: string | number;\n readonly borderless?: boolean;\n readonly radius?: number;\n readonly foreground?: boolean;\n}\n\n/**\n * How far outside its own bounds a control keeps a press: RN's `DEFAULT_PRESS_RECT_OFFSETS`.\n * More room below, because a thumb rolls downwards as it lifts.\n */\nconst DEFAULT_PRESS_RETENTION: Required<Insets> = { top: 20, left: 20, right: 20, bottom: 30 };\n/** RN's `DEFAULT_LONG_PRESS_DELAY_MS`. */\nconst DEFAULT_LONG_PRESS_DELAY = 500;\n/** RN's `DEFAULT_MIN_PRESS_DURATION`: the pressed look stays at least this long on a quick tap. */\nconst DEFAULT_MIN_PRESS_DURATION = 130;\n\n/**\n * Used only until a control has been measured. RN measures the view and cancels when the touch\n * leaves its bounds plus the retention offset; before the first layout arrives there are no\n * bounds to compare against, so fall back to a small movement threshold rather than treating a\n * drag of any length as a tap.\n */\nconst PRESS_CANCEL_DISTANCE = 15;\n\nconst insets = (value: Insets | number | undefined, fallback: Required<Insets>) => {\n if (value === undefined) return fallback;\n if (typeof value === 'number') return { top: value, left: value, right: value, bottom: value };\n return {\n top: value.top ?? 0,\n left: value.left ?? 0,\n right: value.right ?? 0,\n bottom: value.bottom ?? 0,\n };\n};\n\n/** Page-space touch point, tolerating the several shapes a Fabric touch payload can take. */\nfunction touchPoint(event: NativeSyntheticEvent): { x: number; y: number } {\n const native = (event.nativeEvent ?? {}) as {\n pageX?: number;\n pageY?: number;\n touches?: { pageX?: number; pageY?: number }[];\n };\n const touch = native.touches?.[0];\n return {\n x: native.pageX ?? touch?.pageX ?? 0,\n y: native.pageY ?? touch?.pageY ?? 0,\n };\n}\n\n/** What `rippleDrawable` builds: Android's `RippleAndroid` drawable description. */\ninterface RippleDrawable {\n readonly type: 'RippleAndroid';\n readonly color: unknown;\n readonly borderless: boolean;\n readonly rippleRadius: number | undefined;\n}\n\nconst now = (): number => globalThis.performance?.now?.() ?? Date.now();\n\n/**\n * The press machine, and the base of every primitive that takes a touch.\n *\n * It declares no host bindings of its own, because `Text` extends it and a host binding runs on\n * every element that carries it, on every pass. The controls bind theirs through `ControlBase`.\n */\n@Directive()\nexport abstract class TouchableBase extends ViewBase {\n /**\n * Ignore touches entirely. Undefined until set, because React Native tells \"not passed\" from\n * \"passed false\": only a passed `disabled` wins over `aria-disabled` in what is announced.\n */\n readonly disabled = input(undefined, { transform: optionalBoolean });\n\n /**\n * How far outside the hit area a touch may wander before the press is cancelled. Native's\n * `hitSlop` grows the area a touch can start in; this grows the area it may move within.\n */\n readonly pressRetentionOffset = input<Insets | number>();\n /** Milliseconds a touch must be held before `(longPress)` fires. */\n readonly delayLongPress = input(DEFAULT_LONG_PRESS_DELAY, { transform: numberAttribute });\n /** Milliseconds between the touch landing and `(pressIn)`, so a scroll can start first. */\n readonly delayPressIn = input(0, { transform: numberAttribute });\n /** Milliseconds between the touch lifting and `(pressOut)`. */\n readonly delayPressOut = input(0, { transform: numberAttribute });\n /** The pressed state lasts at least this long, so a quick tap still shows it. */\n readonly minPressDuration = input(DEFAULT_MIN_PRESS_DURATION, { transform: numberAttribute });\n /** Whether a scrolling ancestor may take the gesture away mid-press. */\n readonly cancelable = input(true, { transform: booleanAttribute });\n /** Android: a native ripple on press. */\n readonly androidRipple = input<AndroidRipple>(undefined, { alias: 'android_ripple' });\n\n /** The touch lifted inside the press area. Not fired after a `(longPress)` that has a listener. */\n readonly press = output<PressEvent>();\n readonly pressIn = output<PressEvent>();\n readonly pressOut = output<PressEvent>();\n /**\n * The touch has been held for `delayLongPress`. With no listener there is no long press, as in\n * React Native, so a slow tap is still a `press`.\n */\n readonly longPress = output<PressEvent>();\n\n /** Whether a press is in progress, for the pressed look. */\n readonly pressed = signal(false);\n\n /**\n * Whether a pointer is over the control, which on this platform means an iPad with a trackpad\n * or a mouse. Always false on a phone, because a phone never sends a pointer event.\n *\n * Opted into by exactly the elements that opt into being measured, which is the same question\n * asked twice: is this a control, or is it a piece of text that merely inherits the machinery.\n * Registering on everything was the first attempt and put two props on every paragraph on\n * screen, which is the most numerous node in an app paying for a state a label cannot use.\n */\n readonly hovered = signal(false);\n\n /*\n * Methods rather than `computed()`s, because nearly every instance has no ripple and a computed\n * is an allocation per element whether or not it ever holds anything. The drawable is kept for as\n * long as the ripple it came from, which is the memo the computed was there to provide: a fresh\n * object on every pass would re-send the prop on every pass.\n */\n protected rippleBackground(): RippleDrawable | undefined {\n const ripple = this.androidRipple();\n return ripple && !ripple.foreground ? this.drawable(ripple) : undefined;\n }\n\n protected rippleForeground(): RippleDrawable | undefined {\n const ripple = this.androidRipple();\n return ripple?.foreground ? this.drawable(ripple) : undefined;\n }\n\n private drawn: { ripple: AndroidRipple; drawable: RippleDrawable } | null = null;\n\n private drawable(ripple: AndroidRipple): RippleDrawable {\n if (this.drawn?.ripple !== ripple)\n this.drawn = { ripple, drawable: this.rippleDrawable(ripple) };\n return this.drawn.drawable;\n }\n\n /**\n * The drawable description Android's `ReactDrawableHelper` reads.\n *\n * `color` goes through the engine the way every other colour prop does, and has to: the helper\n * switches on the value's runtime type and takes a number or a platform-colour map, and anything\n * else - a `'#ff0000'` written at the call site, say - falls through to `null` and the ripple\n * draws in the theme's own `colorControlHighlight` instead. Nothing is logged and nothing throws,\n * so the ripple appears and is simply the wrong colour. RN's own `TouchableNativeFeedback.Ripple`\n * calls `processColor` here for the same reason.\n */\n private rippleDrawable(ripple: AndroidRipple): RippleDrawable {\n return {\n type: 'RippleAndroid' as const,\n color: this.engine.color(ripple.color),\n borderless: ripple.borderless ?? false,\n rippleRadius: ripple.radius,\n };\n }\n\n /** Where the touch started, so a drag can be told apart from a tap. */\n private origin: { x: number; y: number } | null = null;\n /** The control's own size, from its last layout. Null until it has been measured once. */\n private size: { width: number; height: number } | null = null;\n private cancelled = false;\n private longPressed = false;\n /** How many `(longPress)` listeners there are; the long-press clock only runs with one. */\n private longPressListeners = 0;\n private pressedAt = 0;\n private pressInTimer: ReturnType<typeof setTimeout> | null = null;\n private longPressTimer: ReturnType<typeof setTimeout> | null = null;\n private pressOutTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor() {\n super();\n // output() has to be a member's own initializer for the compiler to see it, so its listeners\n // are counted here, through its public subscribe.\n const subscribe = this.longPress.subscribe.bind(this.longPress);\n this.longPress.subscribe = (callback) => {\n this.longPressListeners++;\n const subscription = subscribe(callback);\n let open = true;\n return {\n unsubscribe: () => {\n if (open) this.longPressListeners--;\n open = false;\n subscription.unsubscribe();\n },\n };\n };\n }\n\n /** Called as a press starts and ends, for a subclass that shows it natively. `Text` does. */\n protected pressedChanged(_pressed: boolean): void {}\n\n /** Whether a touch starting on this node should be claimed. `Text` narrows it. */\n protected claims(): boolean {\n return !this.pressDisabled();\n }\n\n /**\n * Whether presses are refused. `Pressable.js` gives Pressability `disabled` alone, so here\n * `aria-disabled` and `accessibilityState.disabled` change what is announced and nothing else.\n * `TouchableOpacity` and `Text` widen it.\n */\n protected pressDisabled(): boolean {\n return !!this.disabled();\n }\n\n /**\n * `TouchableOpacity.js` and `Text.js`: `disabled ?? aria-disabled ?? accessibilityState.disabled`,\n * which is the merged announced state whenever `disabled` is unset.\n */\n protected disabledByAnyState(): boolean {\n return (this.disabled() ?? this.accessibilityStateProp()?.disabled) === true;\n }\n\n /**\n * Whether the control's size should be tracked. Native only measures a view that asks, so\n * this must not be true for every `<text>`: a pressable text opts in, a label never does.\n */\n protected measures(): boolean {\n return true;\n }\n\n /**\n * Whether a touch this far from where it started is still on the control.\n *\n * Distance from the origin is the wrong question on anything large: a thumb tap on a full-width\n * button easily travels twenty points without ever leaving it, and cancelling there reads as\n * \"the button doesn't work\", intermittently and only for some people. What matters is whether\n * the finger is still within the control plus its hit slop, plus the slop RN allows.\n *\n * The touch began somewhere inside the control but we do not know where, so the bound is the\n * full extent rather than half of it. That errs towards keeping the press, which is the right\n * way to be wrong: a press that survives a drag the user meant as a scroll is a smaller sin\n * than a tap that does nothing.\n */\n private stillOnControl(dx: number, dy: number): boolean {\n if (!this.size) return Math.hypot(dx, dy) <= PRESS_CANCEL_DISTANCE;\n const slop = insets(this.hitSlop(), { top: 0, left: 0, right: 0, bottom: 0 });\n const keep = insets(this.pressRetentionOffset(), DEFAULT_PRESS_RETENTION);\n const horizontal = dx < 0 ? slop.left + keep.left : slop.right + keep.right;\n const vertical = dy < 0 ? slop.top + keep.top : slop.bottom + keep.bottom;\n return (\n Math.abs(dx) <= this.size.width + horizontal && Math.abs(dy) <= this.size.height + vertical\n );\n }\n\n /**\n * A lifecycle hook rather than `inject(DestroyRef).onDestroy`: Angular registers a hook once per\n * directive type, where the callback was a closure and a lookup for every instance - and every\n * `<text>` on screen is one.\n */\n ngOnDestroy(): void {\n this.clearTimers();\n this.stopResponding?.();\n this.stopLayout?.();\n this.stopHover?.();\n this.stopClick?.();\n }\n\n private stopResponding: (() => void) | null = null;\n private stopLayout: (() => void) | null = null;\n private stopHover: (() => void) | null = null;\n private stopClick: (() => void) | null = null;\n\n override ngOnInit(): void {\n super.ngOnInit();\n this.respondIfNeeded();\n this.measureIfNeeded();\n this.hoverIfNeeded();\n this.clickIfNeeded();\n }\n\n override ngOnChanges(): void {\n super.ngOnChanges();\n this.respondIfNeeded();\n this.measureIfNeeded();\n this.hoverIfNeeded();\n this.clickIfNeeded();\n }\n\n /**\n * A press with no touch: Android's `performClick()`, which is what Enter, the D-pad centre and\n * TalkBack's double-tap do to a focused view, and which reaches us as `topClick` alone.\n *\n * `Pressability.js` answers it in `onClick`: `onPress` and nothing around it, not while disabled,\n * and not for a click carrying a `pointerType`, which is the pointer event a touch already\n * pressed through. It presses only the view that was clicked: a touchable the click only bubbled\n * through stops it there, so neither it nor anything above it acts on a click meant for a\n * focusable view inside it.\n *\n * Android only. iOS sends a click only as a pointer event, and the web host binds `topClick` to\n * the DOM's own click, which a mouse press already reached through the responder.\n */\n private clickIfNeeded(): void {\n if (this.stopClick || !this.measures() || nativePlatform() !== 'android') return;\n this.stopClick = this.engine.setEventListener(this.node, 'topClick', (event) => {\n const click = event as PressEvent;\n if (!this.measures() || Object.hasOwn(click.nativeEvent ?? {}, 'pointerType')) return;\n if (click.target !== this.node) {\n click.stopPropagation();\n return;\n }\n if (this.claims()) this.press.emit(click);\n });\n }\n\n /**\n * Join the responder negotiation, once this is something a touch can press.\n *\n * Behind `measures()` for the same reason as layout and hover: a `<text>` is the commonest node\n * on screen and almost never a control, and registering every one cost a handler object, six\n * closures and a responder entry apiece for a touch it would have refused anyway.\n */\n private respondIfNeeded(): void {\n if (this.stopResponding || !this.measures()) return;\n this.stopResponding = this.engine.setResponder(this.node, {\n // Claim the gesture on touch down unless disabled. Because this goes through the\n // negotiation, an ancestor can pre-empt us in the capture pass and a nested pressable\n // wins over us in the bubble pass, neither of which raw touch listeners could express.\n onStartShouldSetResponder: () => this.claims(),\n onResponderGrant: (event) => this.onGrant(event),\n onResponderMove: (event) => this.onMove(event),\n onResponderRelease: (event) => this.onRelease(event),\n onResponderTerminate: (event) => this.onTerminate(event),\n // Yield to an enclosing scroll view when it takes over the drag, unless told not to.\n onResponderTerminationRequest: () => this.cancelable(),\n });\n }\n\n /**\n * `onLayout` is opted into by the engine as soon as something listens for it, which is the only\n * way the native side reports a view's size at all, and the reason it is only asked for once\n * `measures()` says so - a `<text>` answers that from an input, and most of them say no.\n *\n * Called from the lifecycle rather than watched by an effect. An effect per element is an\n * allocation and a scheduler entry for every pressable and every piece of text on screen, to\n * notice a change these two hooks already see.\n */\n /**\n * Hover, on the same terms and behind the same question.\n *\n * Fabric will not dispatch a pointer event to a view whose props have not asked for one, and\n * the engine writes those props when something listens - so listening is the whole opt-in. The\n * gate is `measures()`, which is not what its name is about but is the right question underneath\n * it: is this an actual control, or a piece of text that merely inherits the machinery. A label\n * says no, and two props on every paragraph on screen is not a cost worth paying for a hover\n * state a label has no use for.\n *\n * Never true on a phone, which sends no pointer events at all. This is the one thing an iPad\n * with a trackpad has that a phone does not.\n */\n private hoverIfNeeded(): void {\n if (this.stopHover || !this.measures()) return;\n const enter = this.engine.setEventListener(this.node, 'topPointerEnter', () =>\n this.hovered.set(true),\n );\n const leave = this.engine.setEventListener(this.node, 'topPointerLeave', () =>\n this.hovered.set(false),\n );\n this.stopHover = () => {\n enter();\n leave();\n };\n }\n\n private measureIfNeeded(): void {\n if (this.stopLayout || !this.measures()) return;\n this.stopLayout = this.engine.setEventListener(this.node, 'topLayout', (event) => {\n const layout = (event as NativeSyntheticEvent<{ layout?: { width: number; height: number } }>)\n .nativeEvent?.layout;\n if (layout) this.size = { width: layout.width, height: layout.height };\n });\n }\n\n private onGrant(event: PressEvent): void {\n this.origin = touchPoint(event);\n this.cancelled = false;\n this.longPressed = false;\n this.clearTimers();\n if (this.androidRipple()) {\n const { x, y } = this.origin;\n this.engine.dispatchCommand(this.node, 'hotspotUpdate', [x, y]);\n this.engine.dispatchCommand(this.node, 'setPressed', [true]);\n }\n const delay = this.delayPressIn();\n if (delay > 0) this.pressInTimer = setTimeout(() => this.activate(event), delay);\n else this.activate(event);\n }\n\n /** `pressIn`, and the long-press clock starts from here. */\n private activate(event: PressEvent): void {\n this.pressInTimer = null;\n this.pressedAt = now();\n this.pressed.set(true);\n this.pressedChanged(true);\n this.pressIn.emit(event);\n if (!this.longPressListeners) return;\n this.longPressTimer = setTimeout(() => {\n this.longPressTimer = null;\n this.longPressed = true;\n this.longPress.emit(event);\n }, this.delayLongPress());\n }\n\n private onMove(event: PressEvent): void {\n if (this.cancelled || !this.origin) return;\n const point = touchPoint(event);\n if (this.stillOnControl(point.x - this.origin.x, point.y - this.origin.y)) return;\n // The finger has wandered: this is a drag, not a tap. Give up the press but stay the\n // responder, so a scroll view underneath still gets its gesture.\n this.cancelled = true;\n this.deactivate(event);\n }\n\n private onRelease(event: PressEvent): void {\n if (this.androidRipple()) this.engine.dispatchCommand(this.node, 'setPressed', [false]);\n if (this.cancelled) return;\n // Lifted before the press-in delay ran out: RN still reports a full press.\n if (this.pressInTimer) {\n clearTimeout(this.pressInTimer);\n this.activate(event);\n }\n const longPressed = this.longPressed;\n this.deactivate(event);\n if (!longPressed) this.press.emit(event);\n }\n\n private onTerminate(event: PressEvent): void {\n if (this.androidRipple()) this.engine.dispatchCommand(this.node, 'setPressed', [false]);\n if (this.cancelled) return;\n this.cancelled = true;\n this.deactivate(event);\n }\n\n /** `pressOut`, no sooner than `minPressDuration` after `pressIn` and after `delayPressOut`. */\n private deactivate(event: PressEvent): void {\n if (this.pressInTimer) {\n clearTimeout(this.pressInTimer);\n this.pressInTimer = null;\n return;\n }\n if (this.longPressTimer) {\n clearTimeout(this.longPressTimer);\n this.longPressTimer = null;\n }\n if (!this.pressed()) return;\n const held = now() - this.pressedAt;\n const delay = Math.max(this.delayPressOut(), this.minPressDuration() - held);\n const out = () => {\n this.pressOutTimer = null;\n this.pressed.set(false);\n this.pressedChanged(false);\n this.pressOut.emit(event);\n };\n if (delay > 0) this.pressOutTimer = setTimeout(out, delay);\n else out();\n }\n\n private clearTimers(): void {\n // Every touchable is destroyed through here, and nearly all of them were never pressed.\n if (!this.pressInTimer && !this.longPressTimer && !this.pressOutTimer) return;\n for (const timer of [this.pressInTimer, this.longPressTimer, this.pressOutTimer]) {\n if (timer) clearTimeout(timer);\n }\n this.pressInTimer = this.longPressTimer = this.pressOutTimer = null;\n }\n}\n\n/**\n * A touchable that is a control: `Pressable`, `TouchableOpacity` and `PressBehavior`.\n *\n * The host bindings every control needs live here rather than on `TouchableBase`, which `Text`\n * extends: the state that follows `disabled`, and the Android ripple. Controls are few enough on\n * a screen to pay for a binding on every pass; texts are not.\n */\n@Directive({\n host: {\n // `disabled` is an input of ours, so it cannot reach `ngOnChanges` on the base; this is\n // the one binding that keeps the announced state in step with it.\n '[accessibilityState]': 'accessibilityStateProp()',\n // Nor is it left on the node for `:disabled` to read, so this is what a stylesheet matches.\n '[attr.data-disabled]': \"disabled() ? '' : null\",\n '[nativeBackgroundAndroid]': 'rippleBackground()',\n '[nativeForegroundAndroid]': 'rippleForeground()',\n },\n})\nexport abstract class ControlBase extends TouchableBase {}\n\n/**\n * The press machine on its own, for a component that wants to be pressable rather than to\n * contain something that is.\n *\n * No selector: this is only ever a `hostDirectives` entry. A component listing it gets the whole\n * of `TouchableBase` on its own host node - the responder negotiation, the press rectangle, the\n * delays and the long-press timer - instead of wrapping a `<pressable>` and paying for a second\n * native view.\n *\n * It provides `TouchableBase`, so a primitive on the same node can `inject(TouchableBase)` and\n * read `pressed` without caring whether it landed on this or on a real `<pressable>`.\n */\n@Directive({\n providers: [{ provide: TouchableBase, useExisting: forwardRef(() => PressBehavior) }],\n})\nexport class PressBehavior extends ControlBase {\n protected override accessibleByDefault(): boolean {\n return true;\n }\n\n protected override focusableByDefault(): boolean {\n return true;\n }\n\n protected override disabledForAccessibility(): boolean | undefined {\n return this.disabled();\n }\n}\n\n/**\n * A view that responds to presses. RN's `Pressable`, with the same configuration: hit slop,\n * retention offset, press-in and press-out delays, long press, and an Android ripple.\n *\n * `pressed` is a public signal, so a template can style from it through a template reference:\n * `<pressable #p [style.opacity]=\"p.pressed() ? 0.5 : 1\">`.\n */\n@Directive({\n selector: 'pressable',\n exportAs: 'pressable',\n providers: [{ provide: TouchableBase, useExisting: forwardRef(() => Pressable) }],\n})\nexport class Pressable extends ControlBase {\n /** `Pressable.js`: a control is an accessibility element, and focusable, unless refused. */\n protected override accessibleByDefault(): boolean {\n return true;\n }\n\n protected override focusableByDefault(): boolean {\n return true;\n }\n\n protected override disabledForAccessibility(): boolean | undefined {\n return this.disabled();\n }\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import type { SharedValue, WorkletScrollSpec, WorkletStyleSpec } from './worklets.ts';
2
+ import * as i0 from "@angular/core";
3
+ export { workletScroll, workletStyle, type SharedValue, type WorkletScrollSpec, type WorkletStyleSpec, } from './worklets.ts';
4
+ /** Reanimated's public `SharedValue` surface, which code outside a worklet reads and writes. */
5
+ interface PlainSharedValue<T> extends SharedValue<T> {
6
+ get(): T;
7
+ set(value: T | ((value: T) => T)): void;
8
+ modify(modifier?: (value: T) => T): void;
9
+ addListener(id: number, listener: (value: T) => void): void;
10
+ removeListener(id: number): void;
11
+ }
12
+ /**
13
+ * A shared value as a plain holder, with no second runtime to share it with. Every write reaches
14
+ * the listeners added with `addListener`.
15
+ */
16
+ export declare function sharedValue<T>(initial: T): PlainSharedValue<T>;
17
+ export declare class WorkletStyle {
18
+ readonly workletStyle: import("@angular/core").InputSignal<WorkletStyleSpec>;
19
+ static ɵfac: i0.ɵɵFactoryDeclaration<WorkletStyle, never>;
20
+ static ɵdir: i0.ɵɵDirectiveDeclaration<WorkletStyle, "[workletStyle]", never, { "workletStyle": { "alias": "workletStyle"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
21
+ }
22
+ export declare class WorkletScroll {
23
+ readonly workletScroll: import("@angular/core").InputSignal<WorkletScrollSpec>;
24
+ static ɵfac: i0.ɵɵFactoryDeclaration<WorkletScroll, never>;
25
+ static ɵdir: i0.ɵɵDirectiveDeclaration<WorkletScroll, "[workletScroll]", never, { "workletScroll": { "alias": "workletScroll"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
26
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * `reanimated.ts`, for a browser build.
3
+ *
4
+ * A web bundler resolves `@ng-native/components/reanimated` here, through the `browser` condition
5
+ * in this package's `exports`; Metro, on a device, never sets that condition and gets the native
6
+ * file. A browser has no UI-thread runtime to run a worklet on, so everything here is inert: the
7
+ * names are the same, a template that binds `[workletStyle]` or `[workletScroll]` still renders,
8
+ * and the directives do nothing.
9
+ */
10
+ import { Directive, input } from '@angular/core';
11
+ import * as i0 from "@angular/core";
12
+ export { workletScroll, workletStyle, } from "./worklets.js";
13
+ /**
14
+ * A shared value as a plain holder, with no second runtime to share it with. Every write reaches
15
+ * the listeners added with `addListener`.
16
+ */
17
+ export function sharedValue(initial) {
18
+ let current = initial;
19
+ const listeners = new Map();
20
+ const write = (next) => {
21
+ current = next;
22
+ for (const listener of listeners.values())
23
+ listener(next);
24
+ };
25
+ return {
26
+ get value() {
27
+ return current;
28
+ },
29
+ set value(next) {
30
+ write(next);
31
+ },
32
+ get: () => current,
33
+ set: (next) => write(typeof next === 'function' ? next(current) : next),
34
+ modify: (modifier = (value) => value) => write(modifier(current)),
35
+ addListener: (id, listener) => void listeners.set(id, listener),
36
+ removeListener: (id) => void listeners.delete(id),
37
+ };
38
+ }
39
+ export class WorkletStyle {
40
+ workletStyle = input.required(/* @ts-ignore */
41
+ ...(ngDevMode ? [{ debugName: "workletStyle" }] : /* istanbul ignore next */ []));
42
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: WorkletStyle, deps: [], target: i0.ɵɵFactoryTarget.Directive });
43
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.2.0", type: WorkletStyle, isStandalone: true, selector: "[workletStyle]", inputs: { workletStyle: { classPropertyName: "workletStyle", publicName: "workletStyle", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
44
+ }
45
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: WorkletStyle, decorators: [{
46
+ type: Directive,
47
+ args: [{ selector: '[workletStyle]' }]
48
+ }], propDecorators: { workletStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "workletStyle", required: true }] }] } });
49
+ export class WorkletScroll {
50
+ workletScroll = input.required(/* @ts-ignore */
51
+ ...(ngDevMode ? [{ debugName: "workletScroll" }] : /* istanbul ignore next */ []));
52
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: WorkletScroll, deps: [], target: i0.ɵɵFactoryTarget.Directive });
53
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.2.0", type: WorkletScroll, isStandalone: true, selector: "[workletScroll]", inputs: { workletScroll: { classPropertyName: "workletScroll", publicName: "workletScroll", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
54
+ }
55
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: WorkletScroll, decorators: [{
56
+ type: Directive,
57
+ args: [{ selector: '[workletScroll]' }]
58
+ }], propDecorators: { workletScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "workletScroll", required: true }] }] } });
59
+ //# sourceMappingURL=reanimated-web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reanimated-web.js","sourceRoot":"","sources":["../src/reanimated-web.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;;AAGjD,OAAO,EACL,aAAa,EACb,YAAY,GAIb,MAAM,eAAe,CAAC;AAWvB;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAI,OAAU;IACvC,IAAI,OAAO,GAAG,OAAO,CAAC;IACtB,MAAM,SAAS,GAAG,IAAI,GAAG,EAA8B,CAAC;IACxD,MAAM,KAAK,GAAG,CAAC,IAAO,EAAE,EAAE;QACxB,OAAO,GAAG,IAAI,CAAC;QACf,KAAK,MAAM,QAAQ,IAAI,SAAS,CAAC,MAAM,EAAE;YAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5D,CAAC,CAAC;IACF,OAAO;QACL,IAAI,KAAK;YACP,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,IAAI,KAAK,CAAC,IAAI;YACZ,KAAK,CAAC,IAAI,CAAC,CAAC;QACd,CAAC;QACD,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO;QAClB,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,UAAU,CAAC,CAAC,CAAE,IAAwB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5F,MAAM,EAAE,CAAC,QAAQ,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjE,WAAW,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC;QAC/D,cAAc,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;KAClD,CAAC;AACJ,CAAC;AAGD,MAAM,OAAO,YAAY;IACd,YAAY,GAAG,KAAK,CAAC,QAAQ;qFAAoB,CAAC;uGADhD,YAAY;2FAAZ,YAAY;;2FAAZ,YAAY;kBADxB,SAAS;mBAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE;;AAMzC,MAAM,OAAO,aAAa;IACf,aAAa,GAAG,KAAK,CAAC,QAAQ;sFAAqB,CAAC;uGADlD,aAAa;2FAAb,aAAa;;2FAAb,aAAa;kBADzB,SAAS;mBAAC,EAAE,QAAQ,EAAE,iBAAiB,EAAE","sourcesContent":["/**\n * `reanimated.ts`, for a browser build.\n *\n * A web bundler resolves `@ng-native/components/reanimated` here, through the `browser` condition\n * in this package's `exports`; Metro, on a device, never sets that condition and gets the native\n * file. A browser has no UI-thread runtime to run a worklet on, so everything here is inert: the\n * names are the same, a template that binds `[workletStyle]` or `[workletScroll]` still renders,\n * and the directives do nothing.\n */\nimport { Directive, input } from '@angular/core';\nimport type { SharedValue, WorkletScrollSpec, WorkletStyleSpec } from './worklets.ts';\n\nexport {\n workletScroll,\n workletStyle,\n type SharedValue,\n type WorkletScrollSpec,\n type WorkletStyleSpec,\n} from './worklets.ts';\n\n/** Reanimated's public `SharedValue` surface, which code outside a worklet reads and writes. */\ninterface PlainSharedValue<T> extends SharedValue<T> {\n get(): T;\n set(value: T | ((value: T) => T)): void;\n modify(modifier?: (value: T) => T): void;\n addListener(id: number, listener: (value: T) => void): void;\n removeListener(id: number): void;\n}\n\n/**\n * A shared value as a plain holder, with no second runtime to share it with. Every write reaches\n * the listeners added with `addListener`.\n */\nexport function sharedValue<T>(initial: T): PlainSharedValue<T> {\n let current = initial;\n const listeners = new Map<number, (value: T) => void>();\n const write = (next: T) => {\n current = next;\n for (const listener of listeners.values()) listener(next);\n };\n return {\n get value() {\n return current;\n },\n set value(next) {\n write(next);\n },\n get: () => current,\n set: (next) => write(typeof next === 'function' ? (next as (value: T) => T)(current) : next),\n modify: (modifier = (value) => value) => write(modifier(current)),\n addListener: (id, listener) => void listeners.set(id, listener),\n removeListener: (id) => void listeners.delete(id),\n };\n}\n\n@Directive({ selector: '[workletStyle]' })\nexport class WorkletStyle {\n readonly workletStyle = input.required<WorkletStyleSpec>();\n}\n\n@Directive({ selector: '[workletScroll]' })\nexport class WorkletScroll {\n readonly workletScroll = input.required<WorkletScrollSpec>();\n}\n"]}
@@ -16,7 +16,10 @@ import * as i0 from "@angular/core";
16
16
  * the same, like on iOS, and moved into place after each pass; see `SwipeRefreshLayout`.
17
17
  */
18
18
  export declare class RefreshControl extends ViewBase implements AfterViewChecked {
19
- /** Whether the spinner shows. Two-way: `[(refreshing)]`. */
19
+ /**
20
+ * Whether the spinner shows. Only the app changes it: a pull fires `(refresh)` and leaves this
21
+ * alone, so `[(refreshing)]` and `[refreshing]` behave the same.
22
+ */
20
23
  readonly refreshing: import("@angular/core").ModelSignal<boolean>;
21
24
  /** How far from the top the spinner sits. */
22
25
  readonly progressViewOffset: import("@angular/core").InputSignalWithTransform<number | undefined, unknown>;
@@ -19,7 +19,10 @@ import * as i0 from "@angular/core";
19
19
  * the same, like on iOS, and moved into place after each pass; see `SwipeRefreshLayout`.
20
20
  */
21
21
  export class RefreshControl extends ViewBase {
22
- /** Whether the spinner shows. Two-way: `[(refreshing)]`. */
22
+ /**
23
+ * Whether the spinner shows. Only the app changes it: a pull fires `(refresh)` and leaves this
24
+ * alone, so `[(refreshing)]` and `[refreshing]` behave the same.
25
+ */
23
26
  refreshing = model(false, /* @ts-ignore */
24
27
  ...(ngDevMode ? [{ debugName: "refreshing" }] : /* istanbul ignore next */ []));
25
28
  /** How far from the top the spinner sits. */
@@ -1 +1 @@
1
- {"version":3,"file":"refresh-control.js","sourceRoot":"","sources":["../src/refresh-control.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AfterViewChecked,\n Directive,\n DestroyRef,\n afterEveryRender,\n effect,\n inject,\n input,\n model,\n signal,\n} from '@angular/core';\nimport { Engine, type EngineNode, nativePlatform } from '@ng-native/fabric';\nimport { SwipeRefreshLayout } from './swipe-refresh-layout.ts';\nimport { optionalBoolean, optionalNumber } from './transforms.ts';\nimport { ViewBase } from './view-base.ts';\n\n/**\n * Pull to refresh, as a child of a scroll view. Commits as `PullToRefreshView` on iOS and\n * `AndroidSwipeRefreshLayout` on Android.\n *\n * `refreshing` is a model: the pull fires `(refresh)`, the app sets `refreshing` to true while\n * it works and back to false when done. Native shows the spinner the instant the user pulls,\n * before the app has said anything, so the two can disagree. RN's wrapper reconciles them with\n * `setNativeRefreshing`; so does this. If the app never sets `refreshing` after a pull, the\n * spinner is stopped again, which is what RN's documentation warns about.\n *\n * On Android the swipe layout has to be the scroll view's *parent*, as RN's `ScrollView.js` makes\n * it, with the layout half of the scroll view's style moved onto it. It is written as a child all\n * the same, like on iOS, and moved into place after each pass; see `SwipeRefreshLayout`.\n */\n@Directive({\n selector: 'refresh-control',\n host: {\n '[refreshing]': 'refreshing()',\n '[progressViewOffset]': 'progressViewOffset()',\n '[tintColor]': 'tintColor()',\n '[title]': 'title()',\n '[titleColor]': 'titleColor()',\n '[colors]': 'colors()',\n '[enabled]': 'enabled()',\n '[progressBackgroundColor]': 'progressBackgroundColor()',\n '[size]': 'size()',\n '(refresh)': 'onNativeRefresh()',\n },\n})\nexport class RefreshControl extends ViewBase implements AfterViewChecked {\n /** Whether the spinner shows. Two-way: `[(refreshing)]`. */\n readonly refreshing = model(false);\n /** How far from the top the spinner sits. */\n readonly progressViewOffset = input(undefined, { transform: optionalNumber });\n /** iOS: the spinner's colour. */\n readonly tintColor = input<string>();\n /** iOS: a label under the spinner. */\n readonly title = input<string>();\n /** iOS: the label's colour. */\n readonly titleColor = input<string>();\n /** Android: the colours the spinner cycles through. */\n readonly colors = input<readonly string[]>();\n /** Android: whether pulling does anything. Defaults to true. */\n readonly enabled = input(undefined, { transform: optionalBoolean });\n /** Android: the spinner's background. */\n readonly progressBackgroundColor = input<string>();\n /** Android: the spinner's size. */\n readonly size = input<'default' | 'large'>();\n\n private readonly nativeRefreshing = signal<boolean | null>(null);\n\n /** Android only: what moves this control's node to wrap the scroll view. */\n private readonly wrap =\n nativePlatform() === 'android'\n ? new SwipeRefreshLayout(inject(Engine), this.node as EngineNode)\n : null;\n\n constructor() {\n super();\n const wrap = this.wrap;\n if (wrap) {\n // After every render as well as after this control's own pass: Angular moving the scroll\n // view happens in some other component's pass, and this one's hooks would not see it.\n afterEveryRender(() => wrap.sync());\n inject(DestroyRef).onDestroy(() => wrap.unwrap());\n }\n effect(() => {\n const desired = this.refreshing();\n const native = this.nativeRefreshing();\n if (native !== null && native !== desired) {\n this.nativeRefreshing.set(desired);\n this.engine.dispatchCommand(this.node, 'setNativeRefreshing', [desired]);\n }\n });\n }\n\n /**\n * The scroll view's style is written in the pass that declared this control, so splitting it\n * here reaches native in the same commit.\n */\n ngAfterViewChecked(): void {\n this.wrap?.sync();\n }\n\n /** Native has already started spinning; the app is told and expected to set `refreshing`. */\n protected onNativeRefresh(): void {\n this.nativeRefreshing.set(true);\n }\n}\n"]}
1
+ {"version":3,"file":"refresh-control.js","sourceRoot":"","sources":["../src/refresh-control.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AfterViewChecked,\n Directive,\n DestroyRef,\n afterEveryRender,\n effect,\n inject,\n input,\n model,\n signal,\n} from '@angular/core';\nimport { Engine, type EngineNode, nativePlatform } from '@ng-native/fabric';\nimport { SwipeRefreshLayout } from './swipe-refresh-layout.ts';\nimport { optionalBoolean, optionalNumber } from './transforms.ts';\nimport { ViewBase } from './view-base.ts';\n\n/**\n * Pull to refresh, as a child of a scroll view. Commits as `PullToRefreshView` on iOS and\n * `AndroidSwipeRefreshLayout` on Android.\n *\n * `refreshing` is a model: the pull fires `(refresh)`, the app sets `refreshing` to true while\n * it works and back to false when done. Native shows the spinner the instant the user pulls,\n * before the app has said anything, so the two can disagree. RN's wrapper reconciles them with\n * `setNativeRefreshing`; so does this. If the app never sets `refreshing` after a pull, the\n * spinner is stopped again, which is what RN's documentation warns about.\n *\n * On Android the swipe layout has to be the scroll view's *parent*, as RN's `ScrollView.js` makes\n * it, with the layout half of the scroll view's style moved onto it. It is written as a child all\n * the same, like on iOS, and moved into place after each pass; see `SwipeRefreshLayout`.\n */\n@Directive({\n selector: 'refresh-control',\n host: {\n '[refreshing]': 'refreshing()',\n '[progressViewOffset]': 'progressViewOffset()',\n '[tintColor]': 'tintColor()',\n '[title]': 'title()',\n '[titleColor]': 'titleColor()',\n '[colors]': 'colors()',\n '[enabled]': 'enabled()',\n '[progressBackgroundColor]': 'progressBackgroundColor()',\n '[size]': 'size()',\n '(refresh)': 'onNativeRefresh()',\n },\n})\nexport class RefreshControl extends ViewBase implements AfterViewChecked {\n /**\n * Whether the spinner shows. Only the app changes it: a pull fires `(refresh)` and leaves this\n * alone, so `[(refreshing)]` and `[refreshing]` behave the same.\n */\n readonly refreshing = model(false);\n /** How far from the top the spinner sits. */\n readonly progressViewOffset = input(undefined, { transform: optionalNumber });\n /** iOS: the spinner's colour. */\n readonly tintColor = input<string>();\n /** iOS: a label under the spinner. */\n readonly title = input<string>();\n /** iOS: the label's colour. */\n readonly titleColor = input<string>();\n /** Android: the colours the spinner cycles through. */\n readonly colors = input<readonly string[]>();\n /** Android: whether pulling does anything. Defaults to true. */\n readonly enabled = input(undefined, { transform: optionalBoolean });\n /** Android: the spinner's background. */\n readonly progressBackgroundColor = input<string>();\n /** Android: the spinner's size. */\n readonly size = input<'default' | 'large'>();\n\n private readonly nativeRefreshing = signal<boolean | null>(null);\n\n /** Android only: what moves this control's node to wrap the scroll view. */\n private readonly wrap =\n nativePlatform() === 'android'\n ? new SwipeRefreshLayout(inject(Engine), this.node as EngineNode)\n : null;\n\n constructor() {\n super();\n const wrap = this.wrap;\n if (wrap) {\n // After every render as well as after this control's own pass: Angular moving the scroll\n // view happens in some other component's pass, and this one's hooks would not see it.\n afterEveryRender(() => wrap.sync());\n inject(DestroyRef).onDestroy(() => wrap.unwrap());\n }\n effect(() => {\n const desired = this.refreshing();\n const native = this.nativeRefreshing();\n if (native !== null && native !== desired) {\n this.nativeRefreshing.set(desired);\n this.engine.dispatchCommand(this.node, 'setNativeRefreshing', [desired]);\n }\n });\n }\n\n /**\n * The scroll view's style is written in the pass that declared this control, so splitting it\n * here reaches native in the same commit.\n */\n ngAfterViewChecked(): void {\n this.wrap?.sync();\n }\n\n /** Native has already started spinning; the app is told and expected to set `refreshing`. */\n protected onNativeRefresh(): void {\n this.nativeRefreshing.set(true);\n }\n}\n"]}
@@ -33,6 +33,12 @@ import * as i0 from "@angular/core";
33
33
  export declare class ScrollView extends ScrollViewProps {
34
34
  /** Styles for the view that holds the children, e.g. padding and gap. */
35
35
  readonly contentContainerStyle: import("@angular/core").InputSignal<Record<string, unknown> | undefined>;
36
+ /**
37
+ * Classes for the view that holds the children, matched as if the view were written in the
38
+ * template the scroll view is. See `ContentContainer`. `contentContainerStyle` wins over it, as
39
+ * an inline style does over a class.
40
+ */
41
+ readonly contentContainerClass: import("@angular/core").InputSignal<string | undefined>;
36
42
  /**
37
43
  * The content view's style, with the row direction a horizontal scroll view needs.
38
44
  *
@@ -69,6 +75,16 @@ export declare class ScrollView extends ScrollViewProps {
69
75
  */
70
76
  protected readonly resolvedNestedScroll: import("@angular/core").Signal<boolean | undefined>;
71
77
  constructor();
78
+ /** The content's extent along the axis, and the scroll view's own, for `checkZeroSize`. */
79
+ private contentExtent;
80
+ private ownExtent;
81
+ private zeroSize;
82
+ /**
83
+ * In development only, the scroll view's own layout, to say when it stays at zero size with
84
+ * content in it. A release build listens for nothing, so it commits no `onLayout`.
85
+ */
86
+ private checkZeroSize;
87
+ private extent;
72
88
  /**
73
89
  * Sticky children are found again after each pass, because a pass can add or move them, and the
74
90
  * scroll offset is listened for only while there are any.
@@ -91,5 +107,5 @@ export declare class ScrollView extends ScrollViewProps {
91
107
  layout?: Size;
92
108
  }>): void;
93
109
  static ɵfac: i0.ɵɵFactoryDeclaration<ScrollView, never>;
94
- static ɵcmp: i0.ɵɵComponentDeclaration<ScrollView, "scroll-view", ["scrollView"], { "contentContainerStyle": { "alias": "contentContainerStyle"; "required": false; "isSignal": true; }; "horizontal": { "alias": "horizontal"; "required": false; "isSignal": true; }; "contentOffset": { "alias": "contentOffset"; "required": false; "isSignal": true; }; "maintainVisibleContentPosition": { "alias": "maintainVisibleContentPosition"; "required": false; "isSignal": true; }; "keyboardShouldPersistTaps": { "alias": "keyboardShouldPersistTaps"; "required": false; "isSignal": true; }; "nestedScrollEnabled": { "alias": "nestedScrollEnabled"; "required": false; "isSignal": true; }; "stickyHeaderIndices": { "alias": "stickyHeaderIndices"; "required": false; "isSignal": true; }; }, { "contentSizeChange": "contentSizeChange"; }, ["refreshControl"], ["refresh-control", "*"], true, never>;
110
+ static ɵcmp: i0.ɵɵComponentDeclaration<ScrollView, "scroll-view", ["scrollView"], { "contentContainerStyle": { "alias": "contentContainerStyle"; "required": false; "isSignal": true; }; "contentContainerClass": { "alias": "contentContainerClass"; "required": false; "isSignal": true; }; "horizontal": { "alias": "horizontal"; "required": false; "isSignal": true; }; "contentOffset": { "alias": "contentOffset"; "required": false; "isSignal": true; }; "maintainVisibleContentPosition": { "alias": "maintainVisibleContentPosition"; "required": false; "isSignal": true; }; "keyboardShouldPersistTaps": { "alias": "keyboardShouldPersistTaps"; "required": false; "isSignal": true; }; "nestedScrollEnabled": { "alias": "nestedScrollEnabled"; "required": false; "isSignal": true; }; "stickyHeaderIndices": { "alias": "stickyHeaderIndices"; "required": false; "isSignal": true; }; }, { "contentSizeChange": "contentSizeChange"; }, ["refreshControl"], ["refresh-control", "*"], true, never>;
95
111
  }
@@ -1,11 +1,13 @@
1
1
  import { Component, DestroyRef, ElementRef, afterEveryRender, computed, contentChild, inject, input, output, viewChild, } from '@angular/core';
2
2
  import { nativePlatform } from '@ng-native/fabric';
3
3
  import { dismissKeyboardOnTap } from "./keyboard-taps.js";
4
+ import { ContentContainer } from "./content-container.js";
4
5
  import { RefreshControl } from "./refresh-control.js";
5
6
  import { StickyHeaders } from "./sticky-headers.js";
6
7
  import { optionalBoolean } from "./transforms.js";
7
8
  import { ScrollViewProps } from "./scroll-view-props.js";
8
9
  import { View } from "./view.js";
10
+ import { ZeroSizeWarning, checksZeroSize, written } from "./zero-size-warning.js";
9
11
  import * as i0 from "@angular/core";
10
12
  /**
11
13
  * A scrolling container. Commits as `RCTScrollView`, with the children inside a content view.
@@ -38,6 +40,13 @@ export class ScrollView extends ScrollViewProps {
38
40
  /** Styles for the view that holds the children, e.g. padding and gap. */
39
41
  contentContainerStyle = input(/* @ts-ignore */
40
42
  ...(ngDevMode ? [undefined, { debugName: "contentContainerStyle" }] : /* istanbul ignore next */ []));
43
+ /**
44
+ * Classes for the view that holds the children, matched as if the view were written in the
45
+ * template the scroll view is. See `ContentContainer`. `contentContainerStyle` wins over it, as
46
+ * an inline style does over a class.
47
+ */
48
+ contentContainerClass = input(/* @ts-ignore */
49
+ ...(ngDevMode ? [undefined, { debugName: "contentContainerClass" }] : /* istanbul ignore next */ []));
41
50
  /**
42
51
  * The content view's style, with the row direction a horizontal scroll view needs.
43
52
  *
@@ -86,6 +95,30 @@ export class ScrollView extends ScrollViewProps {
86
95
  const stop = dismissKeyboardOnTap(this.engine, this.node, () => this.keyboardShouldPersistTaps());
87
96
  inject(DestroyRef).onDestroy(stop);
88
97
  this.trackStickyHeaders();
98
+ if (checksZeroSize())
99
+ this.checkZeroSize();
100
+ }
101
+ /** The content's extent along the axis, and the scroll view's own, for `checkZeroSize`. */
102
+ contentExtent = 0;
103
+ ownExtent;
104
+ zeroSize = null;
105
+ /**
106
+ * In development only, the scroll view's own layout, to say when it stays at zero size with
107
+ * content in it. A release build listens for nothing, so it commits no `onLayout`.
108
+ */
109
+ checkZeroSize() {
110
+ const warning = (this.zeroSize = new ZeroSizeWarning(() => written(this.node), () => !!this.horizontal()));
111
+ const stop = this.engine.setEventListener(this.node, 'topLayout', (event) => {
112
+ this.ownExtent = this.extent(event.nativeEvent?.layout);
113
+ warning.laidOut(this.ownExtent, this.contentExtent > 0);
114
+ });
115
+ inject(DestroyRef).onDestroy(() => {
116
+ stop();
117
+ warning.stop();
118
+ });
119
+ }
120
+ extent(size) {
121
+ return (this.horizontal() ? size?.width : size?.height) ?? 0;
89
122
  }
90
123
  /**
91
124
  * Sticky children are found again after each pass, because a pass can add or move them, and the
@@ -135,21 +168,34 @@ export class ScrollView extends ScrollViewProps {
135
168
  const layout = event.nativeEvent?.layout;
136
169
  if (layout)
137
170
  this.contentSizeChange.emit({ width: layout.width, height: layout.height });
171
+ if (this.zeroSize) {
172
+ this.contentExtent = this.extent(layout);
173
+ if (this.ownExtent !== undefined) {
174
+ this.zeroSize.laidOut(this.ownExtent, this.contentExtent > 0);
175
+ }
176
+ }
138
177
  }
139
178
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: ScrollView, deps: [], target: i0.ɵɵFactoryTarget.Component });
140
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.2.0", type: ScrollView, isStandalone: true, selector: "scroll-view", inputs: { contentContainerStyle: { classPropertyName: "contentContainerStyle", publicName: "contentContainerStyle", isSignal: true, isRequired: false, transformFunction: null }, horizontal: { classPropertyName: "horizontal", publicName: "horizontal", isSignal: true, isRequired: false, transformFunction: null }, contentOffset: { classPropertyName: "contentOffset", publicName: "contentOffset", isSignal: true, isRequired: false, transformFunction: null }, maintainVisibleContentPosition: { classPropertyName: "maintainVisibleContentPosition", publicName: "maintainVisibleContentPosition", isSignal: true, isRequired: false, transformFunction: null }, keyboardShouldPersistTaps: { classPropertyName: "keyboardShouldPersistTaps", publicName: "keyboardShouldPersistTaps", isSignal: true, isRequired: false, transformFunction: null }, nestedScrollEnabled: { classPropertyName: "nestedScrollEnabled", publicName: "nestedScrollEnabled", isSignal: true, isRequired: false, transformFunction: null }, stickyHeaderIndices: { classPropertyName: "stickyHeaderIndices", publicName: "stickyHeaderIndices", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentSizeChange: "contentSizeChange" }, host: { properties: { "flexDirection": "horizontal() ? 'row' : 'column'", "horizontal": "horizontal()", "contentOffset": "contentOffset()", "maintainVisibleContentPosition": "maintainVisibleContentPosition()", "scrollEventThrottle": "resolvedThrottle()", "nestedScrollEnabled": "resolvedNestedScroll()" } }, queries: [{ propertyName: "refreshControl", first: true, predicate: RefreshControl, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, read: ElementRef, isSignal: true }], exportAs: ["scrollView"], usesInheritance: true, ngImport: i0, template: `
179
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.2.0", type: ScrollView, isStandalone: true, selector: "scroll-view", inputs: { contentContainerStyle: { classPropertyName: "contentContainerStyle", publicName: "contentContainerStyle", isSignal: true, isRequired: false, transformFunction: null }, contentContainerClass: { classPropertyName: "contentContainerClass", publicName: "contentContainerClass", isSignal: true, isRequired: false, transformFunction: null }, horizontal: { classPropertyName: "horizontal", publicName: "horizontal", isSignal: true, isRequired: false, transformFunction: null }, contentOffset: { classPropertyName: "contentOffset", publicName: "contentOffset", isSignal: true, isRequired: false, transformFunction: null }, maintainVisibleContentPosition: { classPropertyName: "maintainVisibleContentPosition", publicName: "maintainVisibleContentPosition", isSignal: true, isRequired: false, transformFunction: null }, keyboardShouldPersistTaps: { classPropertyName: "keyboardShouldPersistTaps", publicName: "keyboardShouldPersistTaps", isSignal: true, isRequired: false, transformFunction: null }, nestedScrollEnabled: { classPropertyName: "nestedScrollEnabled", publicName: "nestedScrollEnabled", isSignal: true, isRequired: false, transformFunction: null }, stickyHeaderIndices: { classPropertyName: "stickyHeaderIndices", publicName: "stickyHeaderIndices", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentSizeChange: "contentSizeChange" }, host: { properties: { "flexDirection": "horizontal() ? 'row' : 'column'", "horizontal": "horizontal()", "contentOffset": "contentOffset()", "maintainVisibleContentPosition": "maintainVisibleContentPosition()", "scrollEventThrottle": "resolvedThrottle()", "nestedScrollEnabled": "resolvedNestedScroll()" } }, queries: [{ propertyName: "refreshControl", first: true, predicate: RefreshControl, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, read: ElementRef, isSignal: true }], exportAs: ["scrollView"], usesInheritance: true, ngImport: i0, template: `
141
180
  <ng-content select="refresh-control" />
142
- <view #content [style]="contentStyle()" collapsable="false" (layout)="onContentLayout($event)">
181
+ <view
182
+ #content
183
+ [contentContainerOf]="node"
184
+ [contentContainerClass]="contentContainerClass()"
185
+ [style]="contentStyle()"
186
+ collapsable="false"
187
+ (layout)="onContentLayout($event)"
188
+ >
143
189
  <ng-content />
144
190
  </view>
145
- `, isInline: true, dependencies: [{ kind: "directive", type: View, selector: "view" }] });
191
+ `, isInline: true, dependencies: [{ kind: "directive", type: ContentContainer, selector: "[contentContainerOf]", inputs: ["contentContainerOf", "contentContainerClass"] }, { kind: "directive", type: View, selector: "view" }] });
146
192
  }
147
193
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: ScrollView, decorators: [{
148
194
  type: Component,
149
195
  args: [{
150
196
  selector: 'scroll-view',
151
197
  exportAs: 'scrollView',
152
- imports: [View],
198
+ imports: [ContentContainer, View],
153
199
  // `collapsable: false` is load-bearing, not a hint. Fabric flattens views whose props are
154
200
  // layout-only, and a content container with just padding qualifies: it gets no UIView at all.
155
201
  // Touches in its empty areas then land on the scroll view itself, which does not scroll from a
@@ -162,7 +208,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
162
208
  // scroll view, and never attach.
163
209
  template: `
164
210
  <ng-content select="refresh-control" />
165
- <view #content [style]="contentStyle()" collapsable="false" (layout)="onContentLayout($event)">
211
+ <view
212
+ #content
213
+ [contentContainerOf]="node"
214
+ [contentContainerClass]="contentContainerClass()"
215
+ [style]="contentStyle()"
216
+ collapsable="false"
217
+ (layout)="onContentLayout($event)"
218
+ >
166
219
  <ng-content />
167
220
  </view>
168
221
  `,
@@ -177,5 +230,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
177
230
  '[nestedScrollEnabled]': 'resolvedNestedScroll()',
178
231
  },
179
232
  }]
180
- }], ctorParameters: () => [], propDecorators: { contentContainerStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentContainerStyle", required: false }] }], horizontal: [{ type: i0.Input, args: [{ isSignal: true, alias: "horizontal", required: false }] }], contentOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentOffset", required: false }] }], maintainVisibleContentPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "maintainVisibleContentPosition", required: false }] }], keyboardShouldPersistTaps: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyboardShouldPersistTaps", required: false }] }], nestedScrollEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "nestedScrollEnabled", required: false }] }], stickyHeaderIndices: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeaderIndices", required: false }] }], contentSizeChange: [{ type: i0.Output, args: ["contentSizeChange"] }], refreshControl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RefreshControl), { isSignal: true }] }], content: [{ type: i0.ViewChild, args: ['content', { ...{ read: ElementRef }, isSignal: true }] }] } });
233
+ }], ctorParameters: () => [], propDecorators: { contentContainerStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentContainerStyle", required: false }] }], contentContainerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentContainerClass", required: false }] }], horizontal: [{ type: i0.Input, args: [{ isSignal: true, alias: "horizontal", required: false }] }], contentOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentOffset", required: false }] }], maintainVisibleContentPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "maintainVisibleContentPosition", required: false }] }], keyboardShouldPersistTaps: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyboardShouldPersistTaps", required: false }] }], nestedScrollEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "nestedScrollEnabled", required: false }] }], stickyHeaderIndices: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeaderIndices", required: false }] }], contentSizeChange: [{ type: i0.Output, args: ["contentSizeChange"] }], refreshControl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RefreshControl), { isSignal: true }] }], content: [{ type: i0.ViewChild, args: ['content', { ...{ read: ElementRef }, isSignal: true }] }] } });
181
234
  //# sourceMappingURL=scroll-view.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scroll-view.js","sourceRoot":"","sources":["../src/scroll-view.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n DestroyRef,\n ElementRef,\n afterEveryRender,\n computed,\n contentChild,\n inject,\n input,\n output,\n viewChild,\n} from '@angular/core';\nimport { type HostNode, type NativeSyntheticEvent, nativePlatform } from '@ng-native/fabric';\nimport type { Point, Rect, Size } from './events.ts';\nimport { type KeyboardShouldPersistTaps, dismissKeyboardOnTap } from './keyboard-taps.ts';\nimport { RefreshControl } from './refresh-control.ts';\nimport { StickyHeaders } from './sticky-headers.ts';\nimport { optionalBoolean } from './transforms.ts';\nimport { ScrollViewProps } from './scroll-view-props.ts';\nimport { View } from './view.ts';\n\n/**\n * A scrolling container. Commits as `RCTScrollView`, with the children inside a content view.\n *\n * The native scroll view has no `contentContainerStyle`: RN's `ScrollView.js` wraps children in\n * a content view and applies it there, which is done here. The engine gives the host RN's base\n * style (`overflow: 'scroll'` and the flex defaults); without it the content spills out of the\n * scroll view's bounds.\n *\n * `horizontal` changes two things rather than one, and both are needed. RN swaps its whole base\n * style for `baseHorizontal` - the same defaults but `flexDirection: 'row'` - and puts\n * `contentContainerHorizontal` on the content view. With the host left as a column the content\n * view is stretched to the scroll view's width instead of growing past it, so there is nothing to\n * scroll to and a sideways drag does nothing at all. It looks like a scroll view that simply has\n * too little in it.\n *\n * Keyboard policy is the other half of what `ScrollView.js` does in JavaScript. With a text\n * input focused, a tap elsewhere in the scroll view dismisses the keyboard and goes no further\n * (`keyboardShouldPersistTaps: 'never'`, the default), reaches the child first and dismisses only\n * if nothing handled it (`'handled'`), or never dismisses (`'always'`).\n *\n * `stickyHeaderIndices` pins those children of the content to the leading edge, each until the\n * next pushes it off. It is JavaScript in RN as well; see `StickyHeaders`.\n *\n * Events are element events: `(scroll)`, `(scrollBeginDrag)`, `(scrollEndDrag)`,\n * `(momentumScrollBegin)`, `(momentumScrollEnd)`, `(scrollToTop)`. `(contentSizeChange)` is an\n * output, measured from the content view's layout as RN does.\n */\n@Component({\n selector: 'scroll-view',\n exportAs: 'scrollView',\n imports: [View],\n // `collapsable: false` is load-bearing, not a hint. Fabric flattens views whose props are\n // layout-only, and a content container with just padding qualifies: it gets no UIView at all.\n // Touches in its empty areas then land on the scroll view itself, which does not scroll from a\n // direct hit, so dragging anywhere the children do not cover silently does nothing. RN sets the\n // same flag on its content container for the same reason.\n //\n // A refresh control is the scroll view's own child, before the content view, as RN's\n // ScrollView.js commits it. On iOS it finds its scroll view once, when it is inserted, and\n // Fabric mounts bottom-up: inside the content view it would look before that view was in the\n // scroll view, and never attach.\n template: `\n <ng-content select=\"refresh-control\" />\n <view #content [style]=\"contentStyle()\" collapsable=\"false\" (layout)=\"onContentLayout($event)\">\n <ng-content />\n </view>\n `,\n host: {\n // The base style's direction, which `horizontal` decides. A top-level prop rather than a\n // host `[style]`, so the caller's own `[style]` still applies over it as it does in RN.\n '[flexDirection]': \"horizontal() ? 'row' : 'column'\",\n '[horizontal]': 'horizontal()',\n '[contentOffset]': 'contentOffset()',\n '[maintainVisibleContentPosition]': 'maintainVisibleContentPosition()',\n '[scrollEventThrottle]': 'resolvedThrottle()',\n '[nestedScrollEnabled]': 'resolvedNestedScroll()',\n },\n})\nexport class ScrollView extends ScrollViewProps {\n /** Styles for the view that holds the children, e.g. padding and gap. */\n readonly contentContainerStyle = input<Record<string, unknown>>();\n\n /**\n * The content view's style, with the row direction a horizontal scroll view needs.\n *\n * RN's `contentContainerHorizontal`, and in the same order: the caller's own style is applied\n * over it, so a horizontal scroll view whose content really should stack in a column can still\n * say so.\n */\n protected readonly contentStyle = computed(() =>\n this.horizontal()\n ? { flexDirection: 'row', ...this.contentContainerStyle() }\n : this.contentContainerStyle(),\n );\n /** Lay children out in a row and scroll sideways. */\n readonly horizontal = input(undefined, { transform: optionalBoolean });\n /** Where the content starts, before the user scrolls. */\n readonly contentOffset = input<Point>();\n /** Keep what is on screen still when content is added above it. */\n readonly maintainVisibleContentPosition = input<{\n readonly minIndexForVisible: number;\n readonly autoscrollToTopThreshold?: number;\n }>();\n /** What a tap does with the keyboard up. See the class note. Defaults to `never`. */\n readonly keyboardShouldPersistTaps = input<KeyboardShouldPersistTaps>('never');\n /** Android: cooperate with a scrolling ancestor. */\n readonly nestedScrollEnabled = input(undefined, { transform: optionalBoolean });\n\n /** Children of the content, by position, that stick to the leading edge while it scrolls. */\n readonly stickyHeaderIndices = input<readonly number[]>([]);\n\n /** The content view's size changed; the value is its new width and height. */\n readonly contentSizeChange = output<Size>();\n\n private readonly refreshControl = contentChild(RefreshControl);\n private readonly content = viewChild.required('content', { read: ElementRef });\n private readonly sticky = new StickyHeaders(this.engine, this.node, () => !!this.horizontal());\n\n /** RN asks for every scroll event while anything is sticky, which is what keeps it pinned. */\n protected readonly resolvedThrottle = computed(() =>\n this.stickyHeaderIndices().length > 0 ? 1 : this.scrollEventThrottle(),\n );\n\n /**\n * RN's `nestedScrollEnabled ?? true` for a scroll view inside Android's swipe layout: the scroll\n * view has to see a drag before the layout wrapped around it does, or every drag is a pull.\n */\n protected readonly resolvedNestedScroll = computed(\n () =>\n this.nestedScrollEnabled() ??\n (nativePlatform() === 'android' && this.refreshControl() ? true : undefined),\n );\n\n constructor() {\n super();\n const stop = dismissKeyboardOnTap(this.engine, this.node, () =>\n this.keyboardShouldPersistTaps(),\n );\n inject(DestroyRef).onDestroy(stop);\n this.trackStickyHeaders();\n }\n\n /**\n * Sticky children are found again after each pass, because a pass can add or move them, and the\n * scroll offset is listened for only while there are any.\n */\n private trackStickyHeaders(): void {\n let stopScroll: (() => void) | null = null;\n afterEveryRender(() => {\n const indices = this.stickyHeaderIndices();\n if (indices.length === 0 && !stopScroll) return;\n this.sticky.track(this.content().nativeElement as HostNode, indices);\n if (indices.length > 0 && !stopScroll) {\n stopScroll = this.engine.setEventListener(this.node, 'topScroll', (event) => {\n const offset = (event as NativeSyntheticEvent<{ contentOffset?: Point }>).nativeEvent\n ?.contentOffset;\n this.sticky.scrolled((this.horizontal() ? offset?.x : offset?.y) ?? 0);\n });\n } else if (indices.length === 0 && stopScroll) {\n stopScroll();\n stopScroll = null;\n }\n });\n inject(DestroyRef).onDestroy(() => {\n stopScroll?.();\n this.sticky.destroy();\n });\n }\n\n /** Scroll to a position. */\n scrollTo(options: { x?: number; y?: number; animated?: boolean }): void {\n const { x = 0, y = 0, animated = true } = options;\n this.engine.dispatchCommand(this.node, 'scrollTo', [x, y, animated]);\n }\n\n scrollToEnd(options: { animated?: boolean } = {}): void {\n this.engine.dispatchCommand(this.node, 'scrollToEnd', [options.animated ?? true]);\n }\n\n /** Briefly show the scroll indicators, to hint that there is more. */\n flashScrollIndicators(): void {\n this.engine.dispatchCommand(this.node, 'flashScrollIndicators');\n }\n\n /** iOS: zoom so that a rectangle of the content fills the viewport. */\n zoomToRect(rect: Rect, animated = true): void {\n this.engine.dispatchCommand(this.node, 'zoomToRect', [rect, animated]);\n }\n\n protected onContentLayout(event: NativeSyntheticEvent<{ layout?: Size }>): void {\n const layout = event.nativeEvent?.layout;\n if (layout) this.contentSizeChange.emit({ width: layout.width, height: layout.height });\n }\n}\n"]}
1
+ {"version":3,"file":"scroll-view.js","sourceRoot":"","sources":["../src/scroll-view.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n DestroyRef,\n ElementRef,\n afterEveryRender,\n computed,\n contentChild,\n inject,\n input,\n output,\n viewChild,\n} from '@angular/core';\nimport { type HostNode, type NativeSyntheticEvent, nativePlatform } from '@ng-native/fabric';\nimport type { Point, Rect, Size } from './events.ts';\nimport { type KeyboardShouldPersistTaps, dismissKeyboardOnTap } from './keyboard-taps.ts';\nimport { ContentContainer } from './content-container.ts';\nimport { RefreshControl } from './refresh-control.ts';\nimport { StickyHeaders } from './sticky-headers.ts';\nimport { optionalBoolean } from './transforms.ts';\nimport { ScrollViewProps } from './scroll-view-props.ts';\nimport { View } from './view.ts';\nimport { ZeroSizeWarning, checksZeroSize, written } from './zero-size-warning.ts';\n\n/**\n * A scrolling container. Commits as `RCTScrollView`, with the children inside a content view.\n *\n * The native scroll view has no `contentContainerStyle`: RN's `ScrollView.js` wraps children in\n * a content view and applies it there, which is done here. The engine gives the host RN's base\n * style (`overflow: 'scroll'` and the flex defaults); without it the content spills out of the\n * scroll view's bounds.\n *\n * `horizontal` changes two things rather than one, and both are needed. RN swaps its whole base\n * style for `baseHorizontal` - the same defaults but `flexDirection: 'row'` - and puts\n * `contentContainerHorizontal` on the content view. With the host left as a column the content\n * view is stretched to the scroll view's width instead of growing past it, so there is nothing to\n * scroll to and a sideways drag does nothing at all. It looks like a scroll view that simply has\n * too little in it.\n *\n * Keyboard policy is the other half of what `ScrollView.js` does in JavaScript. With a text\n * input focused, a tap elsewhere in the scroll view dismisses the keyboard and goes no further\n * (`keyboardShouldPersistTaps: 'never'`, the default), reaches the child first and dismisses only\n * if nothing handled it (`'handled'`), or never dismisses (`'always'`).\n *\n * `stickyHeaderIndices` pins those children of the content to the leading edge, each until the\n * next pushes it off. It is JavaScript in RN as well; see `StickyHeaders`.\n *\n * Events are element events: `(scroll)`, `(scrollBeginDrag)`, `(scrollEndDrag)`,\n * `(momentumScrollBegin)`, `(momentumScrollEnd)`, `(scrollToTop)`. `(contentSizeChange)` is an\n * output, measured from the content view's layout as RN does.\n */\n@Component({\n selector: 'scroll-view',\n exportAs: 'scrollView',\n imports: [ContentContainer, View],\n // `collapsable: false` is load-bearing, not a hint. Fabric flattens views whose props are\n // layout-only, and a content container with just padding qualifies: it gets no UIView at all.\n // Touches in its empty areas then land on the scroll view itself, which does not scroll from a\n // direct hit, so dragging anywhere the children do not cover silently does nothing. RN sets the\n // same flag on its content container for the same reason.\n //\n // A refresh control is the scroll view's own child, before the content view, as RN's\n // ScrollView.js commits it. On iOS it finds its scroll view once, when it is inserted, and\n // Fabric mounts bottom-up: inside the content view it would look before that view was in the\n // scroll view, and never attach.\n template: `\n <ng-content select=\"refresh-control\" />\n <view\n #content\n [contentContainerOf]=\"node\"\n [contentContainerClass]=\"contentContainerClass()\"\n [style]=\"contentStyle()\"\n collapsable=\"false\"\n (layout)=\"onContentLayout($event)\"\n >\n <ng-content />\n </view>\n `,\n host: {\n // The base style's direction, which `horizontal` decides. A top-level prop rather than a\n // host `[style]`, so the caller's own `[style]` still applies over it as it does in RN.\n '[flexDirection]': \"horizontal() ? 'row' : 'column'\",\n '[horizontal]': 'horizontal()',\n '[contentOffset]': 'contentOffset()',\n '[maintainVisibleContentPosition]': 'maintainVisibleContentPosition()',\n '[scrollEventThrottle]': 'resolvedThrottle()',\n '[nestedScrollEnabled]': 'resolvedNestedScroll()',\n },\n})\nexport class ScrollView extends ScrollViewProps {\n /** Styles for the view that holds the children, e.g. padding and gap. */\n readonly contentContainerStyle = input<Record<string, unknown>>();\n /**\n * Classes for the view that holds the children, matched as if the view were written in the\n * template the scroll view is. See `ContentContainer`. `contentContainerStyle` wins over it, as\n * an inline style does over a class.\n */\n readonly contentContainerClass = input<string>();\n\n /**\n * The content view's style, with the row direction a horizontal scroll view needs.\n *\n * RN's `contentContainerHorizontal`, and in the same order: the caller's own style is applied\n * over it, so a horizontal scroll view whose content really should stack in a column can still\n * say so.\n */\n protected readonly contentStyle = computed(() =>\n this.horizontal()\n ? { flexDirection: 'row', ...this.contentContainerStyle() }\n : this.contentContainerStyle(),\n );\n /** Lay children out in a row and scroll sideways. */\n readonly horizontal = input(undefined, { transform: optionalBoolean });\n /** Where the content starts, before the user scrolls. */\n readonly contentOffset = input<Point>();\n /** Keep what is on screen still when content is added above it. */\n readonly maintainVisibleContentPosition = input<{\n readonly minIndexForVisible: number;\n readonly autoscrollToTopThreshold?: number;\n }>();\n /** What a tap does with the keyboard up. See the class note. Defaults to `never`. */\n readonly keyboardShouldPersistTaps = input<KeyboardShouldPersistTaps>('never');\n /** Android: cooperate with a scrolling ancestor. */\n readonly nestedScrollEnabled = input(undefined, { transform: optionalBoolean });\n\n /** Children of the content, by position, that stick to the leading edge while it scrolls. */\n readonly stickyHeaderIndices = input<readonly number[]>([]);\n\n /** The content view's size changed; the value is its new width and height. */\n readonly contentSizeChange = output<Size>();\n\n private readonly refreshControl = contentChild(RefreshControl);\n private readonly content = viewChild.required('content', { read: ElementRef });\n private readonly sticky = new StickyHeaders(this.engine, this.node, () => !!this.horizontal());\n\n /** RN asks for every scroll event while anything is sticky, which is what keeps it pinned. */\n protected readonly resolvedThrottle = computed(() =>\n this.stickyHeaderIndices().length > 0 ? 1 : this.scrollEventThrottle(),\n );\n\n /**\n * RN's `nestedScrollEnabled ?? true` for a scroll view inside Android's swipe layout: the scroll\n * view has to see a drag before the layout wrapped around it does, or every drag is a pull.\n */\n protected readonly resolvedNestedScroll = computed(\n () =>\n this.nestedScrollEnabled() ??\n (nativePlatform() === 'android' && this.refreshControl() ? true : undefined),\n );\n\n constructor() {\n super();\n const stop = dismissKeyboardOnTap(this.engine, this.node, () =>\n this.keyboardShouldPersistTaps(),\n );\n inject(DestroyRef).onDestroy(stop);\n this.trackStickyHeaders();\n if (checksZeroSize()) this.checkZeroSize();\n }\n\n /** The content's extent along the axis, and the scroll view's own, for `checkZeroSize`. */\n private contentExtent = 0;\n private ownExtent: number | undefined;\n private zeroSize: ZeroSizeWarning | null = null;\n\n /**\n * In development only, the scroll view's own layout, to say when it stays at zero size with\n * content in it. A release build listens for nothing, so it commits no `onLayout`.\n */\n private checkZeroSize(): void {\n const warning = (this.zeroSize = new ZeroSizeWarning(\n () => written(this.node),\n () => !!this.horizontal(),\n ));\n const stop = this.engine.setEventListener(this.node, 'topLayout', (event) => {\n this.ownExtent = this.extent(\n (event as NativeSyntheticEvent<{ layout?: Size }>).nativeEvent?.layout,\n );\n warning.laidOut(this.ownExtent, this.contentExtent > 0);\n });\n inject(DestroyRef).onDestroy(() => {\n stop();\n warning.stop();\n });\n }\n\n private extent(size: Size | undefined): number {\n return (this.horizontal() ? size?.width : size?.height) ?? 0;\n }\n\n /**\n * Sticky children are found again after each pass, because a pass can add or move them, and the\n * scroll offset is listened for only while there are any.\n */\n private trackStickyHeaders(): void {\n let stopScroll: (() => void) | null = null;\n afterEveryRender(() => {\n const indices = this.stickyHeaderIndices();\n if (indices.length === 0 && !stopScroll) return;\n this.sticky.track(this.content().nativeElement as HostNode, indices);\n if (indices.length > 0 && !stopScroll) {\n stopScroll = this.engine.setEventListener(this.node, 'topScroll', (event) => {\n const offset = (event as NativeSyntheticEvent<{ contentOffset?: Point }>).nativeEvent\n ?.contentOffset;\n this.sticky.scrolled((this.horizontal() ? offset?.x : offset?.y) ?? 0);\n });\n } else if (indices.length === 0 && stopScroll) {\n stopScroll();\n stopScroll = null;\n }\n });\n inject(DestroyRef).onDestroy(() => {\n stopScroll?.();\n this.sticky.destroy();\n });\n }\n\n /** Scroll to a position. */\n scrollTo(options: { x?: number; y?: number; animated?: boolean }): void {\n const { x = 0, y = 0, animated = true } = options;\n this.engine.dispatchCommand(this.node, 'scrollTo', [x, y, animated]);\n }\n\n scrollToEnd(options: { animated?: boolean } = {}): void {\n this.engine.dispatchCommand(this.node, 'scrollToEnd', [options.animated ?? true]);\n }\n\n /** Briefly show the scroll indicators, to hint that there is more. */\n flashScrollIndicators(): void {\n this.engine.dispatchCommand(this.node, 'flashScrollIndicators');\n }\n\n /** iOS: zoom so that a rectangle of the content fills the viewport. */\n zoomToRect(rect: Rect, animated = true): void {\n this.engine.dispatchCommand(this.node, 'zoomToRect', [rect, animated]);\n }\n\n protected onContentLayout(event: NativeSyntheticEvent<{ layout?: Size }>): void {\n const layout = event.nativeEvent?.layout;\n if (layout) this.contentSizeChange.emit({ width: layout.width, height: layout.height });\n if (this.zeroSize) {\n this.contentExtent = this.extent(layout);\n if (this.ownExtent !== undefined) {\n this.zeroSize.laidOut(this.ownExtent, this.contentExtent > 0);\n }\n }\n }\n}\n"]}