@lodev09/react-native-true-sheet 3.11.13 → 3.11.14
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/ios/TrueSheetView.mm
CHANGED
|
@@ -382,7 +382,6 @@ using namespace facebook::react;
|
|
|
382
382
|
[_controller.view addSubview:_containerView];
|
|
383
383
|
[LayoutUtil pinView:_containerView toParentView:_controller.view edges:UIRectEdgeAll];
|
|
384
384
|
[_controller.view bringSubviewToFront:_containerView];
|
|
385
|
-
_containerView.accessibilityViewIsModal = YES;
|
|
386
385
|
_controller.accessibilityContentView = _containerView;
|
|
387
386
|
[_controller setupAccessibilityContainer];
|
|
388
387
|
|
|
@@ -43,6 +43,7 @@ static char TrueSheetAccessibilityWindowPreviousElementsKey;
|
|
|
43
43
|
- (void)restoreWindowAccessibilityElements;
|
|
44
44
|
- (void)setSheetAccessibilityElementsHidden:(BOOL)hidden;
|
|
45
45
|
- (void)setAccessibilityContentElement:(UIView *)contentView;
|
|
46
|
+
- (NSArray *)accessibilityGrabberElements;
|
|
46
47
|
- (void)endInteractiveDismissState;
|
|
47
48
|
- (void)emitInteractivePosition;
|
|
48
49
|
- (void)animateInteractiveContainerToTransform:(CGAffineTransform)transform
|
|
@@ -52,6 +53,20 @@ static char TrueSheetAccessibilityWindowPreviousElementsKey;
|
|
|
52
53
|
|
|
53
54
|
@end
|
|
54
55
|
|
|
56
|
+
// VoiceOver delivers the two-finger Z (escape) gesture by walking up the view
|
|
57
|
+
// hierarchy from the focused element, so the sheet's root view handles it.
|
|
58
|
+
@interface TrueSheetControllerView : UIView
|
|
59
|
+
@property (nonatomic, weak) TrueSheetViewController *controller;
|
|
60
|
+
@end
|
|
61
|
+
|
|
62
|
+
@implementation TrueSheetControllerView
|
|
63
|
+
|
|
64
|
+
- (BOOL)accessibilityPerformEscape {
|
|
65
|
+
return [self.controller accessibilityPerformEscape];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@end
|
|
69
|
+
|
|
55
70
|
@implementation TrueSheetViewController {
|
|
56
71
|
TrueSheetPositionState _lastEmittedPositionState;
|
|
57
72
|
CGFloat _lastWidth;
|
|
@@ -214,6 +229,12 @@ static char TrueSheetAccessibilityWindowPreviousElementsKey;
|
|
|
214
229
|
|
|
215
230
|
#pragma mark - View Lifecycle
|
|
216
231
|
|
|
232
|
+
- (void)loadView {
|
|
233
|
+
TrueSheetControllerView *view = [[TrueSheetControllerView alloc] init];
|
|
234
|
+
view.controller = self;
|
|
235
|
+
self.view = view;
|
|
236
|
+
}
|
|
237
|
+
|
|
217
238
|
- (void)viewDidLoad {
|
|
218
239
|
[super viewDidLoad];
|
|
219
240
|
self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
|
|
@@ -321,6 +342,32 @@ static char TrueSheetAccessibilityWindowPreviousElementsKey;
|
|
|
321
342
|
}
|
|
322
343
|
}
|
|
323
344
|
|
|
345
|
+
- (NSArray *)accessibilityGrabberElements {
|
|
346
|
+
if (_grabberView && !_grabberView.hidden) {
|
|
347
|
+
return @[ _grabberView ];
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// The system grabber is an accessibility element UIKit adds to the presented view
|
|
351
|
+
// (a sibling of our root view). Expose it so VoiceOver can resize or dismiss with it.
|
|
352
|
+
// UIKit also keeps a transparent bottom grabber there, so skip invisible views.
|
|
353
|
+
NSMutableArray *elements = [NSMutableArray array];
|
|
354
|
+
for (UIView *subview in self.presentationController.presentedView.subviews) {
|
|
355
|
+
if (subview != self.view && subview.isAccessibilityElement && !subview.hidden && subview.alpha > 0) {
|
|
356
|
+
[elements addObject:subview];
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return elements;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
- (BOOL)accessibilityPerformEscape {
|
|
363
|
+
if (!_isPresented || !self.dismissible) {
|
|
364
|
+
return NO;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
|
|
368
|
+
return YES;
|
|
369
|
+
}
|
|
370
|
+
|
|
324
371
|
- (void)setAccessibilityContentElement:(UIView *)contentView {
|
|
325
372
|
BOOL hasAccessibilityFooterElements = [contentView isKindOfClass:[TrueSheetContainerView class]] &&
|
|
326
373
|
[(TrueSheetContainerView *)contentView hasAccessibilityFooterElements];
|
|
@@ -333,12 +380,12 @@ static char TrueSheetAccessibilityWindowPreviousElementsKey;
|
|
|
333
380
|
// its accessibilityElements getter recomputes live, so a footer/content subtree
|
|
334
381
|
// that remounts (e.g. swapping a footer button on a state change) stays
|
|
335
382
|
// discoverable instead of leaving this snapshot pointing at destroyed views.
|
|
336
|
-
|
|
383
|
+
NSMutableArray *accessibilityElements = [[self accessibilityGrabberElements] mutableCopy];
|
|
337
384
|
if (isAccessibilityModal) {
|
|
338
385
|
NSArray *contentElements = contentView.accessibilityElements;
|
|
339
|
-
accessibilityElements
|
|
386
|
+
[accessibilityElements addObjectsFromArray:contentElements.count > 0 ? contentElements : @[ contentView ]];
|
|
340
387
|
} else {
|
|
341
|
-
accessibilityElements
|
|
388
|
+
[accessibilityElements addObject:contentView];
|
|
342
389
|
}
|
|
343
390
|
|
|
344
391
|
self.view.isAccessibilityElement = NO;
|
|
@@ -351,6 +398,15 @@ static char TrueSheetAccessibilityWindowPreviousElementsKey;
|
|
|
351
398
|
presentedView.accessibilityViewIsModal = isAccessibilityModal;
|
|
352
399
|
presentedView.accessibilityElements = accessibilityElements;
|
|
353
400
|
|
|
401
|
+
// The system grabber is a sibling of our root view, so an escape performed while it
|
|
402
|
+
// is focused walks presentedView → window and never reaches TrueSheetControllerView.
|
|
403
|
+
if (@available(iOS 17.0, *)) {
|
|
404
|
+
__weak __typeof(self) weakSelf = self;
|
|
405
|
+
presentedView.accessibilityPerformEscapeBlock = ^BOOL {
|
|
406
|
+
return [weakSelf accessibilityPerformEscape];
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
|
|
354
410
|
UIWindow *window = self.view.window;
|
|
355
411
|
UIViewController *presentingViewController = [self accessibilityPresentingViewController];
|
|
356
412
|
if (window && presentingViewController.view) {
|
|
@@ -1147,6 +1203,12 @@ static char TrueSheetAccessibilityWindowPreviousElementsKey;
|
|
|
1147
1203
|
_grabberView.onIncrement = nil;
|
|
1148
1204
|
_grabberView.onDecrement = nil;
|
|
1149
1205
|
}
|
|
1206
|
+
|
|
1207
|
+
// Only the topmost sheet may refresh, or a parent's prop update would steal the
|
|
1208
|
+
// window accessibility override from the child presented over it.
|
|
1209
|
+
if (_isPresented && self.isTopmostPresentedController) {
|
|
1210
|
+
[self setupAccessibilityContainer];
|
|
1211
|
+
}
|
|
1150
1212
|
}
|
|
1151
1213
|
|
|
1152
1214
|
- (void)handleGrabberTap {
|
|
@@ -91,6 +91,13 @@ static const CGFloat kHitPaddingVertical = 10.0;
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
// Pad the pill evenly like the system grabber. The view frame itself stays inside
|
|
95
|
+
// the sheet, since the reveal check reads the frame rather than this rect.
|
|
96
|
+
- (CGRect)accessibilityFrame {
|
|
97
|
+
CGRect rect = CGRectInset(_vibrancyView.frame, -kHitPaddingHorizontal, -kHitPaddingVertical);
|
|
98
|
+
return UIAccessibilityConvertFrameToScreenCoordinates(rect, self);
|
|
99
|
+
}
|
|
100
|
+
|
|
94
101
|
- (void)accessibilityIncrement {
|
|
95
102
|
if (_onIncrement) {
|
|
96
103
|
_onIncrement();
|
|
@@ -144,14 +151,17 @@ static const CGFloat kHitPaddingVertical = 10.0;
|
|
|
144
151
|
CGFloat topMargin = [self effectiveTopMargin];
|
|
145
152
|
CGFloat parentWidth = self.superview ? self.superview.bounds.size.width : UIScreen.mainScreen.bounds.size.width;
|
|
146
153
|
|
|
154
|
+
// Keep the frame inside the sheet. A frame above the top edge reads as a clipped element
|
|
155
|
+
// to VoiceOver, and the sheet reveals it on focus by moving to the next detent.
|
|
147
156
|
CGFloat frameWidth = pillWidth + kHitPaddingHorizontal * 2;
|
|
148
|
-
CGFloat
|
|
149
|
-
CGFloat
|
|
157
|
+
CGFloat frameY = MAX(0, topMargin - kHitPaddingVertical);
|
|
158
|
+
CGFloat pillY = topMargin - frameY;
|
|
159
|
+
CGFloat frameHeight = pillY + pillHeight + kHitPaddingVertical;
|
|
150
160
|
|
|
151
161
|
self.frame = CGRectMake((parentWidth - frameWidth) / 2.0, frameY, frameWidth, frameHeight);
|
|
152
162
|
self.backgroundColor = UIColor.clearColor;
|
|
153
163
|
|
|
154
|
-
CGRect pillRect = CGRectMake(kHitPaddingHorizontal,
|
|
164
|
+
CGRect pillRect = CGRectMake(kHitPaddingHorizontal, pillY, pillWidth, pillHeight);
|
|
155
165
|
_vibrancyView.frame = pillRect;
|
|
156
166
|
_vibrancyView.layer.cornerRadius = [self effectiveCornerRadius];
|
|
157
167
|
_vibrancyView.clipsToBounds = YES;
|
package/package.json
CHANGED