@hero-design/rn 8.130.2 → 8.131.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/CHANGELOG.md +12 -0
- package/es/index.js +407 -225
- package/lib/index.js +407 -225
- package/package.json +1 -1
- package/src/components/Tabs/ScrollableTabsHeader/ScrollableTabsHeader.tsx +217 -131
- package/src/components/Tabs/ScrollableTabsHeader/hooks/useIndicatorAnimation.ts +242 -0
- package/src/components/Tabs/StyledScrollableTabs.tsx +68 -21
- package/src/components/Tabs/index.tsx +2 -0
- package/src/theme/components/tabs.ts +9 -2
- package/src/theme/global/colors/ehJobs.ts +1 -0
- package/src/theme/global/colors/ehWork.ts +1 -1
- package/types/components/Checkbox/StyledInlineCheckBox.d.ts +1 -1
- package/types/components/Tabs/ScrollableTabsHeader/ScrollableTabsHeader.d.ts +1 -1
- package/types/components/Tabs/ScrollableTabsHeader/hooks/useIndicatorAnimation.d.ts +75 -0
- package/types/components/Tabs/StyledScrollableTabs.d.ts +13 -8
- package/types/components/Tabs/index.d.ts +3 -1
- package/types/theme/components/tabs.d.ts +9 -2
- package/src/components/Tabs/ScrollableTabsHeader/hooks/useInitHighlightedAnimation.ts +0 -45
- package/types/components/Tabs/ScrollableTabsHeader/hooks/useInitHighlightedAnimation.d.ts +0 -9
package/es/index.js
CHANGED
|
@@ -4977,7 +4977,7 @@ var swagLightGlobalPalette = _objectSpread2(_objectSpread2({}, globalPalette$1),
|
|
|
4977
4977
|
});
|
|
4978
4978
|
|
|
4979
4979
|
var ehWorkBrandSystemPalette = {
|
|
4980
|
-
primary: '#
|
|
4980
|
+
primary: '#7622d7',
|
|
4981
4981
|
onPrimary: '#fdfbff',
|
|
4982
4982
|
secondary: '#b382fd',
|
|
4983
4983
|
onSecondary: palette$4.white,
|
|
@@ -5006,6 +5006,7 @@ var swagSystemPalette = _objectSpread2(_objectSpread2({}, ehWorkSystemPalette),
|
|
|
5006
5006
|
|
|
5007
5007
|
var ehJobsSystemPalette = _objectSpread2(_objectSpread2({}, swagSystemPalette), {}, {
|
|
5008
5008
|
name: 'ehJobs',
|
|
5009
|
+
primary: '#7622d7',
|
|
5009
5010
|
secondary: '#40d1ff',
|
|
5010
5011
|
onSecondary: '#460078',
|
|
5011
5012
|
secondaryHighlightedSurface: '#ecfaff',
|
|
@@ -7136,7 +7137,11 @@ var getTabsTheme = function getTabsTheme(theme) {
|
|
|
7136
7137
|
headerBottom: theme.colors.secondaryOutline,
|
|
7137
7138
|
indicator: theme.colors.primary,
|
|
7138
7139
|
text: theme.colors.onDefaultGlobalSurface,
|
|
7139
|
-
headerBackground: theme.colors.defaultGlobalSurface
|
|
7140
|
+
headerBackground: theme.colors.defaultGlobalSurface,
|
|
7141
|
+
highlightedActiveText: theme.colors.primary,
|
|
7142
|
+
highlightedActiveBorder: theme.colors.primary,
|
|
7143
|
+
highlightedActiveBackground: theme.colors.neutralGlobalSurface,
|
|
7144
|
+
highlightedDisabledText: theme.colors.disabledOnDefaultGlobalSurface
|
|
7140
7145
|
};
|
|
7141
7146
|
var space = {
|
|
7142
7147
|
flatListHorizontalPadding: theme.space.small,
|
|
@@ -7144,14 +7149,17 @@ var getTabsTheme = function getTabsTheme(theme) {
|
|
|
7144
7149
|
itemVerticalPadding: theme.space.small,
|
|
7145
7150
|
itemMargin: theme.space.smallMedium,
|
|
7146
7151
|
outlineHorizontalPadding: theme.space.small,
|
|
7147
|
-
|
|
7148
|
-
|
|
7152
|
+
tabIndicatorBottom: -theme.space.xxsmall,
|
|
7153
|
+
highlightedItemMargin: theme.space.xsmall,
|
|
7154
|
+
highlightedBarTopPadding: theme.space.xxsmall
|
|
7149
7155
|
};
|
|
7150
7156
|
var radii = {
|
|
7151
|
-
|
|
7157
|
+
highlightedOutline: theme.radii.medium
|
|
7152
7158
|
};
|
|
7153
7159
|
var borderWidths = {
|
|
7154
|
-
headerBottom: theme.borderWidths.medium
|
|
7160
|
+
headerBottom: theme.borderWidths.medium,
|
|
7161
|
+
highlightedHeaderBottom: theme.borderWidths.base,
|
|
7162
|
+
highlightedActiveBorder: theme.borderWidths.base
|
|
7155
7163
|
};
|
|
7156
7164
|
var sizes = {
|
|
7157
7165
|
indicator: theme.sizes.xxsmall
|
|
@@ -28110,43 +28118,85 @@ var HeaderTabWrapper = index$c(View)(function (_ref) {
|
|
|
28110
28118
|
backgroundColor: theme.__hd__.tabs.colors.headerBackground
|
|
28111
28119
|
};
|
|
28112
28120
|
});
|
|
28121
|
+
var getItemMarginLeft = function getItemMarginLeft(isFirstItem, themeVariant, highlightedMargin, defaultMargin) {
|
|
28122
|
+
if (isFirstItem) return 0;
|
|
28123
|
+
if (themeVariant === 'highlighted') return highlightedMargin;
|
|
28124
|
+
return defaultMargin;
|
|
28125
|
+
};
|
|
28113
28126
|
var HeaderTabItem = index$c(Animated.View)(function (_ref2) {
|
|
28114
28127
|
var theme = _ref2.theme,
|
|
28115
|
-
isFirstItem = _ref2.isFirstItem
|
|
28128
|
+
isFirstItem = _ref2.isFirstItem,
|
|
28129
|
+
themeVariant = _ref2.themeVariant;
|
|
28116
28130
|
return {
|
|
28117
|
-
marginLeft: isFirstItem
|
|
28118
|
-
paddingVertical: theme.__hd__.tabs.space.itemVerticalPadding
|
|
28131
|
+
marginLeft: getItemMarginLeft(isFirstItem, themeVariant, theme.__hd__.tabs.space.highlightedItemMargin, theme.__hd__.tabs.space.itemMargin),
|
|
28132
|
+
paddingVertical: theme.__hd__.tabs.space.itemVerticalPadding,
|
|
28133
|
+
alignItems: 'center',
|
|
28134
|
+
justifyContent: 'center'
|
|
28119
28135
|
};
|
|
28120
28136
|
});
|
|
28121
|
-
|
|
28137
|
+
// Three-piece pill: left cap + body + right cap, all native-driver animated.
|
|
28138
|
+
// Splitting into pieces keeps border-radius on fixed-width views so scaleX
|
|
28139
|
+
// never distorts the rounded corners. Cap width equals the border-radius so
|
|
28140
|
+
// the rounded edge is fully contained within the cap piece.
|
|
28141
|
+
var HeaderTabPillLeft = index$c(Animated.View)(function (_ref3) {
|
|
28122
28142
|
var theme = _ref3.theme;
|
|
28123
|
-
return
|
|
28124
|
-
|
|
28125
|
-
|
|
28143
|
+
return {
|
|
28144
|
+
position: 'absolute',
|
|
28145
|
+
top: 0,
|
|
28146
|
+
bottom: 0,
|
|
28147
|
+
left: 0,
|
|
28148
|
+
width: theme.__hd__.tabs.radii.highlightedOutline,
|
|
28149
|
+
borderTopLeftRadius: theme.__hd__.tabs.radii.highlightedOutline,
|
|
28150
|
+
backgroundColor: theme.__hd__.tabs.colors.highlightedActiveBackground
|
|
28151
|
+
};
|
|
28126
28152
|
});
|
|
28127
|
-
var
|
|
28128
|
-
var theme = _ref4.theme
|
|
28129
|
-
themeActive = _ref4.themeActive;
|
|
28153
|
+
var HeaderTabPillBody = index$c(Animated.View)(function (_ref4) {
|
|
28154
|
+
var theme = _ref4.theme;
|
|
28130
28155
|
return {
|
|
28131
|
-
|
|
28132
|
-
|
|
28156
|
+
position: 'absolute',
|
|
28157
|
+
top: 0,
|
|
28158
|
+
bottom: 0,
|
|
28159
|
+
left: 0,
|
|
28160
|
+
width: 1,
|
|
28161
|
+
backgroundColor: theme.__hd__.tabs.colors.highlightedActiveBackground
|
|
28133
28162
|
};
|
|
28134
28163
|
});
|
|
28135
|
-
var
|
|
28164
|
+
var HeaderTabPillRight = index$c(Animated.View)(function (_ref5) {
|
|
28136
28165
|
var theme = _ref5.theme;
|
|
28166
|
+
return {
|
|
28167
|
+
position: 'absolute',
|
|
28168
|
+
top: 0,
|
|
28169
|
+
bottom: 0,
|
|
28170
|
+
left: 0,
|
|
28171
|
+
width: theme.__hd__.tabs.radii.highlightedOutline,
|
|
28172
|
+
borderTopRightRadius: theme.__hd__.tabs.radii.highlightedOutline,
|
|
28173
|
+
backgroundColor: theme.__hd__.tabs.colors.highlightedActiveBackground
|
|
28174
|
+
};
|
|
28175
|
+
});
|
|
28176
|
+
var HeaderTabItemActiveBorder = index$c(Animated.View)(function (_ref6) {
|
|
28177
|
+
var theme = _ref6.theme;
|
|
28178
|
+
return {
|
|
28179
|
+
position: 'absolute',
|
|
28180
|
+
bottom: 0,
|
|
28181
|
+
width: 1,
|
|
28182
|
+
height: theme.__hd__.tabs.borderWidths.highlightedActiveBorder,
|
|
28183
|
+
backgroundColor: theme.__hd__.tabs.colors.highlightedActiveBorder
|
|
28184
|
+
};
|
|
28185
|
+
});
|
|
28186
|
+
var HeaderTabItemWrapper = index$c(View)(function (_ref7) {
|
|
28187
|
+
var theme = _ref7.theme;
|
|
28137
28188
|
return _objectSpread2({
|
|
28138
28189
|
paddingHorizontal: theme.__hd__.tabs.space.outlineHorizontalPadding,
|
|
28139
|
-
paddingVertical: theme.__hd__.tabs.space.outlineVerticalPadding,
|
|
28140
28190
|
position: 'relative',
|
|
28141
28191
|
justifyContent: 'center'
|
|
28142
28192
|
}, !isAndroid8 && {
|
|
28143
28193
|
alignItems: 'center'
|
|
28144
28194
|
});
|
|
28145
28195
|
});
|
|
28146
|
-
var HeaderTabItemIndicator = index$c(Animated.View)(function (
|
|
28147
|
-
var theme =
|
|
28196
|
+
var HeaderTabItemIndicator = index$c(Animated.View)(function (_ref8) {
|
|
28197
|
+
var theme = _ref8.theme;
|
|
28148
28198
|
return {
|
|
28149
|
-
width:
|
|
28199
|
+
width: 1,
|
|
28150
28200
|
height: theme.__hd__.tabs.sizes.indicator,
|
|
28151
28201
|
position: 'absolute',
|
|
28152
28202
|
bottom: theme.__hd__.tabs.space.tabIndicatorBottom,
|
|
@@ -28227,109 +28277,204 @@ var TabWithBadge = function TabWithBadge(_ref) {
|
|
|
28227
28277
|
return /*#__PURE__*/React__default.createElement(View, null, tabItem);
|
|
28228
28278
|
};
|
|
28229
28279
|
|
|
28230
|
-
|
|
28231
|
-
|
|
28232
|
-
|
|
28233
|
-
|
|
28234
|
-
|
|
28235
|
-
|
|
28236
|
-
|
|
28237
|
-
|
|
28238
|
-
|
|
28239
|
-
|
|
28240
|
-
|
|
28241
|
-
|
|
28242
|
-
|
|
28280
|
+
/**
|
|
28281
|
+
* Drives two visual layers that slide to the selected tab on every press:
|
|
28282
|
+
*
|
|
28283
|
+
* Layer 1 — bottom border / underline (indicatorStyle)
|
|
28284
|
+
* ─────────────────────────────────────────────────────
|
|
28285
|
+
* Uses the "width:1 + scaleX" trick: the element has a fixed stylesheet
|
|
28286
|
+
* width of 1px and scaleX is set to the target pixel width, giving a visual
|
|
28287
|
+
* width of 1 × scaleX pixels without touching any layout property.
|
|
28288
|
+
* Both translateX and scaleX are transform properties → native driver.
|
|
28289
|
+
* Caveat: scaleX also scales border-radius, so this layer has no border-radius.
|
|
28290
|
+
*
|
|
28291
|
+
* Layer 2 — pill background (pillLeftStyle / pillBodyStyle / pillRightStyle)
|
|
28292
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
28293
|
+
* The pill is split into three absolutely-positioned children so that
|
|
28294
|
+
* border-radius is never distorted by scale:
|
|
28295
|
+
*
|
|
28296
|
+
* ┌──────────────────────────────────────────────────────┐
|
|
28297
|
+
* │ [cap-left 8px] [body width-1 + scaleX] [cap-right 8px] │
|
|
28298
|
+
* └──────────────────────────────────────────────────────┘
|
|
28299
|
+
*
|
|
28300
|
+
* cap-left — fixed 8px wide, borderTopLeftRadius:8, translateX = pillX
|
|
28301
|
+
* body — width:1 + scaleX trick (scaleX = tabWidth - 16),
|
|
28302
|
+
* transformOrigin 'left center',
|
|
28303
|
+
* translateX = pillX + 8 (via Animated.add)
|
|
28304
|
+
* cap-right — fixed 8px wide, borderTopRightRadius:8,
|
|
28305
|
+
* translateX = pillX + tabWidth - 8 (via Animated.add)
|
|
28306
|
+
*
|
|
28307
|
+
* All four animated values use the native driver (translateX and scaleX are
|
|
28308
|
+
* transform properties). `width` is never animated, so no JS driver needed.
|
|
28309
|
+
*
|
|
28310
|
+
* Driver summary:
|
|
28311
|
+
* indicatorX native translateX — slides the bottom border
|
|
28312
|
+
* indicatorScaleX native scaleX — stretches the bottom border
|
|
28313
|
+
* pillX native translateX — slides all three pill pieces
|
|
28314
|
+
* pillBodyScaleX native scaleX — stretches the pill body
|
|
28315
|
+
* pillRightOffsetX native translateX — positions the right cap
|
|
28316
|
+
* (Animated.add: pillX + tabWidth - 8)
|
|
28317
|
+
*/
|
|
28318
|
+
var useIndicatorAnimation = function useIndicatorAnimation(_ref) {
|
|
28319
|
+
var selectedIndex = _ref.selectedIndex,
|
|
28243
28320
|
tabsLength = _ref.tabsLength,
|
|
28244
|
-
|
|
28245
|
-
|
|
28246
|
-
|
|
28247
|
-
|
|
28248
|
-
|
|
28249
|
-
|
|
28321
|
+
pillCapWidth = _ref.pillCapWidth;
|
|
28322
|
+
// Layer 1 — native driver (bottom border / underline).
|
|
28323
|
+
var indicatorX = React__default.useRef(new Animated.Value(0)).current;
|
|
28324
|
+
var indicatorScaleX = React__default.useRef(new Animated.Value(1)).current;
|
|
28325
|
+
// Layer 2 — native driver (pill background, three-piece split).
|
|
28326
|
+
// pillX: left edge of the pill (shared by all three pieces as base).
|
|
28327
|
+
// pillBodyScaleX: scaleX for the body piece (tabWidth - 2 * CAP_WIDTH).
|
|
28328
|
+
// pillRightOffset: additional x offset for the right cap (tabWidth - CAP_WIDTH).
|
|
28329
|
+
var pillX = React__default.useRef(new Animated.Value(0)).current;
|
|
28330
|
+
var pillBodyScaleX = React__default.useRef(new Animated.Value(1)).current;
|
|
28331
|
+
var pillRightOffset = React__default.useRef(new Animated.Value(0)).current;
|
|
28332
|
+
// Stable ref so callbacks don't capture stale closures.
|
|
28333
|
+
var layoutsRef = React__default.useRef([]);
|
|
28334
|
+
var runningAnimRef = React__default.useRef(null);
|
|
28335
|
+
var pendingIndexRef = React__default.useRef(undefined);
|
|
28336
|
+
var initializedRef = React__default.useRef(false);
|
|
28337
|
+
// Resize layout cache when tabsLength changes.
|
|
28250
28338
|
React__default.useEffect(function () {
|
|
28251
|
-
|
|
28252
|
-
return;
|
|
28253
|
-
}
|
|
28254
|
-
var animation = Animated.parallel(_toConsumableArray(Array.from({
|
|
28339
|
+
layoutsRef.current = Array.from({
|
|
28255
28340
|
length: tabsLength
|
|
28256
|
-
}
|
|
28257
|
-
return
|
|
28258
|
-
toValue: i === selectedIndex ? 1 : 0,
|
|
28259
|
-
duration: 150,
|
|
28260
|
-
useNativeDriver: Platform.OS !== 'web'
|
|
28261
|
-
});
|
|
28262
|
-
})));
|
|
28263
|
-
animation.start();
|
|
28264
|
-
return function () {
|
|
28265
|
-
animation.stop();
|
|
28266
|
-
};
|
|
28267
|
-
}, [selectedIndex]);
|
|
28268
|
-
return {
|
|
28269
|
-
tabsAnims: tabsAnims
|
|
28270
|
-
};
|
|
28271
|
-
};
|
|
28272
|
-
|
|
28273
|
-
var TRANSLATE_DISTANCE = 30;
|
|
28274
|
-
var animateOpacity = function animateOpacity(animatedValue, toValue) {
|
|
28275
|
-
return Animated.timing(animatedValue, {
|
|
28276
|
-
toValue: toValue,
|
|
28277
|
-
duration: 150,
|
|
28278
|
-
easing: Easing.ease,
|
|
28279
|
-
useNativeDriver: Platform.OS !== 'web'
|
|
28280
|
-
});
|
|
28281
|
-
};
|
|
28282
|
-
var animateTranslateX = function animateTranslateX(animatedValue, toValue) {
|
|
28283
|
-
return Animated.spring(animatedValue, {
|
|
28284
|
-
toValue: toValue,
|
|
28285
|
-
useNativeDriver: Platform.OS !== 'web'
|
|
28286
|
-
});
|
|
28287
|
-
};
|
|
28288
|
-
var useInitUnderlinedAnimation = function useInitUnderlinedAnimation(_ref) {
|
|
28289
|
-
var tabsLength = _ref.tabsLength,
|
|
28290
|
-
_ref$selectedIndex = _ref.selectedIndex,
|
|
28291
|
-
selectedIndex = _ref$selectedIndex === void 0 ? 0 : _ref$selectedIndex,
|
|
28292
|
-
variant = _ref.variant;
|
|
28293
|
-
var previousIndex = React__default.useRef(0);
|
|
28294
|
-
var translateXAnims = useAnimatedValueArray(Array.from({
|
|
28295
|
-
length: tabsLength
|
|
28296
|
-
}).map(function () {
|
|
28297
|
-
return 0;
|
|
28298
|
-
}));
|
|
28299
|
-
var opacityAnims = useAnimatedValueArray(Array.from({
|
|
28300
|
-
length: tabsLength
|
|
28301
|
-
}).map(function (_, i) {
|
|
28302
|
-
return selectedIndex !== undefined && selectedIndex === i ? 1 : 0;
|
|
28303
|
-
}));
|
|
28304
|
-
var underlinedTranslateX = translateXAnims.map(function (anim) {
|
|
28305
|
-
return anim.interpolate({
|
|
28306
|
-
inputRange: [-1, 0, 1],
|
|
28307
|
-
outputRange: [-TRANSLATE_DISTANCE, 0, TRANSLATE_DISTANCE]
|
|
28341
|
+
}, function (_, i) {
|
|
28342
|
+
return layoutsRef.current[i];
|
|
28308
28343
|
});
|
|
28309
|
-
});
|
|
28310
|
-
var
|
|
28311
|
-
|
|
28312
|
-
|
|
28313
|
-
|
|
28344
|
+
}, [tabsLength]);
|
|
28345
|
+
var animateTo = React__default.useCallback(function (index, animate) {
|
|
28346
|
+
var _runningAnimRef$curre;
|
|
28347
|
+
var layout = layoutsRef.current[index];
|
|
28348
|
+
if (!layout) return;
|
|
28349
|
+
(_runningAnimRef$curre = runningAnimRef.current) === null || _runningAnimRef$curre === void 0 || _runningAnimRef$curre.stop();
|
|
28350
|
+
runningAnimRef.current = null;
|
|
28351
|
+
// Layer 1: bottom-border element has width:1, so scaleX = pixel width.
|
|
28352
|
+
var indicatorScaleXValue = layout.width;
|
|
28353
|
+
// Layer 2 body: width:1 element, scaleX fills space between the two caps.
|
|
28354
|
+
var bodyScaleX = Math.max(layout.width - pillCapWidth * 2, 0);
|
|
28355
|
+
// Layer 2 right cap: offset from pillX to reach the right edge.
|
|
28356
|
+
// Clamped to 0 so the right cap never slides left of the pill's origin
|
|
28357
|
+
// when the tab is narrower than one cap width.
|
|
28358
|
+
var rightOffset = Math.max(layout.width - pillCapWidth, 0);
|
|
28359
|
+
if (!animate || !initializedRef.current) {
|
|
28360
|
+
// First render — snap all values immediately without animation.
|
|
28361
|
+
indicatorX.setValue(layout.x);
|
|
28362
|
+
indicatorScaleX.setValue(indicatorScaleXValue);
|
|
28363
|
+
pillX.setValue(layout.x);
|
|
28364
|
+
pillBodyScaleX.setValue(bodyScaleX);
|
|
28365
|
+
pillRightOffset.setValue(rightOffset);
|
|
28366
|
+
initializedRef.current = true;
|
|
28367
|
+
return;
|
|
28368
|
+
}
|
|
28369
|
+
// All five animations run on the native driver (UI thread):
|
|
28370
|
+
// indicatorX — slides the bottom border
|
|
28371
|
+
// indicatorScaleX — stretches the bottom border
|
|
28372
|
+
// pillX — slides all three pill pieces together
|
|
28373
|
+
// pillBodyScaleX — resizes the body piece to fill between caps
|
|
28374
|
+
// pillRightOffset — keeps the right cap at the pill's right edge
|
|
28375
|
+
var anim = Animated.parallel([Animated.timing(indicatorX, {
|
|
28376
|
+
toValue: layout.x,
|
|
28377
|
+
useNativeDriver: true
|
|
28378
|
+
}), Animated.timing(indicatorScaleX, {
|
|
28379
|
+
toValue: indicatorScaleXValue,
|
|
28380
|
+
useNativeDriver: true
|
|
28381
|
+
}), Animated.timing(pillX, {
|
|
28382
|
+
toValue: layout.x,
|
|
28383
|
+
useNativeDriver: true
|
|
28384
|
+
}), Animated.timing(pillBodyScaleX, {
|
|
28385
|
+
toValue: bodyScaleX,
|
|
28386
|
+
useNativeDriver: true
|
|
28387
|
+
}), Animated.timing(pillRightOffset, {
|
|
28388
|
+
toValue: rightOffset,
|
|
28389
|
+
useNativeDriver: true
|
|
28390
|
+
})]);
|
|
28391
|
+
runningAnimRef.current = anim;
|
|
28392
|
+
anim.start(function (_ref2) {
|
|
28393
|
+
var finished = _ref2.finished;
|
|
28394
|
+
if (finished) runningAnimRef.current = null;
|
|
28314
28395
|
});
|
|
28315
|
-
});
|
|
28396
|
+
}, [indicatorX, indicatorScaleX, pillX, pillBodyScaleX, pillRightOffset, pillCapWidth]);
|
|
28397
|
+
// Animate to selected tab whenever selectedIndex changes.
|
|
28316
28398
|
React__default.useEffect(function () {
|
|
28317
|
-
if (
|
|
28318
|
-
|
|
28319
|
-
|
|
28320
|
-
|
|
28321
|
-
|
|
28322
|
-
|
|
28323
|
-
}
|
|
28324
|
-
// Split animations into 2 sets of parallel animations to prevent race condition.
|
|
28325
|
-
Animated.parallel([animateOpacity(opacityAnims[selectedIndex], 1), animateTranslateX(translateXAnims[selectedIndex], 0)]).start();
|
|
28326
|
-
Animated.parallel([animateOpacity(opacityAnims[previousIndex.current], 0), animateTranslateX(translateXAnims[previousIndex.current], selectedIndex > previousIndex.current ? 1 : -1)]).start();
|
|
28327
|
-
previousIndex.current = selectedIndex;
|
|
28399
|
+
if (selectedIndex === undefined) return;
|
|
28400
|
+
if (layoutsRef.current[selectedIndex]) {
|
|
28401
|
+
animateTo(selectedIndex, initializedRef.current);
|
|
28402
|
+
} else {
|
|
28403
|
+
// Layout not yet measured — store as pending and resolve in onTabLayout.
|
|
28404
|
+
pendingIndexRef.current = selectedIndex;
|
|
28328
28405
|
}
|
|
28329
|
-
}, [selectedIndex,
|
|
28406
|
+
}, [selectedIndex, animateTo]);
|
|
28407
|
+
// Stop any in-flight animation on unmount.
|
|
28408
|
+
React__default.useEffect(function () {
|
|
28409
|
+
return function () {
|
|
28410
|
+
var _runningAnimRef$curre2;
|
|
28411
|
+
(_runningAnimRef$curre2 = runningAnimRef.current) === null || _runningAnimRef$curre2 === void 0 || _runningAnimRef$curre2.stop();
|
|
28412
|
+
};
|
|
28413
|
+
}, []);
|
|
28414
|
+
var onTabLayout = React__default.useCallback(function (index, event) {
|
|
28415
|
+
var _event$nativeEvent$la = event.nativeEvent.layout,
|
|
28416
|
+
x = _event$nativeEvent$la.x,
|
|
28417
|
+
width = _event$nativeEvent$la.width;
|
|
28418
|
+
var prev = layoutsRef.current[index];
|
|
28419
|
+
// Skip if layout hasn't meaningfully changed (sub-pixel tolerance).
|
|
28420
|
+
if (prev && Math.abs(prev.x - x) < 0.5 && Math.abs(prev.width - width) < 0.5) {
|
|
28421
|
+
return;
|
|
28422
|
+
}
|
|
28423
|
+
layoutsRef.current[index] = {
|
|
28424
|
+
x: x,
|
|
28425
|
+
width: width
|
|
28426
|
+
};
|
|
28427
|
+
// Animate if this tab is the selected one (covers the pending case where
|
|
28428
|
+
// selectedIndex was set before the layout was measured).
|
|
28429
|
+
if (index === selectedIndex || index === pendingIndexRef.current) {
|
|
28430
|
+
if (index === pendingIndexRef.current) pendingIndexRef.current = undefined;
|
|
28431
|
+
animateTo(index, initializedRef.current);
|
|
28432
|
+
}
|
|
28433
|
+
// If no tab is selected yet, snap indicators to tab 0 on its first
|
|
28434
|
+
// layout so they appear at a sensible default position.
|
|
28435
|
+
if (!initializedRef.current && index === 0 && selectedIndex === undefined) {
|
|
28436
|
+
indicatorScaleX.setValue(width);
|
|
28437
|
+
pillX.setValue(x);
|
|
28438
|
+
pillBodyScaleX.setValue(Math.max(width - pillCapWidth * 2, 0));
|
|
28439
|
+
pillRightOffset.setValue(Math.max(width - pillCapWidth, 0));
|
|
28440
|
+
initializedRef.current = true;
|
|
28441
|
+
}
|
|
28442
|
+
}, [animateTo, selectedIndex, pillCapWidth]);
|
|
28443
|
+
// Layer 1: transformOrigin 'left center' pins scaleX expansion to left edge.
|
|
28444
|
+
var indicatorStyle = {
|
|
28445
|
+
transformOrigin: 'left center',
|
|
28446
|
+
transform: [{
|
|
28447
|
+
translateX: indicatorX
|
|
28448
|
+
}, {
|
|
28449
|
+
scaleX: indicatorScaleX
|
|
28450
|
+
}]
|
|
28451
|
+
};
|
|
28452
|
+
// Layer 2: three pieces, all absolutely positioned, all native driver.
|
|
28453
|
+
// Animated.add computes derived positions without creating JS-driver nodes.
|
|
28454
|
+
var pillLeftStyle = {
|
|
28455
|
+
transform: [{
|
|
28456
|
+
translateX: pillX
|
|
28457
|
+
}]
|
|
28458
|
+
};
|
|
28459
|
+
var pillBodyStyle = {
|
|
28460
|
+
transformOrigin: 'left center',
|
|
28461
|
+
transform: [{
|
|
28462
|
+
translateX: Animated.add(pillX, pillCapWidth)
|
|
28463
|
+
}, {
|
|
28464
|
+
scaleX: pillBodyScaleX
|
|
28465
|
+
}]
|
|
28466
|
+
};
|
|
28467
|
+
var pillRightStyle = {
|
|
28468
|
+
transform: [{
|
|
28469
|
+
translateX: Animated.add(pillX, pillRightOffset)
|
|
28470
|
+
}]
|
|
28471
|
+
};
|
|
28330
28472
|
return {
|
|
28331
|
-
|
|
28332
|
-
|
|
28473
|
+
indicatorStyle: indicatorStyle,
|
|
28474
|
+
pillLeftStyle: pillLeftStyle,
|
|
28475
|
+
pillBodyStyle: pillBodyStyle,
|
|
28476
|
+
pillRightStyle: pillRightStyle,
|
|
28477
|
+
onTabLayout: onTabLayout
|
|
28333
28478
|
};
|
|
28334
28479
|
};
|
|
28335
28480
|
|
|
@@ -28349,7 +28494,7 @@ var getTabItem$1 = function getTabItem(_ref) {
|
|
|
28349
28494
|
}
|
|
28350
28495
|
if (typeof item === 'string') {
|
|
28351
28496
|
return /*#__PURE__*/React__default.createElement(Typography.Body, {
|
|
28352
|
-
variant: active ? '
|
|
28497
|
+
variant: active ? 'small-bold' : 'small',
|
|
28353
28498
|
numberOfLines: 1,
|
|
28354
28499
|
style: {
|
|
28355
28500
|
color: color
|
|
@@ -28360,130 +28505,167 @@ var getTabItem$1 = function getTabItem(_ref) {
|
|
|
28360
28505
|
color: color
|
|
28361
28506
|
});
|
|
28362
28507
|
};
|
|
28363
|
-
var
|
|
28364
|
-
var
|
|
28365
|
-
|
|
28366
|
-
|
|
28367
|
-
|
|
28368
|
-
|
|
28369
|
-
|
|
28370
|
-
|
|
28508
|
+
var TabItemComponent = /*#__PURE__*/React__default.memo(function (_ref2) {
|
|
28509
|
+
var _tab$inactiveItem;
|
|
28510
|
+
var tab = _ref2.tab,
|
|
28511
|
+
index = _ref2.index,
|
|
28512
|
+
active = _ref2.active,
|
|
28513
|
+
variant = _ref2.variant,
|
|
28514
|
+
onTabPress = _ref2.onTabPress,
|
|
28515
|
+
onLayout = _ref2.onLayout;
|
|
28516
|
+
var theme = useTheme$1();
|
|
28517
|
+
var isHighlighted = variant === 'highlighted';
|
|
28518
|
+
var getTextColor = function getTextColor() {
|
|
28519
|
+
if (isHighlighted) {
|
|
28520
|
+
if (tab.disabled) return theme.__hd__.tabs.colors.highlightedDisabledText;
|
|
28521
|
+
if (active) return theme.__hd__.tabs.colors.highlightedActiveText;
|
|
28522
|
+
}
|
|
28523
|
+
return active ? theme.__hd__.tabs.colors.active : theme.__hd__.tabs.colors.inactive;
|
|
28524
|
+
};
|
|
28525
|
+
var inactiveItem = (_tab$inactiveItem = tab.inactiveItem) !== null && _tab$inactiveItem !== void 0 ? _tab$inactiveItem : tab.activeItem;
|
|
28526
|
+
var tabItem = getTabItem$1({
|
|
28527
|
+
item: active ? tab.activeItem : inactiveItem,
|
|
28528
|
+
color: getTextColor(),
|
|
28529
|
+
active: active
|
|
28530
|
+
});
|
|
28531
|
+
var handlePress = React__default.useCallback(function () {
|
|
28532
|
+
return onTabPress(tab.key);
|
|
28533
|
+
}, [onTabPress, tab.key]);
|
|
28534
|
+
return /*#__PURE__*/React__default.createElement(TouchableWithoutFeedback, {
|
|
28535
|
+
key: tab.key,
|
|
28536
|
+
onPress: handlePress,
|
|
28537
|
+
testID: tab.testID,
|
|
28538
|
+
disabled: tab.disabled
|
|
28539
|
+
}, /*#__PURE__*/React__default.createElement(HeaderTabItem, {
|
|
28540
|
+
testID: "tab-item-".concat(index),
|
|
28541
|
+
isFirstItem: index === 0,
|
|
28542
|
+
themeVariant: variant,
|
|
28543
|
+
onLayout: onLayout
|
|
28544
|
+
}, /*#__PURE__*/React__default.createElement(HeaderTabItemWrapper, null, /*#__PURE__*/React__default.createElement(TabWithBadge, {
|
|
28545
|
+
config: tab.badge,
|
|
28546
|
+
tabItem: tabItem
|
|
28547
|
+
}))));
|
|
28548
|
+
});
|
|
28549
|
+
var ScrollableTabHeader = function ScrollableTabHeader(_ref3) {
|
|
28550
|
+
var onTabPress = _ref3.onTabPress,
|
|
28551
|
+
rawSelectedIndex = _ref3.selectedIndex,
|
|
28552
|
+
tabs = _ref3.tabs,
|
|
28553
|
+
barStyle = _ref3.barStyle,
|
|
28554
|
+
testID = _ref3.testID,
|
|
28555
|
+
_ref3$insets = _ref3.insets,
|
|
28556
|
+
insets = _ref3$insets === void 0 ? {
|
|
28371
28557
|
top: 0,
|
|
28372
28558
|
bottom: 0,
|
|
28373
28559
|
right: 0,
|
|
28374
28560
|
left: 0
|
|
28375
|
-
} :
|
|
28376
|
-
|
|
28377
|
-
variant =
|
|
28561
|
+
} : _ref3$insets,
|
|
28562
|
+
_ref3$variant = _ref3.variant,
|
|
28563
|
+
variant = _ref3$variant === void 0 ? 'highlighted' : _ref3$variant;
|
|
28564
|
+
var selectedIndex = rawSelectedIndex !== undefined && rawSelectedIndex >= 0 ? rawSelectedIndex : undefined;
|
|
28378
28565
|
var theme = useTheme$1();
|
|
28379
|
-
var
|
|
28380
|
-
|
|
28381
|
-
var
|
|
28382
|
-
tabsLength: tabs.length,
|
|
28383
|
-
selectedIndex: selectedIndex,
|
|
28384
|
-
variant: variant
|
|
28385
|
-
}),
|
|
28386
|
-
underlinedTranslateX = _useInitUnderlinedAni.underlinedTranslateX,
|
|
28387
|
-
underlinedOpacity = _useInitUnderlinedAni.underlinedOpacity;
|
|
28388
|
-
// Init highlighted animation data
|
|
28389
|
-
var _useInitHighlightedAn = useInitHighlightedAnimation({
|
|
28566
|
+
var scrollViewRef = React__default.useRef(null);
|
|
28567
|
+
var isHighlighted = variant === 'highlighted';
|
|
28568
|
+
var _useIndicatorAnimatio = useIndicatorAnimation({
|
|
28390
28569
|
selectedIndex: selectedIndex,
|
|
28391
28570
|
tabsLength: tabs.length,
|
|
28392
|
-
|
|
28571
|
+
pillCapWidth: theme.__hd__.tabs.radii.highlightedOutline
|
|
28393
28572
|
}),
|
|
28394
|
-
|
|
28395
|
-
|
|
28396
|
-
|
|
28397
|
-
|
|
28398
|
-
|
|
28399
|
-
|
|
28400
|
-
|
|
28573
|
+
indicatorStyle = _useIndicatorAnimatio.indicatorStyle,
|
|
28574
|
+
pillLeftStyle = _useIndicatorAnimatio.pillLeftStyle,
|
|
28575
|
+
pillBodyStyle = _useIndicatorAnimatio.pillBodyStyle,
|
|
28576
|
+
pillRightStyle = _useIndicatorAnimatio.pillRightStyle,
|
|
28577
|
+
onTabLayout = _useIndicatorAnimatio.onTabLayout;
|
|
28578
|
+
// Scroll to the selected tab after its layout is known.
|
|
28579
|
+
var handleTabLayout = React__default.useCallback(function (index, event) {
|
|
28580
|
+
if (index === selectedIndex) {
|
|
28581
|
+
var _scrollViewRef$curren;
|
|
28582
|
+
(_scrollViewRef$curren = scrollViewRef.current) === null || _scrollViewRef$curren === void 0 || _scrollViewRef$curren.scrollTo({
|
|
28583
|
+
x: event.nativeEvent.layout.x,
|
|
28584
|
+
animated: true
|
|
28401
28585
|
});
|
|
28402
28586
|
}
|
|
28403
|
-
|
|
28587
|
+
onTabLayout(index, event);
|
|
28588
|
+
}, [selectedIndex, onTabLayout]);
|
|
28589
|
+
// Memoize per-tab layout handlers so TabItemComponent memo is not broken.
|
|
28590
|
+
var tabLayoutHandlers = React__default.useMemo(function () {
|
|
28591
|
+
return tabs.map(function (_, i) {
|
|
28592
|
+
return function (event) {
|
|
28593
|
+
return handleTabLayout(i, event);
|
|
28594
|
+
};
|
|
28595
|
+
});
|
|
28596
|
+
},
|
|
28597
|
+
// Handlers only need to change when tab count or selection changes.
|
|
28598
|
+
[tabs, handleTabLayout]);
|
|
28599
|
+
var scrollViewStyle = React__default.useMemo(function () {
|
|
28600
|
+
return {
|
|
28601
|
+
borderBottomColor: theme.__hd__.tabs.colors.headerBottom,
|
|
28602
|
+
borderBottomWidth: isHighlighted ? theme.__hd__.tabs.borderWidths.highlightedHeaderBottom : theme.__hd__.tabs.sizes.indicator
|
|
28404
28603
|
};
|
|
28405
|
-
}, [
|
|
28604
|
+
}, [theme, isHighlighted]);
|
|
28605
|
+
var contentContainerStyle = React__default.useMemo(function () {
|
|
28606
|
+
return _objectSpread2({
|
|
28607
|
+
paddingHorizontal: theme.__hd__.tabs.space.flatListHorizontalPadding,
|
|
28608
|
+
position: 'relative'
|
|
28609
|
+
}, Platform.OS === 'android' && {
|
|
28610
|
+
borderBottomColor: theme.__hd__.tabs.colors.headerBottom,
|
|
28611
|
+
borderBottomWidth: isHighlighted ? theme.__hd__.tabs.borderWidths.highlightedHeaderBottom : theme.__hd__.tabs.sizes.indicator
|
|
28612
|
+
});
|
|
28613
|
+
}, [theme, isHighlighted]);
|
|
28614
|
+
var wrapperStyle = React__default.useMemo(function () {
|
|
28615
|
+
return [isHighlighted && {
|
|
28616
|
+
paddingTop: theme.__hd__.tabs.space.highlightedBarTopPadding
|
|
28617
|
+
}, barStyle];
|
|
28618
|
+
}, [isHighlighted, theme, barStyle]);
|
|
28406
28619
|
return /*#__PURE__*/React__default.createElement(HeaderTabWrapper, {
|
|
28620
|
+
testID: "tab-header-wrapper",
|
|
28407
28621
|
themeInsets: insets,
|
|
28408
|
-
style:
|
|
28409
|
-
}, /*#__PURE__*/React__default.createElement(
|
|
28622
|
+
style: wrapperStyle
|
|
28623
|
+
}, /*#__PURE__*/React__default.createElement(View, {
|
|
28624
|
+
style: isHighlighted ? {
|
|
28625
|
+
overflow: 'hidden'
|
|
28626
|
+
} : undefined
|
|
28627
|
+
}, /*#__PURE__*/React__default.createElement(ScrollView, {
|
|
28628
|
+
ref: scrollViewRef,
|
|
28410
28629
|
testID: testID,
|
|
28411
|
-
ref: flatListRef,
|
|
28412
28630
|
horizontal: true,
|
|
28413
|
-
data: tabs,
|
|
28414
|
-
keyExtractor: function keyExtractor(tab) {
|
|
28415
|
-
return String(tab.key);
|
|
28416
|
-
},
|
|
28417
28631
|
showsHorizontalScrollIndicator: false,
|
|
28418
|
-
|
|
28419
|
-
|
|
28420
|
-
|
|
28421
|
-
var _flatListRef$current2;
|
|
28422
|
-
return (_flatListRef$current2 = flatListRef.current) === null || _flatListRef$current2 === void 0 ? void 0 : _flatListRef$current2.scrollToIndex({
|
|
28423
|
-
index: index,
|
|
28424
|
-
viewPosition: 0.5
|
|
28425
|
-
});
|
|
28426
|
-
}, 100);
|
|
28427
|
-
},
|
|
28632
|
+
contentContainerStyle: contentContainerStyle,
|
|
28633
|
+
style: scrollViewStyle
|
|
28634
|
+
}, /*#__PURE__*/React__default.createElement(View, {
|
|
28428
28635
|
style: {
|
|
28429
|
-
|
|
28430
|
-
|
|
28431
|
-
},
|
|
28432
|
-
contentContainerStyle: _objectSpread2({
|
|
28433
|
-
paddingHorizontal: theme.__hd__.tabs.space.flatListHorizontalPadding
|
|
28434
|
-
}, Platform.OS === 'android' && {
|
|
28435
|
-
borderBottomColor: theme.__hd__.tabs.colors.headerBottom,
|
|
28436
|
-
borderBottomWidth: theme.__hd__.tabs.sizes.indicator
|
|
28437
|
-
}),
|
|
28438
|
-
renderItem: function renderItem(_ref4) {
|
|
28439
|
-
var tab = _ref4.item,
|
|
28440
|
-
index = _ref4.index;
|
|
28441
|
-
var key = tab.key,
|
|
28442
|
-
tabItemTestID = tab.testID,
|
|
28443
|
-
activeItem = tab.activeItem,
|
|
28444
|
-
originalInactiveItem = tab.inactiveItem,
|
|
28445
|
-
badge = tab.badge;
|
|
28446
|
-
var active = selectedIndex === index;
|
|
28447
|
-
var activeAnimated = tabsAnims[index];
|
|
28448
|
-
var outlineScale = activeAnimated.interpolate({
|
|
28449
|
-
inputRange: [0, 1],
|
|
28450
|
-
outputRange: [0.5, 1]
|
|
28451
|
-
});
|
|
28452
|
-
var inactiveItem = originalInactiveItem !== null && originalInactiveItem !== void 0 ? originalInactiveItem : activeItem;
|
|
28453
|
-
var tabItem = getTabItem$1({
|
|
28454
|
-
item: active ? activeItem : inactiveItem,
|
|
28455
|
-
color: active ? theme.__hd__.tabs.colors.active : theme.__hd__.tabs.colors.inactive,
|
|
28456
|
-
active: active
|
|
28457
|
-
});
|
|
28458
|
-
return /*#__PURE__*/React__default.createElement(TouchableWithoutFeedback, {
|
|
28459
|
-
key: key,
|
|
28460
|
-
onPress: function onPress() {
|
|
28461
|
-
onTabPress(key);
|
|
28462
|
-
},
|
|
28463
|
-
testID: tabItemTestID
|
|
28464
|
-
}, /*#__PURE__*/React__default.createElement(HeaderTabItem, {
|
|
28465
|
-
isFirstItem: index === 0
|
|
28466
|
-
}, variant === 'highlighted' && /*#__PURE__*/React__default.createElement(HeaderTabItemOutlineWrapper, null, /*#__PURE__*/React__default.createElement(HeaderTabItemOutline, {
|
|
28467
|
-
themeActive: active,
|
|
28468
|
-
style: {
|
|
28469
|
-
flex: 1,
|
|
28470
|
-
transform: [{
|
|
28471
|
-
scaleX: outlineScale
|
|
28472
|
-
}]
|
|
28473
|
-
}
|
|
28474
|
-
})), /*#__PURE__*/React__default.createElement(HeaderTabItemWrapper, null, /*#__PURE__*/React__default.createElement(TabWithBadge, {
|
|
28475
|
-
config: badge,
|
|
28476
|
-
tabItem: tabItem
|
|
28477
|
-
})), variant === 'underlined' && /*#__PURE__*/React__default.createElement(HeaderTabItemIndicator, {
|
|
28478
|
-
style: {
|
|
28479
|
-
opacity: underlinedOpacity[index],
|
|
28480
|
-
transform: [{
|
|
28481
|
-
translateX: underlinedTranslateX[index]
|
|
28482
|
-
}]
|
|
28483
|
-
}
|
|
28484
|
-
})));
|
|
28636
|
+
flexDirection: 'row',
|
|
28637
|
+
position: 'relative'
|
|
28485
28638
|
}
|
|
28486
|
-
}
|
|
28639
|
+
}, isHighlighted && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(HeaderTabPillLeft, {
|
|
28640
|
+
testID: "tab-pill-background",
|
|
28641
|
+
style: pillLeftStyle
|
|
28642
|
+
}), /*#__PURE__*/React__default.createElement(HeaderTabPillBody, {
|
|
28643
|
+
style: pillBodyStyle
|
|
28644
|
+
}), /*#__PURE__*/React__default.createElement(HeaderTabPillRight, {
|
|
28645
|
+
testID: "tab-pill-background-right",
|
|
28646
|
+
style: pillRightStyle
|
|
28647
|
+
})), tabs.map(function (tab, index) {
|
|
28648
|
+
return /*#__PURE__*/React__default.createElement(TabItemComponent, {
|
|
28649
|
+
key: tab.key,
|
|
28650
|
+
tab: tab,
|
|
28651
|
+
index: index,
|
|
28652
|
+
active: selectedIndex === index,
|
|
28653
|
+
variant: variant,
|
|
28654
|
+
onTabPress: onTabPress,
|
|
28655
|
+
onLayout: tabLayoutHandlers[index]
|
|
28656
|
+
});
|
|
28657
|
+
}), isHighlighted ? /*#__PURE__*/React__default.createElement(HeaderTabItemActiveBorder, {
|
|
28658
|
+
testID: "tab-active-border",
|
|
28659
|
+
style: _objectSpread2({
|
|
28660
|
+
position: 'absolute',
|
|
28661
|
+
bottom: 0
|
|
28662
|
+
}, indicatorStyle)
|
|
28663
|
+
}) : /*#__PURE__*/React__default.createElement(HeaderTabItemIndicator, {
|
|
28664
|
+
testID: "tab-underline-indicator",
|
|
28665
|
+
style: _objectSpread2({
|
|
28666
|
+
position: 'absolute'
|
|
28667
|
+
}, indicatorStyle)
|
|
28668
|
+
})))));
|
|
28487
28669
|
};
|
|
28488
28670
|
|
|
28489
28671
|
var useHandlePageScroll = function useHandlePageScroll() {
|