@symbiote-native/components 1.0.0 → 2.0.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.
- package/README.md +3 -4
- package/build/behaviors/activity-indicator/index.android.d.ts +1 -0
- package/build/behaviors/activity-indicator/index.android.js +16 -0
- package/build/behaviors/activity-indicator/index.d.ts +3 -0
- package/build/behaviors/activity-indicator/index.ios.d.ts +1 -0
- package/build/behaviors/activity-indicator/index.ios.js +14 -0
- package/build/behaviors/activity-indicator/index.js +5 -0
- package/build/behaviors/activity-indicator/shared.d.ts +18 -0
- package/build/behaviors/activity-indicator/shared.js +149 -0
- package/build/behaviors/button.d.ts +2 -0
- package/build/behaviors/button.js +328 -0
- package/build/behaviors/image-background.d.ts +2 -0
- package/build/behaviors/image-background.js +139 -0
- package/build/behaviors/image.d.ts +1 -1
- package/build/behaviors/image.js +2 -2
- package/build/behaviors/input-accessory-view.d.ts +1 -1
- package/build/behaviors/input-accessory-view.js +2 -2
- package/build/behaviors/pressable.d.ts +59 -1
- package/build/behaviors/pressable.js +93 -18
- package/build/behaviors/refresh-control.d.ts +2 -0
- package/build/behaviors/refresh-control.js +83 -0
- package/build/behaviors/scroll-view/index.android.d.ts +1 -0
- package/build/behaviors/scroll-view/index.android.js +52 -0
- package/build/behaviors/scroll-view/index.d.ts +2 -0
- package/build/behaviors/scroll-view/index.ios.d.ts +1 -0
- package/build/behaviors/scroll-view/index.ios.js +10 -0
- package/build/behaviors/scroll-view/index.js +5 -0
- package/build/behaviors/scroll-view/shared.d.ts +11 -0
- package/build/behaviors/scroll-view/shared.js +291 -0
- package/build/behaviors/scroll-view/sticky.d.ts +17 -0
- package/build/behaviors/scroll-view/sticky.js +568 -0
- package/build/behaviors/switch.d.ts +1 -1
- package/build/behaviors/switch.js +9 -5
- package/build/behaviors/text-input.d.ts +2 -2
- package/build/behaviors/text-input.js +43 -15
- package/build/behaviors/touchable-highlight.d.ts +9 -0
- package/build/behaviors/touchable-highlight.js +192 -0
- package/build/behaviors/touchable-native-feedback.d.ts +20 -0
- package/build/behaviors/touchable-native-feedback.js +333 -0
- package/build/behaviors/touchable-opacity.d.ts +12 -0
- package/build/behaviors/touchable-opacity.js +227 -0
- package/build/behaviors/touchable-without-feedback.d.ts +2 -0
- package/build/behaviors/touchable-without-feedback.js +296 -0
- package/build/component-names/index.android.js +29 -19
- package/build/component-names/index.ios.js +31 -19
- package/build/component-names/shared.d.ts +2 -1
- package/build/component-names/shared.js +16 -6
- package/build/descriptor.js +4 -4
- package/build/fold-host-bag.js +2 -2
- package/build/index.d.ts +17 -11
- package/build/index.js +44 -8
- package/build/register.d.ts +1 -0
- package/build/register.js +55 -0
- package/build/scroll-view-commands.d.ts +4 -0
- package/build/scroll-view-commands.js +30 -31
- package/build/state/text-input.d.ts +4 -1
- package/build/view/render-button.d.ts +36 -1
- package/build/view/render-button.js +101 -12
- package/build/view/render-image/index.js +2 -2
- package/build/view/render-input-accessory-view.js +1 -1
- package/build/view/render-modal.js +3 -3
- package/build/view/render-pressable/index.d.ts +2 -0
- package/build/view/render-pressable/index.js +24 -0
- package/build/view/render-scroll-view.d.ts +1 -0
- package/build/view/render-scroll-view.js +18 -9
- package/build/view/render-switch.d.ts +4 -1
- package/build/view/render-switch.js +2 -2
- package/build/view/render-text-input.js +2 -2
- package/build/view/render-touchable-native-feedback.d.ts +19 -0
- package/build/view/render-touchable-native-feedback.js +19 -0
- package/host-primitives.cjs +202 -150
- package/host-primitives.d.cts +0 -2
- package/package.json +8 -17
- package/build/state-style.d.ts +0 -15
- package/build/state-style.js +0 -47
- package/build/view/render-activity-indicator.d.ts +0 -25
- package/build/view/render-activity-indicator.js +0 -88
- package/build/view/render-image-background.d.ts +0 -9
- package/build/view/render-image-background.js +0 -48
- package/lowering-fixtures.cjs +0 -259
- package/lowering-fixtures.d.cts +0 -17
- package/specialize-state-style.cjs +0 -219
- package/specialize-state-style.d.cts +0 -15
|
@@ -1,23 +1,112 @@
|
|
|
1
|
-
// Button: shared render half (framework-agnostic)
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// Button: shared render half (framework-agnostic). Ported against RN's own
|
|
2
|
+
// `Libraries/Components/Button.js` — a touchable wrapping a `View` wrapping a `Text`, where the
|
|
3
|
+
// VIEW is what carries the look on Android and is empty on iOS.
|
|
4
|
+
//
|
|
5
|
+
// The inner view is not optional chrome. RN's Button is the one control in the library that ships
|
|
6
|
+
// a finished appearance, and on Android that appearance — a filled, elevated, rounded Material
|
|
7
|
+
// button with an uppercased label — lives entirely on that node. A port that renders only the
|
|
8
|
+
// touchable and the text is an iOS port, which is what this file was until 2026-09-09: blue text on
|
|
9
|
+
// nothing, wherever Android was.
|
|
10
|
+
//
|
|
11
|
+
// What is NOT here, because a layer below already does it: the `aria-*` -> `accessibilityState`
|
|
12
|
+
// fold RN performs in `Button.js:326-331`. The engine folds those for every node
|
|
13
|
+
// (`core/engine/src/accessibility-props.ts`), so repeating it here would fold twice.
|
|
14
|
+
import { Platform } from '@symbiote-native/engine';
|
|
15
|
+
// Button.js:394-437, one constant per literal so a value cannot drift silently.
|
|
4
16
|
const IOS_BUTTON_BLUE = '#007AFF';
|
|
5
|
-
const
|
|
17
|
+
const IOS_DISABLED_TEXT = '#cdcdcd';
|
|
18
|
+
const ANDROID_BUTTON_BLUE = '#2196F3';
|
|
19
|
+
const ANDROID_DISABLED_BACKGROUND = '#dfdfdf';
|
|
20
|
+
const ANDROID_DISABLED_TEXT = '#a1a1a1';
|
|
21
|
+
const ANDROID_TEXT = 'white';
|
|
22
|
+
const ANDROID_ELEVATION = 4;
|
|
23
|
+
const ANDROID_DISABLED_ELEVATION = 0;
|
|
24
|
+
const ANDROID_BORDER_RADIUS = 2;
|
|
25
|
+
const TEXT_MARGIN = 8;
|
|
26
|
+
const IOS_FONT_SIZE = 18;
|
|
27
|
+
const ANDROID_FONT_WEIGHT = '500';
|
|
6
28
|
// RN's Button is accessibilityRole="button"; the role string is a native accessibility enum value.
|
|
7
29
|
export const BUTTON_ACCESSIBILITY_ROLE = 'button';
|
|
30
|
+
// `styles.text` — the platform-invariant half plus the platform's own. RN spells the margin as
|
|
31
|
+
// MARGIN, not padding: the label pushes the button's edges outward rather than insetting itself,
|
|
32
|
+
// so a background (Android) or a tap target (both) is 16pt taller than the glyphs.
|
|
8
33
|
export const buttonTextStyle = {
|
|
9
|
-
color: IOS_BUTTON_BLUE,
|
|
10
34
|
textAlign: 'center',
|
|
11
|
-
|
|
12
|
-
|
|
35
|
+
margin: TEXT_MARGIN,
|
|
36
|
+
...Platform.select({
|
|
37
|
+
ios: { color: IOS_BUTTON_BLUE, fontSize: IOS_FONT_SIZE },
|
|
38
|
+
android: { color: ANDROID_TEXT, fontWeight: ANDROID_FONT_WEIGHT },
|
|
39
|
+
default: { color: IOS_BUTTON_BLUE, fontSize: IOS_FONT_SIZE },
|
|
40
|
+
}),
|
|
13
41
|
};
|
|
14
|
-
//
|
|
15
|
-
|
|
42
|
+
// `styles.button` — empty on iOS, the whole Material look on Android.
|
|
43
|
+
export const buttonViewStyle = Platform.select({
|
|
44
|
+
ios: {},
|
|
45
|
+
android: {
|
|
46
|
+
elevation: ANDROID_ELEVATION,
|
|
47
|
+
backgroundColor: ANDROID_BUTTON_BLUE,
|
|
48
|
+
borderRadius: ANDROID_BORDER_RADIUS,
|
|
49
|
+
},
|
|
50
|
+
default: {},
|
|
51
|
+
}) ?? {};
|
|
52
|
+
/**
|
|
53
|
+
* The label style with `color` and `disabled` folded in.
|
|
54
|
+
*
|
|
55
|
+
* `color` tints the TEXT on iOS and the BUTTON on Android (Button.js:318-324), so on Android this
|
|
56
|
+
* ignores it — see `resolveButtonViewStyle`, which is where it lands there. `disabled` wins over
|
|
57
|
+
* `color` on both, because RN pushes `textDisabled` after the tint.
|
|
58
|
+
*/
|
|
16
59
|
export function resolveButtonTextStyle(color, disabled) {
|
|
17
60
|
const style = { ...buttonTextStyle };
|
|
18
|
-
if (color !== undefined)
|
|
61
|
+
if (color !== undefined && Platform.OS !== 'android')
|
|
19
62
|
style.color = color;
|
|
20
|
-
if (disabled === true)
|
|
21
|
-
style.color =
|
|
63
|
+
if (disabled === true) {
|
|
64
|
+
style.color =
|
|
65
|
+
Platform.OS === 'android' ? ANDROID_DISABLED_TEXT : IOS_DISABLED_TEXT;
|
|
66
|
+
}
|
|
67
|
+
return style;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The inner view's style with `color` and `disabled` folded in — `{}` on iOS in every combination,
|
|
71
|
+
* which is RN's own answer there and the reason the node looked droppable.
|
|
72
|
+
*/
|
|
73
|
+
export function resolveButtonViewStyle(color, disabled) {
|
|
74
|
+
if (Platform.OS !== 'android')
|
|
75
|
+
return buttonViewStyle;
|
|
76
|
+
const style = { ...buttonViewStyle };
|
|
77
|
+
if (color !== undefined)
|
|
78
|
+
style.backgroundColor = color;
|
|
79
|
+
if (disabled === true) {
|
|
80
|
+
style.elevation = ANDROID_DISABLED_ELEVATION;
|
|
81
|
+
style.backgroundColor = ANDROID_DISABLED_BACKGROUND;
|
|
82
|
+
}
|
|
22
83
|
return style;
|
|
23
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* The label as it is rendered: UPPERCASE on Android (Button.js:352-353).
|
|
87
|
+
*
|
|
88
|
+
* RN also asserts the title is a string one line above. Not reproduced: the assert is a dev-only
|
|
89
|
+
* `invariant`, and every adapter here types `title: string`.
|
|
90
|
+
*/
|
|
91
|
+
export function resolveButtonTitle(title) {
|
|
92
|
+
return Platform.OS === 'android' ? title.toUpperCase() : title;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Whether the button is disabled, which `aria-disabled` may decide on its own.
|
|
96
|
+
*
|
|
97
|
+
* Button.js:337-338 — `props.disabled != null ? props.disabled : accessibilityState.disabled`. The
|
|
98
|
+
* engine already folds `aria-disabled` into the committed `accessibilityState`, but that fold is a
|
|
99
|
+
* PAYLOAD fold: it cannot suppress the press or grey the label, which is what this is for.
|
|
100
|
+
*/
|
|
101
|
+
export function resolveButtonDisabled(disabled, ariaDisabled, accessibilityState) {
|
|
102
|
+
if (disabled !== undefined)
|
|
103
|
+
return disabled;
|
|
104
|
+
return ariaDisabled ?? accessibilityState?.disabled;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Button.js:356-359 — `'no'` becomes `'no-hide-descendants'`, so the label inside cannot take
|
|
108
|
+
* focus separately from the button that contains it.
|
|
109
|
+
*/
|
|
110
|
+
export function resolveButtonImportantForAccessibility(value) {
|
|
111
|
+
return value === 'no' ? 'no-hide-descendants' : value;
|
|
112
|
+
}
|
|
@@ -132,7 +132,7 @@ export const IMAGE_VIEW_PROP_NAMES = [
|
|
|
132
132
|
'referrerPolicy',
|
|
133
133
|
];
|
|
134
134
|
// The whole of Image's prop mapping, with the `el()` wrap taken off. Split out because a LOWERED
|
|
135
|
-
// `<
|
|
135
|
+
// `<image>` has no component body to run it in: its behavior's `foldPayload` needs the same
|
|
136
136
|
// bag at commit time, and a second implementation of this is the exact drift this file already paid
|
|
137
137
|
// for once (`adapters/svelte/src/components/image/image-logic.ts` reproduces it by hand, with a
|
|
138
138
|
// comment saying it had to because nothing here was exported).
|
|
@@ -166,5 +166,5 @@ export function mapImageProps(view) {
|
|
|
166
166
|
}
|
|
167
167
|
export function renderImage(view) {
|
|
168
168
|
dlog('Image -> RCTImageView');
|
|
169
|
-
return el('
|
|
169
|
+
return el('image', mapImageProps(view));
|
|
170
170
|
}
|
|
@@ -49,5 +49,5 @@ export function mapInputAccessoryViewProps(view) {
|
|
|
49
49
|
export function renderInputAccessoryView(view) {
|
|
50
50
|
dlog('InputAccessoryView -> RCTInputAccessoryView');
|
|
51
51
|
// Empty structural children: the adapter appends the user children directly under the host.
|
|
52
|
-
return el('
|
|
52
|
+
return el('input-accessory-view', mapInputAccessoryViewProps(view), []);
|
|
53
53
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// node: it lives in the SAME childSet and commits through the SAME completeRoot as the rest of
|
|
3
3
|
// the tree. The native iOS/Android view presents its own window internally; there is no second
|
|
4
4
|
// root or second surface on the JS side. So this is a thin render exactly like the others: it
|
|
5
|
-
// maps to the `
|
|
5
|
+
// maps to the `modal` intrinsic the host config routes to ModalHostView, wrapping a
|
|
6
6
|
// full-screen container View that holds the user children (injected by the adapter). Shared
|
|
7
7
|
// verbatim: React and Vue both bridge this Descriptor; the keep-alive state lives in state/modal.ts.
|
|
8
8
|
import { dlog, } from '@symbiote-native/engine';
|
|
@@ -52,8 +52,8 @@ export function renderModal(view) {
|
|
|
52
52
|
// collapsable:false keeps the container as a real shadow node (RN sets this so the wrapper is
|
|
53
53
|
// never flattened away under the host). Empty structural children: the adapter injects the
|
|
54
54
|
// user children UNDER this container, never as a direct sibling of the host.
|
|
55
|
-
const container = el('
|
|
56
|
-
return el('
|
|
55
|
+
const container = el('view', { style: containerStyle, collapsable: false }, []);
|
|
56
|
+
return el('modal', {
|
|
57
57
|
...view.passthrough,
|
|
58
58
|
style: MODAL_HOST_STYLE,
|
|
59
59
|
transparent: view.transparent,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { IAccessibilityStateValue } from '../../accessibility-props';
|
|
2
2
|
import type { IPressHandlers } from '../../state/pressable';
|
|
3
3
|
export declare function resolveDisabledAccessibilityState(accessibilityState: IAccessibilityStateValue | undefined, disabled: boolean | undefined): IAccessibilityStateValue | undefined;
|
|
4
|
+
export declare function resolvePressableFocusable(focusable: boolean | undefined): boolean;
|
|
5
|
+
export declare function resolveTouchableFocusable(focusable: boolean | undefined, hasOnPress: boolean, disabled: boolean | undefined): boolean;
|
|
4
6
|
export declare function shouldSuppressPress(disabled: boolean | undefined): boolean;
|
|
5
7
|
export declare function shouldClaimResponder(disabled: boolean | undefined): boolean;
|
|
6
8
|
export declare function isTerminationAllowed(cancelable: boolean | undefined): boolean;
|
|
@@ -12,6 +12,30 @@ export function resolveDisabledAccessibilityState(accessibilityState, disabled)
|
|
|
12
12
|
? { ...accessibilityState, disabled }
|
|
13
13
|
: accessibilityState;
|
|
14
14
|
}
|
|
15
|
+
// RN computes `focusable` in all five touchables and we computed it nowhere until 2026-09-09, so a
|
|
16
|
+
// DISABLED control stayed focusable — a keyboard, a TV remote or switch control could land on
|
|
17
|
+
// something that cannot be pressed. There are TWO formulas, split by primitive and not by platform;
|
|
18
|
+
// do not collapse them.
|
|
19
|
+
//
|
|
20
|
+
// Pressable defaults it ON (Pressable.js:258). `!== false`, not `?? true`: only a literal `false`
|
|
21
|
+
// opts out, the same shape `accessible` uses one file over.
|
|
22
|
+
export function resolvePressableFocusable(focusable) {
|
|
23
|
+
return focusable !== false;
|
|
24
|
+
}
|
|
25
|
+
// The four Touchable* additionally require a press handler and a non-disabled state —
|
|
26
|
+
// TouchableOpacity.js:336-340, TouchableHighlight.js:370-374,
|
|
27
|
+
// TouchableWithoutFeedback.js:263-266, TouchableNativeFeedback.js:369-372, one expression verbatim.
|
|
28
|
+
//
|
|
29
|
+
// `hasOnPress` is RN's `onPress !== undefined` and NOT `hasTouchablePressHandler`, which also counts
|
|
30
|
+
// onPressIn/onPressOut/onLongPress — that gate is the underlay's, and reusing it here would make a
|
|
31
|
+
// press-in-only Touchable focusable where RN leaves it out of the focus order.
|
|
32
|
+
//
|
|
33
|
+
// A Touchable that composes our Pressable passes the result DOWN as the `focusable` prop; Pressable
|
|
34
|
+
// then applies `!== false` to a value that is already boolean, which is why the two compose without
|
|
35
|
+
// either side knowing about the other.
|
|
36
|
+
export function resolveTouchableFocusable(focusable, hasOnPress, disabled) {
|
|
37
|
+
return (resolvePressableFocusable(focusable) && hasOnPress && disabled !== true);
|
|
38
|
+
}
|
|
15
39
|
// The 3 agnostic gating predicates behind the listener bag below. Angular has no bag to spread -
|
|
16
40
|
// it binds these directly onto template event outputs (see adapters/angular/src/components/
|
|
17
41
|
// pressable/index.ts), so they're exported and shared rather than folded back into
|
|
@@ -26,6 +26,7 @@ export interface IScrollForwarding {
|
|
|
26
26
|
capturesViewportHeight: boolean;
|
|
27
27
|
collapsableChildren: boolean;
|
|
28
28
|
}
|
|
29
|
+
export declare function preservesContentChildren(maintainVisibleContentPosition: unknown, snapToAlignment: unknown): boolean;
|
|
29
30
|
export declare function resolveScrollForwarding(inputs: IScrollForwardingInputs): IScrollForwarding;
|
|
30
31
|
export type IContentSize = {
|
|
31
32
|
width: number;
|
|
@@ -58,11 +58,11 @@ export function selectScrollIntrinsics(isHorizontal, contentContainerStyle) {
|
|
|
58
58
|
// ViewManager, not RCTScrollView+flag); on iOS both intrinsics map back to RCTScrollView.
|
|
59
59
|
// The name table does the per-platform mapping; here we only pick the intrinsic.
|
|
60
60
|
const scrollViewIntrinsic = isHorizontal
|
|
61
|
-
? '
|
|
62
|
-
: '
|
|
61
|
+
? 'horizontal-scroll-view'
|
|
62
|
+
: 'scroll-view';
|
|
63
63
|
const contentIntrinsic = isHorizontal
|
|
64
|
-
? '
|
|
65
|
-
: '
|
|
64
|
+
? 'horizontal-scroll-content'
|
|
65
|
+
: 'scroll-content';
|
|
66
66
|
const scrollViewBaseStyle = isHorizontal
|
|
67
67
|
? SCROLL_VIEW_BASE_HORIZONTAL
|
|
68
68
|
: SCROLL_VIEW_BASE_VERTICAL;
|
|
@@ -82,12 +82,21 @@ export function selectScrollIntrinsics(isHorizontal, contentContainerStyle) {
|
|
|
82
82
|
// throttle passes through untouched. These two magic numbers were copied into all three adapters.
|
|
83
83
|
const STICKY_NATIVE_SCROLL_THROTTLE = 1;
|
|
84
84
|
const STICKY_JS_SCROLL_THROTTLE = 16;
|
|
85
|
+
// maintainVisibleContentPosition (and Android snapToAlignment) anchor against MOUNTED cell views;
|
|
86
|
+
// Android Fabric view-flattens layout-only cells away, so RN keeps them as real views with
|
|
87
|
+
// collapsableChildren={false} on the content container (ScrollView.js:1731 `preserveChildren`).
|
|
88
|
+
// No-op on iOS.
|
|
89
|
+
//
|
|
90
|
+
// Named and exported rather than inlined because the LOWERED path needs the same answer from a
|
|
91
|
+
// different place — the host behavior's slot fold, which has the owner's raw props and none of the
|
|
92
|
+
// sticky inputs `resolveScrollForwarding` also takes. A second inline copy would be invisible to
|
|
93
|
+
// `tests/lowered-primitive-fold-parity.test.ts`, whose oracle is shared value IMPORTS.
|
|
94
|
+
export function preservesContentChildren(maintainVisibleContentPosition, snapToAlignment) {
|
|
95
|
+
return (maintainVisibleContentPosition !== undefined ||
|
|
96
|
+
snapToAlignment !== undefined);
|
|
97
|
+
}
|
|
85
98
|
export function resolveScrollForwarding(inputs) {
|
|
86
|
-
|
|
87
|
-
// Android Fabric view-flattens layout-only cells away, so RN keeps them as real views with
|
|
88
|
-
// collapsableChildren={false} on the content container (ScrollView.js preserveChildren). No-op on iOS.
|
|
89
|
-
const collapsableChildren = inputs.maintainVisibleContentPosition !== undefined ||
|
|
90
|
-
inputs.snapToAlignment !== undefined;
|
|
99
|
+
const collapsableChildren = preservesContentChildren(inputs.maintainVisibleContentPosition, inputs.snapToAlignment);
|
|
91
100
|
if (!inputs.hasStickyHeaders) {
|
|
92
101
|
return {
|
|
93
102
|
mode: 'plain',
|
|
@@ -5,9 +5,12 @@ export type ISwitchTrackColor = {
|
|
|
5
5
|
false?: string;
|
|
6
6
|
true?: string;
|
|
7
7
|
};
|
|
8
|
+
export type ISwitchChangeEvent = ISymbioteEvent & {
|
|
9
|
+
value: boolean;
|
|
10
|
+
};
|
|
8
11
|
export interface ISwitchProps extends IAccessibilityProps, IAriaProps {
|
|
9
12
|
value?: boolean;
|
|
10
|
-
onValueChange?: (
|
|
13
|
+
onValueChange?: (event: ISwitchChangeEvent) => void;
|
|
11
14
|
disabled?: boolean;
|
|
12
15
|
trackColor?: ISwitchTrackColor;
|
|
13
16
|
thumbColor?: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Switch: the render half (framework-agnostic). Maps the resolved props onto the single
|
|
2
|
-
// `
|
|
2
|
+
// `switch` host node: the strict value fold lands as the `value` Fabric prop, the
|
|
3
3
|
// track colors take platform-specific prop NAMES (iOS onTintColor/tintColor vs Android
|
|
4
4
|
// trackColorFor*/trackTintColor, supplied via `platform`), thumbColor → thumbTintColor, and
|
|
5
5
|
// ios_backgroundColor folds into the style as the pill that shows through the shrunken track.
|
|
@@ -13,7 +13,7 @@ const IOS_BACKGROUND_BORDER_RADIUS = 16;
|
|
|
13
13
|
// (lastNativeReport, the snap-back effect), so it may not share a tag the behavior registry would
|
|
14
14
|
// also attach to; see that behavior's module header and `.claude/rules/host-primitive-tier.md`,
|
|
15
15
|
// "A lowered element and its wrapper must not share an intrinsic tag" (the TextInput precedent).
|
|
16
|
-
const SWITCH_MANAGED_INTRINSIC = '
|
|
16
|
+
const SWITCH_MANAGED_INTRINSIC = 'switch-managed';
|
|
17
17
|
// Fold ios_backgroundColor into the style, matching RN's iOS branch: it paints the
|
|
18
18
|
// background that shows through the shrunken track. Untouched when unset, so a caller's own
|
|
19
19
|
// backgroundColor wins by simply not passing ios_backgroundColor.
|
|
@@ -12,8 +12,8 @@ import { el } from '../descriptor.js';
|
|
|
12
12
|
// same native view; the tag is what decides whether the engine's TextInput machine attaches, and
|
|
13
13
|
// on this path the adapter's own lifecycle already owns that state. Sharing the tag would run both
|
|
14
14
|
// copies at once. Full reasoning in `component-names/shared.ts`.
|
|
15
|
-
const SINGLELINE_INTRINSIC = '
|
|
16
|
-
const MULTILINE_INTRINSIC = '
|
|
15
|
+
const SINGLELINE_INTRINSIC = 'text-input-managed';
|
|
16
|
+
const MULTILINE_INTRINSIC = 'text-input-multiline-managed';
|
|
17
17
|
export function renderTextInput(view) {
|
|
18
18
|
const intrinsic = view.multiline ? MULTILINE_INTRINSIC : SINGLELINE_INTRINSIC;
|
|
19
19
|
dlog(`TextInput render multiline=${String(view.multiline)} ` +
|
|
@@ -15,3 +15,22 @@ export declare function selectableBackground(rippleRadius?: number): IThemeAttrB
|
|
|
15
15
|
export declare function selectableBackgroundBorderless(rippleRadius?: number): IThemeAttrBackground;
|
|
16
16
|
export declare function rippleBackground(color: string, borderless: boolean, rippleRadius?: number): IRippleBackground;
|
|
17
17
|
export declare function backgroundProps(background: INativeFeedbackBackground, useForeground: boolean): Record<string, INativeFeedbackBackground>;
|
|
18
|
+
/**
|
|
19
|
+
* RN's four statics, under RN's own spelling — `TouchableNativeFeedback.Ripple(color, borderless)`.
|
|
20
|
+
*
|
|
21
|
+
* A NAMESPACE OBJECT rather than a component value, and that is the whole of what survived the
|
|
22
|
+
* wrapper: the element is a tag now, and a tag is a string, which cannot carry properties. Shared
|
|
23
|
+
* rather than copied five times because every member is a pure dict producer with no framework in
|
|
24
|
+
* it; each adapter re-exports it verbatim, as it does the background types beside it.
|
|
25
|
+
*
|
|
26
|
+
* NOT the spelling for NEW code, and not redundant either. RN's docs point at `Pressable`'s
|
|
27
|
+
* declarative `android_ripple={{ color, borderless }}`, which the pressable behavior resolves
|
|
28
|
+
* (`behaviors/pressable.ts`, `asRippleConfig`). These four stay because the
|
|
29
|
+
* `touchable-native-feedback` tag folds `background` and nothing else produces that value.
|
|
30
|
+
*/
|
|
31
|
+
export declare const TouchableNativeFeedback: {
|
|
32
|
+
SelectableBackground: typeof selectableBackground;
|
|
33
|
+
SelectableBackgroundBorderless: typeof selectableBackgroundBorderless;
|
|
34
|
+
Ripple: typeof rippleBackground;
|
|
35
|
+
canUseNativeForeground: typeof canUseNativeForeground;
|
|
36
|
+
};
|
|
@@ -41,3 +41,22 @@ export function backgroundProps(background, useForeground) {
|
|
|
41
41
|
}
|
|
42
42
|
return { nativeBackgroundAndroid: background };
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* RN's four statics, under RN's own spelling — `TouchableNativeFeedback.Ripple(color, borderless)`.
|
|
46
|
+
*
|
|
47
|
+
* A NAMESPACE OBJECT rather than a component value, and that is the whole of what survived the
|
|
48
|
+
* wrapper: the element is a tag now, and a tag is a string, which cannot carry properties. Shared
|
|
49
|
+
* rather than copied five times because every member is a pure dict producer with no framework in
|
|
50
|
+
* it; each adapter re-exports it verbatim, as it does the background types beside it.
|
|
51
|
+
*
|
|
52
|
+
* NOT the spelling for NEW code, and not redundant either. RN's docs point at `Pressable`'s
|
|
53
|
+
* declarative `android_ripple={{ color, borderless }}`, which the pressable behavior resolves
|
|
54
|
+
* (`behaviors/pressable.ts`, `asRippleConfig`). These four stay because the
|
|
55
|
+
* `touchable-native-feedback` tag folds `background` and nothing else produces that value.
|
|
56
|
+
*/
|
|
57
|
+
export const TouchableNativeFeedback = {
|
|
58
|
+
SelectableBackground: selectableBackground,
|
|
59
|
+
SelectableBackgroundBorderless: selectableBackgroundBorderless,
|
|
60
|
+
Ripple: rippleBackground,
|
|
61
|
+
canUseNativeForeground,
|
|
62
|
+
};
|