@onekeyfe/react-native-pager-view 6.7.0-alpha.436 → 6.7.0-alpha.445
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 +16 -0
- package/android/build.gradle +1 -0
- package/android/src/androidTest/java/com/reactnativepagerview/CollapsiblePagerTabReservationTest.kt +135 -0
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerHost.kt +88 -12
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerNativeHeaders.kt +442 -15
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerViewManager.kt +11 -1
- package/android/src/main/java/com/reactnativepagerview/event/NativeHeaderPressEvent.kt +8 -0
- package/docs/SPEC.md +298 -3
- package/ios/RNCCollapsiblePagerViewComponentView.mm +834 -20
- package/ios/tests/RNCCollapsiblePagerFirstFrameTests.mm +61 -0
- package/ios/tests/RNCCollapsiblePagerHitTestTests.mm +22 -0
- package/lib/module/CollapsiblePagerView.js +37 -5
- package/lib/module/CollapsiblePagerView.web.js +519 -6
- package/lib/module/CollapsiblePagerViewNativeComponent.ts +6 -0
- package/lib/module/NativeScrollerNativeComponent.ts +0 -1
- package/lib/typescript/src/CollapsiblePagerView.d.ts +31 -2
- package/lib/typescript/src/CollapsiblePagerView.web.d.ts +44 -1
- package/lib/typescript/src/CollapsiblePagerViewNativeComponent.d.ts +11 -0
- package/lib/typescript/src/NativeScroller.d.ts +2 -2
- package/package.json +3 -2
- package/src/CollapsiblePagerView.tsx +68 -5
- package/src/CollapsiblePagerView.web.tsx +464 -5
- package/src/CollapsiblePagerViewNativeComponent.ts +6 -0
- package/src/NativeScroller.tsx +2 -3
- package/src/NativeScrollerNativeComponent.ts +0 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import React from "react";
|
|
4
|
-
import {
|
|
4
|
+
import { createNamedIcon } from "@onekeyfe/react-native-image/icon/dom";
|
|
5
|
+
import { I18nManager, Platform, processColor, StyleSheet, View } from "react-native";
|
|
5
6
|
import { WebCollapsiblePagerPage } from "./WebCollapsiblePagerPage.js";
|
|
6
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
8
|
const COLLAPSE_ANIMATION_NAME = "ok-collapsible-pager-collapse";
|
|
8
9
|
const COLLAPSE_STYLE_ID = "ok-collapsible-pager-styles";
|
|
9
10
|
const PAGER_HEADER_INSET = "--ok-collapsible-pager-header-inset";
|
|
@@ -48,6 +49,10 @@ export class CollapsiblePagerView extends React.PureComponent {
|
|
|
48
49
|
};
|
|
49
50
|
root = null;
|
|
50
51
|
track = null;
|
|
52
|
+
tabProgress = null;
|
|
53
|
+
tabProgressFrame = null;
|
|
54
|
+
tabProgressGeneration = 0;
|
|
55
|
+
tabButtons = new Map();
|
|
51
56
|
headerSlot = null;
|
|
52
57
|
stickySlot = null;
|
|
53
58
|
cssTimelineSupported = false;
|
|
@@ -80,6 +85,7 @@ export class CollapsiblePagerView extends React.PureComponent {
|
|
|
80
85
|
configureFrame = null;
|
|
81
86
|
pendingTopFrame = null;
|
|
82
87
|
transitionTimer = null;
|
|
88
|
+
transitionGeneration = 0;
|
|
83
89
|
pageScrollState = "idle";
|
|
84
90
|
configuredScrollElement = null;
|
|
85
91
|
timelineName = `--ok-collapsible-pager-${++collapsiblePagerWebInstance}`;
|
|
@@ -115,6 +121,9 @@ export class CollapsiblePagerView extends React.PureComponent {
|
|
|
115
121
|
this.scheduleScrollConfiguration();
|
|
116
122
|
this.syncFallbackHeader();
|
|
117
123
|
this.notifyMountedPagesChanged();
|
|
124
|
+
this.syncToolbar();
|
|
125
|
+
this.tabProgress = this.state.selectedPage;
|
|
126
|
+
this.syncTabColors();
|
|
118
127
|
this.emitDiagnostics("mounted");
|
|
119
128
|
}
|
|
120
129
|
componentDidUpdate(previousProps, _previousState, routeSnapshot) {
|
|
@@ -166,12 +175,17 @@ export class CollapsiblePagerView extends React.PureComponent {
|
|
|
166
175
|
this.scheduleScrollConfiguration();
|
|
167
176
|
this.syncFallbackHeader();
|
|
168
177
|
this.notifyMountedPagesChanged();
|
|
178
|
+
this.syncToolbar();
|
|
179
|
+
if (previousProps.isActive === false && this.props.isActive !== false) this.readTabProgress();
|
|
180
|
+
if (this.props.isActive === false || !this.tabColorWeights()) this.cancelTabProgressFrame();
|
|
181
|
+
this.syncTabColors();
|
|
169
182
|
}
|
|
170
183
|
componentWillUnmount() {
|
|
171
184
|
// Activity can disconnect effects before the inactive update commits.
|
|
172
185
|
const routeTarget = this.captureRouteTarget(this.props);
|
|
173
186
|
if (routeTarget) this.setRouteTarget(routeTarget);
|
|
174
187
|
this.disposed = true;
|
|
188
|
+
this.setToolbarSlot(null);
|
|
175
189
|
this.selectionRestoreToken += 1;
|
|
176
190
|
this.cancelPendingTopFrame();
|
|
177
191
|
this.savePageOffset(this.state.selectedPage);
|
|
@@ -214,6 +228,7 @@ export class CollapsiblePagerView extends React.PureComponent {
|
|
|
214
228
|
};
|
|
215
229
|
observeChrome() {
|
|
216
230
|
this.chromeObserver = new ResizeObserver(this.scheduleChromeMeasurement);
|
|
231
|
+
if (this.root) this.chromeObserver.observe(this.root);
|
|
217
232
|
if (this.headerContent) this.chromeObserver.observe(this.headerContent);
|
|
218
233
|
if (this.stickyContent) this.chromeObserver.observe(this.stickyContent);
|
|
219
234
|
this.scheduleChromeMeasurement();
|
|
@@ -232,6 +247,8 @@ export class CollapsiblePagerView extends React.PureComponent {
|
|
|
232
247
|
this.measuredStickyHeight = nextSticky;
|
|
233
248
|
this.headerMeasured = Boolean(header?.isConnected);
|
|
234
249
|
this.stickyMeasured = Boolean(sticky?.isConnected);
|
|
250
|
+
this.syncToolbar();
|
|
251
|
+
this.syncTabColors();
|
|
235
252
|
if (headerChanged || stickyChanged) {
|
|
236
253
|
this.forceUpdate();
|
|
237
254
|
this.scheduleScrollConfiguration();
|
|
@@ -442,29 +459,138 @@ export class CollapsiblePagerView extends React.PureComponent {
|
|
|
442
459
|
}));
|
|
443
460
|
}
|
|
444
461
|
finishPageTransition = () => {
|
|
462
|
+
this.transitionGeneration += 1;
|
|
445
463
|
if (this.transitionTimer !== null) {
|
|
446
464
|
clearTimeout(this.transitionTimer);
|
|
447
465
|
this.transitionTimer = null;
|
|
448
466
|
}
|
|
467
|
+
this.readTabProgress();
|
|
468
|
+
this.cancelTabProgressFrame();
|
|
469
|
+
this.syncTabColors();
|
|
449
470
|
this.emitPageScrollState("idle");
|
|
471
|
+
this.syncToolbar();
|
|
450
472
|
};
|
|
451
473
|
beginPageTransition() {
|
|
474
|
+
this.suspendToolbar();
|
|
452
475
|
if (this.transitionTimer !== null) clearTimeout(this.transitionTimer);
|
|
476
|
+
const generation = ++this.transitionGeneration;
|
|
453
477
|
this.emitPageScrollState("settling");
|
|
454
|
-
this.transitionTimer = setTimeout(
|
|
478
|
+
this.transitionTimer = setTimeout(() => {
|
|
479
|
+
if (generation === this.transitionGeneration) this.finishPageTransition();
|
|
480
|
+
}, 320);
|
|
455
481
|
}
|
|
456
482
|
onTrackTransitionEnd = event => {
|
|
457
483
|
if (event.target === this.track && event.propertyName === "transform") {
|
|
484
|
+
this.readTabProgress();
|
|
485
|
+
if (this.tabColorWeights() && this.tabProgress !== null && Math.abs(this.tabProgress - this.state.selectedPage) > 0.001) return;
|
|
458
486
|
this.finishPageTransition();
|
|
459
487
|
}
|
|
460
488
|
};
|
|
461
489
|
setTrack = node => {
|
|
462
490
|
const track = webElement(node);
|
|
463
491
|
if (track === this.track) return;
|
|
492
|
+
this.cancelTabProgressFrame();
|
|
464
493
|
this.track?.removeEventListener("transitionend", this.onTrackTransitionEnd);
|
|
465
494
|
this.track = track;
|
|
466
495
|
this.track?.addEventListener("transitionend", this.onTrackTransitionEnd);
|
|
467
496
|
};
|
|
497
|
+
cancelTabProgressFrame() {
|
|
498
|
+
this.tabProgressGeneration += 1;
|
|
499
|
+
if (this.tabProgressFrame !== null) cancelAnimationFrame(this.tabProgressFrame);
|
|
500
|
+
this.tabProgressFrame = null;
|
|
501
|
+
}
|
|
502
|
+
readTabProgress() {
|
|
503
|
+
const track = this.track;
|
|
504
|
+
const width = this.root?.getBoundingClientRect().width ?? 0;
|
|
505
|
+
if (!track?.isConnected || width <= 0) return null;
|
|
506
|
+
const transform = track.ownerDocument.defaultView?.getComputedStyle(track).transform;
|
|
507
|
+
const matrix = transform?.match(/^matrix(3d)?\(([^)]+)\)$/);
|
|
508
|
+
const offset = matrix ? Number(matrix[2].split(",")[matrix[1] ? 12 : 4]) : transform === "none" ? 0 : NaN;
|
|
509
|
+
if (!Number.isFinite(offset)) return null;
|
|
510
|
+
this.tabProgress = Math.min(Math.max(0, -offset / width), Math.max(0, this.pages().length - 1));
|
|
511
|
+
return this.tabProgress;
|
|
512
|
+
}
|
|
513
|
+
startTabProgressFrames() {
|
|
514
|
+
this.cancelTabProgressFrame();
|
|
515
|
+
if (!this.tabColorWeights() || typeof requestAnimationFrame !== "function") return;
|
|
516
|
+
const track = this.track;
|
|
517
|
+
const root = this.root;
|
|
518
|
+
const width = root?.getBoundingClientRect().width ?? 0;
|
|
519
|
+
if (!track?.isConnected || !root?.isConnected || width <= 0 || this.props.isActive === false) return;
|
|
520
|
+
const generation = this.tabProgressGeneration;
|
|
521
|
+
const selection = this.selectionRestoreToken;
|
|
522
|
+
const keys = JSON.stringify(this.pages().map(pageKey));
|
|
523
|
+
const owner = this.pageScrollElement(this.state.selectedPage);
|
|
524
|
+
const sample = () => {
|
|
525
|
+
if (generation !== this.tabProgressGeneration || this.disposed) return;
|
|
526
|
+
this.tabProgressFrame = null;
|
|
527
|
+
if (this.track !== track || this.root !== root || !track.isConnected || !root.isConnected || this.props.isActive === false || selection !== this.selectionRestoreToken || keys !== JSON.stringify(this.pages().map(pageKey)) || owner !== this.pageScrollElement(this.state.selectedPage) || width !== root.getBoundingClientRect().width || !this.tabColorWeights()) {
|
|
528
|
+
this.cancelTabProgressFrame();
|
|
529
|
+
this.readTabProgress();
|
|
530
|
+
this.syncTabColors();
|
|
531
|
+
if (this.transitionTimer !== null) this.startTabProgressFrames();
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
this.readTabProgress();
|
|
535
|
+
this.syncTabColors();
|
|
536
|
+
if (this.transitionTimer !== null) this.tabProgressFrame = requestAnimationFrame(sample);
|
|
537
|
+
};
|
|
538
|
+
sample();
|
|
539
|
+
}
|
|
540
|
+
tabColorWeights() {
|
|
541
|
+
const config = this.props.nativeTabBar;
|
|
542
|
+
if (!config?.controlled || config.style?.variant !== "text" || this.tabProgress === null) return null;
|
|
543
|
+
const keys = [];
|
|
544
|
+
React.Children.forEach(this.props.children, child => {
|
|
545
|
+
if (child !== null && child !== undefined && typeof child !== "boolean") keys.push(pageKey(child, keys.length));
|
|
546
|
+
});
|
|
547
|
+
const itemKeys = config.items.map(item => item.key);
|
|
548
|
+
if (!keys.length || !keys.includes(config.selectedKey ?? "") || new Set(keys).size !== keys.length || new Set(itemKeys).size !== itemKeys.length || keys.some(key => !itemKeys.includes(key))) return null;
|
|
549
|
+
const progress = Math.min(Math.max(0, this.tabProgress), keys.length - 1);
|
|
550
|
+
const source = Math.floor(progress);
|
|
551
|
+
const destination = Math.min(source + 1, keys.length - 1);
|
|
552
|
+
const fraction = progress - source;
|
|
553
|
+
return new Map(keys.map((key, index) => [key, index === source ? 1 - fraction : index === destination ? fraction : 0]));
|
|
554
|
+
}
|
|
555
|
+
tabFontOwnerKey(weights) {
|
|
556
|
+
const config = this.props.nativeTabBar;
|
|
557
|
+
const semantic = config?.controlled ? config.selectedKey : config?.items[this.state.selectedPage]?.key;
|
|
558
|
+
if (!weights || this.tabProgress === null) return semantic;
|
|
559
|
+
const keys = Array.from(weights.keys());
|
|
560
|
+
const progress = Math.min(Math.max(0, this.tabProgress), keys.length - 1);
|
|
561
|
+
return keys[Math.floor(progress + 0.5)];
|
|
562
|
+
}
|
|
563
|
+
tabColor(selected, weight) {
|
|
564
|
+
const style = this.props.nativeTabBar?.style;
|
|
565
|
+
const active = style?.activeTextColor ?? "#000000";
|
|
566
|
+
const inactive = style?.inactiveTextColor ?? "#666666";
|
|
567
|
+
if (weight === undefined) return String(selected ? active : inactive);
|
|
568
|
+
if (weight <= 0) return String(inactive);
|
|
569
|
+
if (weight >= 1) return String(active);
|
|
570
|
+
const first = processColor(inactive);
|
|
571
|
+
const last = processColor(active);
|
|
572
|
+
if (typeof first !== "number" || typeof last !== "number") return String(selected ? active : inactive);
|
|
573
|
+
const channel = shift => (first >>> shift & 255) * (1 - weight) + (last >>> shift & 255) * weight;
|
|
574
|
+
return `rgba(${Math.round(channel(16))}, ${Math.round(channel(8))}, ${Math.round(channel(0))}, ${(channel(24) / 255).toFixed(4)})`;
|
|
575
|
+
}
|
|
576
|
+
syncTabColors() {
|
|
577
|
+
const weights = this.tabColorWeights();
|
|
578
|
+
const config = this.props.nativeTabBar;
|
|
579
|
+
if (!config) return;
|
|
580
|
+
const selectedKey = config.controlled ? config.selectedKey : config.items[this.state.selectedPage]?.key;
|
|
581
|
+
const fontOwnerKey = this.tabFontOwnerKey(weights);
|
|
582
|
+
for (const [key, button] of this.tabButtons) {
|
|
583
|
+
const fontSelected = key === fontOwnerKey;
|
|
584
|
+
button.style.color = this.tabColor(key === selectedKey, weights ? weights.get(key) ?? 0 : undefined);
|
|
585
|
+
button.style.fontWeight = config.style?.variant === "text" && fontSelected ? "600" : "500";
|
|
586
|
+
const fontFamily = (fontSelected ? config.style?.activeFontFamily ?? config.style?.fontFamily : config.style?.fontFamily) ?? "";
|
|
587
|
+
if (config.controlled && config.style?.variant === "text") {
|
|
588
|
+
button.style.fontFamily = config.style?.fontFamily ?? "";
|
|
589
|
+
const label = button.querySelector(".ok-pager-tab-label");
|
|
590
|
+
if (label) label.style.fontFamily = fontFamily;
|
|
591
|
+
} else button.style.fontFamily = fontFamily;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
468
594
|
pageScrollElement(index) {
|
|
469
595
|
const pageHost = this.pageHosts.get(index);
|
|
470
596
|
return pageHost?.querySelector("[data-collapsible-pager-scroll]") ?? pageHost?.querySelector(".ok-native-list-viewport") ?? pageHost;
|
|
@@ -479,7 +605,9 @@ export class CollapsiblePagerView extends React.PureComponent {
|
|
|
479
605
|
this.root?.removeEventListener("touchend", this.onOverlayTouchEnd);
|
|
480
606
|
this.root?.removeEventListener("touchcancel", this.onOverlayTouchEnd);
|
|
481
607
|
this.overlayTouch = null;
|
|
608
|
+
if (this.root) this.chromeObserver?.unobserve(this.root);
|
|
482
609
|
this.root = root;
|
|
610
|
+
if (root) this.chromeObserver?.observe(root);else this.suspendToolbar();
|
|
483
611
|
root?.addEventListener("ok-collapsible-pager-scroll-key-changed", this.onScrollOwnerIdentityChanged);
|
|
484
612
|
root?.addEventListener("wheel", this.onOverlayWheel, {
|
|
485
613
|
passive: false
|
|
@@ -749,11 +877,15 @@ export class CollapsiblePagerView extends React.PureComponent {
|
|
|
749
877
|
if (this.routeTarget && this.routeTarget.key !== expectedKey) this.setRouteTarget(null);
|
|
750
878
|
this.cancelPendingTopFrame();
|
|
751
879
|
this.savePageOffset(this.state.selectedPage);
|
|
752
|
-
if (animated) this.beginPageTransition();else
|
|
880
|
+
if (animated) this.beginPageTransition();else {
|
|
881
|
+
this.finishPageTransition();
|
|
882
|
+
this.tabProgress = position;
|
|
883
|
+
}
|
|
753
884
|
this.setState({
|
|
754
885
|
selectedPage: position,
|
|
755
886
|
animateTransition: animated
|
|
756
887
|
}, () => {
|
|
888
|
+
if (animated) this.startTabProgressFrames();
|
|
757
889
|
this.scheduleScrollConfiguration();
|
|
758
890
|
const restore = () => {
|
|
759
891
|
if (this.selectionRestoreToken !== selectionToken || this.state.selectedPage !== position || this.pages().map(pageKey)[position] !== expectedKey || !this.pageScrollElement(position)?.isConnected) return;
|
|
@@ -824,6 +956,7 @@ export class CollapsiblePagerView extends React.PureComponent {
|
|
|
824
956
|
this.cancelPendingTopFrame();
|
|
825
957
|
this.horizontalTouch = true;
|
|
826
958
|
this.emitPageScrollState("dragging");
|
|
959
|
+
this.suspendToolbar();
|
|
827
960
|
}
|
|
828
961
|
};
|
|
829
962
|
onTouchEnd = event => {
|
|
@@ -856,9 +989,387 @@ export class CollapsiblePagerView extends React.PureComponent {
|
|
|
856
989
|
this.horizontalTouch = false;
|
|
857
990
|
if (wasHorizontal) this.finishPageTransition();
|
|
858
991
|
};
|
|
992
|
+
toolbarSlot = null;
|
|
993
|
+
toolbarButton = null;
|
|
994
|
+
toolbarIconIdentity = "";
|
|
995
|
+
toolbarLoadedIcon = null;
|
|
996
|
+
toolbarPendingIdentity = "";
|
|
997
|
+
toolbarReadyIcon = null;
|
|
998
|
+
toolbarFailedIdentity = "";
|
|
999
|
+
toolbarAnimation = null;
|
|
1000
|
+
toolbarPresence = false;
|
|
1001
|
+
toolbarPresenceInterrupted = false;
|
|
1002
|
+
toolbarImage = null;
|
|
1003
|
+
toolbarGeneration = 0;
|
|
1004
|
+
ownsSettledToolbar() {
|
|
1005
|
+
return this.props.nativeTabBar?.controlled === true && this.props.nativeTabBar.toolbar !== undefined;
|
|
1006
|
+
}
|
|
1007
|
+
toolbarCanCommit() {
|
|
1008
|
+
if (!this.ownsSettledToolbar()) return true;
|
|
1009
|
+
if (this.disposed || this.props.isActive === false || this.horizontalTouch || this.transitionTimer !== null || this.pageScrollState !== "idle" || !this.root?.isConnected) return false;
|
|
1010
|
+
const actual = this.readTabProgress();
|
|
1011
|
+
if (actual === null || Math.abs(actual - this.state.selectedPage) > 0.001) return false;
|
|
1012
|
+
const config = this.props.nativeTabBar;
|
|
1013
|
+
const keys = [];
|
|
1014
|
+
React.Children.forEach(this.props.children, child => {
|
|
1015
|
+
if (child !== null && child !== undefined && typeof child !== "boolean") keys.push(pageKey(child, keys.length));
|
|
1016
|
+
});
|
|
1017
|
+
const itemKeys = config.items.map(item => item.key);
|
|
1018
|
+
const valid = keys.length > 0 && new Set(keys).size === keys.length && new Set(itemKeys).size === itemKeys.length && keys.every(key => itemKeys.includes(key));
|
|
1019
|
+
return !valid || !keys.includes(config.selectedKey ?? "") || keys[this.state.selectedPage] === config.selectedKey;
|
|
1020
|
+
}
|
|
1021
|
+
cancelToolbarPending() {
|
|
1022
|
+
if (this.toolbarPendingIdentity || this.toolbarImage || this.toolbarReadyIcon) this.toolbarGeneration += 1;
|
|
1023
|
+
if (this.toolbarImage) this.toolbarImage.onload = this.toolbarImage.onerror = null;
|
|
1024
|
+
this.toolbarImage = null;
|
|
1025
|
+
this.toolbarPendingIdentity = "";
|
|
1026
|
+
this.toolbarReadyIcon = null;
|
|
1027
|
+
}
|
|
1028
|
+
setToolbarInteractive(enabled) {
|
|
1029
|
+
const button = this.toolbarButton;
|
|
1030
|
+
if (!button) return;
|
|
1031
|
+
if (!enabled) {
|
|
1032
|
+
if (button.ownerDocument.activeElement === button) button.blur();
|
|
1033
|
+
if (this.toolbarTouchKey !== undefined) this.toolbarTouchKey = null;
|
|
1034
|
+
}
|
|
1035
|
+
button.disabled = !enabled;
|
|
1036
|
+
button.style.pointerEvents = enabled ? "auto" : "none";
|
|
1037
|
+
button.tabIndex = enabled ? 0 : -1;
|
|
1038
|
+
button.setAttribute("aria-hidden", String(!enabled));
|
|
1039
|
+
}
|
|
1040
|
+
suspendToolbar() {
|
|
1041
|
+
if (!this.ownsSettledToolbar()) return;
|
|
1042
|
+
this.setToolbarInteractive(false);
|
|
1043
|
+
this.cancelToolbarPending();
|
|
1044
|
+
if (this.toolbarAnimation && this.toolbarButton) {
|
|
1045
|
+
const opacity = this.toolbarButton.ownerDocument.defaultView?.getComputedStyle(this.toolbarButton).opacity;
|
|
1046
|
+
this.toolbarAnimation.cancel();
|
|
1047
|
+
this.toolbarAnimation = null;
|
|
1048
|
+
this.toolbarButton.style.opacity = opacity || this.toolbarButton.style.opacity;
|
|
1049
|
+
this.toolbarPresenceInterrupted = true;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
setToolbarSlot = slot => {
|
|
1053
|
+
if (this.toolbarSlot === slot) return;
|
|
1054
|
+
this.toolbarAnimation?.cancel();
|
|
1055
|
+
this.toolbarAnimation = null;
|
|
1056
|
+
this.cancelToolbarPending();
|
|
1057
|
+
this.toolbarGeneration += 1;
|
|
1058
|
+
this.toolbarButton?.remove();
|
|
1059
|
+
this.toolbarButton = null;
|
|
1060
|
+
this.toolbarOwnerKey = undefined;
|
|
1061
|
+
this.toolbarOwnerEntry = undefined;
|
|
1062
|
+
this.toolbarIconIdentity = "";
|
|
1063
|
+
this.toolbarLoadedIcon = null;
|
|
1064
|
+
this.toolbarFailedIdentity = "";
|
|
1065
|
+
this.toolbarPresence = false;
|
|
1066
|
+
this.toolbarPresenceInterrupted = false;
|
|
1067
|
+
this.toolbarTouchKey = null;
|
|
1068
|
+
this.toolbarSlot = slot;
|
|
1069
|
+
if (slot) this.syncToolbar();
|
|
1070
|
+
};
|
|
1071
|
+
animateToolbar(visible) {
|
|
1072
|
+
const button = this.toolbarButton;
|
|
1073
|
+
if (!button || this.toolbarPresence === visible && !this.toolbarPresenceInterrupted) return;
|
|
1074
|
+
this.toolbarPresenceInterrupted = false;
|
|
1075
|
+
this.toolbarPresence = visible;
|
|
1076
|
+
const current = button.ownerDocument.defaultView?.getComputedStyle(button).opacity ?? button.style.opacity;
|
|
1077
|
+
this.toolbarAnimation?.cancel();
|
|
1078
|
+
this.toolbarAnimation = null;
|
|
1079
|
+
button.style.opacity = visible ? "1" : "0";
|
|
1080
|
+
const finish = () => {
|
|
1081
|
+
button.hidden = !visible;
|
|
1082
|
+
if (!visible && !this.toolbarOwnerKey && this.toolbarButton === button) {
|
|
1083
|
+
button.remove();
|
|
1084
|
+
this.toolbarButton = null;
|
|
1085
|
+
}
|
|
1086
|
+
};
|
|
1087
|
+
if (typeof button.animate !== "function") {
|
|
1088
|
+
finish();
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
1091
|
+
button.hidden = false;
|
|
1092
|
+
const animation = button.animate([{
|
|
1093
|
+
opacity: current || "0"
|
|
1094
|
+
}, {
|
|
1095
|
+
opacity: visible ? "1" : "0"
|
|
1096
|
+
}], {
|
|
1097
|
+
duration: 100,
|
|
1098
|
+
fill: "forwards"
|
|
1099
|
+
});
|
|
1100
|
+
this.toolbarAnimation = animation;
|
|
1101
|
+
animation.onfinish = () => {
|
|
1102
|
+
if (this.toolbarAnimation !== animation || this.toolbarButton !== button || this.toolbarPresence !== visible) return;
|
|
1103
|
+
animation.cancel();
|
|
1104
|
+
this.toolbarAnimation = null;
|
|
1105
|
+
finish();
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
hideToolbar(failed) {
|
|
1109
|
+
this.setToolbarInteractive(false);
|
|
1110
|
+
this.toolbarOwnerKey = undefined;
|
|
1111
|
+
this.toolbarOwnerEntry = undefined;
|
|
1112
|
+
this.toolbarButton?.removeAttribute("data-testid");
|
|
1113
|
+
this.toolbarButton?.removeAttribute("aria-label");
|
|
1114
|
+
if (failed) this.toolbarButton?.replaceChildren();
|
|
1115
|
+
this.animateToolbar(false);
|
|
1116
|
+
}
|
|
1117
|
+
commitToolbar(key, entry, icon, identity) {
|
|
1118
|
+
const button = this.toolbarButton;
|
|
1119
|
+
if (!button || !this.toolbarCanCommit()) return;
|
|
1120
|
+
if (this.toolbarOwnerKey !== key && this.toolbarTouchKey !== undefined) this.toolbarTouchKey = null;
|
|
1121
|
+
const size = Math.min(128, Math.max(1, entry.size ?? 38));
|
|
1122
|
+
const iconSize = Math.min(size, Math.max(1, entry.iconSize ?? 24));
|
|
1123
|
+
const contentWidth = Math.min(size, Math.max(0, entry.contentWidth ?? 24));
|
|
1124
|
+
const trailingInset = Math.min(128, Math.max(0, entry.trailingInset ?? 20));
|
|
1125
|
+
if (button.firstChild !== icon) button.replaceChildren(icon);
|
|
1126
|
+
Object.assign(button.style, {
|
|
1127
|
+
position: "absolute",
|
|
1128
|
+
width: `${size}px`,
|
|
1129
|
+
height: `${size}px`,
|
|
1130
|
+
borderRadius: "50%",
|
|
1131
|
+
top: "50%",
|
|
1132
|
+
transform: "translateY(-50%)",
|
|
1133
|
+
insetInlineEnd: `${trailingInset - (size - contentWidth) / 2}px`,
|
|
1134
|
+
padding: `${(size - iconSize) / 2}px`,
|
|
1135
|
+
color: entry.iconColor ?? "#000000"
|
|
1136
|
+
});
|
|
1137
|
+
button.style.setProperty("--pager-toolbar-base", entry.selected ? entry.selectedBackgroundColor ?? "transparent" : "transparent");
|
|
1138
|
+
button.style.setProperty("--pager-toolbar-hover", entry.hoverBackgroundColor ?? "transparent");
|
|
1139
|
+
button.style.setProperty("--pager-toolbar-pressed", entry.pressedBackgroundColor ?? "transparent");
|
|
1140
|
+
button.setAttribute("aria-label", entry.accessibilityLabel ?? "");
|
|
1141
|
+
if (entry.testID) button.setAttribute("data-testid", entry.testID);else button.removeAttribute("data-testid");
|
|
1142
|
+
this.toolbarOwnerKey = key;
|
|
1143
|
+
this.toolbarOwnerEntry = {
|
|
1144
|
+
...entry
|
|
1145
|
+
};
|
|
1146
|
+
this.toolbarIconIdentity = identity;
|
|
1147
|
+
this.toolbarLoadedIcon = icon;
|
|
1148
|
+
this.toolbarPendingIdentity = "";
|
|
1149
|
+
this.toolbarReadyIcon = null;
|
|
1150
|
+
this.toolbarImage = null;
|
|
1151
|
+
this.animateToolbar(true);
|
|
1152
|
+
this.setToolbarInteractive(true);
|
|
1153
|
+
}
|
|
1154
|
+
syncToolbar() {
|
|
1155
|
+
const slot = this.toolbarSlot;
|
|
1156
|
+
if (!slot) return;
|
|
1157
|
+
if (!this.toolbarCanCommit()) {
|
|
1158
|
+
this.suspendToolbar();
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
const config = this.props.nativeTabBar;
|
|
1162
|
+
const key = config?.controlled ? config.selectedKey : config?.items[this.state.selectedPage]?.key;
|
|
1163
|
+
const entry = key ? config?.toolbar?.[key] : undefined;
|
|
1164
|
+
if (!entry?.iconName || !key) {
|
|
1165
|
+
this.cancelToolbarPending();
|
|
1166
|
+
this.hideToolbar(false);
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
let button = this.toolbarButton;
|
|
1170
|
+
if (!button) {
|
|
1171
|
+
button = slot.ownerDocument.createElement("button");
|
|
1172
|
+
button.type = "button";
|
|
1173
|
+
button.className = "ok-pager-toolbar";
|
|
1174
|
+
button.style.opacity = "0";
|
|
1175
|
+
button.hidden = true;
|
|
1176
|
+
button.disabled = true;
|
|
1177
|
+
button.addEventListener("pointerdown", () => {
|
|
1178
|
+
this.toolbarTouchKey = button.disabled ? null : this.toolbarOwnerKey ?? null;
|
|
1179
|
+
});
|
|
1180
|
+
button.addEventListener("pointercancel", () => {
|
|
1181
|
+
this.toolbarTouchKey = null;
|
|
1182
|
+
});
|
|
1183
|
+
button.onclick = event => {
|
|
1184
|
+
if (this.toolbarButton !== event.currentTarget) return;
|
|
1185
|
+
const pointer = event.detail !== 0;
|
|
1186
|
+
const touched = this.toolbarTouchKey;
|
|
1187
|
+
if (pointer) this.toolbarTouchKey = undefined;
|
|
1188
|
+
const current = this.props.nativeTabBar;
|
|
1189
|
+
const semantic = current?.controlled ? current.selectedKey : current?.items[this.state.selectedPage]?.key;
|
|
1190
|
+
const owner = this.toolbarOwnerKey;
|
|
1191
|
+
if (button.disabled || !this.toolbarCanCommit() || !owner || owner !== semantic || !this.toolbarOwnerEntry || pointer && touched !== owner) return;
|
|
1192
|
+
const rect = button.getBoundingClientRect();
|
|
1193
|
+
this.props.onNativeToolbarPress?.({
|
|
1194
|
+
nativeEvent: {
|
|
1195
|
+
key: owner,
|
|
1196
|
+
anchorRect: {
|
|
1197
|
+
x: rect.x,
|
|
1198
|
+
y: rect.y,
|
|
1199
|
+
width: rect.width,
|
|
1200
|
+
height: rect.height
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
});
|
|
1204
|
+
};
|
|
1205
|
+
slot.appendChild(button);
|
|
1206
|
+
this.toolbarButton = button;
|
|
1207
|
+
this.toolbarPresence = false;
|
|
1208
|
+
}
|
|
1209
|
+
const size = Math.min(128, Math.max(1, entry.size ?? 38));
|
|
1210
|
+
const iconSize = Math.min(size, Math.max(1, entry.iconSize ?? 24));
|
|
1211
|
+
const identity = `${entry.iconName}|${entry.iconColor ?? "#000000"}|${iconSize}`;
|
|
1212
|
+
if (identity === this.toolbarIconIdentity && this.toolbarLoadedIcon) {
|
|
1213
|
+
this.cancelToolbarPending();
|
|
1214
|
+
this.commitToolbar(key, entry, this.toolbarLoadedIcon, identity);
|
|
1215
|
+
return;
|
|
1216
|
+
}
|
|
1217
|
+
if (identity === this.toolbarPendingIdentity) {
|
|
1218
|
+
if (this.toolbarReadyIcon) this.commitToolbar(key, entry, this.toolbarReadyIcon, identity);
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
this.cancelToolbarPending();
|
|
1222
|
+
this.setToolbarInteractive(false);
|
|
1223
|
+
this.toolbarPendingIdentity = identity;
|
|
1224
|
+
if (identity === this.toolbarFailedIdentity) {
|
|
1225
|
+
this.hideToolbar(true);
|
|
1226
|
+
return;
|
|
1227
|
+
}
|
|
1228
|
+
const generation = ++this.toolbarGeneration;
|
|
1229
|
+
const icon = createNamedIcon(button.ownerDocument, entry.iconName);
|
|
1230
|
+
icon.setAttribute("width", String(iconSize));
|
|
1231
|
+
icon.setAttribute("height", String(iconSize));
|
|
1232
|
+
const use = icon.querySelector("use");
|
|
1233
|
+
const fail = () => {
|
|
1234
|
+
if (this.toolbarGeneration !== generation || this.toolbarPendingIdentity !== identity) return;
|
|
1235
|
+
this.toolbarImage = null;
|
|
1236
|
+
this.toolbarFailedIdentity = identity;
|
|
1237
|
+
this.hideToolbar(true);
|
|
1238
|
+
};
|
|
1239
|
+
if (!use) {
|
|
1240
|
+
fail();
|
|
1241
|
+
return;
|
|
1242
|
+
}
|
|
1243
|
+
const ready = () => {
|
|
1244
|
+
if (this.disposed || this.toolbarGeneration !== generation || this.toolbarPendingIdentity !== identity) return;
|
|
1245
|
+
this.toolbarImage = null;
|
|
1246
|
+
this.toolbarReadyIcon = icon;
|
|
1247
|
+
this.syncToolbar();
|
|
1248
|
+
};
|
|
1249
|
+
const href = use.getAttribute("href") ?? use.getAttribute("xlink:href") ?? "";
|
|
1250
|
+
const view = button.ownerDocument.defaultView;
|
|
1251
|
+
if (view?.Image && href.split("#")[0]) {
|
|
1252
|
+
const image = new view.Image();
|
|
1253
|
+
this.toolbarImage = image;
|
|
1254
|
+
image.onload = ready;
|
|
1255
|
+
image.onerror = fail;
|
|
1256
|
+
image.src = href.split("#")[0];
|
|
1257
|
+
} else ready();
|
|
1258
|
+
}
|
|
1259
|
+
renderNativeTabBar() {
|
|
1260
|
+
const config = this.props.nativeTabBar;
|
|
1261
|
+
if (!config?.items.length || config.style?.variant !== "text" && config.controlled !== true && config.toolbar === undefined) return null;
|
|
1262
|
+
const style = config.style;
|
|
1263
|
+
const variant = style?.variant ?? "underline";
|
|
1264
|
+
const selectedKey = config.controlled ? config.selectedKey : config.items[this.state.selectedPage]?.key;
|
|
1265
|
+
const toolbarEntries = config.toolbar === undefined ? undefined : Object.values(config.toolbar);
|
|
1266
|
+
const reservedWidth = toolbarEntries === undefined ? 0 : toolbarEntries.length === 0 ? 44 : Math.max(...toolbarEntries.map(entry => {
|
|
1267
|
+
const size = Math.min(128, Math.max(1, entry.size ?? 38));
|
|
1268
|
+
return Math.min(size, Math.max(0, entry.contentWidth ?? 24)) + Math.min(128, Math.max(0, entry.trailingInset ?? 20));
|
|
1269
|
+
}));
|
|
1270
|
+
const segmented = variant === "segmented";
|
|
1271
|
+
const reserveTextFaces = config.controlled && variant === "text";
|
|
1272
|
+
const colorWeights = this.tabColorWeights();
|
|
1273
|
+
const fontOwnerKey = this.tabFontOwnerKey(colorWeights);
|
|
1274
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
1275
|
+
className: "ok-pager-tab-bar",
|
|
1276
|
+
dir: this.props.layoutDirection === "rtl" || (this.props.layoutDirection ?? "locale") === "locale" && I18nManager.isRTL ? "rtl" : "ltr",
|
|
1277
|
+
style: {
|
|
1278
|
+
display: "flex",
|
|
1279
|
+
alignItems: "center",
|
|
1280
|
+
position: "relative",
|
|
1281
|
+
height: style?.height ?? 44,
|
|
1282
|
+
backgroundColor: String(style?.backgroundColor ?? "transparent"),
|
|
1283
|
+
minWidth: 0
|
|
1284
|
+
}
|
|
1285
|
+
}, /*#__PURE__*/React.createElement("style", null, `.ok-pager-tab{box-sizing:border-box;appearance:none;border:0;background:transparent;cursor:default;white-space:nowrap;flex-shrink:0;line-height:normal}.ok-pager-toolbar{box-sizing:border-box;appearance:none;border:1px solid transparent;cursor:default;display:flex;align-items:center;justify-content:center;background:var(--pager-toolbar-base)}.ok-pager-toolbar:hover:enabled{background:var(--pager-toolbar-hover)}.ok-pager-toolbar:active:enabled{background:var(--pager-toolbar-pressed)}`), /*#__PURE__*/React.createElement("div", {
|
|
1286
|
+
role: "tablist",
|
|
1287
|
+
style: {
|
|
1288
|
+
display: "flex",
|
|
1289
|
+
overflowX: segmented ? "hidden" : "auto",
|
|
1290
|
+
flex: 1,
|
|
1291
|
+
padding: `${style?.contentPaddingVertical ?? 0}px ${style?.contentPaddingHorizontal ?? 20}px`,
|
|
1292
|
+
gap: style?.itemSpacing ?? 8
|
|
1293
|
+
}
|
|
1294
|
+
}, ...config.items.map((item, position) => {
|
|
1295
|
+
const selected = item.key === selectedKey;
|
|
1296
|
+
const fontSelected = item.key === fontOwnerKey;
|
|
1297
|
+
return /*#__PURE__*/React.createElement("button", {
|
|
1298
|
+
key: item.key,
|
|
1299
|
+
role: "tab",
|
|
1300
|
+
type: "button",
|
|
1301
|
+
className: "ok-pager-tab",
|
|
1302
|
+
"aria-selected": selected,
|
|
1303
|
+
ref: button => {
|
|
1304
|
+
if (button) this.tabButtons.set(item.key, button);else this.tabButtons.delete(item.key);
|
|
1305
|
+
},
|
|
1306
|
+
"aria-label": item.accessibilityLabel ?? item.title,
|
|
1307
|
+
"data-testid": item.testID,
|
|
1308
|
+
style: {
|
|
1309
|
+
padding: variant === "text" ? "6px 10px" : "6px 8px",
|
|
1310
|
+
minWidth: 44,
|
|
1311
|
+
height: (style?.height ?? 44) - 2 * (style?.contentPaddingVertical ?? 0),
|
|
1312
|
+
fontSize: style?.fontSize ?? (variant === "text" ? 18 : 16),
|
|
1313
|
+
fontWeight: variant === "text" && fontSelected ? 600 : 500,
|
|
1314
|
+
fontFamily: reserveTextFaces ? style?.fontFamily : fontSelected ? style?.activeFontFamily ?? style?.fontFamily : style?.fontFamily,
|
|
1315
|
+
display: reserveTextFaces ? "inline-grid" : undefined,
|
|
1316
|
+
gridTemplateAreas: reserveTextFaces ? '"label"' : undefined,
|
|
1317
|
+
alignItems: reserveTextFaces ? "center" : undefined,
|
|
1318
|
+
color: this.tabColor(selected, colorWeights ? colorWeights.get(item.key) ?? 0 : undefined),
|
|
1319
|
+
flex: segmented ? 1 : undefined,
|
|
1320
|
+
borderRadius: segmented ? 999 : 0,
|
|
1321
|
+
backgroundColor: segmented && selected ? String(style?.indicatorColor ?? "transparent") : "transparent",
|
|
1322
|
+
borderBottom: variant === "underline" && selected ? `${style?.indicatorHeight ?? 2}px solid ${String(style?.indicatorColor ?? "#000000")}` : undefined
|
|
1323
|
+
},
|
|
1324
|
+
onClick: () => {
|
|
1325
|
+
if (!config.controlled) {
|
|
1326
|
+
const animated = this.props.nativeTabPressAnimationEnabled ?? Math.abs(position - this.state.selectedPage) <= 1;
|
|
1327
|
+
if (animated) this.setPage(position);else this.setPageWithoutAnimation(position);
|
|
1328
|
+
}
|
|
1329
|
+
this.props.onNativeTabPress?.({
|
|
1330
|
+
nativeEvent: {
|
|
1331
|
+
position,
|
|
1332
|
+
key: item.key
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
}
|
|
1336
|
+
}, reserveTextFaces ? [/*#__PURE__*/React.createElement("span", {
|
|
1337
|
+
key: "label",
|
|
1338
|
+
className: "ok-pager-tab-label",
|
|
1339
|
+
style: {
|
|
1340
|
+
gridArea: "label",
|
|
1341
|
+
fontFamily: fontSelected ? style?.activeFontFamily ?? style?.fontFamily : style?.fontFamily
|
|
1342
|
+
}
|
|
1343
|
+
}, item.title), ...[false, true].map(active => /*#__PURE__*/React.createElement("span", {
|
|
1344
|
+
key: active ? "active-width" : "normal-width",
|
|
1345
|
+
"aria-hidden": true,
|
|
1346
|
+
style: {
|
|
1347
|
+
gridArea: "label",
|
|
1348
|
+
visibility: "hidden",
|
|
1349
|
+
pointerEvents: "none",
|
|
1350
|
+
userSelect: "none",
|
|
1351
|
+
fontWeight: active ? 600 : 500,
|
|
1352
|
+
fontFamily: active ? style?.activeFontFamily ?? style?.fontFamily : style?.fontFamily
|
|
1353
|
+
}
|
|
1354
|
+
}, item.title))] : item.title);
|
|
1355
|
+
})), config.toolbar !== undefined ? /*#__PURE__*/React.createElement("div", {
|
|
1356
|
+
ref: this.setToolbarSlot,
|
|
1357
|
+
className: "ok-pager-toolbar-slot",
|
|
1358
|
+
style: {
|
|
1359
|
+
flexShrink: 0,
|
|
1360
|
+
width: reservedWidth,
|
|
1361
|
+
height: "100%",
|
|
1362
|
+
position: "relative"
|
|
1363
|
+
}
|
|
1364
|
+
}) : null);
|
|
1365
|
+
}
|
|
859
1366
|
render() {
|
|
860
1367
|
const {
|
|
861
1368
|
children: _children,
|
|
1369
|
+
nativeTabBar: _nativeTabBar,
|
|
1370
|
+
nativeTabPressAnimationEnabled: _nativeTabPressAnimationEnabled,
|
|
1371
|
+
onNativeTabPress: _onNativeTabPress,
|
|
1372
|
+
onNativeToolbarPress: _onNativeToolbarPress,
|
|
862
1373
|
header,
|
|
863
1374
|
stickyHeader,
|
|
864
1375
|
topOverlay: _topOverlay,
|
|
@@ -927,9 +1438,11 @@ export class CollapsiblePagerView extends React.PureComponent {
|
|
|
927
1438
|
top: this.headerHeight,
|
|
928
1439
|
height: this.stickyHeaderHeight
|
|
929
1440
|
}, collapseAnimation],
|
|
930
|
-
children: this.hasExplicitStickyHeaderHeight ?
|
|
1441
|
+
children: this.hasExplicitStickyHeaderHeight ? /*#__PURE__*/_jsxs(_Fragment, {
|
|
1442
|
+
children: [this.renderNativeTabBar(), stickyHeader]
|
|
1443
|
+
}) : /*#__PURE__*/_jsxs(View, {
|
|
931
1444
|
ref: this.setStickyContent,
|
|
932
|
-
children: stickyHeader
|
|
1445
|
+
children: [this.renderNativeTabBar(), stickyHeader]
|
|
933
1446
|
})
|
|
934
1447
|
}), /*#__PURE__*/_jsx(View, {
|
|
935
1448
|
ref: this.setTrack,
|
|
@@ -38,6 +38,10 @@ export type OnNativeTabPressEventData = Readonly<{
|
|
|
38
38
|
position: CodegenTypes.Int32;
|
|
39
39
|
key: string;
|
|
40
40
|
}>;
|
|
41
|
+
export type OnNativeToolbarPressEventData = Readonly<{
|
|
42
|
+
key: string;
|
|
43
|
+
anchorRect: Readonly<{ x: CodegenTypes.Double; y: CodegenTypes.Double; width: CodegenTypes.Double; height: CodegenTypes.Double }>;
|
|
44
|
+
}>;
|
|
41
45
|
export type OnScrollEdgeCapabilityEventData = Readonly<{ available: boolean }>;
|
|
42
46
|
|
|
43
47
|
/**
|
|
@@ -60,6 +64,7 @@ export interface NativeProps extends ViewProps {
|
|
|
60
64
|
externalTopOverlayTag?: CodegenTypes.WithDefault<CodegenTypes.Int32, 0>;
|
|
61
65
|
pageKeys?: string;
|
|
62
66
|
retainedPages?: string;
|
|
67
|
+
nativeTabBarConfig?: string;
|
|
63
68
|
nativeTabBarItems?: string;
|
|
64
69
|
nativeTabBarHeight?: CodegenTypes.Double;
|
|
65
70
|
nativeTabBarVariant?: string;
|
|
@@ -81,6 +86,7 @@ export interface NativeProps extends ViewProps {
|
|
|
81
86
|
onPageSelected?: CodegenTypes.DirectEventHandler<OnPageSelectedEventData>;
|
|
82
87
|
onPageScrollStateChanged?: CodegenTypes.DirectEventHandler<OnPageScrollStateChangedEventData>;
|
|
83
88
|
onCollapsibleStateChanged?: CodegenTypes.DirectEventHandler<OnCollapsibleStateChangedEventData>;
|
|
89
|
+
onNativeToolbarPress?: CodegenTypes.DirectEventHandler<OnNativeToolbarPressEventData>;
|
|
84
90
|
onNativeTabPress?: CodegenTypes.DirectEventHandler<OnNativeTabPressEventData>;
|
|
85
91
|
onNativeSubHeaderPress?: CodegenTypes.DirectEventHandler<OnNativeTabPressEventData>;
|
|
86
92
|
onScrollEdgeCapability?: CodegenTypes.DirectEventHandler<OnScrollEdgeCapabilityEventData>;
|