@symbiote-native/react 0.4.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 +32 -16
- package/build/components/activity-indicator-props.d.ts +4 -0
- package/build/components/activity-indicator-props.js +1 -0
- package/build/components/{button.d.ts → button-props.d.ts} +0 -2
- package/build/components/button-props.js +1 -0
- package/build/components/flat-list/index.js +2 -2
- package/build/components/image/image-props.d.ts +4 -0
- package/build/components/image/image-props.js +1 -0
- package/build/components/image-background-props.d.ts +9 -0
- package/build/components/image-background-props.js +1 -0
- package/build/components/input-accessory-view-props.d.ts +10 -0
- package/build/components/input-accessory-view-props.js +1 -0
- package/build/components/keyboard-avoiding-view/index.js +4 -4
- package/build/components/modal/index.js +3 -3
- package/build/components/pressable/{index.d.ts → pressable-props.d.ts} +4 -4
- package/build/components/pressable/pressable-props.js +1 -0
- package/build/components/{refresh-control/index.d.ts → refresh-control-props.d.ts} +3 -3
- package/build/components/refresh-control-props.js +1 -0
- package/build/components/safe-area-view-props.d.ts +11 -0
- package/build/components/safe-area-view-props.js +1 -0
- package/build/components/scroll-view/{shared.d.ts → scroll-view-props.d.ts} +4 -26
- package/build/components/scroll-view/scroll-view-props.js +1 -0
- package/build/components/switch/switch-props.d.ts +4 -0
- package/build/components/switch/switch-props.js +1 -0
- package/build/components/text-input/text-input-props.d.ts +4 -0
- package/build/components/text-input/text-input-props.js +1 -0
- package/build/components/touchable/touchable-props.d.ts +17 -0
- package/build/components/touchable/touchable-props.js +1 -0
- package/build/components/touchable-native-feedback/touchable-native-feedback-props.d.ts +8 -0
- package/build/components/touchable-native-feedback/touchable-native-feedback-props.js +1 -0
- package/build/components/touchable-without-feedback/touchable-without-feedback-props.d.ts +6 -0
- package/build/components/touchable-without-feedback/touchable-without-feedback-props.js +1 -0
- package/build/components/virtualized-list/index.js +83 -38
- package/build/components.d.ts +3 -4
- package/build/components.js +5 -17
- package/build/create-portal/index.js +1 -1
- package/build/create-tunnel/index.js +1 -1
- package/build/descriptor-to-react/index.js +1 -1
- package/build/host-config.d.ts +2 -2
- package/build/host-config.js +51 -10
- package/build/host-instance.js +1 -1
- package/build/index.d.ts +23 -27
- package/build/index.js +14 -14
- package/build/jsx-dev-runtime.d.ts +3 -0
- package/build/jsx-dev-runtime.js +10 -0
- package/build/jsx-namespace.type-check.d.ts +1 -0
- package/build/jsx-namespace.type-check.js +7 -0
- package/build/jsx-runtime.d.ts +62 -0
- package/build/jsx-runtime.js +1 -0
- package/build/modules/animated/create-animated-component.d.ts +2 -1
- package/build/modules/animated/create-animated-component.js +7 -1
- package/build/modules/animated/index.d.ts +0 -1
- package/build/modules/animated/index.js +16 -22
- package/build/modules/image/index.d.ts +3 -0
- package/build/modules/image/index.js +14 -0
- package/build/register.d.ts +1 -0
- package/build/register.js +15 -0
- package/build/render.js +2 -4
- package/metro-css-parser.cjs +2 -1
- package/package.json +28 -8
- package/build/components/activity-indicator/index.android.d.ts +0 -3
- package/build/components/activity-indicator/index.android.js +0 -17
- package/build/components/activity-indicator/index.d.ts +0 -1
- package/build/components/activity-indicator/index.ios.d.ts +0 -3
- package/build/components/activity-indicator/index.ios.js +0 -16
- package/build/components/activity-indicator/index.js +0 -4
- package/build/components/activity-indicator/shared.d.ts +0 -6
- package/build/components/activity-indicator/shared.js +0 -22
- package/build/components/button.js +0 -42
- package/build/components/image/index.d.ts +0 -9
- package/build/components/image/index.js +0 -28
- package/build/components/image-background/index.d.ts +0 -10
- package/build/components/image-background/index.js +0 -46
- package/build/components/input-accessory-view/index.d.ts +0 -11
- package/build/components/input-accessory-view/index.js +0 -19
- package/build/components/pressable/index.js +0 -100
- package/build/components/refresh-control/index.js +0 -21
- package/build/components/safe-area-view/index.d.ts +0 -11
- package/build/components/safe-area-view/index.js +0 -18
- package/build/components/scroll-view/index.android.d.ts +0 -3
- package/build/components/scroll-view/index.android.js +0 -61
- package/build/components/scroll-view/index.d.ts +0 -1
- package/build/components/scroll-view/index.ios.d.ts +0 -3
- package/build/components/scroll-view/index.ios.js +0 -29
- package/build/components/scroll-view/index.js +0 -4
- package/build/components/scroll-view/shared.js +0 -240
- package/build/components/scroll-view/sticky-header.d.ts +0 -18
- package/build/components/scroll-view/sticky-header.js +0 -227
- package/build/components/switch/index.android.d.ts +0 -3
- package/build/components/switch/index.android.js +0 -18
- package/build/components/switch/index.d.ts +0 -1
- package/build/components/switch/index.ios.d.ts +0 -3
- package/build/components/switch/index.ios.js +0 -16
- package/build/components/switch/index.js +0 -6
- package/build/components/switch/shared.d.ts +0 -9
- package/build/components/switch/shared.js +0 -60
- package/build/components/text-input/index.d.ts +0 -50
- package/build/components/text-input/index.js +0 -172
- package/build/components/touchable/index.d.ts +0 -22
- package/build/components/touchable/index.js +0 -165
- package/build/components/touchable-native-feedback/index.d.ts +0 -18
- package/build/components/touchable-native-feedback/index.js +0 -32
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
// The Touchable* family, all built on Pressable. Ported against RN's own sources
|
|
2
|
-
// (.vendors/react-native/.../Components/Touchable/*.js) after the 2026-08-19 audit found ten
|
|
3
|
-
// divergences; the shared halves live in @symbiote-native/components and React owns only the
|
|
4
|
-
// lifecycle — refs, effects, the real timers, the Animated wiring, and the child clone:
|
|
5
|
-
// TouchableOpacity: an Animated.Value fades toward activeOpacity on press-in and back to the
|
|
6
|
-
// style's own resting opacity on press-out, driven from onPressIn/onPressOut.
|
|
7
|
-
// TouchableHighlight: the underlay machine drives a `shown` flag (NOT `pressed` — RN holds the
|
|
8
|
-
// underlay for delayPressOut past the tap); the container takes the underlay color and the
|
|
9
|
-
// child takes the lowered opacity, RN's split.
|
|
10
|
-
// TouchableWithoutFeedback: the same press-timing machine with the visual half left empty —
|
|
11
|
-
// "without feedback" means no VISUAL, not no timing.
|
|
12
|
-
import { Children, cloneElement, createElement, isValidElement, useEffect, useRef, useState, } from 'react';
|
|
13
|
-
import { createHighlightUnderlayHandlers, createHighlightUnderlayRuntime, createTouchableFeedbackHandlers, createTouchableFeedbackRuntime, hasTouchablePressHandler, resolveHighlightExtraStyles, restingOpacityFromStyle, DEFAULT_ACTIVE_OPACITY, OPACITY_ACTIVE_GRANT_DURATION_MS, OPACITY_INACTIVE_DURATION_MS, TOUCHABLE_MIN_PRESS_DURATION_MS, } from '@symbiote-native/components';
|
|
14
|
-
import { Pressable } from '../pressable/index.js';
|
|
15
|
-
import { Animated } from '../../modules/animated/index.js';
|
|
16
|
-
// The real setTimeout the shared machines schedule on (core/components has no timer globals).
|
|
17
|
-
// Returns a canceller so an early release flushes the timer.
|
|
18
|
-
function scheduleTimeout(callback, ms) {
|
|
19
|
-
const id = setTimeout(callback, ms);
|
|
20
|
-
return () => clearTimeout(id);
|
|
21
|
-
}
|
|
22
|
-
export const TouchableOpacity = props => {
|
|
23
|
-
const { activeOpacity = DEFAULT_ACTIVE_OPACITY, style,
|
|
24
|
-
// className is pulled out here, like style, and applied to the inner Animated.View below —
|
|
25
|
-
// left in ...rest it would land on the outer Pressable instead, which is not where `style`
|
|
26
|
-
// (the opacity-fade node) goes.
|
|
27
|
-
className, children, disabled, onPressIn, onPressOut, delayPressIn = 0, delayPressOut = 0,
|
|
28
|
-
// RN's Touchables override Pressability's 130ms floor with 0 (TouchableOpacity.js:195); the
|
|
29
|
-
// active visual is held by the fade's own duration instead.
|
|
30
|
-
minPressDuration = TOUCHABLE_MIN_PRESS_DURATION_MS, ...rest } = props;
|
|
31
|
-
// RN's _getChildStyleOpacityWithDefault: the fade settles at the opacity the CALLER's style
|
|
32
|
-
// asks for, not at a hard 1 — and must START there, or the first paint jumps to fully opaque.
|
|
33
|
-
const restingOpacity = restingOpacityFromStyle(style);
|
|
34
|
-
// One Animated.Value per mount. The Animated.View leaf commits its current value every frame,
|
|
35
|
-
// so timing it animates the real view.
|
|
36
|
-
const opacity = useRef(new Animated.Value(restingOpacity)).current;
|
|
37
|
-
// The shared press-scheduling cell (delayPressIn timer + activation clock), held across renders.
|
|
38
|
-
const runtime = useRef(createTouchableFeedbackRuntime()).current;
|
|
39
|
-
function setOpacityTo(toValue, duration) {
|
|
40
|
-
// useNativeDriver: true is RN's own (TouchableOpacity.js:242). opacity is natively drivable
|
|
41
|
-
// and the fade then survives a busy JS thread, which is the whole point of the feedback.
|
|
42
|
-
Animated.timing(opacity, {
|
|
43
|
-
toValue,
|
|
44
|
-
duration,
|
|
45
|
-
easing: Animated.Easing.inOut(Animated.Easing.quad),
|
|
46
|
-
useNativeDriver: true,
|
|
47
|
-
}).start();
|
|
48
|
-
}
|
|
49
|
-
// RN's componentDidUpdate: a changed `disabled` or a changed style opacity re-settles the view,
|
|
50
|
-
// so a Touchable disabled mid-press does not stay stuck at its active opacity.
|
|
51
|
-
const hasRendered = useRef(false);
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
// RN runs this on UPDATE only. Firing at mount would animate over the value the
|
|
54
|
-
// Animated.Value was just constructed with.
|
|
55
|
-
if (!hasRendered.current) {
|
|
56
|
-
hasRendered.current = true;
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
setOpacityTo(restingOpacity, OPACITY_INACTIVE_DURATION_MS);
|
|
60
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps -- setOpacityTo is re-made per render
|
|
61
|
-
}, [disabled, restingOpacity]);
|
|
62
|
-
// RN's componentWillUnmount: stop the fade so a teardown mid-animation leaves no driver running
|
|
63
|
-
// against a node that is gone.
|
|
64
|
-
useEffect(() => () => {
|
|
65
|
-
opacity.resetAnimation();
|
|
66
|
-
}, [opacity]);
|
|
67
|
-
// The shared machine owns the delayPressIn/minPressDuration scheduling; the adapter supplies only
|
|
68
|
-
// the native seam — the Animated opacity fade + the framework emit — as activate/deactivate.
|
|
69
|
-
const { handlePressIn, handlePressOut } = createTouchableFeedbackHandlers({
|
|
70
|
-
delayPressIn,
|
|
71
|
-
delayPressOut,
|
|
72
|
-
minPressDuration,
|
|
73
|
-
schedule: scheduleTimeout,
|
|
74
|
-
now: Date.now,
|
|
75
|
-
}, runtime, {
|
|
76
|
-
activate(event) {
|
|
77
|
-
setOpacityTo(activeOpacity, OPACITY_ACTIVE_GRANT_DURATION_MS);
|
|
78
|
-
onPressIn?.(event);
|
|
79
|
-
},
|
|
80
|
-
deactivate(event) {
|
|
81
|
-
setOpacityTo(restingOpacity, OPACITY_INACTIVE_DURATION_MS);
|
|
82
|
-
onPressOut?.(event);
|
|
83
|
-
},
|
|
84
|
-
});
|
|
85
|
-
return createElement(Pressable, { ...rest, disabled, onPressIn: handlePressIn, onPressOut: handlePressOut }, createElement(Animated.View, { style: [style, { opacity }], className }, children));
|
|
86
|
-
};
|
|
87
|
-
// RN's render: the lowered opacity is cloned onto the CHILD while the container keeps an opaque
|
|
88
|
-
// underlay (TouchableHighlight.js). Fold both onto the container instead and the opacity fades the
|
|
89
|
-
// very underlay it is meant to reveal — `underlayColor: 'black'` paints grey. React is the one
|
|
90
|
-
// adapter that can reach the child without a wrapper view perturbing the flex chain.
|
|
91
|
-
// A non-element child (text, a fragment, nothing at all) has no style prop to compose onto, so it
|
|
92
|
-
// passes through untouched rather than throwing the way RN's Children.only would.
|
|
93
|
-
function withChildStyle(children, extra) {
|
|
94
|
-
const child = Children.count(children) === 1 ? children : undefined;
|
|
95
|
-
if (!isValidElement(child))
|
|
96
|
-
return children;
|
|
97
|
-
return cloneElement(child, { style: [child.props.style, extra] });
|
|
98
|
-
}
|
|
99
|
-
export const TouchableHighlight = props => {
|
|
100
|
-
const { activeOpacity, underlayColor, style, children, onPress, onPressIn, onPressOut, onShowUnderlay, onHideUnderlay, delayPressOut = 0, ...rest } = props;
|
|
101
|
-
// `shown` is NOT `pressed`: RN holds the underlay for delayPressOut past the tap so a press too
|
|
102
|
-
// fast to see still flashes, and the pressed flag is already false by then.
|
|
103
|
-
const [shown, setShown] = useState(false);
|
|
104
|
-
const runtime = useRef(createHighlightUnderlayRuntime()).current;
|
|
105
|
-
// RN's _hasPressHandler gate: no press handler, no underlay. onLongPress is only READ here —
|
|
106
|
-
// it stays in `rest` for Pressable to fire directly.
|
|
107
|
-
const hasPressHandler = hasTouchablePressHandler({
|
|
108
|
-
onPress,
|
|
109
|
-
onPressIn,
|
|
110
|
-
onPressOut,
|
|
111
|
-
onLongPress: rest.onLongPress,
|
|
112
|
-
});
|
|
113
|
-
const underlay = createHighlightUnderlayHandlers({ delayPressOut, hasPressHandler, schedule: scheduleTimeout }, runtime, { setShown, onShowUnderlay, onHideUnderlay });
|
|
114
|
-
const extraStyles = resolveHighlightExtraStyles({
|
|
115
|
-
shown,
|
|
116
|
-
hasPressHandler,
|
|
117
|
-
underlayColor,
|
|
118
|
-
activeOpacity,
|
|
119
|
-
});
|
|
120
|
-
// Visual first, then the caller's callback — RN's order in _createPressabilityConfig.
|
|
121
|
-
function handlePressIn(event) {
|
|
122
|
-
underlay.handlePressIn(event);
|
|
123
|
-
onPressIn?.(event);
|
|
124
|
-
}
|
|
125
|
-
function handlePress(event) {
|
|
126
|
-
underlay.handlePress(event);
|
|
127
|
-
onPress?.(event);
|
|
128
|
-
}
|
|
129
|
-
function handlePressOut(event) {
|
|
130
|
-
underlay.handlePressOut(event);
|
|
131
|
-
onPressOut?.(event);
|
|
132
|
-
}
|
|
133
|
-
return createElement(Pressable, {
|
|
134
|
-
...rest,
|
|
135
|
-
style: extraStyles === undefined ? style : [style, extraStyles.underlay],
|
|
136
|
-
onPress: handlePress,
|
|
137
|
-
onPressIn: handlePressIn,
|
|
138
|
-
onPressOut: handlePressOut,
|
|
139
|
-
}, extraStyles === undefined
|
|
140
|
-
? children
|
|
141
|
-
: withChildStyle(children, extraStyles.child));
|
|
142
|
-
};
|
|
143
|
-
export const TouchableWithoutFeedback = props => {
|
|
144
|
-
const { children, onPressIn, onPressOut, delayPressIn = 0, delayPressOut = 0, minPressDuration = TOUCHABLE_MIN_PRESS_DURATION_MS, ...rest } = props;
|
|
145
|
-
// RN's TouchableWithoutFeedback builds a FULL Pressability config with delayPressIn /
|
|
146
|
-
// delayPressOut / minPressDuration: 0 — the same shared machine TouchableOpacity uses, with the
|
|
147
|
-
// visual half left empty. Spreading the delay props onto Pressable instead did nothing: it does
|
|
148
|
-
// not read them, and they leaked to the host as unknown props.
|
|
149
|
-
const runtime = useRef(createTouchableFeedbackRuntime()).current;
|
|
150
|
-
const { handlePressIn, handlePressOut } = createTouchableFeedbackHandlers({
|
|
151
|
-
delayPressIn,
|
|
152
|
-
delayPressOut,
|
|
153
|
-
minPressDuration,
|
|
154
|
-
schedule: scheduleTimeout,
|
|
155
|
-
now: Date.now,
|
|
156
|
-
}, runtime, {
|
|
157
|
-
activate(event) {
|
|
158
|
-
onPressIn?.(event);
|
|
159
|
-
},
|
|
160
|
-
deactivate(event) {
|
|
161
|
-
onPressOut?.(event);
|
|
162
|
-
},
|
|
163
|
-
});
|
|
164
|
-
return createElement(Pressable, { ...rest, onPressIn: handlePressIn, onPressOut: handlePressOut }, children);
|
|
165
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { type FC, type ReactNode } from 'react';
|
|
2
|
-
import { type INativeFeedbackBackground, type IThemeAttrBackground, type IRippleBackground } from '@symbiote-native/components';
|
|
3
|
-
import { type IPressableProps } from '../pressable';
|
|
4
|
-
export type { INativeFeedbackBackground, IThemeAttrBackground, IRippleBackground, } from '@symbiote-native/components';
|
|
5
|
-
type ITouchableNativeFeedbackBaseProps = Omit<IPressableProps, 'style' | 'children'> & {
|
|
6
|
-
background?: INativeFeedbackBackground;
|
|
7
|
-
useForeground?: boolean;
|
|
8
|
-
children?: ReactNode;
|
|
9
|
-
};
|
|
10
|
-
export type ITouchableNativeFeedbackProps = ITouchableNativeFeedbackBaseProps;
|
|
11
|
-
interface ITouchableNativeFeedbackComponent extends FC<ITouchableNativeFeedbackProps> {
|
|
12
|
-
SelectableBackground: (rippleRadius?: number) => IThemeAttrBackground;
|
|
13
|
-
SelectableBackgroundBorderless: (rippleRadius?: number) => IThemeAttrBackground;
|
|
14
|
-
Ripple: (color: string, borderless: boolean, rippleRadius?: number) => IRippleBackground;
|
|
15
|
-
canUseNativeForeground: () => boolean;
|
|
16
|
-
}
|
|
17
|
-
declare const TouchableNativeFeedback: ITouchableNativeFeedbackComponent;
|
|
18
|
-
export { TouchableNativeFeedback };
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
// TouchableNativeFeedback: Android's ripple/state-drawable touchable, built on Pressable like the
|
|
2
|
-
// rest of the family. RN realizes its feedback by cloning the child into an RCTView carrying native
|
|
3
|
-
// ripple props; we instead nest the child under a feedback View that carries those props, inside a
|
|
4
|
-
// Pressable that owns the press wiring. The native props (nativeBackgroundAndroid /
|
|
5
|
-
// nativeForegroundAndroid) are read by Android's ReactViewManager; on iOS they are inert props, so
|
|
6
|
-
// the component still renders its child with working press wiring. The static factories +
|
|
7
|
-
// background mapping are shared in @symbiote-native/components/view. React only attaches them onto the
|
|
8
|
-
// component value and nests the feedback View.
|
|
9
|
-
import { createElement } from 'react';
|
|
10
|
-
import { dlog } from '@symbiote-native/engine';
|
|
11
|
-
import { backgroundProps, canUseNativeForeground, rippleBackground, selectableBackground, selectableBackgroundBorderless, } from '@symbiote-native/components';
|
|
12
|
-
import { View } from '../../components.js';
|
|
13
|
-
import { Pressable } from '../pressable/index.js';
|
|
14
|
-
const TouchableNativeFeedbackImpl = props => {
|
|
15
|
-
const { background, useForeground = false, children, ...rest } = props;
|
|
16
|
-
// RN defaults a missing background to SelectableBackground() so the touchable always has
|
|
17
|
-
// feedback; mirror that here.
|
|
18
|
-
const resolved = background ?? selectableBackground();
|
|
19
|
-
dlog(`TouchableNativeFeedback render ${resolved.type} useForeground ${useForeground}`);
|
|
20
|
-
const nativeProps = backgroundProps(resolved, useForeground);
|
|
21
|
-
// The native ripple props ride a dedicated feedback View nested under the Pressable; the
|
|
22
|
-
// Pressable owns the press wiring, the feedback View owns the drawable.
|
|
23
|
-
const feedback = createElement(View, nativeProps, children);
|
|
24
|
-
return createElement(Pressable, rest, feedback);
|
|
25
|
-
};
|
|
26
|
-
const TouchableNativeFeedback = Object.assign(TouchableNativeFeedbackImpl, {
|
|
27
|
-
SelectableBackground: selectableBackground,
|
|
28
|
-
SelectableBackgroundBorderless: selectableBackgroundBorderless,
|
|
29
|
-
Ripple: rippleBackground,
|
|
30
|
-
canUseNativeForeground,
|
|
31
|
-
});
|
|
32
|
-
export { TouchableNativeFeedback };
|