@oxyhq/bloom 0.72.1 → 0.72.2
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/lib/commonjs/overlay/index.js +53 -32
- package/lib/commonjs/overlay/index.js.map +1 -1
- package/lib/module/overlay/index.js +53 -32
- package/lib/module/overlay/index.js.map +1 -1
- package/lib/typescript/commonjs/overlay/index.d.ts +16 -4
- package/lib/typescript/commonjs/overlay/index.d.ts.map +1 -1
- package/lib/typescript/module/overlay/index.d.ts +16 -4
- package/lib/typescript/module/overlay/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/backdrop-nesting.test.tsx +95 -0
- package/src/overlay/index.tsx +47 -31
|
@@ -90,9 +90,21 @@ function OverlayRoot({
|
|
|
90
90
|
}
|
|
91
91
|
OverlayRoot.displayName = 'OverlayRoot';
|
|
92
92
|
/**
|
|
93
|
-
* Full-bleed blur + dim that dismisses the surface when pressed.
|
|
94
|
-
*
|
|
95
|
-
*
|
|
93
|
+
* Full-bleed blur + dim that dismisses the surface when pressed.
|
|
94
|
+
*
|
|
95
|
+
* The dismiss target is a hit box that fills this component and sits BEHIND
|
|
96
|
+
* `children`, never around them. It used to wrap them, which read fine on
|
|
97
|
+
* native but is invalid on web: the hit box carries `accessibilityRole="button"`,
|
|
98
|
+
* so react-native-web renders it as a real `<button>` — and every control inside
|
|
99
|
+
* any Bloom surface (a dialog's own buttons, a menu's rows) became a nested
|
|
100
|
+
* `<button>`. React reports that as a hydration error, and the nested control's
|
|
101
|
+
* activation behaviour is undefined per the HTML spec.
|
|
102
|
+
*
|
|
103
|
+
* Hit testing is unchanged: the hit box still covers the whole area, `children`
|
|
104
|
+
* render above it and take their own presses, and a press that lands on empty
|
|
105
|
+
* space falls through to the hit box. Layout styles passed via `style` stay on
|
|
106
|
+
* the outer box, so a caller that centres its panel with this component (the
|
|
107
|
+
* centred dialog) keeps doing so.
|
|
96
108
|
*/
|
|
97
109
|
const Backdrop = exports.Backdrop = /*#__PURE__*/(0, _react.memo)(function Backdrop({
|
|
98
110
|
onPress,
|
|
@@ -134,35 +146,44 @@ const Backdrop = exports.Backdrop = /*#__PURE__*/(0, _react.memo)(function Backd
|
|
|
134
146
|
const dimFade = (0, _reactNativeReanimated.useAnimatedStyle)(() => ({
|
|
135
147
|
opacity: (progress ? progress.value : 1) * staticOpacity * dimOpacity
|
|
136
148
|
}), [progress, staticOpacity, dimOpacity]);
|
|
137
|
-
return
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
149
|
+
return (
|
|
150
|
+
/*#__PURE__*/
|
|
151
|
+
// `box-none` so this box never takes a press itself: the hit box below and
|
|
152
|
+
// `children` above are what receive them.
|
|
153
|
+
(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
154
|
+
pointerEvents: "box-none",
|
|
155
|
+
style: [_reactNative.StyleSheet.absoluteFill, rootStyle],
|
|
156
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
|
|
157
|
+
pointerEvents: "auto",
|
|
158
|
+
onPress: inert ? undefined : onPress,
|
|
159
|
+
disabled: inert
|
|
160
|
+
// A dimming layer is not a focus stop on web: Escape and the panel's own
|
|
161
|
+
// controls are the keyboard paths out. It stays labelled for screen
|
|
162
|
+
// readers that surface it as the dismiss affordance.
|
|
163
|
+
,
|
|
164
|
+
focusable: false,
|
|
165
|
+
accessibilityRole: inert ? undefined : 'button',
|
|
166
|
+
accessibilityLabel: inert ? undefined : accessibilityLabel,
|
|
167
|
+
testID: testID,
|
|
168
|
+
style: _reactNative.StyleSheet.absoluteFill,
|
|
169
|
+
children: [blurIntensity > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(AnimatedBlurView, {
|
|
170
|
+
intensity: blurIntensity,
|
|
171
|
+
tint: blurTint
|
|
172
|
+
// Android's default blur is a no-op on many devices; this is the
|
|
173
|
+
// implementation that actually renders there.
|
|
174
|
+
,
|
|
175
|
+
experimentalBlurMethod: "dimezisBlurView",
|
|
176
|
+
pointerEvents: "none",
|
|
177
|
+
style: [_reactNative.StyleSheet.absoluteFill, layerStyle, blurFade]
|
|
178
|
+
}) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
|
|
179
|
+
pointerEvents: "none",
|
|
180
|
+
style: [_reactNative.StyleSheet.absoluteFill, {
|
|
181
|
+
backgroundColor: resolvedDimColor
|
|
182
|
+
}, layerStyle, dimFade]
|
|
183
|
+
})]
|
|
184
|
+
}), children]
|
|
185
|
+
})
|
|
186
|
+
);
|
|
166
187
|
});
|
|
167
188
|
Backdrop.displayName = 'Backdrop';
|
|
168
189
|
const styles = _reactNative.StyleSheet.create({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","require","_expoBlur","_reactNative","_reactNativeReanimated","_interopRequireWildcard","_webViewStyle","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","AnimatedBlurView","Animated","createAnimatedComponent","BlurView","BACKDROP_BLUR_INTENSITY","exports","BACKDROP_DIM_OPACITY","OverlayRoot","children","style","testID","jsx","View","pointerEvents","styles","root","displayName","Backdrop","memo","onPress","progress","disabled","blurIntensity","blurTint","dimColor","dimOpacity","layerStyle","accessibilityLabel","inert","flat","StyleSheet","flatten","opacity","styleOpacity","backgroundColor","styleBackground","rootStyle","staticOpacity","resolvedDimColor","blurFade","useAnimatedStyle","value","dimFade","jsxs","Pressable","undefined","focusable","accessibilityRole","
|
|
1
|
+
{"version":3,"names":["_react","require","_expoBlur","_reactNative","_reactNativeReanimated","_interopRequireWildcard","_webViewStyle","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","AnimatedBlurView","Animated","createAnimatedComponent","BlurView","BACKDROP_BLUR_INTENSITY","exports","BACKDROP_DIM_OPACITY","OverlayRoot","children","style","testID","jsx","View","pointerEvents","styles","root","displayName","Backdrop","memo","onPress","progress","disabled","blurIntensity","blurTint","dimColor","dimOpacity","layerStyle","accessibilityLabel","inert","flat","StyleSheet","flatten","opacity","styleOpacity","backgroundColor","styleBackground","rootStyle","staticOpacity","resolvedDimColor","blurFade","useAnimatedStyle","value","dimFade","jsxs","absoluteFill","Pressable","undefined","focusable","accessibilityRole","intensity","tint","experimentalBlurMethod","create","position","Platform","OS","WEB_POSITION_FIXED","top","left","right","bottom"],"sourceRoot":"../../../src","sources":["overlay/index.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -83,9 +83,21 @@ export function OverlayRoot({
|
|
|
83
83
|
}
|
|
84
84
|
OverlayRoot.displayName = 'OverlayRoot';
|
|
85
85
|
/**
|
|
86
|
-
* Full-bleed blur + dim that dismisses the surface when pressed.
|
|
87
|
-
*
|
|
88
|
-
*
|
|
86
|
+
* Full-bleed blur + dim that dismisses the surface when pressed.
|
|
87
|
+
*
|
|
88
|
+
* The dismiss target is a hit box that fills this component and sits BEHIND
|
|
89
|
+
* `children`, never around them. It used to wrap them, which read fine on
|
|
90
|
+
* native but is invalid on web: the hit box carries `accessibilityRole="button"`,
|
|
91
|
+
* so react-native-web renders it as a real `<button>` — and every control inside
|
|
92
|
+
* any Bloom surface (a dialog's own buttons, a menu's rows) became a nested
|
|
93
|
+
* `<button>`. React reports that as a hydration error, and the nested control's
|
|
94
|
+
* activation behaviour is undefined per the HTML spec.
|
|
95
|
+
*
|
|
96
|
+
* Hit testing is unchanged: the hit box still covers the whole area, `children`
|
|
97
|
+
* render above it and take their own presses, and a press that lands on empty
|
|
98
|
+
* space falls through to the hit box. Layout styles passed via `style` stay on
|
|
99
|
+
* the outer box, so a caller that centres its panel with this component (the
|
|
100
|
+
* centred dialog) keeps doing so.
|
|
89
101
|
*/
|
|
90
102
|
export const Backdrop = /*#__PURE__*/memo(function Backdrop({
|
|
91
103
|
onPress,
|
|
@@ -127,35 +139,44 @@ export const Backdrop = /*#__PURE__*/memo(function Backdrop({
|
|
|
127
139
|
const dimFade = useAnimatedStyle(() => ({
|
|
128
140
|
opacity: (progress ? progress.value : 1) * staticOpacity * dimOpacity
|
|
129
141
|
}), [progress, staticOpacity, dimOpacity]);
|
|
130
|
-
return
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
142
|
+
return (
|
|
143
|
+
/*#__PURE__*/
|
|
144
|
+
// `box-none` so this box never takes a press itself: the hit box below and
|
|
145
|
+
// `children` above are what receive them.
|
|
146
|
+
_jsxs(View, {
|
|
147
|
+
pointerEvents: "box-none",
|
|
148
|
+
style: [StyleSheet.absoluteFill, rootStyle],
|
|
149
|
+
children: [/*#__PURE__*/_jsxs(Pressable, {
|
|
150
|
+
pointerEvents: "auto",
|
|
151
|
+
onPress: inert ? undefined : onPress,
|
|
152
|
+
disabled: inert
|
|
153
|
+
// A dimming layer is not a focus stop on web: Escape and the panel's own
|
|
154
|
+
// controls are the keyboard paths out. It stays labelled for screen
|
|
155
|
+
// readers that surface it as the dismiss affordance.
|
|
156
|
+
,
|
|
157
|
+
focusable: false,
|
|
158
|
+
accessibilityRole: inert ? undefined : 'button',
|
|
159
|
+
accessibilityLabel: inert ? undefined : accessibilityLabel,
|
|
160
|
+
testID: testID,
|
|
161
|
+
style: StyleSheet.absoluteFill,
|
|
162
|
+
children: [blurIntensity > 0 ? /*#__PURE__*/_jsx(AnimatedBlurView, {
|
|
163
|
+
intensity: blurIntensity,
|
|
164
|
+
tint: blurTint
|
|
165
|
+
// Android's default blur is a no-op on many devices; this is the
|
|
166
|
+
// implementation that actually renders there.
|
|
167
|
+
,
|
|
168
|
+
experimentalBlurMethod: "dimezisBlurView",
|
|
169
|
+
pointerEvents: "none",
|
|
170
|
+
style: [StyleSheet.absoluteFill, layerStyle, blurFade]
|
|
171
|
+
}) : null, /*#__PURE__*/_jsx(Animated.View, {
|
|
172
|
+
pointerEvents: "none",
|
|
173
|
+
style: [StyleSheet.absoluteFill, {
|
|
174
|
+
backgroundColor: resolvedDimColor
|
|
175
|
+
}, layerStyle, dimFade]
|
|
176
|
+
})]
|
|
177
|
+
}), children]
|
|
178
|
+
})
|
|
179
|
+
);
|
|
159
180
|
});
|
|
160
181
|
Backdrop.displayName = 'Backdrop';
|
|
161
182
|
const styles = StyleSheet.create({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["memo","BlurView","Platform","Pressable","StyleSheet","View","Animated","useAnimatedStyle","WEB_POSITION_FIXED","jsx","_jsx","jsxs","_jsxs","AnimatedBlurView","createAnimatedComponent","BACKDROP_BLUR_INTENSITY","BACKDROP_DIM_OPACITY","OverlayRoot","children","style","testID","pointerEvents","styles","root","displayName","Backdrop","onPress","progress","disabled","blurIntensity","blurTint","dimColor","dimOpacity","layerStyle","accessibilityLabel","inert","flat","flatten","opacity","styleOpacity","backgroundColor","styleBackground","rootStyle","staticOpacity","resolvedDimColor","blurFade","value","dimFade","undefined","focusable","accessibilityRole","
|
|
1
|
+
{"version":3,"names":["memo","BlurView","Platform","Pressable","StyleSheet","View","Animated","useAnimatedStyle","WEB_POSITION_FIXED","jsx","_jsx","jsxs","_jsxs","AnimatedBlurView","createAnimatedComponent","BACKDROP_BLUR_INTENSITY","BACKDROP_DIM_OPACITY","OverlayRoot","children","style","testID","pointerEvents","styles","root","displayName","Backdrop","onPress","progress","disabled","blurIntensity","blurTint","dimColor","dimOpacity","layerStyle","accessibilityLabel","inert","flat","flatten","opacity","styleOpacity","backgroundColor","styleBackground","rootStyle","staticOpacity","resolvedDimColor","blurFade","value","dimFade","absoluteFill","undefined","focusable","accessibilityRole","intensity","tint","experimentalBlurMethod","create","position","OS","top","left","right","bottom"],"sourceRoot":"../../../src","sources":["overlay/index.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,IAAI,QAAwB,OAAO;AAC5C,SAASC,QAAQ,QAAQ,WAAW;AACpC,SACEC,QAAQ,EACRC,SAAS,EACTC,UAAU,EACVC,IAAI,QAGC,cAAc;AACrB,OAAOC,QAAQ,IAAIC,gBAAgB,QAA0B,yBAAyB;AAEtF,SAASC,kBAAkB,QAAQ,6BAA0B;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAE9D,MAAMC,gBAAgB,GAAGP,QAAQ,CAACQ,uBAAuB,CAACb,QAAQ,CAAC;;AAEnE;AACA;AACA;AACA;AACA,OAAO,MAAMc,uBAAuB,GAAG,EAAE;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,oBAAoB,GAAG,IAAI;AAQxC;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,WAAWA,CAAC;EAAEC,QAAQ;EAAEC,KAAK;EAAEC;AAAyB,CAAC,EAAE;EACzE,oBACEV,IAAA,CAACL,IAAI;IAACgB,aAAa,EAAC,UAAU;IAACF,KAAK,EAAE,CAACG,MAAM,CAACC,IAAI,EAAEJ,KAAK,CAAE;IAACC,MAAM,EAAEA,MAAO;IAAAF,QAAA,EACxEA;EAAQ,CACL,CAAC;AAEX;AAEAD,WAAW,CAACO,WAAW,GAAG,aAAa;AAwCvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,QAAQ,gBAAGzB,IAAI,CAAC,SAASyB,QAAQA,CAAC;EAC7CC,OAAO;EACPC,QAAQ;EACRC,QAAQ,GAAG,KAAK;EAChBC,aAAa,GAAGd,uBAAuB;EACvCe,QAAQ,GAAG,MAAM;EACjBC,QAAQ,GAAG,MAAM;EACjBC,UAAU,GAAGhB,oBAAoB;EACjCG,KAAK;EACLc,UAAU;EACVf,QAAQ;EACRgB,kBAAkB,GAAG,SAAS;EAC9Bd;AACa,CAAC,EAAE;EAChB,MAAMe,KAAK,GAAGP,QAAQ,IAAI,CAACF,OAAO;;EAElC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,MAAMU,IAAe,GAAGhC,UAAU,CAACiC,OAAO,CAAClB,KAAK,CAAC,IAAI,CAAC,CAAC;EACvD,MAAM;IAAEmB,OAAO,EAAEC,YAAY;IAAEC,eAAe,EAAEC,eAAe;IAAE,GAAGC;EAAU,CAAC,GAAGN,IAAI;EACtF,MAAMO,aAAa,GAAG,OAAOJ,YAAY,KAAK,QAAQ,GAAGA,YAAY,GAAG,CAAC;EACzE,MAAMK,gBAAgB,GAAG,OAAOH,eAAe,KAAK,QAAQ,GAAGA,eAAe,GAAGV,QAAQ;;EAEzF;EACA,MAAMc,QAAQ,GAAGtC,gBAAgB,CAC/B,OAAO;IAAE+B,OAAO,EAAE,CAACX,QAAQ,GAAGA,QAAQ,CAACmB,KAAK,GAAG,CAAC,IAAIH;EAAc,CAAC,CAAC,EACpE,CAAChB,QAAQ,EAAEgB,aAAa,CAC1B,CAAC;EACD,MAAMI,OAAO,GAAGxC,gBAAgB,CAC9B,OAAO;IAAE+B,OAAO,EAAE,CAACX,QAAQ,GAAGA,QAAQ,CAACmB,KAAK,GAAG,CAAC,IAAIH,aAAa,GAAGX;EAAW,CAAC,CAAC,EACjF,CAACL,QAAQ,EAAEgB,aAAa,EAAEX,UAAU,CACtC,CAAC;EAED;IAAA;IACE;IACA;IACApB,KAAA,CAACP,IAAI;MAACgB,aAAa,EAAC,UAAU;MAACF,KAAK,EAAE,CAACf,UAAU,CAAC4C,YAAY,EAAEN,SAAS,CAAE;MAAAxB,QAAA,gBACzEN,KAAA,CAACT,SAAS;QACRkB,aAAa,EAAC,MAAM;QACpBK,OAAO,EAAES,KAAK,GAAGc,SAAS,GAAGvB,OAAQ;QACrCE,QAAQ,EAAEO;QACV;QACA;QACA;QAAA;QACAe,SAAS,EAAE,KAAM;QACjBC,iBAAiB,EAAEhB,KAAK,GAAGc,SAAS,GAAG,QAAS;QAChDf,kBAAkB,EAAEC,KAAK,GAAGc,SAAS,GAAGf,kBAAmB;QAC3Dd,MAAM,EAAEA,MAAO;QACfD,KAAK,EAAEf,UAAU,CAAC4C,YAAa;QAAA9B,QAAA,GAE9BW,aAAa,GAAG,CAAC,gBAChBnB,IAAA,CAACG,gBAAgB;UACfuC,SAAS,EAAEvB,aAAc;UACzBwB,IAAI,EAAEvB;UACN;UACA;UAAA;UACAwB,sBAAsB,EAAC,iBAAiB;UACxCjC,aAAa,EAAC,MAAM;UACpBF,KAAK,EAAE,CAACf,UAAU,CAAC4C,YAAY,EAAEf,UAAU,EAAEY,QAAQ;QAAE,CACxD,CAAC,GACA,IAAI,eACRnC,IAAA,CAACJ,QAAQ,CAACD,IAAI;UACZgB,aAAa,EAAC,MAAM;UACpBF,KAAK,EAAE,CAACf,UAAU,CAAC4C,YAAY,EAAE;YAAER,eAAe,EAAEI;UAAiB,CAAC,EAAEX,UAAU,EAAEc,OAAO;QAAE,CAC9F,CAAC;MAAA,CACO,CAAC,EACX7B,QAAQ;IAAA,CACL;EAAC;AAEX,CAAC,CAAC;AAEFO,QAAQ,CAACD,WAAW,GAAG,UAAU;AAEjC,MAAMF,MAAM,GAAGlB,UAAU,CAACmD,MAAM,CAAC;EAC/BhC,IAAI,EAAE;IACJ;IACA;IACA;IACA;IACA;IACAiC,QAAQ,EAAEtD,QAAQ,CAACuD,EAAE,KAAK,KAAK,GAAGjD,kBAAkB,GAAG,UAAU;IACjEkD,GAAG,EAAE,CAAC;IACNC,IAAI,EAAE,CAAC;IACPC,KAAK,EAAE,CAAC;IACRC,MAAM,EAAE;EACV;AACF,CAAC,CAAC","ignoreList":[]}
|
|
@@ -103,15 +103,27 @@ export interface BackdropProps {
|
|
|
103
103
|
* express — the web dialog's CSS keyframes, for instance.
|
|
104
104
|
*/
|
|
105
105
|
layerStyle?: StyleProp<ViewStyle>;
|
|
106
|
-
/** Rendered ON TOP of the dim,
|
|
106
|
+
/** Rendered ON TOP of the dim, as a sibling of the press target (Dialog's panel does this). */
|
|
107
107
|
children?: ReactNode;
|
|
108
108
|
accessibilityLabel?: string;
|
|
109
109
|
testID?: string;
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
|
-
* Full-bleed blur + dim that dismisses the surface when pressed.
|
|
113
|
-
*
|
|
114
|
-
*
|
|
112
|
+
* Full-bleed blur + dim that dismisses the surface when pressed.
|
|
113
|
+
*
|
|
114
|
+
* The dismiss target is a hit box that fills this component and sits BEHIND
|
|
115
|
+
* `children`, never around them. It used to wrap them, which read fine on
|
|
116
|
+
* native but is invalid on web: the hit box carries `accessibilityRole="button"`,
|
|
117
|
+
* so react-native-web renders it as a real `<button>` — and every control inside
|
|
118
|
+
* any Bloom surface (a dialog's own buttons, a menu's rows) became a nested
|
|
119
|
+
* `<button>`. React reports that as a hydration error, and the nested control's
|
|
120
|
+
* activation behaviour is undefined per the HTML spec.
|
|
121
|
+
*
|
|
122
|
+
* Hit testing is unchanged: the hit box still covers the whole area, `children`
|
|
123
|
+
* render above it and take their own presses, and a press that lands on empty
|
|
124
|
+
* space falls through to the hit box. Layout styles passed via `style` stay on
|
|
125
|
+
* the outer box, so a caller that centres its panel with this component (the
|
|
126
|
+
* centred dialog) keeps doing so.
|
|
115
127
|
*/
|
|
116
128
|
export declare const Backdrop: import("react").NamedExoticComponent<BackdropProps>;
|
|
117
129
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/overlay/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AACtB,OAAiB,EAAoB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAMvF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAMxE;yBANe,WAAW;;;AAU3B,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACxC,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B;;;OAGG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/overlay/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AACtB,OAAiB,EAAoB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAMvF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAMxE;yBANe,WAAW;;;AAU3B,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACxC,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B;;;OAGG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,QAAQ,qDA2EnB,CAAC"}
|
|
@@ -103,15 +103,27 @@ export interface BackdropProps {
|
|
|
103
103
|
* express — the web dialog's CSS keyframes, for instance.
|
|
104
104
|
*/
|
|
105
105
|
layerStyle?: StyleProp<ViewStyle>;
|
|
106
|
-
/** Rendered ON TOP of the dim,
|
|
106
|
+
/** Rendered ON TOP of the dim, as a sibling of the press target (Dialog's panel does this). */
|
|
107
107
|
children?: ReactNode;
|
|
108
108
|
accessibilityLabel?: string;
|
|
109
109
|
testID?: string;
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
|
-
* Full-bleed blur + dim that dismisses the surface when pressed.
|
|
113
|
-
*
|
|
114
|
-
*
|
|
112
|
+
* Full-bleed blur + dim that dismisses the surface when pressed.
|
|
113
|
+
*
|
|
114
|
+
* The dismiss target is a hit box that fills this component and sits BEHIND
|
|
115
|
+
* `children`, never around them. It used to wrap them, which read fine on
|
|
116
|
+
* native but is invalid on web: the hit box carries `accessibilityRole="button"`,
|
|
117
|
+
* so react-native-web renders it as a real `<button>` — and every control inside
|
|
118
|
+
* any Bloom surface (a dialog's own buttons, a menu's rows) became a nested
|
|
119
|
+
* `<button>`. React reports that as a hydration error, and the nested control's
|
|
120
|
+
* activation behaviour is undefined per the HTML spec.
|
|
121
|
+
*
|
|
122
|
+
* Hit testing is unchanged: the hit box still covers the whole area, `children`
|
|
123
|
+
* render above it and take their own presses, and a press that lands on empty
|
|
124
|
+
* space falls through to the hit box. Layout styles passed via `style` stay on
|
|
125
|
+
* the outer box, so a caller that centres its panel with this component (the
|
|
126
|
+
* centred dialog) keeps doing so.
|
|
115
127
|
*/
|
|
116
128
|
export declare const Backdrop: import("react").NamedExoticComponent<BackdropProps>;
|
|
117
129
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/overlay/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AACtB,OAAiB,EAAoB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAMvF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAMxE;yBANe,WAAW;;;AAU3B,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACxC,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B;;;OAGG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/overlay/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AACtB,OAAiB,EAAoB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAMvF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAMxE;yBANe,WAAW;;;AAU3B,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACxC,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B;;;OAGG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,QAAQ,qDA2EnB,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// The bug these tests exist for: `Backdrop`'s dismiss target carries
|
|
6
|
+
// `accessibilityRole="button"`, which react-native-web renders as a real
|
|
7
|
+
// `<button>`. While that target WRAPPED `children`, every control inside a
|
|
8
|
+
// Bloom surface became a nested `<button>` — invalid HTML, reported by React as
|
|
9
|
+
// a hydration error, and with activation behaviour the spec leaves undefined.
|
|
10
|
+
// It reproduced on any dialog with a button in it (Mention's post-options menu:
|
|
11
|
+
// "Dismiss Post options" containing "Insights").
|
|
12
|
+
//
|
|
13
|
+
// The fix makes the hit box a SIBLING behind `children`. These tests pin both
|
|
14
|
+
// halves of that: no nesting, and the dismiss press still works.
|
|
15
|
+
|
|
16
|
+
import { createElement } from 'react';
|
|
17
|
+
import { act } from 'react';
|
|
18
|
+
import { createRoot, type Root } from 'react-dom/client';
|
|
19
|
+
|
|
20
|
+
// The whole point is what react-native-web puts in the DOM, so this suite runs
|
|
21
|
+
// against the REAL RNW — the repo-wide `react-native` mock emits no host
|
|
22
|
+
// elements and would make every assertion below vacuous.
|
|
23
|
+
jest.mock('react-native', () => jest.requireActual('react-native-web'));
|
|
24
|
+
|
|
25
|
+
import { Pressable, Text } from 'react-native';
|
|
26
|
+
|
|
27
|
+
import { Backdrop } from '../overlay';
|
|
28
|
+
|
|
29
|
+
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
|
|
30
|
+
|
|
31
|
+
function render(node: ReturnType<typeof createElement>): { root: Root; container: HTMLElement } {
|
|
32
|
+
const container = document.createElement('div');
|
|
33
|
+
document.body.appendChild(container);
|
|
34
|
+
const root = createRoot(container);
|
|
35
|
+
act(() => {
|
|
36
|
+
root.render(node);
|
|
37
|
+
});
|
|
38
|
+
return { root, container };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('Backdrop DOM nesting (web)', () => {
|
|
42
|
+
it('does not make a pressable child a nested <button>', () => {
|
|
43
|
+
const { root, container } = render(
|
|
44
|
+
createElement(Backdrop, {
|
|
45
|
+
onPress: () => {},
|
|
46
|
+
accessibilityLabel: 'Dismiss Post options',
|
|
47
|
+
testID: 'backdrop',
|
|
48
|
+
children: createElement(
|
|
49
|
+
Pressable,
|
|
50
|
+
{ accessibilityRole: 'button', accessibilityLabel: 'Insights', onPress: () => {} },
|
|
51
|
+
createElement(Text, null, 'Insights'),
|
|
52
|
+
),
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// Vacuity floor: the child button must actually be in the DOM, otherwise
|
|
57
|
+
// "no nesting" would pass on an empty tree.
|
|
58
|
+
const inner = container.querySelector('[aria-label="Insights"]');
|
|
59
|
+
expect(inner?.tagName).toBe('BUTTON');
|
|
60
|
+
expect(container.querySelector('[aria-label="Dismiss Post options"]')?.tagName).toBe('BUTTON');
|
|
61
|
+
|
|
62
|
+
expect(container.querySelectorAll('button button')).toHaveLength(0);
|
|
63
|
+
|
|
64
|
+
act(() => root.unmount());
|
|
65
|
+
container.remove();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('still dismisses when the backdrop itself is pressed', () => {
|
|
69
|
+
const onPress = jest.fn();
|
|
70
|
+
const { root, container } = render(
|
|
71
|
+
createElement(Backdrop, { onPress, accessibilityLabel: 'Dismiss dialog', children: null }),
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const hitBox = container.querySelector<HTMLElement>('[aria-label="Dismiss dialog"]');
|
|
75
|
+
expect(hitBox).not.toBeNull();
|
|
76
|
+
act(() => {
|
|
77
|
+
hitBox?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
78
|
+
});
|
|
79
|
+
expect(onPress).toHaveBeenCalledTimes(1);
|
|
80
|
+
|
|
81
|
+
act(() => root.unmount());
|
|
82
|
+
container.remove();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('emits no dismiss affordance at all when inert', () => {
|
|
86
|
+
const { root, container } = render(
|
|
87
|
+
createElement(Backdrop, { disabled: true, onPress: () => {}, children: null }),
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
expect(container.querySelectorAll('button')).toHaveLength(0);
|
|
91
|
+
|
|
92
|
+
act(() => root.unmount());
|
|
93
|
+
container.remove();
|
|
94
|
+
});
|
|
95
|
+
});
|
package/src/overlay/index.tsx
CHANGED
|
@@ -124,16 +124,28 @@ export interface BackdropProps {
|
|
|
124
124
|
* express — the web dialog's CSS keyframes, for instance.
|
|
125
125
|
*/
|
|
126
126
|
layerStyle?: StyleProp<ViewStyle>;
|
|
127
|
-
/** Rendered ON TOP of the dim,
|
|
127
|
+
/** Rendered ON TOP of the dim, as a sibling of the press target (Dialog's panel does this). */
|
|
128
128
|
children?: ReactNode;
|
|
129
129
|
accessibilityLabel?: string;
|
|
130
130
|
testID?: string;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
/**
|
|
134
|
-
* Full-bleed blur + dim that dismisses the surface when pressed.
|
|
135
|
-
*
|
|
136
|
-
*
|
|
134
|
+
* Full-bleed blur + dim that dismisses the surface when pressed.
|
|
135
|
+
*
|
|
136
|
+
* The dismiss target is a hit box that fills this component and sits BEHIND
|
|
137
|
+
* `children`, never around them. It used to wrap them, which read fine on
|
|
138
|
+
* native but is invalid on web: the hit box carries `accessibilityRole="button"`,
|
|
139
|
+
* so react-native-web renders it as a real `<button>` — and every control inside
|
|
140
|
+
* any Bloom surface (a dialog's own buttons, a menu's rows) became a nested
|
|
141
|
+
* `<button>`. React reports that as a hydration error, and the nested control's
|
|
142
|
+
* activation behaviour is undefined per the HTML spec.
|
|
143
|
+
*
|
|
144
|
+
* Hit testing is unchanged: the hit box still covers the whole area, `children`
|
|
145
|
+
* render above it and take their own presses, and a press that lands on empty
|
|
146
|
+
* space falls through to the hit box. Layout styles passed via `style` stay on
|
|
147
|
+
* the outer box, so a caller that centres its panel with this component (the
|
|
148
|
+
* centred dialog) keeps doing so.
|
|
137
149
|
*/
|
|
138
150
|
export const Backdrop = memo(function Backdrop({
|
|
139
151
|
onPress,
|
|
@@ -175,36 +187,40 @@ export const Backdrop = memo(function Backdrop({
|
|
|
175
187
|
);
|
|
176
188
|
|
|
177
189
|
return (
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
190
|
+
// `box-none` so this box never takes a press itself: the hit box below and
|
|
191
|
+
// `children` above are what receive them.
|
|
192
|
+
<View pointerEvents="box-none" style={[StyleSheet.absoluteFill, rootStyle]}>
|
|
193
|
+
<Pressable
|
|
194
|
+
pointerEvents="auto"
|
|
195
|
+
onPress={inert ? undefined : onPress}
|
|
196
|
+
disabled={inert}
|
|
197
|
+
// A dimming layer is not a focus stop on web: Escape and the panel's own
|
|
198
|
+
// controls are the keyboard paths out. It stays labelled for screen
|
|
199
|
+
// readers that surface it as the dismiss affordance.
|
|
200
|
+
focusable={false}
|
|
201
|
+
accessibilityRole={inert ? undefined : 'button'}
|
|
202
|
+
accessibilityLabel={inert ? undefined : accessibilityLabel}
|
|
203
|
+
testID={testID}
|
|
204
|
+
style={StyleSheet.absoluteFill}
|
|
205
|
+
>
|
|
206
|
+
{blurIntensity > 0 ? (
|
|
207
|
+
<AnimatedBlurView
|
|
208
|
+
intensity={blurIntensity}
|
|
209
|
+
tint={blurTint}
|
|
210
|
+
// Android's default blur is a no-op on many devices; this is the
|
|
211
|
+
// implementation that actually renders there.
|
|
212
|
+
experimentalBlurMethod="dimezisBlurView"
|
|
213
|
+
pointerEvents="none"
|
|
214
|
+
style={[StyleSheet.absoluteFill, layerStyle, blurFade]}
|
|
215
|
+
/>
|
|
216
|
+
) : null}
|
|
217
|
+
<Animated.View
|
|
198
218
|
pointerEvents="none"
|
|
199
|
-
style={[StyleSheet.absoluteFill, layerStyle,
|
|
219
|
+
style={[StyleSheet.absoluteFill, { backgroundColor: resolvedDimColor }, layerStyle, dimFade]}
|
|
200
220
|
/>
|
|
201
|
-
|
|
202
|
-
<Animated.View
|
|
203
|
-
pointerEvents="none"
|
|
204
|
-
style={[StyleSheet.absoluteFill, { backgroundColor: resolvedDimColor }, layerStyle, dimFade]}
|
|
205
|
-
/>
|
|
221
|
+
</Pressable>
|
|
206
222
|
{children}
|
|
207
|
-
</
|
|
223
|
+
</View>
|
|
208
224
|
);
|
|
209
225
|
});
|
|
210
226
|
|