@ng-native/components 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/pressable.d.ts +3 -3
- package/dist/pressable.js +6 -4
- package/dist/pressable.js.map +1 -1
- package/dist/safe-area-provider.js +3 -2
- package/dist/safe-area-provider.js.map +1 -1
- package/dist/switch.js +2 -1
- package/dist/switch.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -73,7 +73,7 @@ package under Node (tests, tooling).
|
|
|
73
73
|
[modal](https://ng-native.com/packages/components/modal) and
|
|
74
74
|
[animation](https://ng-native.com/packages/components/animation)
|
|
75
75
|
- [Root README](https://github.com/ng-native/ng-native/blob/main/README.md) and
|
|
76
|
-
[ARCHITECTURE.md](https://github.com/ng-native/ng-native/blob/main/ARCHITECTURE.md)
|
|
76
|
+
[ARCHITECTURE.md](https://github.com/ng-native/ng-native/blob/main/docs/ARCHITECTURE.md)
|
|
77
77
|
|
|
78
78
|
## License
|
|
79
79
|
|
package/dist/pressable.d.ts
CHANGED
|
@@ -175,9 +175,9 @@ export declare abstract class TouchableBase extends ViewBase {
|
|
|
175
175
|
/**
|
|
176
176
|
* A touchable that is a control: `Pressable`, `TouchableOpacity` and `PressBehavior`.
|
|
177
177
|
*
|
|
178
|
-
* The
|
|
179
|
-
*
|
|
180
|
-
*
|
|
178
|
+
* The host bindings every control needs live here rather than on `TouchableBase`, which `Text`
|
|
179
|
+
* extends: the state that follows `disabled`, and the Android ripple. Controls are few enough on
|
|
180
|
+
* a screen to pay for a binding on every pass; texts are not.
|
|
181
181
|
*/
|
|
182
182
|
export declare abstract class ControlBase extends TouchableBase {
|
|
183
183
|
static ɵfac: i0.ɵɵFactoryDeclaration<ControlBase, never>;
|
package/dist/pressable.js
CHANGED
|
@@ -401,13 +401,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
|
|
|
401
401
|
/**
|
|
402
402
|
* A touchable that is a control: `Pressable`, `TouchableOpacity` and `PressBehavior`.
|
|
403
403
|
*
|
|
404
|
-
* The
|
|
405
|
-
*
|
|
406
|
-
*
|
|
404
|
+
* The host bindings every control needs live here rather than on `TouchableBase`, which `Text`
|
|
405
|
+
* extends: the state that follows `disabled`, and the Android ripple. Controls are few enough on
|
|
406
|
+
* a screen to pay for a binding on every pass; texts are not.
|
|
407
407
|
*/
|
|
408
408
|
export class ControlBase extends TouchableBase {
|
|
409
409
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: ControlBase, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
410
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.2.0", type: ControlBase, isStandalone: true, host: { properties: { "accessibilityState": "accessibilityStateProp()", "nativeBackgroundAndroid": "rippleBackground()", "nativeForegroundAndroid": "rippleForeground()" } }, usesInheritance: true, ngImport: i0 });
|
|
410
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.2.0", type: ControlBase, isStandalone: true, host: { properties: { "accessibilityState": "accessibilityStateProp()", "attr.data-disabled": "disabled() ? '' : null", "nativeBackgroundAndroid": "rippleBackground()", "nativeForegroundAndroid": "rippleForeground()" } }, usesInheritance: true, ngImport: i0 });
|
|
411
411
|
}
|
|
412
412
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: ControlBase, decorators: [{
|
|
413
413
|
type: Directive,
|
|
@@ -416,6 +416,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
|
|
|
416
416
|
// `disabled` is an input of ours, so it cannot reach `ngOnChanges` on the base; this is
|
|
417
417
|
// the one binding that keeps the announced state in step with it.
|
|
418
418
|
'[accessibilityState]': 'accessibilityStateProp()',
|
|
419
|
+
// Nor is it left on the node for `:disabled` to read, so this is what a stylesheet matches.
|
|
420
|
+
'[attr.data-disabled]': "disabled() ? '' : null",
|
|
419
421
|
'[nativeBackgroundAndroid]': 'rippleBackground()',
|
|
420
422
|
'[nativeForegroundAndroid]': 'rippleForeground()',
|
|
421
423
|
},
|
package/dist/pressable.js.map
CHANGED
|
@@ -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 three host bindings every control needs live here rather than on `TouchableBase`, which\n * `Text` extends: the state that follows `disabled`, and the Android ripple. Controls are few\n * enough on 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 '[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 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"]}
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
*
|
|
14
14
|
* **A `<safe-area-view>` needs one above it**, which is less obvious than it sounds. The native
|
|
15
15
|
* view walks its superviews for a provider and falls back to reading its own insets - but only
|
|
16
|
-
* once, as it enters the window, before it has been laid out, and nothing
|
|
17
|
-
* provider it therefore insets by zero and looks like it is working
|
|
16
|
+
* once, as it enters the window, before it has been laid out, and nothing notifies it when they
|
|
17
|
+
* change. With no provider it therefore insets by zero and looks like it is working, until a later
|
|
18
|
+
* update to that view happens to re-read them and the content jumps.
|
|
18
19
|
*
|
|
19
20
|
* That is also why a presented screen needs its own: it is outside the stack's view tree, which
|
|
20
21
|
* is the same reason it has no header. Give a modal a provider of its own with
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-area-provider.js","sourceRoot":"","sources":["../src/safe-area-provider.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"safe-area-provider.js","sourceRoot":"","sources":["../src/safe-area-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EACL,SAAS,EACT,UAAU,EACV,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,MAAM,EACN,KAAK,GACN,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAA2B,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAiB,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;;AAE5D,4FAA4F;AAC5F,SAAS,WAAW,CAAC,MAAc;IACjC,OAAO;QACL,uBAAuB,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE;QAC/C,yBAAyB,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE;QACnD,0BAA0B,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QACrD,wBAAwB,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;KAClD,CAAC;AACJ,CAAC;AAWD,MAAM,OAAO,gBAAgB;IAC3B;;;OAGG;IACM,YAAY,GAAG,KAAK,CAAC,IAAI,oFAAI,SAAS,EAAE,gBAAgB,GAAG,CAAC;IAErE;QACE,0BAA0B,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,aAAyB,CAAC;QAC1D,SAAS,CAAC,IAAI,CAAC,CAAC;QAEhB,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CACnC,IAAI,EACJ,cAAc,EACd,CAAC,KAAqC,EAAE,EAAE;YACxC,MAAM,MAAM,GAAG,KAAK,EAAE,WAAW,CAAC;YAClC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;gBAAE,OAAO;YAC5C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YACzC,mFAAmF;YACnF,8DAA8D;YAC9D,MAAM,EAAE,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACnD,CAAC,CACF,CAAC;QACF,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;uGA3BU,gBAAgB;2FAAhB,gBAAgB,uOAFjB,gBAAgB;;2FAEf,gBAAgB;kBAJ5B,SAAS;mBAAC;oBACT,QAAQ,EAAE,oBAAoB;oBAC9B,QAAQ,EAAE,gBAAgB;iBAC3B","sourcesContent":["/**\n * The view that measures the safe area and reports it, for the layouts that need the numbers.\n *\n * ```html\n * <safe-area-provider>\n * <native-stack-outlet />\n * </safe-area-provider>\n * ```\n *\n * One, at the root, wrapping everything. What it measures is its own frame and the insets around\n * it, which is why it has to be the thing filling the window rather than a view somewhere inside\n * it. It fills by default and paints nothing.\n *\n * **A `<safe-area-view>` needs one above it**, which is less obvious than it sounds. The native\n * view walks its superviews for a provider and falls back to reading its own insets - but only\n * once, as it enters the window, before it has been laid out, and nothing notifies it when they\n * change. With no provider it therefore insets by zero and looks like it is working, until a later\n * update to that view happens to re-read them and the content jumps.\n *\n * That is also why a presented screen needs its own: it is outside the stack's view tree, which\n * is the same reason it has no header. Give a modal a provider of its own with\n * `[reportInsets]=\"false\"`, so its geometry stays out of the app-wide `SafeArea` while it is up.\n */\nimport {\n Component,\n DestroyRef,\n ElementRef,\n Renderer2,\n booleanAttribute,\n inject,\n input,\n} from '@angular/core';\nimport { SafeArea, type Frame, type Insets } from '@ng-native/device';\nimport { Engine, claimHost, type HostNode } from '@ng-native/fabric';\nimport { registerSafeAreaComponents } from './safe-area.ts';\n\n/** The insets, in the form the cascade carries: one custom property per edge, in points. */\nfunction insetTokens(insets: Insets): Record<string, { length: number }> {\n return {\n '--safe-area-inset-top': { length: insets.top },\n '--safe-area-inset-right': { length: insets.right },\n '--safe-area-inset-bottom': { length: insets.bottom },\n '--safe-area-inset-left': { length: insets.left },\n };\n}\n\ninterface InsetsChange {\n readonly insets: Insets;\n readonly frame: Frame;\n}\n\n@Component({\n selector: 'safe-area-provider',\n template: '<ng-content />',\n})\nexport class SafeAreaProvider {\n /**\n * Whether what this measures becomes `SafeArea.insets`. The app has one safe area; a second\n * provider inside a modal is there so native descendants can find one, not to redefine it.\n */\n readonly reportInsets = input(true, { transform: booleanAttribute });\n\n constructor() {\n registerSafeAreaComponents();\n const host = inject(ElementRef).nativeElement as HostNode;\n claimHost(host);\n\n const area = inject(SafeArea);\n const engine = inject(Engine, { optional: true });\n const stop = inject(Renderer2).listen(\n host,\n 'insetsChange',\n (event: { nativeEvent?: InsetsChange }) => {\n const change = event?.nativeEvent;\n if (!change || !this.reportInsets()) return;\n area.report(change.insets, change.frame);\n // Also published to the stylesheet, where a padding that clears the home indicator\n // belongs. `env()` on the web; a seeded custom property here.\n engine?.updateTokens(insetTokens(change.insets));\n },\n );\n inject(DestroyRef).onDestroy(stop);\n }\n}\n"]}
|
package/dist/switch.js
CHANGED
|
@@ -83,7 +83,7 @@ export class Switch extends ViewBase {
|
|
|
83
83
|
this.engine.dispatchCommand(this.node, command, [desired]);
|
|
84
84
|
}
|
|
85
85
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: Switch, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
86
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.2.0", type: Switch, isStandalone: true, selector: "switch", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, thumbColor: { classPropertyName: "thumbColor", publicName: "thumbColor", isSignal: true, isRequired: false, transformFunction: null }, trackColor: { classPropertyName: "trackColor", publicName: "trackColor", isSignal: true, isRequired: false, transformFunction: null }, iosBackgroundColor: { classPropertyName: "iosBackgroundColor", publicName: "ios_backgroundColor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, host: { listeners: { "change": "onNativeChange($event)" }, properties: { "accessibilityState": "accessibilityStateProp()", "value": "checked()", "disabled": "disabled()", "enabled": "enabled()", "thumbTintColor": "thumbColor()", "tintColor": "trackColor()?.false", "trackColorForTrue": "trackColor()?.true", "trackColorForFalse": "trackColor()?.false", "trackTintColor": "checked() ? trackColor()?.true : trackColor()?.false", "style.backgroundColor": "iosBackgroundColor()", "style.borderRadius": "iosBackgroundColor() ? 16 : undefined" } }, usesInheritance: true, usesOnChanges: true, ngImport: i0 });
|
|
86
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.2.0", type: Switch, isStandalone: true, selector: "switch", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, thumbColor: { classPropertyName: "thumbColor", publicName: "thumbColor", isSignal: true, isRequired: false, transformFunction: null }, trackColor: { classPropertyName: "trackColor", publicName: "trackColor", isSignal: true, isRequired: false, transformFunction: null }, iosBackgroundColor: { classPropertyName: "iosBackgroundColor", publicName: "ios_backgroundColor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, host: { listeners: { "change": "onNativeChange($event)" }, properties: { "accessibilityState": "accessibilityStateProp()", "value": "checked()", "disabled": "disabled()", "attr.data-disabled": "disabled() ? '' : null", "enabled": "enabled()", "thumbTintColor": "thumbColor()", "tintColor": "trackColor()?.false", "trackColorForTrue": "trackColor()?.true", "trackColorForFalse": "trackColor()?.false", "trackTintColor": "checked() ? trackColor()?.true : trackColor()?.false", "style.backgroundColor": "iosBackgroundColor()", "style.borderRadius": "iosBackgroundColor() ? 16 : undefined" } }, usesInheritance: true, usesOnChanges: true, ngImport: i0 });
|
|
87
87
|
}
|
|
88
88
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: Switch, decorators: [{
|
|
89
89
|
type: Directive,
|
|
@@ -95,6 +95,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
|
|
|
95
95
|
'[accessibilityState]': 'accessibilityStateProp()',
|
|
96
96
|
'[value]': 'checked()',
|
|
97
97
|
'[disabled]': 'disabled()',
|
|
98
|
+
'[attr.data-disabled]': "disabled() ? '' : null",
|
|
98
99
|
'[enabled]': 'enabled()',
|
|
99
100
|
'[thumbTintColor]': 'thumbColor()',
|
|
100
101
|
'[tintColor]': 'trackColor()?.false',
|
package/dist/switch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"switch.js","sourceRoot":"","sources":["../src/switch.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,QAAQ,EAER,eAAe,EACf,QAAQ,EACR,MAAM,EACN,MAAM,EACN,KAAK,EACL,KAAK,GACN,MAAM,eAAe,CAAC;AACvB,OAAO,EAA6B,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;;AAE1C;;;;;;;;;;;;;GAaG;
|
|
1
|
+
{"version":3,"file":"switch.js","sourceRoot":"","sources":["../src/switch.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Directive,\n Injector,\n type SimpleChanges,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n model,\n} from '@angular/core';\nimport { type NativeSyntheticEvent, nativePlatform } from '@ng-native/fabric';\nimport { ControlledModel } from './controlled-model.ts';\nimport { optionalBoolean } from './transforms.ts';\nimport { ViewBase } from './view-base.ts';\n\n/**\n * A toggle, wired for signal forms as a `FormCheckboxControl` (`checked`, not `value`). Commits\n * as `Switch` on iOS and `AndroidSwitch` on Android.\n *\n * The two platforms spell the same props differently, so both spellings are sent and each\n * native side reads its own; a prop it does not know is ignored.\n *\n * Controlled as React Native's `Switch` is: bind `checked` and the app's value is what the switch\n * shows. The user flips it, the app keeps the old value, and a prop diff has nothing to send,\n * because the prop never changed; native is the only side that moved. So once the pass the flip\n * started has rendered, the switch compares the model with what native reported and, if they\n * differ, sends the command RN's wrapper sends - `setValue` on iOS, `setNativeValue` on Android.\n * See `ControlledModel` for how the model comes to say what the app says.\n */\n@Directive({\n selector: 'switch',\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 '[value]': 'checked()',\n '[disabled]': 'disabled()',\n '[attr.data-disabled]': \"disabled() ? '' : null\",\n '[enabled]': 'enabled()',\n '[thumbTintColor]': 'thumbColor()',\n '[tintColor]': 'trackColor()?.false',\n '[trackColorForTrue]': 'trackColor()?.true',\n '[trackColorForFalse]': 'trackColor()?.false',\n '[trackTintColor]': 'checked() ? trackColor()?.true : trackColor()?.false',\n '[style.backgroundColor]': 'iosBackgroundColor()',\n '[style.borderRadius]': 'iosBackgroundColor() ? 16 : undefined',\n '(change)': 'onNativeChange($event)',\n },\n})\nexport class Switch extends ViewBase {\n readonly checked = model<boolean>(false);\n /** Ignore touches and grey out. */\n readonly disabled = input(undefined, { transform: optionalBoolean });\n\n /** `Switch.js`: `accessibilityRole={props.accessibilityRole ?? 'switch'}`. */\n protected override roleByDefault(): 'switch' {\n return 'switch';\n }\n\n protected override disabledForAccessibility(): boolean | undefined {\n return this.disabled();\n }\n\n protected override checkedForAccessibility(): boolean {\n return this.checked();\n }\n /** The colour of the knob. */\n readonly thumbColor = input<string>();\n /** The track colour for each state. */\n readonly trackColor = input<{ readonly false?: string; readonly true?: string }>();\n /** iOS: the colour behind the track when off, seen where the track is transparent. */\n readonly iosBackgroundColor = input<string>(undefined, { alias: 'ios_backgroundColor' });\n\n protected readonly enabled = computed(() => {\n const disabled = this.disabled();\n return disabled === undefined ? undefined : !disabled;\n });\n\n private readonly injector = inject(Injector);\n private readonly control = new ControlledModel(this.checked, 'checked');\n /** What native reported last, until the pass it started has rendered and been compared. */\n private nativeValue: boolean | null = null;\n\n constructor() {\n super();\n effect(() => {\n // Android spells the value `on` and iOS the on-track colour `onTintColor`. Angular refuses\n // both as host bindings because they read as event handlers, so they go to the node.\n this.engine.setProp(this.node, 'on', this.checked());\n this.engine.setProp(this.node, 'onTintColor', this.trackColor()?.true);\n });\n }\n\n override ngOnChanges(changes: SimpleChanges): void {\n super.ngOnChanges(changes);\n this.control.noteChanges(changes);\n }\n\n protected onNativeChange(event: NativeSyntheticEvent<{ value?: boolean }>): void {\n this.nativeValue = event.nativeEvent?.value ?? false;\n this.control.propose(this.nativeValue);\n afterNextRender({ write: () => this.reconcile() }, { injector: this.injector });\n }\n\n /**\n * After the app's bindings have settled, not before: a flip the app accepts reaches the model\n * during change detection, and comparing any earlier would send native back the value it is\n * about to be given. A value set from code later needs none of this, as the prop changes.\n */\n private reconcile(): void {\n const native = this.nativeValue;\n this.nativeValue = null;\n const desired = this.checked();\n if (native === null || native === desired) return;\n const command = nativePlatform() === 'android' ? 'setNativeValue' : 'setValue';\n this.engine.dispatchCommand(this.node, command, [desired]);\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ng-native/components",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Angular Native's core components: view, text, image, pressable, scroll-view, virtual-list, text-input and the rest of React Native's set.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@ng-native/fabric": "0.1.
|
|
43
|
-
"@ng-native/device": "0.1.
|
|
42
|
+
"@ng-native/fabric": "0.1.3",
|
|
43
|
+
"@ng-native/device": "0.1.3"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@angular/core": "^22.0.0",
|