@oxy.so/bloom 4.18.0 → 4.19.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/docs/adoption-matrix.mdx +5 -5
- package/docs/overlay.mdx +32 -0
- package/docs/portal.mdx +37 -0
- package/docs/rating.mdx +19 -2
- package/docs/select.mdx +10 -0
- package/lib/commonjs/bottom-sheet/BottomSheet.web.js +1 -0
- package/lib/commonjs/bottom-sheet/BottomSheet.web.js.map +1 -1
- package/lib/commonjs/chat-list/parts.js +1 -1
- package/lib/commonjs/chat-list/parts.js.map +1 -1
- package/lib/commonjs/chat-screen/ChatBackground.js +6 -6
- package/lib/commonjs/chat-screen/ChatBackground.js.map +1 -1
- package/lib/commonjs/dialog/Dialog.js +5 -0
- package/lib/commonjs/dialog/Dialog.js.map +1 -1
- package/lib/commonjs/dialog/Dialog.web.js +4 -1
- package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
- package/lib/commonjs/index.js +7 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +7 -0
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/location-puck/LocationPuck.js +1 -1
- package/lib/commonjs/location-puck/LocationPuck.js.map +1 -1
- package/lib/commonjs/mail-list/parts.js +1 -1
- package/lib/commonjs/mail-list/parts.js.map +1 -1
- package/lib/commonjs/media-card/parts.js +1 -1
- package/lib/commonjs/media-card/parts.js.map +1 -1
- package/lib/commonjs/overlay/Overlay.js +23 -4
- package/lib/commonjs/overlay/Overlay.js.map +1 -1
- package/lib/commonjs/overlay/OverlayInertBoundary.js +78 -0
- package/lib/commonjs/overlay/OverlayInertBoundary.js.map +1 -0
- package/lib/commonjs/overlay/index.js +14 -0
- package/lib/commonjs/overlay/index.js.map +1 -1
- package/lib/commonjs/overlay/modal-registry.js +104 -0
- package/lib/commonjs/overlay/modal-registry.js.map +1 -0
- package/lib/commonjs/overlay/use-hardware-back.js +32 -0
- package/lib/commonjs/overlay/use-hardware-back.js.map +1 -0
- package/lib/commonjs/overlay/use-modal-overlay-active.js +33 -0
- package/lib/commonjs/overlay/use-modal-overlay-active.js.map +1 -0
- package/lib/commonjs/portal/index.js +7 -0
- package/lib/commonjs/portal/index.js.map +1 -1
- package/lib/commonjs/portal/index.web.js +7 -0
- package/lib/commonjs/portal/index.web.js.map +1 -1
- package/lib/commonjs/rating/Rating.js +33 -2
- package/lib/commonjs/rating/Rating.js.map +1 -1
- package/lib/commonjs/search/Search.js +36 -3
- package/lib/commonjs/search/Search.js.map +1 -1
- package/lib/commonjs/settings-modal/SettingsModal.js +19 -12
- package/lib/commonjs/settings-modal/SettingsModal.js.map +1 -1
- package/lib/commonjs/teleport/PortalHost.js +1 -1
- package/lib/commonjs/zoomable-media-gallery/ZoomableMediaGallery.js +32 -12
- package/lib/commonjs/zoomable-media-gallery/ZoomableMediaGallery.js.map +1 -1
- package/lib/module/bottom-sheet/BottomSheet.web.js +1 -0
- package/lib/module/bottom-sheet/BottomSheet.web.js.map +1 -1
- package/lib/module/chat-list/parts.js +1 -1
- package/lib/module/chat-list/parts.js.map +1 -1
- package/lib/module/chat-screen/ChatBackground.js +6 -6
- package/lib/module/chat-screen/ChatBackground.js.map +1 -1
- package/lib/module/dialog/Dialog.js +5 -0
- package/lib/module/dialog/Dialog.js.map +1 -1
- package/lib/module/dialog/Dialog.web.js +4 -1
- package/lib/module/dialog/Dialog.web.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +1 -1
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/location-puck/LocationPuck.js +1 -1
- package/lib/module/location-puck/LocationPuck.js.map +1 -1
- package/lib/module/mail-list/parts.js +1 -1
- package/lib/module/mail-list/parts.js.map +1 -1
- package/lib/module/media-card/parts.js +1 -1
- package/lib/module/media-card/parts.js.map +1 -1
- package/lib/module/overlay/Overlay.js +23 -4
- package/lib/module/overlay/Overlay.js.map +1 -1
- package/lib/module/overlay/OverlayInertBoundary.js +73 -0
- package/lib/module/overlay/OverlayInertBoundary.js.map +1 -0
- package/lib/module/overlay/index.js +2 -0
- package/lib/module/overlay/index.js.map +1 -1
- package/lib/module/overlay/modal-registry.js +96 -0
- package/lib/module/overlay/modal-registry.js.map +1 -0
- package/lib/module/overlay/use-hardware-back.js +29 -0
- package/lib/module/overlay/use-hardware-back.js.map +1 -0
- package/lib/module/overlay/use-modal-overlay-active.js +28 -0
- package/lib/module/overlay/use-modal-overlay-active.js.map +1 -0
- package/lib/module/portal/index.js +4 -0
- package/lib/module/portal/index.js.map +1 -1
- package/lib/module/portal/index.web.js +4 -0
- package/lib/module/portal/index.web.js.map +1 -1
- package/lib/module/rating/Rating.js +32 -2
- package/lib/module/rating/Rating.js.map +1 -1
- package/lib/module/search/Search.js +37 -4
- package/lib/module/search/Search.js.map +1 -1
- package/lib/module/settings-modal/SettingsModal.js +20 -13
- package/lib/module/settings-modal/SettingsModal.js.map +1 -1
- package/lib/module/teleport/PortalHost.js +1 -1
- package/lib/module/zoomable-media-gallery/ZoomableMediaGallery.js +32 -12
- package/lib/module/zoomable-media-gallery/ZoomableMediaGallery.js.map +1 -1
- package/lib/typescript/commonjs/bottom-sheet/BottomSheet.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/Dialog.web.d.ts +2 -1
- package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +1 -1
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.web.d.ts +1 -1
- package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/overlay/Overlay.d.ts +1 -1
- package/lib/typescript/commonjs/overlay/Overlay.d.ts.map +1 -1
- package/lib/typescript/commonjs/overlay/OverlayInertBoundary.d.ts +6 -0
- package/lib/typescript/commonjs/overlay/OverlayInertBoundary.d.ts.map +1 -0
- package/lib/typescript/commonjs/overlay/index.d.ts +3 -1
- package/lib/typescript/commonjs/overlay/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/overlay/modal-registry.d.ts +53 -0
- package/lib/typescript/commonjs/overlay/modal-registry.d.ts.map +1 -0
- package/lib/typescript/commonjs/overlay/types.d.ts +36 -0
- package/lib/typescript/commonjs/overlay/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/overlay/use-hardware-back.d.ts +11 -0
- package/lib/typescript/commonjs/overlay/use-hardware-back.d.ts.map +1 -0
- package/lib/typescript/commonjs/overlay/use-modal-overlay-active.d.ts +7 -0
- package/lib/typescript/commonjs/overlay/use-modal-overlay-active.d.ts.map +1 -0
- package/lib/typescript/commonjs/portal/index.d.ts +2 -0
- package/lib/typescript/commonjs/portal/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/portal/index.web.d.ts +2 -0
- package/lib/typescript/commonjs/portal/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/rating/Rating.d.ts +9 -1
- package/lib/typescript/commonjs/rating/Rating.d.ts.map +1 -1
- package/lib/typescript/commonjs/rating/types.d.ts +9 -0
- package/lib/typescript/commonjs/rating/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/search/Search.d.ts.map +1 -1
- package/lib/typescript/commonjs/select/types.d.ts +7 -0
- package/lib/typescript/commonjs/select/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/settings-modal/SettingsModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/teleport/PortalHost.d.ts +1 -1
- package/lib/typescript/commonjs/zoomable-media-gallery/ZoomableMediaGallery.d.ts.map +1 -1
- package/lib/typescript/module/bottom-sheet/BottomSheet.web.d.ts.map +1 -1
- package/lib/typescript/module/dialog/Dialog.web.d.ts +2 -1
- package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +1 -1
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/index.web.d.ts +1 -1
- package/lib/typescript/module/index.web.d.ts.map +1 -1
- package/lib/typescript/module/overlay/Overlay.d.ts +1 -1
- package/lib/typescript/module/overlay/Overlay.d.ts.map +1 -1
- package/lib/typescript/module/overlay/OverlayInertBoundary.d.ts +6 -0
- package/lib/typescript/module/overlay/OverlayInertBoundary.d.ts.map +1 -0
- package/lib/typescript/module/overlay/index.d.ts +3 -1
- package/lib/typescript/module/overlay/index.d.ts.map +1 -1
- package/lib/typescript/module/overlay/modal-registry.d.ts +53 -0
- package/lib/typescript/module/overlay/modal-registry.d.ts.map +1 -0
- package/lib/typescript/module/overlay/types.d.ts +36 -0
- package/lib/typescript/module/overlay/types.d.ts.map +1 -1
- package/lib/typescript/module/overlay/use-hardware-back.d.ts +11 -0
- package/lib/typescript/module/overlay/use-hardware-back.d.ts.map +1 -0
- package/lib/typescript/module/overlay/use-modal-overlay-active.d.ts +7 -0
- package/lib/typescript/module/overlay/use-modal-overlay-active.d.ts.map +1 -0
- package/lib/typescript/module/portal/index.d.ts +2 -0
- package/lib/typescript/module/portal/index.d.ts.map +1 -1
- package/lib/typescript/module/portal/index.web.d.ts +2 -0
- package/lib/typescript/module/portal/index.web.d.ts.map +1 -1
- package/lib/typescript/module/rating/Rating.d.ts +9 -1
- package/lib/typescript/module/rating/Rating.d.ts.map +1 -1
- package/lib/typescript/module/rating/types.d.ts +9 -0
- package/lib/typescript/module/rating/types.d.ts.map +1 -1
- package/lib/typescript/module/search/Search.d.ts.map +1 -1
- package/lib/typescript/module/select/types.d.ts +7 -0
- package/lib/typescript/module/select/types.d.ts.map +1 -1
- package/lib/typescript/module/settings-modal/SettingsModal.d.ts.map +1 -1
- package/lib/typescript/module/teleport/PortalHost.d.ts +1 -1
- package/lib/typescript/module/zoomable-media-gallery/ZoomableMediaGallery.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/bottom-sheet/BottomSheet.web.tsx +6 -2
- package/src/chat-list/parts.tsx +1 -1
- package/src/chat-screen/ChatBackground.tsx +6 -6
- package/src/dialog/Dialog.tsx +9 -1
- package/src/dialog/Dialog.web.tsx +7 -4
- package/src/index.ts +1 -0
- package/src/index.web.ts +1 -0
- package/src/location-puck/LocationPuck.tsx +1 -1
- package/src/mail-list/parts.tsx +1 -1
- package/src/media-card/parts.tsx +1 -1
- package/src/overlay/Overlay.tsx +36 -14
- package/src/overlay/OverlayInertBoundary.tsx +72 -0
- package/src/overlay/index.ts +3 -1
- package/src/overlay/modal-registry.ts +101 -0
- package/src/overlay/types.ts +37 -0
- package/src/overlay/use-hardware-back.ts +27 -0
- package/src/overlay/use-modal-overlay-active.ts +31 -0
- package/src/portal/index.ts +5 -0
- package/src/portal/index.web.ts +5 -0
- package/src/rating/Rating.tsx +37 -2
- package/src/rating/types.ts +9 -0
- package/src/search/Search.tsx +42 -4
- package/src/select/types.ts +7 -0
- package/src/settings-modal/SettingsModal.tsx +20 -15
- package/src/teleport/PortalHost.tsx +1 -1
- package/src/zoomable-media-gallery/ZoomableMediaGallery.tsx +33 -12
|
@@ -2,9 +2,17 @@ import React from 'react';
|
|
|
2
2
|
import type { RatingProps } from './types';
|
|
3
3
|
/** 5 → "5.0", 4.9 → "4.9", 4.923 → "4.92". */
|
|
4
4
|
export declare function formatRatingValue(value: number | string): string;
|
|
5
|
+
/**
|
|
6
|
+
* The number a drawn rating value stands for, for the `stars` fill: a number
|
|
7
|
+
* is itself; a string is read after dropping bidi/format characters, with a
|
|
8
|
+
* comma or Arabic decimal separator (U+066B) accepted as the decimal point and
|
|
9
|
+
* Arabic-Indic digits accepted — so "4,5" wrapped in FSI…PDI is 4.5. Otherwise it is
|
|
10
|
+
* `Number()`'s reading, so anything unreadable is `NaN` (no fill).
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseRatingValue(value: number | string): number;
|
|
5
13
|
/** How much of star `index` (0-based) a rating fills, `0..1`. */
|
|
6
14
|
export declare function starFill(rating: number, index: number): number;
|
|
7
|
-
declare function RatingComponent({ value, count, countStyle, reviewsLabel, newLabel, size, variant, color, starColor, countColor, emptyStarColor, accessibilityLabel, style, testID, }: RatingProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
declare function RatingComponent({ value, count, countStyle, reviewsLabel, newLabel, size, variant, color, starColor, countColor, emptyStarColor, fillValue, accessibilityLabel, style, testID, }: RatingProps): import("react/jsx-runtime").JSX.Element;
|
|
8
16
|
export declare const Rating: React.MemoExoticComponent<typeof RatingComponent>;
|
|
9
17
|
export {};
|
|
10
18
|
//# sourceMappingURL=Rating.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Rating.d.ts","sourceRoot":"","sources":["../../../../src/rating/Rating.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAe,MAAM,OAAO,CAAC;AAQpC,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"Rating.d.ts","sourceRoot":"","sources":["../../../../src/rating/Rating.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAe,MAAM,OAAO,CAAC;AAQpC,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,SAAS,CAAC;AAkCvD,8CAA8C;AAC9C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAIhE;AAkBD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAS/D;AAED,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAG9D;AAkDD,iBAAS,eAAe,CAAC,EACvB,KAAK,EACL,KAAK,EACL,UAA0B,EAC1B,YAAwB,EACxB,QAAgB,EAChB,IAAe,EACf,OAAmB,EACnB,KAAK,EACL,SAAS,EACT,UAAU,EACV,cAAc,EACd,SAAS,EACT,kBAAkB,EAClB,KAAK,EACL,MAAM,GACP,EAAE,WAAW,2CAmDb;AAED,eAAO,MAAM,MAAM,mDAAwB,CAAC"}
|
|
@@ -40,6 +40,15 @@ export interface RatingProps {
|
|
|
40
40
|
countColor?: string;
|
|
41
41
|
/** `stars` variant: the unfilled part of each star. Default the theme's border colour. */
|
|
42
42
|
emptyStarColor?: string;
|
|
43
|
+
/**
|
|
44
|
+
* `stars` variant: the number the stars are filled to, clamped to `0..5`,
|
|
45
|
+
* independent of the drawn `value`. Pass it with a localised `value` string
|
|
46
|
+
* (`value="4,5"` with `fillValue={4.5}`) so the text follows the locale and
|
|
47
|
+
* the fill does not depend on parsing it. Without it a string `value` is
|
|
48
|
+
* parsed (bidi marks dropped, a comma decimal accepted). Ignored by
|
|
49
|
+
* `compact` and while there is no rating (`value` empty).
|
|
50
|
+
*/
|
|
51
|
+
fillValue?: number;
|
|
43
52
|
/**
|
|
44
53
|
* Overrides the composed accessible name ("Rated 4.92 out of 5, 128
|
|
45
54
|
* reviews"), which is English — pass a translated sentence here.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/rating/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,8FAA8F;AAC9F,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5C,oEAAoE;AACpE,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,SAAS,CAAC;AAEzD;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC;AAEhD,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC/B,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,uGAAuG;IACvG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,sFAAsF;IACtF,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0FAA0F;IAC1F,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,iEAAiE;AACjE,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iFAAiF;IACjF,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,mCAAmC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACzD,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,wFAAwF;IACxF,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/rating/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,8FAA8F;AAC9F,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5C,oEAAoE;AACpE,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,SAAS,CAAC;AAEzD;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC;AAEhD,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC/B,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,uGAAuG;IACvG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,sFAAsF;IACtF,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0FAA0F;IAC1F,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,iEAAiE;AACjE,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iFAAiF;IACjF,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,mCAAmC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACzD,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,wFAAwF;IACxF,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Search.d.ts","sourceRoot":"","sources":["../../../../src/search/Search.tsx"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,SAAS,EAAQ,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"Search.d.ts","sourceRoot":"","sources":["../../../../src/search/Search.tsx"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,SAAS,EAAQ,MAAM,cAAc,CAAC;AAQ9D,OAAO,EAA4C,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAYnG,eAAO,MAAM,MAAM;YAPT,mBAAmB,CAAC,OAAO,CAAC;IACpC;;OAEG;kBACW,MAAM,IAAI;6CA6FzB,CAAC"}
|
|
@@ -33,6 +33,13 @@ export type SelectTriggerProps = {
|
|
|
33
33
|
/**
|
|
34
34
|
* Utility classes APPENDED to the part's own — never substituted for them, so
|
|
35
35
|
* a single layout class cannot strip the chrome.
|
|
36
|
+
*
|
|
37
|
+
* Never pin a HEIGHT here (`h-8`). The value's line box is 20 × the system
|
|
38
|
+
* font scale, and on native Yoga measures the text at most as tall as the
|
|
39
|
+
* space left inside the field: a fixed height cuts the glyphs in half on
|
|
40
|
+
* Android (OxyHQ/Mention#1126 — `h-8` is 28dp there, leaving 15.5dp for a
|
|
41
|
+
* 20dp line). Size a compact trigger with its padding (`fieldStyle`) so the
|
|
42
|
+
* text sets the height.
|
|
36
43
|
*/
|
|
37
44
|
className?: string;
|
|
38
45
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/select/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE1E,OAAO,KAAK,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7D,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC;AAErC,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;;OAGG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/select/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsModal.d.ts","sourceRoot":"","sources":["../../../../src/settings-modal/SettingsModal.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,kBAAkB,EAAqC,MAAM,SAAS,CAAC;AAmFrF,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,IAAI,EAAE,cAAc,EACpB,OAAO,EACP,aAAa,EACb,MAAM,EACN,KAAK,EACL,IAAI,EAAE,cAAc,EACpB,WAAW,EACX,YAAY,EACZ,WAA0B,EAC1B,MAAM,EACN,MAAM,GACP,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"SettingsModal.d.ts","sourceRoot":"","sources":["../../../../src/settings-modal/SettingsModal.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,kBAAkB,EAAqC,MAAM,SAAS,CAAC;AAmFrF,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,IAAI,EAAE,cAAc,EACpB,OAAO,EACP,aAAa,EACb,MAAM,EACN,KAAK,EACL,IAAI,EAAE,cAAc,EACpB,WAAW,EACX,YAAY,EACZ,WAA0B,EAC1B,MAAM,EACN,MAAM,GACP,EAAE,kBAAkB,kDA4VpB"}
|
|
@@ -14,7 +14,7 @@ import type { PortalHostProps } from "./types";
|
|
|
14
14
|
* export default function App() {
|
|
15
15
|
* return (
|
|
16
16
|
* <PortalProvider>
|
|
17
|
-
* <PortalHost style={StyleSheet.
|
|
17
|
+
* <PortalHost style={StyleSheet.absoluteFill} name="overlay" />
|
|
18
18
|
* </PortalProvider>
|
|
19
19
|
* );
|
|
20
20
|
* }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ZoomableMediaGallery.d.ts","sourceRoot":"","sources":["../../../../src/zoomable-media-gallery/ZoomableMediaGallery.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6E,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ZoomableMediaGallery.d.ts","sourceRoot":"","sources":["../../../../src/zoomable-media-gallery/ZoomableMediaGallery.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6E,MAAM,OAAO,CAAC;AAmElG,OAAO,KAAK,EAGV,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AA0lCjB,eAAO,MAAM,oBAAoB,8GAA4B,CAAC;AA4K9D,eAAe,oBAAoB,CAAC"}
|
package/package.json
CHANGED
|
@@ -32,8 +32,12 @@ function WebShell({ children }: BottomSheetShellProps) {
|
|
|
32
32
|
{/* `OverlayRoot` owns the portal-root pointer-events opt-in (see
|
|
33
33
|
`src/overlay`). It used to ride in the style array below as an
|
|
34
34
|
RN-only box-none value, which never reached the DOM — the whole
|
|
35
|
-
sheet, backdrop included, was click-through on web.
|
|
36
|
-
|
|
35
|
+
sheet, backdrop included, was click-through on web. `modal`:
|
|
36
|
+
the sheet dims and blocks the page, so the app's
|
|
37
|
+
`OverlayInertBoundary` makes that page inert while it is open.
|
|
38
|
+
(Native needs no flag — its shell is an RN `Modal`, a separate
|
|
39
|
+
window the screen reader is already confined to.) */}
|
|
40
|
+
<OverlayRoot style={webStyles.rootView} modal>
|
|
37
41
|
<GestureHandlerRootView style={StyleSheet.absoluteFill}>
|
|
38
42
|
{children}
|
|
39
43
|
</GestureHandlerRootView>
|
package/src/chat-list/parts.tsx
CHANGED
|
@@ -64,7 +64,7 @@ export function RowLink({
|
|
|
64
64
|
};
|
|
65
65
|
const interactive = Boolean(onPress || href || onLongPress);
|
|
66
66
|
const style: WebCssStyle = {
|
|
67
|
-
...StyleSheet.
|
|
67
|
+
...StyleSheet.absoluteFill,
|
|
68
68
|
borderRadius: CHAT_ROW_RADIUS,
|
|
69
69
|
'--bloom-chat-ring': paint.ring,
|
|
70
70
|
};
|
|
@@ -44,9 +44,9 @@ function PatternLayer({
|
|
|
44
44
|
<View
|
|
45
45
|
pointerEvents="none"
|
|
46
46
|
testID="chat-background-pattern"
|
|
47
|
-
style={StyleSheet.
|
|
47
|
+
style={StyleSheet.absoluteFill}
|
|
48
48
|
>
|
|
49
|
-
<Svg style={StyleSheet.
|
|
49
|
+
<Svg style={StyleSheet.absoluteFill} width="100%" height="100%">
|
|
50
50
|
<Defs>
|
|
51
51
|
<Pattern
|
|
52
52
|
id={id}
|
|
@@ -83,9 +83,9 @@ function GradientLayer({ colors }: { colors: string[] }) {
|
|
|
83
83
|
<View
|
|
84
84
|
pointerEvents="none"
|
|
85
85
|
testID="chat-background-gradient"
|
|
86
|
-
style={StyleSheet.
|
|
86
|
+
style={StyleSheet.absoluteFill}
|
|
87
87
|
>
|
|
88
|
-
<Svg style={StyleSheet.
|
|
88
|
+
<Svg style={StyleSheet.absoluteFill} width="100%" height="100%">
|
|
89
89
|
<Defs>
|
|
90
90
|
<LinearGradient id={id} x1="0" y1="0" x2="0.35" y2="1">
|
|
91
91
|
{colors.map((color, i) => (
|
|
@@ -159,13 +159,13 @@ function ChatBackgroundComponent({
|
|
|
159
159
|
accessibilityElementsHidden
|
|
160
160
|
importantForAccessibility="no-hide-descendants"
|
|
161
161
|
testID="chat-background-image"
|
|
162
|
-
style={StyleSheet.
|
|
162
|
+
style={StyleSheet.absoluteFill}
|
|
163
163
|
/>
|
|
164
164
|
<View
|
|
165
165
|
pointerEvents="none"
|
|
166
166
|
testID="chat-background-dim"
|
|
167
167
|
style={[
|
|
168
|
-
StyleSheet.
|
|
168
|
+
StyleSheet.absoluteFill,
|
|
169
169
|
{ backgroundColor: paint.imageDim, opacity: dim },
|
|
170
170
|
]}
|
|
171
171
|
/>
|
package/src/dialog/Dialog.tsx
CHANGED
|
@@ -546,7 +546,15 @@ function SideSheet({
|
|
|
546
546
|
return (
|
|
547
547
|
// `OverlayRoot` takes this drawer's place in the open-order overlay stack.
|
|
548
548
|
// It mounts here, past the `mounted` guard, so the rank tracks OPENING.
|
|
549
|
-
|
|
549
|
+
// `onRequestClose`: the drawer is not an RN `Modal`, so Android back would
|
|
550
|
+
// otherwise pass straight to the screen behind it. A drawer that refuses
|
|
551
|
+
// backdrop dismissal still swallows the press, and stays open.
|
|
552
|
+
<OverlayRoot
|
|
553
|
+
style={[sideStyles.root, containerStyle]}
|
|
554
|
+
className={containerClassName}
|
|
555
|
+
onRequestClose={handleBackdropPress}
|
|
556
|
+
modal
|
|
557
|
+
>
|
|
550
558
|
<Backdrop
|
|
551
559
|
testID={testID ? `${testID}-backdrop` : DIALOG_SHEET_BACKDROP_TESTID}
|
|
552
560
|
accessibilityLabel={label ? `Dismiss ${label}` : 'Dismiss dialog'}
|
|
@@ -144,7 +144,8 @@ function useDialogCss(): void {
|
|
|
144
144
|
* Accessibility: the panel has `role="dialog"` and the `title`/`description`
|
|
145
145
|
* props (when provided) become the `aria-labelledby` / `aria-describedby`
|
|
146
146
|
* targets. Pressing the backdrop dismisses. Pressing `Escape` dismisses.
|
|
147
|
-
*
|
|
147
|
+
* While it is open the page behind is `inert` — provided the app wraps its
|
|
148
|
+
* content in `OverlayInertBoundary` (`OverlayRoot modal` below registers it).
|
|
148
149
|
*
|
|
149
150
|
* Web motion never uses reanimated `exiting` (which throws `removeChild` on
|
|
150
151
|
* concurrent React unmounts): the centered card uses CSS keyframes and the
|
|
@@ -354,8 +355,10 @@ function CenterOrSideDialog({
|
|
|
354
355
|
overlay stack. It mounts here, inside the `isOpen` guard, which
|
|
355
356
|
is what makes the rank track OPENING rather than mounting — the
|
|
356
357
|
dialog is declared once at the app root and stays mounted for
|
|
357
|
-
the app's lifetime.
|
|
358
|
-
|
|
358
|
+
the app's lifetime. `modal` makes the app's
|
|
359
|
+
`OverlayInertBoundary` take the page out of the tab order and
|
|
360
|
+
the accessibility tree while it is open. */}
|
|
361
|
+
<OverlayRoot modal>
|
|
359
362
|
{/* The press target IS the full-viewport box, so it uses
|
|
360
363
|
`Backdrop` (which opts back in from the Portal root's
|
|
361
364
|
`pointer-events: none` via the `pointerEvents` PROP — the style
|
|
@@ -746,7 +749,7 @@ function SheetSurface({
|
|
|
746
749
|
);
|
|
747
750
|
|
|
748
751
|
return (
|
|
749
|
-
<OverlayRoot style={[sheetStyles.root, containerStyle]} className={containerClassName}>
|
|
752
|
+
<OverlayRoot style={[sheetStyles.root, containerStyle]} className={containerClassName} modal>
|
|
750
753
|
<Backdrop
|
|
751
754
|
testID={testID ? `${testID}-backdrop` : DIALOG_SHEET_BACKDROP_TESTID}
|
|
752
755
|
accessibilityLabel={label ? `Dismiss ${label}` : 'Dismiss dialog'}
|
package/src/index.ts
CHANGED
package/src/index.web.ts
CHANGED
|
@@ -81,7 +81,7 @@ const PULSE_SCALE = 0.18;
|
|
|
81
81
|
|
|
82
82
|
/** One full-size layer that centres whatever it holds on the box's centre. */
|
|
83
83
|
const layerStyle: ViewStyle = {
|
|
84
|
-
...StyleSheet.
|
|
84
|
+
...StyleSheet.absoluteFill,
|
|
85
85
|
alignItems: 'center',
|
|
86
86
|
justifyContent: 'center',
|
|
87
87
|
};
|
package/src/mail-list/parts.tsx
CHANGED
|
@@ -77,7 +77,7 @@ export function MailRowLink({
|
|
|
77
77
|
};
|
|
78
78
|
const interactive = Boolean(onPress || href || onLongPress);
|
|
79
79
|
const style: WebCssStyle = {
|
|
80
|
-
...StyleSheet.
|
|
80
|
+
...StyleSheet.absoluteFill,
|
|
81
81
|
borderRadius: MAIL_ROW_RADIUS,
|
|
82
82
|
'--bloom-mail-ring': paint.accent,
|
|
83
83
|
};
|
package/src/media-card/parts.tsx
CHANGED
|
@@ -287,7 +287,7 @@ export function CardLink({ name, onPress, href, onLongPress, selected = false, r
|
|
|
287
287
|
if (!IS_WEB && href) void Linking.openURL(href).catch(() => undefined);
|
|
288
288
|
};
|
|
289
289
|
const style: WebCssStyle = {
|
|
290
|
-
...StyleSheet.
|
|
290
|
+
...StyleSheet.absoluteFill,
|
|
291
291
|
borderRadius: radius,
|
|
292
292
|
'--bloom-media-card-ring': paint.ring,
|
|
293
293
|
};
|
package/src/overlay/Overlay.tsx
CHANGED
|
@@ -57,6 +57,8 @@ import { WEB_POSITION_FIXED } from '../styles/web-view-style';
|
|
|
57
57
|
import { StyledView } from '../styles/styled-primitives';
|
|
58
58
|
import { SurfaceLevelProvider } from '../styles/surface-levels';
|
|
59
59
|
import { layerForRank, type OverlayLayer } from './stack';
|
|
60
|
+
import { useHardwareBack } from './use-hardware-back';
|
|
61
|
+
import { useModalOverlayRegistration } from './use-modal-overlay-active';
|
|
60
62
|
import { useOverlayLayer } from './use-overlay-layer';
|
|
61
63
|
import type { OverlayRootProps, BackdropProps } from './types';
|
|
62
64
|
|
|
@@ -109,32 +111,43 @@ export const BACKDROP_DIM_OPACITY = 0.28;
|
|
|
109
111
|
* every Bloom surface already puts it. Descendants that need to order
|
|
110
112
|
* themselves within the surface read `useOverlayLayerContext()`.
|
|
111
113
|
*/
|
|
112
|
-
export function OverlayRoot({
|
|
114
|
+
export function OverlayRoot({
|
|
115
|
+
children,
|
|
116
|
+
className,
|
|
117
|
+
style,
|
|
118
|
+
testID,
|
|
119
|
+
zIndex,
|
|
120
|
+
onRequestClose,
|
|
121
|
+
modal = false,
|
|
122
|
+
}: OverlayRootProps) {
|
|
123
|
+
// On the root rather than in each surface: every portaled surface mounts one
|
|
124
|
+
// inside its open guard, so this is the one place that cannot be forgotten.
|
|
125
|
+
// The gallery once forgot it and Android back finished the whole activity.
|
|
126
|
+
useHardwareBack(onRequestClose);
|
|
113
127
|
// Split into two components rather than branching on the hook: a pinned root
|
|
114
128
|
// must not CONSUME a rank either. The toast host is pinned and mounts for the
|
|
115
129
|
// whole life of the app, so holding a rank would keep the live set permanently
|
|
116
130
|
// non-empty — the counter would never reset and depths would climb for the
|
|
117
131
|
// rest of the session.
|
|
118
132
|
return zIndex === undefined ? (
|
|
119
|
-
<StackedOverlayRoot className={className} style={style} testID={testID}>
|
|
133
|
+
<StackedOverlayRoot className={className} style={style} testID={testID} modal={modal}>
|
|
120
134
|
{children}
|
|
121
135
|
</StackedOverlayRoot>
|
|
122
136
|
) : (
|
|
123
|
-
<PinnedOverlayRoot zIndex={zIndex} className={className} style={style} testID={testID}>
|
|
137
|
+
<PinnedOverlayRoot zIndex={zIndex} className={className} style={style} testID={testID} modal={modal}>
|
|
124
138
|
{children}
|
|
125
139
|
</PinnedOverlayRoot>
|
|
126
140
|
);
|
|
127
141
|
}
|
|
128
142
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}: Omit<OverlayRootProps, 'zIndex'>) {
|
|
143
|
+
type OverlayRootViewProps = Pick<OverlayRootProps, 'children' | 'className' | 'style' | 'testID'> & {
|
|
144
|
+
modal: boolean;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
function StackedOverlayRoot({ children, className, style, testID, modal }: OverlayRootViewProps) {
|
|
135
148
|
const layer = useOverlayLayer();
|
|
136
149
|
return (
|
|
137
|
-
<OverlayRootView layer={layer} className={className} style={style} testID={testID}>
|
|
150
|
+
<OverlayRootView layer={layer} className={className} style={style} testID={testID} modal={modal}>
|
|
138
151
|
{children}
|
|
139
152
|
</OverlayRootView>
|
|
140
153
|
);
|
|
@@ -146,7 +159,8 @@ function PinnedOverlayRoot({
|
|
|
146
159
|
style,
|
|
147
160
|
testID,
|
|
148
161
|
zIndex,
|
|
149
|
-
|
|
162
|
+
modal,
|
|
163
|
+
}: OverlayRootViewProps & { zIndex: number }) {
|
|
150
164
|
// Outside the stack, so descendants must not read stack depths from it
|
|
151
165
|
// either — every slot is the pinned depth.
|
|
152
166
|
const layer = useMemo(
|
|
@@ -154,7 +168,7 @@ function PinnedOverlayRoot({
|
|
|
154
168
|
[zIndex],
|
|
155
169
|
);
|
|
156
170
|
return (
|
|
157
|
-
<OverlayRootView layer={layer} className={className} style={style} testID={testID}>
|
|
171
|
+
<OverlayRootView layer={layer} className={className} style={style} testID={testID} modal={modal}>
|
|
158
172
|
{children}
|
|
159
173
|
</OverlayRootView>
|
|
160
174
|
);
|
|
@@ -166,14 +180,22 @@ function OverlayRootView({
|
|
|
166
180
|
style,
|
|
167
181
|
testID,
|
|
168
182
|
layer,
|
|
169
|
-
|
|
183
|
+
modal,
|
|
184
|
+
}: OverlayRootViewProps & { layer: OverlayLayer }) {
|
|
185
|
+
// Android cannot confine TalkBack from this side of the outlet — the app's
|
|
186
|
+
// `OverlayInertBoundary` hides the content once it hears a modal is open.
|
|
187
|
+
useModalOverlayRegistration(modal);
|
|
170
188
|
return (
|
|
171
189
|
<OverlayLayerContext.Provider value={layer}>
|
|
172
190
|
{/* `pointerEvents` stays a PROP: react-native-web resolves the RN-only
|
|
173
191
|
`box-none` from the prop path only, and as a style entry it is silently
|
|
174
|
-
dropped — which makes the whole portaled surface click-through.
|
|
192
|
+
dropped — which makes the whole portaled surface click-through.
|
|
193
|
+
`accessibilityViewIsModal` sits HERE, not on the panel: iOS hides only
|
|
194
|
+
the modal view's SIBLINGS, and at the native outlet this root is the
|
|
195
|
+
sibling of the app content, where the panel is not. */}
|
|
175
196
|
<StyledView
|
|
176
197
|
pointerEvents="box-none"
|
|
198
|
+
accessibilityViewIsModal={modal && Platform.OS !== 'web' ? true : undefined}
|
|
177
199
|
className={className}
|
|
178
200
|
style={[styles.root, { zIndex: layer.root }, style]}
|
|
179
201
|
testID={testID}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `OverlayInertBoundary` — the app content's half of a modal overlay.
|
|
3
|
+
*
|
|
4
|
+
* A modal Bloom surface renders at the portal outlet, which is the app
|
|
5
|
+
* content's SIBLING. It can mark itself modal (`accessibilityViewIsModal`, which
|
|
6
|
+
* iOS honours by hiding the siblings), but it cannot hide the app on Android:
|
|
7
|
+
* TalkBack only skips a subtree whose OWN root says
|
|
8
|
+
* `importantForAccessibility="no-hide-descendants"`, and that root belongs to
|
|
9
|
+
* the app. Without it, TalkBack walked from the settings modal straight into
|
|
10
|
+
* the Home feed behind it (OxyHQ/Mention#1126).
|
|
11
|
+
*
|
|
12
|
+
* The app wraps its content — everything that is NOT the `PortalOutlet` — in
|
|
13
|
+
* this boundary. While any modal overlay is open (`./modal-registry.ts`) it
|
|
14
|
+
* takes that content out of the accessibility tree:
|
|
15
|
+
*
|
|
16
|
+
* - Android: `importantForAccessibility="no-hide-descendants"`.
|
|
17
|
+
* - iOS: `accessibilityElementsHidden`, alongside the surface's own
|
|
18
|
+
* `accessibilityViewIsModal` (either alone is enough; both costs nothing).
|
|
19
|
+
* - Web: `inert`, which removes the subtree from the tab order AND the
|
|
20
|
+
* accessibility tree, plus `aria-hidden` for engines that lag on `inert`.
|
|
21
|
+
* The web portal root is a child of `document.body`, never of the app
|
|
22
|
+
* root, so the surface itself is untouched. Web dialogs set no focus trap
|
|
23
|
+
* of their own, so nothing is applied twice.
|
|
24
|
+
*
|
|
25
|
+
* Layout: on web the boundary is `display: contents`, so it generates no box
|
|
26
|
+
* and a document-scrolling page lays out exactly as without it. On native it is
|
|
27
|
+
* a `flex: 1` view — the content it wraps already fills the root there — and it
|
|
28
|
+
* is never collapsed, because flattening a layout-only view would drop the
|
|
29
|
+
* accessibility prop the moment it is needed.
|
|
30
|
+
*/
|
|
31
|
+
import { Platform, StyleSheet, View } from 'react-native';
|
|
32
|
+
|
|
33
|
+
import type { OverlayInertBoundaryProps } from './types';
|
|
34
|
+
import { useModalOverlayActive } from './use-modal-overlay-active';
|
|
35
|
+
|
|
36
|
+
export function OverlayInertBoundary({ children, style, testID }: OverlayInertBoundaryProps) {
|
|
37
|
+
const active = useModalOverlayActive();
|
|
38
|
+
|
|
39
|
+
if (Platform.OS === 'web') {
|
|
40
|
+
return (
|
|
41
|
+
<View
|
|
42
|
+
testID={testID}
|
|
43
|
+
style={[styles.web, style]}
|
|
44
|
+
aria-hidden={active ? true : undefined}
|
|
45
|
+
{...(active ? { inert: true } : null)}
|
|
46
|
+
>
|
|
47
|
+
{children}
|
|
48
|
+
</View>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<View
|
|
54
|
+
testID={testID}
|
|
55
|
+
collapsable={false}
|
|
56
|
+
style={[styles.native, style]}
|
|
57
|
+
importantForAccessibility={active ? 'no-hide-descendants' : 'auto'}
|
|
58
|
+
accessibilityElementsHidden={active}
|
|
59
|
+
>
|
|
60
|
+
{children}
|
|
61
|
+
</View>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
OverlayInertBoundary.displayName = 'OverlayInertBoundary';
|
|
66
|
+
|
|
67
|
+
const styles = StyleSheet.create({
|
|
68
|
+
native: { flex: 1 },
|
|
69
|
+
// No box of its own on web: the wrapped content lays out against the
|
|
70
|
+
// boundary's parent, flex tree or document scroll alike.
|
|
71
|
+
web: { display: 'contents' },
|
|
72
|
+
});
|
package/src/overlay/index.ts
CHANGED
|
@@ -7,6 +7,8 @@ export {
|
|
|
7
7
|
type OverlayLayer,
|
|
8
8
|
} from './stack';
|
|
9
9
|
export { useOverlayLayer } from './use-overlay-layer';
|
|
10
|
+
export { useModalOverlayActive } from './use-modal-overlay-active';
|
|
11
|
+
export { OverlayInertBoundary } from './OverlayInertBoundary';
|
|
10
12
|
export {
|
|
11
13
|
useOverlayLayerContext,
|
|
12
14
|
BACKDROP_BLUR_INTENSITY,
|
|
@@ -14,4 +16,4 @@ export {
|
|
|
14
16
|
OverlayRoot,
|
|
15
17
|
Backdrop,
|
|
16
18
|
} from './Overlay';
|
|
17
|
-
export type { OverlayRootProps, BackdropProps } from './types';
|
|
19
|
+
export type { OverlayRootProps, BackdropProps, OverlayInertBoundaryProps } from './types';
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which MODAL overlays are open right now, as a subscribable store.
|
|
3
|
+
*
|
|
4
|
+
* ## Why this exists
|
|
5
|
+
*
|
|
6
|
+
* A modal surface has to keep a screen reader inside it. iOS can do that from
|
|
7
|
+
* the overlay's side: `accessibilityViewIsModal` on the `OverlayRoot` hides its
|
|
8
|
+
* siblings, and at the native portal outlet the app content IS a sibling.
|
|
9
|
+
* Android has no equivalent. TalkBack keeps walking into the app behind the
|
|
10
|
+
* open surface (OxyHQ/Mention#1126: the Home feed stayed reachable under the
|
|
11
|
+
* settings modal), and the only switch that stops it —
|
|
12
|
+
* `importantForAccessibility="no-hide-descendants"` — has to sit ON the app
|
|
13
|
+
* content. A portaled surface cannot reach that view: the outlet renders it as
|
|
14
|
+
* the content's sibling, not its ancestor.
|
|
15
|
+
*
|
|
16
|
+
* So the knowledge travels the other way. Every `OverlayRoot` with `modal`
|
|
17
|
+
* registers here while it is mounted, and `OverlayInertBoundary` — which the
|
|
18
|
+
* app wraps around its own content — subscribes and hides what it wraps while
|
|
19
|
+
* anything modal is open.
|
|
20
|
+
*
|
|
21
|
+
* Non-modal overlays (menus, popovers, tooltips, toasts, the shell drawers)
|
|
22
|
+
* never register: the content under an anchored menu must stay reachable.
|
|
23
|
+
*
|
|
24
|
+
* Tokens rather than a counter so StrictMode's mount/unmount/remount and an
|
|
25
|
+
* unmatched release can never drift the count: a token is either in the set or
|
|
26
|
+
* not.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
interface ModalRegistry {
|
|
30
|
+
live: Set<object>;
|
|
31
|
+
listeners: Set<() => void>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
declare global {
|
|
35
|
+
// eslint-disable-next-line no-var
|
|
36
|
+
var __oxy_so_bloom_modal_overlays__: ModalRegistry | undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* `globalThis`-anchored for the same reason as `./stack.ts`: the surfaces that
|
|
41
|
+
* register (`./dialog`, `./settings-modal`, …) and the boundary the app mounts
|
|
42
|
+
* (`./portal`) are imported through different subpaths, and a bundler can
|
|
43
|
+
* resolve those through different export conditions. Two physical copies of
|
|
44
|
+
* this module would each keep their own set, and the boundary would never hear
|
|
45
|
+
* about the surfaces.
|
|
46
|
+
*/
|
|
47
|
+
function registry(): ModalRegistry {
|
|
48
|
+
globalThis.__oxy_so_bloom_modal_overlays__ ??= { live: new Set(), listeners: new Set() };
|
|
49
|
+
return globalThis.__oxy_so_bloom_modal_overlays__;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function notify(reg: ModalRegistry): void {
|
|
53
|
+
for (const listener of Array.from(reg.listeners)) listener();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Mark a modal overlay as open. Returns its release. Called from an effect in
|
|
58
|
+
* `OverlayRoot`, which React balances even under StrictMode.
|
|
59
|
+
*/
|
|
60
|
+
export function registerModalOverlay(token: object): () => void {
|
|
61
|
+
const reg = registry();
|
|
62
|
+
const wasActive = reg.live.size > 0;
|
|
63
|
+
reg.live.add(token);
|
|
64
|
+
if (!wasActive) notify(reg);
|
|
65
|
+
return () => {
|
|
66
|
+
const current = registry();
|
|
67
|
+
if (!current.live.delete(token)) return;
|
|
68
|
+
if (current.live.size === 0) notify(current);
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Whether any modal overlay is open. */
|
|
73
|
+
export function hasActiveModalOverlays(): boolean {
|
|
74
|
+
return registry().live.size > 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** How many modal overlays are open. Exported for tests. */
|
|
78
|
+
export function activeModalOverlayCount(): number {
|
|
79
|
+
return registry().live.size;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Subscribe to changes in `hasActiveModalOverlays()`. Listeners fire only when
|
|
84
|
+
* the answer flips — a second modal opening over a first changes nothing for
|
|
85
|
+
* the content underneath.
|
|
86
|
+
*/
|
|
87
|
+
export function subscribeModalOverlays(listener: () => void): () => void {
|
|
88
|
+
const reg = registry();
|
|
89
|
+
reg.listeners.add(listener);
|
|
90
|
+
return () => {
|
|
91
|
+
registry().listeners.delete(listener);
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Test seam — drops all open modals, notifying current subscribers. */
|
|
96
|
+
export function resetModalOverlays(): void {
|
|
97
|
+
const reg = registry();
|
|
98
|
+
const wasActive = reg.live.size > 0;
|
|
99
|
+
reg.live.clear();
|
|
100
|
+
if (wasActive) notify(reg);
|
|
101
|
+
}
|
package/src/overlay/types.ts
CHANGED
|
@@ -23,6 +23,43 @@ export interface OverlayRootProps {
|
|
|
23
23
|
* `./stack.ts` exists to remove.
|
|
24
24
|
*/
|
|
25
25
|
zIndex?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Android hardware back while this surface is open. A portaled surface is not
|
|
28
|
+
* an RN `Modal`, so nothing else consumes the press: without this the app's
|
|
29
|
+
* own back handling runs and, at the root of a stack, finishes the activity —
|
|
30
|
+
* the surface "closes" by closing the whole app. Called and consumed while the
|
|
31
|
+
* root is mounted; later-opened surfaces register later, and `BackHandler`
|
|
32
|
+
* runs the newest listener first, so the top surface closes first. A blocking
|
|
33
|
+
* surface still passes a handler (a no-op) so the press is swallowed rather
|
|
34
|
+
* than falling through to the screen underneath.
|
|
35
|
+
*/
|
|
36
|
+
onRequestClose?: () => void;
|
|
37
|
+
/**
|
|
38
|
+
* The surface is modal: a screen reader must not wander into the app behind
|
|
39
|
+
* it. Two effects:
|
|
40
|
+
*
|
|
41
|
+
* - Native: sets `accessibilityViewIsModal` on this root, which is the app
|
|
42
|
+
* content's sibling at the portal outlet (iOS confines VoiceOver to it).
|
|
43
|
+
* - Every platform: registers the surface as an open modal while mounted
|
|
44
|
+
* (`./modal-registry.ts`), so the app's `OverlayInertBoundary` hides the
|
|
45
|
+
* content behind it — the only way to confine TalkBack on Android, and
|
|
46
|
+
* what makes the content `inert` on web.
|
|
47
|
+
*
|
|
48
|
+
* Dialogs, sheets, the settings modal and the media viewer set it; anchored
|
|
49
|
+
* surfaces (menus, popovers, tooltips), toasts and the shell drawers do not.
|
|
50
|
+
*/
|
|
51
|
+
modal?: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface OverlayInertBoundaryProps {
|
|
55
|
+
/** The app's own content — everything EXCEPT the `PortalOutlet`. */
|
|
56
|
+
children?: ReactNode;
|
|
57
|
+
/**
|
|
58
|
+
* Native only (web renders no box). Defaults to `flex: 1`; override when the
|
|
59
|
+
* boundary's parent is not a column that the content should fill.
|
|
60
|
+
*/
|
|
61
|
+
style?: StyleProp<ViewStyle>;
|
|
62
|
+
testID?: string;
|
|
26
63
|
}
|
|
27
64
|
|
|
28
65
|
export interface BackdropProps {
|