@fountain-ui/core 2.0.0-beta.13 → 2.0.0-beta.16
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/build/commonjs/ButtonBase/ButtonBase.js +3 -2
- package/build/commonjs/ButtonBase/ButtonBase.js.map +1 -1
- package/build/commonjs/CircularProgress/CircularProgress.js +15 -11
- package/build/commonjs/CircularProgress/CircularProgress.js.map +1 -1
- package/build/commonjs/Tab/Tab.js +9 -5
- package/build/commonjs/Tab/Tab.js.map +1 -1
- package/build/commonjs/Tabs/IndexAwareTab.js +28 -0
- package/build/commonjs/Tabs/IndexAwareTab.js.map +1 -0
- package/build/commonjs/Tabs/TabIndicator.js +27 -13
- package/build/commonjs/Tabs/TabIndicator.js.map +1 -1
- package/build/commonjs/Tabs/TabIndicatorProps.js.map +1 -1
- package/build/commonjs/Tabs/Tabs.js +43 -62
- package/build/commonjs/Tabs/Tabs.js.map +1 -1
- package/build/commonjs/Tabs/TabsProps.js.map +1 -1
- package/build/commonjs/Tabs/index.js.map +1 -1
- package/build/commonjs/Tabs/useScrollViewReaction.js +65 -0
- package/build/commonjs/Tabs/useScrollViewReaction.js.map +1 -0
- package/build/commonjs/hooks/useValidWindowDimensions/index.ios.js +14 -7
- package/build/commonjs/hooks/useValidWindowDimensions/index.ios.js.map +1 -1
- package/build/module/ButtonBase/ButtonBase.js +3 -2
- package/build/module/ButtonBase/ButtonBase.js.map +1 -1
- package/build/module/CircularProgress/CircularProgress.js +15 -11
- package/build/module/CircularProgress/CircularProgress.js.map +1 -1
- package/build/module/Tab/Tab.js +5 -5
- package/build/module/Tab/Tab.js.map +1 -1
- package/build/module/Tabs/IndexAwareTab.js +18 -0
- package/build/module/Tabs/IndexAwareTab.js.map +1 -0
- package/build/module/Tabs/TabIndicator.js +26 -14
- package/build/module/Tabs/TabIndicator.js.map +1 -1
- package/build/module/Tabs/TabIndicatorProps.js.map +1 -1
- package/build/module/Tabs/Tabs.js +42 -60
- package/build/module/Tabs/Tabs.js.map +1 -1
- package/build/module/Tabs/TabsProps.js.map +1 -1
- package/build/module/Tabs/index.js.map +1 -1
- package/build/module/Tabs/useScrollViewReaction.js +54 -0
- package/build/module/Tabs/useScrollViewReaction.js.map +1 -0
- package/build/module/hooks/useValidWindowDimensions/index.ios.js +15 -9
- package/build/module/hooks/useValidWindowDimensions/index.ios.js.map +1 -1
- package/build/typescript/CircularProgress/CircularProgress.d.ts +1 -1
- package/build/typescript/Tabs/IndexAwareTab.d.ts +9 -0
- package/build/typescript/Tabs/TabIndicatorProps.d.ts +2 -2
- package/build/typescript/Tabs/Tabs.d.ts +4 -1
- package/build/typescript/Tabs/TabsProps.d.ts +22 -9
- package/build/typescript/Tabs/index.d.ts +1 -1
- package/build/typescript/Tabs/useScrollViewReaction.d.ts +9 -0
- package/build/typescript/hooks/useValidWindowDimensions/index.ios.d.ts +2 -1
- package/package.json +2 -2
- package/src/ButtonBase/ButtonBase.tsx +6 -2
- package/src/CircularProgress/CircularProgress.tsx +23 -15
- package/src/Tab/Tab.tsx +5 -5
- package/src/Tabs/IndexAwareTab.tsx +30 -0
- package/src/Tabs/TabIndicator.tsx +26 -14
- package/src/Tabs/TabIndicatorProps.ts +2 -2
- package/src/Tabs/Tabs.tsx +50 -62
- package/src/Tabs/TabsProps.ts +25 -9
- package/src/Tabs/index.ts +1 -1
- package/src/Tabs/useScrollViewReaction.ts +63 -0
- package/src/hooks/useValidWindowDimensions/index.ios.ts +16 -10
- package/build/commonjs/Tabs/useTabsWidth.js +0 -26
- package/build/commonjs/Tabs/useTabsWidth.js.map +0 -1
- package/build/module/Tabs/useTabsWidth.js +0 -18
- package/build/module/Tabs/useTabsWidth.js.map +0 -1
- package/build/typescript/Tabs/useTabsWidth.d.ts +0 -2
- package/src/Tabs/useTabsWidth.ts +0 -20
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","cloneElement","useEffect","useMemo","useRef","ScrollView","View","Easing","useSharedValue","withTiming","css","useTheme","TabIndicator","useTabsWidth","useTabCoordinates","useStyles","theme","root","fixedRoot","flexDirection","fixedTab","flex","scrollableContainer","paddingHorizontal","spacing","ANIMATION_CONFIG","duration","easing","out","exp","Tabs","props","children","index","indexProp","disableIndicator","keyboardDismissMode","keyboardShouldPersistTaps","onChange","scrollable","scrollValue","scrollValueProp","style","variant","otherProps","styles","containerWidth","handleLayout","scrollViewRef","coordinates","updateCoordinate","internalScrollValue","isReadyToRenderIndicator","length","animateTab","value","scrollPosition","coordinate","tabWidth","x2","x1","Math","floor","scrollView","current","scrollTo","x","y","animated","tabElements","Children","map","child","onLayout","event","width","nativeEvent","layout","onMouseDown","e","preventDefault","onPress","selected","enableIndicatorPlaceholder","enableIndicator","undefined","indicator"],"sources":["Tabs.tsx"],"sourcesContent":["import React, { cloneElement, useEffect, useMemo, useRef } from 'react';\nimport { GestureResponderEvent, LayoutChangeEvent, ScrollView, View } from 'react-native';\nimport type { WithTimingConfig } from 'react-native-reanimated';\nimport { Easing, useSharedValue, withTiming } from 'react-native-reanimated';\nimport { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';\nimport { css, useTheme } from '../styles';\nimport type TabsProps from './TabsProps';\nimport TabIndicator from './TabIndicator';\nimport useTabsWidth from './useTabsWidth';\nimport useTabCoordinates from './useTabCoordinates';\n\ntype TabsStyleKeys =\n | 'root'\n | 'fixedRoot'\n | 'fixedTab'\n | 'scrollableContainer';\n\ntype TabsStyles = NamedStylesStringUnion<TabsStyleKeys>;\n\nconst useStyles: UseStyles<TabsStyles> = function (): TabsStyles {\n const theme = useTheme();\n\n return {\n root: {},\n fixedRoot: {\n flexDirection: 'row',\n },\n fixedTab: {\n flex: 1,\n },\n scrollableContainer: {\n paddingHorizontal: theme.spacing(1),\n },\n };\n};\n\nconst ANIMATION_CONFIG: Readonly<WithTimingConfig> = {\n duration: 200,\n easing: Easing.out(Easing.exp),\n};\n\nexport default function Tabs(props: TabsProps) {\n const {\n children,\n index: indexProp,\n disableIndicator = false,\n keyboardDismissMode = 'none',\n keyboardShouldPersistTaps = 'never',\n onChange,\n scrollable = false,\n scrollValue: scrollValueProp,\n style,\n variant = 'primary',\n ...otherProps\n } = props;\n\n const styles = useStyles();\n\n const [containerWidth, handleLayout] = useTabsWidth();\n\n const scrollViewRef = useRef<ScrollView | null>(null);\n\n const { coordinates, updateCoordinate } = useTabCoordinates(children);\n\n const internalScrollValue = useSharedValue(0);\n const scrollValue = scrollValueProp ?? internalScrollValue;\n\n const isReadyToRenderIndicator = coordinates.length > 0;\n\n useEffect(() => {\n const animateTab = (index: number) => {\n scrollValue.value = withTiming(index, ANIMATION_CONFIG);\n };\n\n animateTab(indexProp);\n }, [indexProp, scrollValue]);\n\n const scrollPosition = useMemo<number>(() => {\n const coordinate = coordinates[indexProp - 1];\n\n if (coordinate) {\n const tabWidth = coordinate.x2 - coordinate.x1;\n return Math.floor(coordinate.x1 + tabWidth / 2);\n }\n\n return 0;\n }, [indexProp, coordinates]);\n\n useEffect(() => {\n const scrollView = scrollViewRef.current;\n\n if (scrollView) {\n scrollView.scrollTo({ x: scrollPosition, y: 0, animated: true });\n }\n }, [scrollPosition, containerWidth]);\n\n const tabElements = React.Children.map(children, (child, index) => {\n const onLayout = (event: LayoutChangeEvent) => {\n const { x, width } = event.nativeEvent.layout;\n\n updateCoordinate(index, x, width);\n };\n\n const onMouseDown = (e: GestureResponderEvent) => {\n if (keyboardShouldPersistTaps === 'always') {\n e.preventDefault();\n }\n };\n\n const onPress = () => {\n onChange?.(index);\n // @ts-ignore\n child.props.onPress?.();\n };\n\n const selected = index === indexProp;\n const enableIndicatorPlaceholder = disableIndicator\n ? false\n : (isReadyToRenderIndicator ? false : selected);\n\n //@ts-ignore\n return cloneElement(child, {\n enableIndicator: enableIndicatorPlaceholder,\n onLayout,\n onPress,\n onMouseDown,\n variant,\n selected,\n style: scrollable ? undefined : styles.fixedTab,\n });\n });\n\n const indicator = (\n <TabIndicator\n coordinates={coordinates}\n disabled={disableIndicator}\n scrollable={scrollable}\n scrollValue={scrollValue}\n />\n );\n\n return (\n <View\n onLayout={handleLayout}\n style={css([\n styles.root,\n scrollable ? undefined : styles.fixedRoot,\n style,\n ])}\n {...otherProps}\n >\n {scrollable ? (\n <ScrollView\n automaticallyAdjustContentInsets={false}\n bounces={false}\n contentContainerStyle={styles.scrollableContainer}\n directionalLockEnabled={true}\n horizontal={true}\n ref={scrollViewRef}\n scrollsToTop={false}\n showsHorizontalScrollIndicator={false}\n showsVerticalScrollIndicator={false}\n keyboardDismissMode={keyboardDismissMode}\n keyboardShouldPersistTaps={keyboardShouldPersistTaps}\n >\n {tabElements}\n {indicator}\n </ScrollView>\n ) : (\n <React.Fragment>\n {tabElements}\n {indicator}\n </React.Fragment>\n )}\n </View>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["React","cloneElement","forwardRef","useImperativeHandle","ScrollView","View","useSharedValue","css","useTheme","TabIndicator","IndexAwareTab","useTabCoordinates","useScrollViewReaction","useStyles","theme","root","fixedRoot","flexDirection","fixedTab","flex","scrollableContainer","paddingHorizontal","spacing","Tabs","props","ref","children","initialIndex","disableIndicator","keyboardDismissMode","keyboardShouldPersistTaps","onChange","scrollable","style","variant","UNSTABLE_sharedIndex","fallbackSharedIndex","sharedIndex","getCurrentIndex","value","setTab","newIndex","styles","coordinates","updateCoordinate","scrollViewRef","onLayout","isReadyToRenderIndicator","length","tabElements","Children","map","child","index","event","x","width","nativeEvent","layout","onMouseDown","e","preventDefault","onPress","tabElement","enableIndicator","undefined","tabIndicator"],"sources":["Tabs.tsx"],"sourcesContent":["import React, { cloneElement, forwardRef, useImperativeHandle } from 'react';\nimport type { GestureResponderEvent, LayoutChangeEvent } from 'react-native';\nimport { ScrollView, View } from 'react-native';\nimport { useSharedValue } from 'react-native-reanimated';\nimport { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';\nimport { css, useTheme } from '../styles';\nimport type TabsProps from './TabsProps';\nimport type { TabsInstance } from './TabsProps';\nimport TabIndicator from './TabIndicator';\nimport IndexAwareTab from './IndexAwareTab';\nimport useTabCoordinates from './useTabCoordinates';\nimport useScrollViewReaction from './useScrollViewReaction';\n\ntype TabsStyleKeys =\n | 'root'\n | 'fixedRoot'\n | 'fixedTab'\n | 'scrollableContainer';\n\ntype TabsStyles = NamedStylesStringUnion<TabsStyleKeys>;\n\nconst useStyles: UseStyles<TabsStyles> = function (): TabsStyles {\n const theme = useTheme();\n\n return {\n root: {},\n fixedRoot: {\n flexDirection: 'row',\n },\n fixedTab: {\n flex: 1,\n },\n scrollableContainer: {\n paddingHorizontal: theme.spacing(1),\n },\n };\n};\n\nconst Tabs = forwardRef<TabsInstance, TabsProps>(function Tabs(props, ref) {\n const {\n children,\n initialIndex = 0,\n disableIndicator = false,\n keyboardDismissMode = 'none',\n keyboardShouldPersistTaps = 'never',\n onChange,\n scrollable = false,\n style,\n variant = 'primary',\n UNSTABLE_sharedIndex,\n } = props;\n\n const fallbackSharedIndex = useSharedValue<number>(initialIndex);\n\n const sharedIndex = UNSTABLE_sharedIndex ?? fallbackSharedIndex;\n\n const getCurrentIndex = (): number => sharedIndex.value;\n\n const setTab = (newIndex: number) => {\n sharedIndex.value = newIndex;\n };\n\n useImperativeHandle(\n ref,\n () => ({\n getCurrentIndex,\n setTab,\n }),\n [sharedIndex],\n );\n\n const styles = useStyles();\n\n const { coordinates, updateCoordinate } = useTabCoordinates(children);\n\n const { scrollViewRef, onLayout } = useScrollViewReaction(sharedIndex, coordinates);\n\n const isReadyToRenderIndicator = coordinates.length > 0;\n\n const tabElements = React.Children.map(children, (child, index) => {\n const onLayout = (event: LayoutChangeEvent) => {\n const { x, width } = event.nativeEvent.layout;\n\n updateCoordinate(index, x, width);\n };\n\n const onMouseDown = (e: GestureResponderEvent) => {\n if (keyboardShouldPersistTaps === 'always') {\n e.preventDefault();\n }\n };\n\n const onPress = () => {\n setTab(index);\n\n onChange?.(index);\n // @ts-ignore\n child.props.onPress?.();\n };\n\n // @ts-ignore\n const tabElement = cloneElement(child, {\n enableIndicator: !disableIndicator && !isReadyToRenderIndicator,\n onLayout,\n onPress,\n onMouseDown,\n variant,\n style: scrollable ? undefined : styles.fixedTab,\n });\n\n return (\n <IndexAwareTab\n children={tabElement}\n index={index}\n sharedIndex={sharedIndex}\n />\n );\n });\n\n const tabIndicator = isReadyToRenderIndicator ? (\n <TabIndicator\n coordinates={coordinates}\n disabled={disableIndicator}\n scrollable={scrollable}\n sharedIndex={sharedIndex}\n />\n ) : null;\n\n return (\n <View\n onLayout={onLayout}\n style={css([\n styles.root,\n scrollable ? undefined : styles.fixedRoot,\n style,\n ])}\n >\n {scrollable ? (\n <ScrollView\n automaticallyAdjustContentInsets={false}\n bounces={false}\n contentContainerStyle={styles.scrollableContainer}\n directionalLockEnabled={true}\n horizontal={true}\n ref={scrollViewRef}\n scrollsToTop={false}\n showsHorizontalScrollIndicator={false}\n showsVerticalScrollIndicator={false}\n keyboardDismissMode={keyboardDismissMode}\n keyboardShouldPersistTaps={keyboardShouldPersistTaps}\n >\n {tabElements}\n {tabIndicator}\n </ScrollView>\n ) : (\n <React.Fragment>\n {tabElements}\n {tabIndicator}\n </React.Fragment>\n )}\n </View>\n );\n});\n\nexport default Tabs;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["TabsProps.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"names":[],"sources":["TabsProps.ts"],"sourcesContent":["import type { ReactNode, Ref } from 'react';\nimport type { ViewProps } from 'react-native';\nimport type { SharedValue } from 'react-native-reanimated';\nimport type { TabVariant } from '../Tab';\nimport type { OverridableComponentProps } from '../types';\n\nexport type KeyboardDismissMode =\n 'none'\n | 'on-drag'\n | 'interactive'; // ios only\n\nexport type KeyboardShouldPersistTaps =\n 'never'\n | boolean\n | 'always'\n | 'handled'; // app only\n\nexport interface TabsInstance {\n /**\n * Get current tab index.\n */\n getCurrentIndex: () => number;\n\n /**\n * Function to scroll to a specific tab. Invalid index is ignored.\n * @param index\n */\n setTab: (index: number) => void;\n}\n\nexport default interface TabsProps extends OverridableComponentProps<ViewProps, {\n ref?: Ref<TabsInstance>;\n\n /**\n * Collection of Tab components.\n */\n children: ReactNode;\n\n /**\n * If `true`, the indicator is disabled.\n * @default false\n */\n disableIndicator?: boolean;\n\n /**\n * Index of initial tab that should be selected.\n * @default 0\n */\n initialIndex?: number;\n\n /**\n * keyboard dismissing condition of dragging.\n * @default 'none'\n */\n keyboardDismissMode?: KeyboardDismissMode,\n\n /**\n * keyboard persisting condition of tapping.\n * @default 'never'\n */\n keyboardShouldPersistTaps?: KeyboardShouldPersistTaps,\n\n /**\n * Callback fired when a tab is selected.\n */\n onChange?: (newIndex: number) => void;\n\n /**\n * If `true`, the component will be able to scroll.\n * @default false\n */\n scrollable?: boolean;\n\n /**\n * Unstable API.\n */\n UNSTABLE_sharedIndex?: SharedValue<number>;\n\n /**\n * The variant to use.\n * @default 'primary'\n */\n variant?: TabVariant;\n}> {}\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["default"],"sources":["index.ts"],"sourcesContent":["export { default } from './Tabs';\nexport type { default as TabsProps } from './TabsProps'
|
|
1
|
+
{"version":3,"names":["default"],"sources":["index.ts"],"sourcesContent":["export { default } from './Tabs';\nexport type { default as TabsProps, TabsInstance } from './TabsProps';\n"],"mappings":"AAAA,SAASA,OAAT,QAAwB,QAAxB"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useCallback, useRef } from 'react';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
import { runOnJS, scrollTo, useAnimatedReaction, useAnimatedRef } from 'react-native-reanimated';
|
|
4
|
+
export default function useScrollViewReaction(sharedIndex, coordinates) {
|
|
5
|
+
const scrollViewRef = useAnimatedRef();
|
|
6
|
+
const lastScrolledXRef = useRef(NaN);
|
|
7
|
+
|
|
8
|
+
const scrollToX = x => {
|
|
9
|
+
if (Number.isFinite(x)) {
|
|
10
|
+
var _scrollViewRef$curren;
|
|
11
|
+
|
|
12
|
+
(_scrollViewRef$curren = scrollViewRef.current) === null || _scrollViewRef$curren === void 0 ? void 0 : _scrollViewRef$curren.scrollTo({
|
|
13
|
+
x,
|
|
14
|
+
y: 0,
|
|
15
|
+
animated: true
|
|
16
|
+
});
|
|
17
|
+
didScrollToX(x);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const didScrollToX = x => {
|
|
22
|
+
lastScrolledXRef.current = x;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const onLayout = useCallback(() => {
|
|
26
|
+
scrollToX(lastScrolledXRef.current);
|
|
27
|
+
}, []);
|
|
28
|
+
useAnimatedReaction(() => {
|
|
29
|
+
const prevIndex = sharedIndex.value - 1;
|
|
30
|
+
const prevCoordinate = coordinates[prevIndex];
|
|
31
|
+
|
|
32
|
+
if (prevCoordinate) {
|
|
33
|
+
const prevTabWidth = prevCoordinate.x2 - prevCoordinate.x1;
|
|
34
|
+
return Math.floor(prevCoordinate.x1 + prevTabWidth / 2);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return 0;
|
|
38
|
+
}, (x, prevX) => {
|
|
39
|
+
if (x !== prevX) {
|
|
40
|
+
if (Platform.OS === 'web') {
|
|
41
|
+
runOnJS(scrollToX)(x);
|
|
42
|
+
} else {
|
|
43
|
+
scrollTo(scrollViewRef, x, 0, true);
|
|
44
|
+
runOnJS(didScrollToX)(x);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}, [coordinates]);
|
|
48
|
+
return {
|
|
49
|
+
scrollViewRef,
|
|
50
|
+
onLayout
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
;
|
|
54
|
+
//# sourceMappingURL=useScrollViewReaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useCallback","useRef","Platform","runOnJS","scrollTo","useAnimatedReaction","useAnimatedRef","useScrollViewReaction","sharedIndex","coordinates","scrollViewRef","lastScrolledXRef","NaN","scrollToX","x","Number","isFinite","current","y","animated","didScrollToX","onLayout","prevIndex","value","prevCoordinate","prevTabWidth","x2","x1","Math","floor","prevX","OS"],"sources":["useScrollViewReaction.ts"],"sourcesContent":["import type { MutableRefObject } from 'react';\nimport { useCallback, useRef } from 'react';\nimport type { ScrollView, ViewProps } from 'react-native';\nimport { Platform } from 'react-native';\nimport { runOnJS, scrollTo, SharedValue, useAnimatedReaction, useAnimatedRef } from 'react-native-reanimated';\nimport type TabCoordinate from './TabCoordinate';\n\nexport interface UseScrollViewReaction {\n scrollViewRef: MutableRefObject<ScrollView | null>;\n onLayout: ViewProps['onLayout'];\n}\n\nexport default function useScrollViewReaction(\n sharedIndex: SharedValue<number>,\n coordinates: TabCoordinate[],\n): UseScrollViewReaction {\n const scrollViewRef = useAnimatedRef<ScrollView>();\n\n const lastScrolledXRef = useRef<number>(NaN);\n\n const scrollToX = (x: number) => {\n if (Number.isFinite(x)) {\n scrollViewRef.current?.scrollTo({ x, y: 0, animated: true });\n\n didScrollToX(x);\n }\n };\n\n const didScrollToX = (x: number) => {\n lastScrolledXRef.current = x;\n };\n\n const onLayout = useCallback(() => {\n scrollToX(lastScrolledXRef.current);\n }, []);\n\n useAnimatedReaction(\n () => {\n const prevIndex = sharedIndex.value - 1;\n const prevCoordinate = coordinates[prevIndex];\n\n if (prevCoordinate) {\n const prevTabWidth = prevCoordinate.x2 - prevCoordinate.x1;\n return Math.floor(prevCoordinate.x1 + prevTabWidth / 2);\n }\n\n return 0;\n },\n (x, prevX) => {\n if (x !== prevX) {\n if (Platform.OS === 'web') {\n runOnJS(scrollToX)(x);\n } else {\n scrollTo(scrollViewRef, x, 0, true);\n runOnJS(didScrollToX)(x);\n }\n }\n },\n [coordinates],\n );\n\n return { scrollViewRef, onLayout };\n};\n"],"mappings":"AACA,SAASA,WAAT,EAAsBC,MAAtB,QAAoC,OAApC;AAEA,SAASC,QAAT,QAAyB,cAAzB;AACA,SAASC,OAAT,EAAkBC,QAAlB,EAAyCC,mBAAzC,EAA8DC,cAA9D,QAAoF,yBAApF;AAQA,eAAe,SAASC,qBAAT,CACXC,WADW,EAEXC,WAFW,EAGU;EACrB,MAAMC,aAAa,GAAGJ,cAAc,EAApC;EAEA,MAAMK,gBAAgB,GAAGV,MAAM,CAASW,GAAT,CAA/B;;EAEA,MAAMC,SAAS,GAAIC,CAAD,IAAe;IAC7B,IAAIC,MAAM,CAACC,QAAP,CAAgBF,CAAhB,CAAJ,EAAwB;MAAA;;MACpB,yBAAAJ,aAAa,CAACO,OAAd,gFAAuBb,QAAvB,CAAgC;QAAEU,CAAF;QAAKI,CAAC,EAAE,CAAR;QAAWC,QAAQ,EAAE;MAArB,CAAhC;MAEAC,YAAY,CAACN,CAAD,CAAZ;IACH;EACJ,CAND;;EAQA,MAAMM,YAAY,GAAIN,CAAD,IAAe;IAChCH,gBAAgB,CAACM,OAAjB,GAA2BH,CAA3B;EACH,CAFD;;EAIA,MAAMO,QAAQ,GAAGrB,WAAW,CAAC,MAAM;IAC/Ba,SAAS,CAACF,gBAAgB,CAACM,OAAlB,CAAT;EACH,CAF2B,EAEzB,EAFyB,CAA5B;EAIAZ,mBAAmB,CACf,MAAM;IACF,MAAMiB,SAAS,GAAGd,WAAW,CAACe,KAAZ,GAAoB,CAAtC;IACA,MAAMC,cAAc,GAAGf,WAAW,CAACa,SAAD,CAAlC;;IAEA,IAAIE,cAAJ,EAAoB;MAChB,MAAMC,YAAY,GAAGD,cAAc,CAACE,EAAf,GAAoBF,cAAc,CAACG,EAAxD;MACA,OAAOC,IAAI,CAACC,KAAL,CAAWL,cAAc,CAACG,EAAf,GAAoBF,YAAY,GAAG,CAA9C,CAAP;IACH;;IAED,OAAO,CAAP;EACH,CAXc,EAYf,CAACX,CAAD,EAAIgB,KAAJ,KAAc;IACV,IAAIhB,CAAC,KAAKgB,KAAV,EAAiB;MACb,IAAI5B,QAAQ,CAAC6B,EAAT,KAAgB,KAApB,EAA2B;QACvB5B,OAAO,CAACU,SAAD,CAAP,CAAmBC,CAAnB;MACH,CAFD,MAEO;QACHV,QAAQ,CAACM,aAAD,EAAgBI,CAAhB,EAAmB,CAAnB,EAAsB,IAAtB,CAAR;QACAX,OAAO,CAACiB,YAAD,CAAP,CAAsBN,CAAtB;MACH;IACJ;EACJ,CArBc,EAsBf,CAACL,WAAD,CAtBe,CAAnB;EAyBA,OAAO;IAAEC,aAAF;IAAiBW;EAAjB,CAAP;AACH;AAAA"}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { Dimensions } from 'react-native';
|
|
3
3
|
export default function useValidWindowDimensions() {
|
|
4
|
-
const window =
|
|
5
|
-
const [validWindow, setValidWindow] = useState(window);
|
|
4
|
+
const [window, setWindow] = useState(() => Dimensions.get('window'));
|
|
6
5
|
useEffect(() => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
const subscription = Dimensions.addEventListener('change', newDimension => {
|
|
7
|
+
const {
|
|
8
|
+
window: newWindow
|
|
9
|
+
} = newDimension;
|
|
10
|
+
|
|
11
|
+
if (newWindow.width !== 0 && newWindow.height !== 0) {
|
|
12
|
+
setWindow(newWindow);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
return subscription.remove;
|
|
16
|
+
}, []);
|
|
17
|
+
return window;
|
|
12
18
|
}
|
|
13
19
|
//# sourceMappingURL=index.ios.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["useEffect","useState","Dimensions","useValidWindowDimensions","window","setWindow","get","subscription","addEventListener","newDimension","newWindow","width","height","remove"],"sources":["index.ios.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport type { ScaledSize } from 'react-native';\nimport { Dimensions } from 'react-native';\n\nexport default function useValidWindowDimensions(): ScaledSize {\n const [window, setWindow] = useState<ScaledSize>(() => Dimensions.get('window'));\n\n useEffect(() => {\n const subscription = Dimensions.addEventListener('change', (newDimension) => {\n const { window: newWindow } = newDimension;\n\n if (newWindow.width !== 0 && newWindow.height !== 0) {\n setWindow(newWindow);\n }\n });\n\n return subscription.remove;\n }, []);\n\n return window;\n}\n"],"mappings":"AAAA,SAASA,SAAT,EAAoBC,QAApB,QAAoC,OAApC;AAEA,SAASC,UAAT,QAA2B,cAA3B;AAEA,eAAe,SAASC,wBAAT,GAAgD;EAC3D,MAAM,CAACC,MAAD,EAASC,SAAT,IAAsBJ,QAAQ,CAAa,MAAMC,UAAU,CAACI,GAAX,CAAe,QAAf,CAAnB,CAApC;EAEAN,SAAS,CAAC,MAAM;IACZ,MAAMO,YAAY,GAAGL,UAAU,CAACM,gBAAX,CAA4B,QAA5B,EAAuCC,YAAD,IAAkB;MACzE,MAAM;QAAEL,MAAM,EAAEM;MAAV,IAAwBD,YAA9B;;MAEA,IAAIC,SAAS,CAACC,KAAV,KAAoB,CAApB,IAAyBD,SAAS,CAACE,MAAV,KAAqB,CAAlD,EAAqD;QACjDP,SAAS,CAACK,SAAD,CAAT;MACH;IACJ,CANoB,CAArB;IAQA,OAAOH,YAAY,CAACM,MAApB;EACH,CAVQ,EAUN,EAVM,CAAT;EAYA,OAAOT,MAAP;AACH"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import type { SharedValue } from 'react-native-reanimated';
|
|
4
|
+
export interface IndexAwareTabProps {
|
|
5
|
+
children: ReactElement;
|
|
6
|
+
index: number;
|
|
7
|
+
sharedIndex: SharedValue<number>;
|
|
8
|
+
}
|
|
9
|
+
export default function IndexAwareTab(props: IndexAwareTabProps): ReactElement<any, string | React.JSXElementConstructor<any>>;
|
|
@@ -16,8 +16,8 @@ export default interface TabIndicatorProps extends OverridableComponentProps<Vie
|
|
|
16
16
|
*/
|
|
17
17
|
scrollable: boolean;
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* Shared index value for using animated interpolation.
|
|
20
20
|
*/
|
|
21
|
-
|
|
21
|
+
sharedIndex: SharedValue<number>;
|
|
22
22
|
}> {
|
|
23
23
|
}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
import type TabsProps from './TabsProps';
|
|
2
|
-
|
|
3
|
+
import type { TabsInstance } from './TabsProps';
|
|
4
|
+
declare const Tabs: React.ForwardRefExoticComponent<Pick<TabsProps, "testID" | "style" | "onLayout" | "keyboardDismissMode" | "children" | "pointerEvents" | "onStartShouldSetResponder" | "onMoveShouldSetResponder" | "onResponderEnd" | "onResponderGrant" | "onResponderReject" | "onResponderMove" | "onResponderRelease" | "onResponderStart" | "onResponderTerminationRequest" | "onResponderTerminate" | "onStartShouldSetResponderCapture" | "onMoveShouldSetResponderCapture" | "hitSlop" | "removeClippedSubviews" | "nativeID" | "collapsable" | "needsOffscreenAlphaCompositing" | "renderToHardwareTextureAndroid" | "focusable" | "shouldRasterizeIOS" | "isTVSelectable" | "hasTVPreferredFocus" | "tvParallaxProperties" | "tvParallaxShiftDistanceX" | "tvParallaxShiftDistanceY" | "tvParallaxTiltAngle" | "tvParallaxMagnification" | "onTouchStart" | "onTouchMove" | "onTouchEnd" | "onTouchCancel" | "onTouchEndCapture" | "accessible" | "accessibilityActions" | "accessibilityLabel" | "accessibilityRole" | "accessibilityState" | "accessibilityHint" | "accessibilityValue" | "onAccessibilityAction" | "accessibilityLiveRegion" | "importantForAccessibility" | "accessibilityElementsHidden" | "accessibilityViewIsModal" | "onAccessibilityEscape" | "onAccessibilityTap" | "onMagicTap" | "accessibilityIgnoresInvertColors" | "variant" | "keyboardShouldPersistTaps" | "onChange" | "disableIndicator" | "initialIndex" | "scrollable" | "UNSTABLE_sharedIndex"> & React.RefAttributes<TabsInstance>>;
|
|
5
|
+
export default Tabs;
|
|
@@ -1,24 +1,37 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { ReactNode, Ref } from 'react';
|
|
2
2
|
import type { ViewProps } from 'react-native';
|
|
3
|
-
import
|
|
3
|
+
import type { SharedValue } from 'react-native-reanimated';
|
|
4
4
|
import type { TabVariant } from '../Tab';
|
|
5
5
|
import type { OverridableComponentProps } from '../types';
|
|
6
6
|
export declare type KeyboardDismissMode = 'none' | 'on-drag' | 'interactive';
|
|
7
7
|
export declare type KeyboardShouldPersistTaps = 'never' | boolean | 'always' | 'handled';
|
|
8
|
-
export
|
|
8
|
+
export interface TabsInstance {
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Get current tab index.
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
getCurrentIndex: () => number;
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Function to scroll to a specific tab. Invalid index is ignored.
|
|
15
|
+
* @param index
|
|
15
16
|
*/
|
|
16
|
-
index: number;
|
|
17
|
+
setTab: (index: number) => void;
|
|
18
|
+
}
|
|
19
|
+
export default interface TabsProps extends OverridableComponentProps<ViewProps, {
|
|
20
|
+
ref?: Ref<TabsInstance>;
|
|
21
|
+
/**
|
|
22
|
+
* Collection of Tab components.
|
|
23
|
+
*/
|
|
24
|
+
children: ReactNode;
|
|
17
25
|
/**
|
|
18
26
|
* If `true`, the indicator is disabled.
|
|
19
27
|
* @default false
|
|
20
28
|
*/
|
|
21
29
|
disableIndicator?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Index of initial tab that should be selected.
|
|
32
|
+
* @default 0
|
|
33
|
+
*/
|
|
34
|
+
initialIndex?: number;
|
|
22
35
|
/**
|
|
23
36
|
* keyboard dismissing condition of dragging.
|
|
24
37
|
* @default 'none'
|
|
@@ -39,9 +52,9 @@ export default interface TabsProps extends OverridableComponentProps<ViewProps,
|
|
|
39
52
|
*/
|
|
40
53
|
scrollable?: boolean;
|
|
41
54
|
/**
|
|
42
|
-
*
|
|
55
|
+
* Unstable API.
|
|
43
56
|
*/
|
|
44
|
-
|
|
57
|
+
UNSTABLE_sharedIndex?: SharedValue<number>;
|
|
45
58
|
/**
|
|
46
59
|
* The variant to use.
|
|
47
60
|
* @default 'primary'
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default } from './Tabs';
|
|
2
|
-
export type { default as TabsProps } from './TabsProps';
|
|
2
|
+
export type { default as TabsProps, TabsInstance } from './TabsProps';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { MutableRefObject } from 'react';
|
|
2
|
+
import type { ScrollView, ViewProps } from 'react-native';
|
|
3
|
+
import { SharedValue } from 'react-native-reanimated';
|
|
4
|
+
import type TabCoordinate from './TabCoordinate';
|
|
5
|
+
export interface UseScrollViewReaction {
|
|
6
|
+
scrollViewRef: MutableRefObject<ScrollView | null>;
|
|
7
|
+
onLayout: ViewProps['onLayout'];
|
|
8
|
+
}
|
|
9
|
+
export default function useScrollViewReaction(sharedIndex: SharedValue<number>, coordinates: TabCoordinate[]): UseScrollViewReaction;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ScaledSize } from 'react-native';
|
|
2
|
+
export default function useValidWindowDimensions(): ScaledSize;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fountain-ui/core",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.16",
|
|
4
4
|
"author": "Fountain-UI Team",
|
|
5
5
|
"description": "React components that implement Tappytoon's Fountain Design.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"publishConfig": {
|
|
68
68
|
"access": "public"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "4f247070bf942db98feafb9573e8c1dc3fc1d758"
|
|
71
71
|
}
|
|
@@ -17,7 +17,7 @@ const MINIFIED_SCALE = .96;
|
|
|
17
17
|
|
|
18
18
|
// at "node_modules/react-native/Libraries/Pressability.js"
|
|
19
19
|
// const DEFAULT_MIN_PRESS_DURATION = 130;
|
|
20
|
-
const
|
|
20
|
+
const SCALE_EFFECT_PRESS_IN_DELAY = 130;
|
|
21
21
|
|
|
22
22
|
type TimingAnimationValue = Animated.Value | Animated.ValueXY;
|
|
23
23
|
type TimingAnimationToValue = Animated.TimingAnimationConfig['toValue'];
|
|
@@ -95,6 +95,10 @@ export default function ButtonBase(props: ButtonBaseProps) {
|
|
|
95
95
|
transform: [{ scale }],
|
|
96
96
|
};
|
|
97
97
|
|
|
98
|
+
const pressDelay = pressEffect === 'scale'
|
|
99
|
+
? SCALE_EFFECT_PRESS_IN_DELAY
|
|
100
|
+
: 0;
|
|
101
|
+
|
|
98
102
|
return (
|
|
99
103
|
<AnimatedPressable
|
|
100
104
|
disabled={disabled}
|
|
@@ -105,7 +109,7 @@ export default function ButtonBase(props: ButtonBaseProps) {
|
|
|
105
109
|
animatedStyle,
|
|
106
110
|
styleProp,
|
|
107
111
|
]}
|
|
108
|
-
unstable_pressDelay={
|
|
112
|
+
unstable_pressDelay={pressDelay}
|
|
109
113
|
{...otherProps}
|
|
110
114
|
>
|
|
111
115
|
{typeof children !== 'function' ? (
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import React, { useEffect } from 'react';
|
|
2
|
-
import { ViewProps } from 'react-native';
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import type { ViewProps } from 'react-native';
|
|
3
|
+
import { Animated, Easing } from 'react-native';
|
|
3
4
|
import { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';
|
|
4
|
-
import type { WithTimingConfig } from 'react-native-reanimated';
|
|
5
|
-
import Animated, { Easing, useAnimatedStyle, useSharedValue, withRepeat, withTiming } from 'react-native-reanimated';
|
|
6
5
|
import { CircularProgress as CircularProgressIcon } from '../internal/icons';
|
|
7
6
|
import { OverridableComponentProps } from '../types';
|
|
8
7
|
|
|
9
8
|
type CircularProgressStyles = NamedStylesStringUnion<'root'>;
|
|
10
9
|
|
|
11
|
-
const ANIMATION_CONFIG: Readonly<WithTimingConfig> = { duration: 900, easing: Easing.linear };
|
|
12
|
-
|
|
13
10
|
const MIN_ROTATE_DEGREE = 0;
|
|
14
11
|
const MAX_ROTATE_DEGREE = 360;
|
|
15
12
|
|
|
@@ -27,18 +24,29 @@ export default function CircularProgress(props: OverridableComponentProps<ViewPr
|
|
|
27
24
|
|
|
28
25
|
const styles = useStyles();
|
|
29
26
|
|
|
30
|
-
const rotate =
|
|
27
|
+
const rotate = useRef(new Animated.Value(MIN_ROTATE_DEGREE)).current;
|
|
31
28
|
|
|
32
|
-
const animatedStyle =
|
|
33
|
-
transform: [{
|
|
34
|
-
|
|
29
|
+
const animatedStyle = {
|
|
30
|
+
transform: [{
|
|
31
|
+
rotate: rotate.interpolate({
|
|
32
|
+
inputRange: [MIN_ROTATE_DEGREE, MAX_ROTATE_DEGREE],
|
|
33
|
+
outputRange: [`${MIN_ROTATE_DEGREE}deg`, `${MAX_ROTATE_DEGREE}deg`],
|
|
34
|
+
}),
|
|
35
|
+
}],
|
|
36
|
+
};
|
|
35
37
|
|
|
36
38
|
useEffect(() => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
Animated.loop(
|
|
40
|
+
Animated.timing(
|
|
41
|
+
rotate,
|
|
42
|
+
{
|
|
43
|
+
toValue: MAX_ROTATE_DEGREE,
|
|
44
|
+
duration: 900,
|
|
45
|
+
easing: Easing.linear,
|
|
46
|
+
useNativeDriver: true,
|
|
47
|
+
},
|
|
48
|
+
),
|
|
49
|
+
).start();
|
|
42
50
|
}, []);
|
|
43
51
|
|
|
44
52
|
return (
|
package/src/Tab/Tab.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { cloneElement } from 'react';
|
|
2
2
|
import { Platform, Text } from 'react-native';
|
|
3
3
|
import Badge from '../Badge';
|
|
4
4
|
import TabBase from '../TabBase';
|
|
@@ -26,9 +26,9 @@ export default function Tab(props: TabProps) {
|
|
|
26
26
|
const {
|
|
27
27
|
badgeVisible = false,
|
|
28
28
|
children,
|
|
29
|
-
enableIndicator,
|
|
29
|
+
enableIndicator = false,
|
|
30
30
|
icon: defaultIcon,
|
|
31
|
-
selected,
|
|
31
|
+
selected = false,
|
|
32
32
|
selectedIcon,
|
|
33
33
|
variant = 'primary',
|
|
34
34
|
style,
|
|
@@ -59,7 +59,7 @@ export default function Tab(props: TabProps) {
|
|
|
59
59
|
const pressEffect = selected ? 'none' : 'opacity';
|
|
60
60
|
|
|
61
61
|
const icon = selected ? (selectedIcon || defaultIcon) : defaultIcon;
|
|
62
|
-
const iconElement = icon ?
|
|
62
|
+
const iconElement = icon ? cloneElement(icon, { fill: color }) : null;
|
|
63
63
|
|
|
64
64
|
return (
|
|
65
65
|
<TabBase
|
|
@@ -78,7 +78,7 @@ export default function Tab(props: TabProps) {
|
|
|
78
78
|
style={css(fontStyle)}
|
|
79
79
|
/>
|
|
80
80
|
|
|
81
|
-
{enableIndicator ? <TabIndicator/> : null}
|
|
81
|
+
{(enableIndicator && selected) ? <TabIndicator/> : null}
|
|
82
82
|
</TabBase>
|
|
83
83
|
);
|
|
84
84
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import React, { cloneElement, useState } from 'react';
|
|
3
|
+
import type { SharedValue } from 'react-native-reanimated';
|
|
4
|
+
import { runOnJS, useAnimatedReaction } from 'react-native-reanimated';
|
|
5
|
+
|
|
6
|
+
export interface IndexAwareTabProps {
|
|
7
|
+
children: ReactElement;
|
|
8
|
+
index: number;
|
|
9
|
+
sharedIndex: SharedValue<number>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default function IndexAwareTab(props: IndexAwareTabProps) {
|
|
13
|
+
const {
|
|
14
|
+
children,
|
|
15
|
+
index,
|
|
16
|
+
sharedIndex,
|
|
17
|
+
} = props;
|
|
18
|
+
|
|
19
|
+
const [selected, setSelected] = useState(index === sharedIndex.value);
|
|
20
|
+
|
|
21
|
+
useAnimatedReaction(
|
|
22
|
+
() => index === sharedIndex.value,
|
|
23
|
+
(result) => {
|
|
24
|
+
runOnJS(setSelected)(result);
|
|
25
|
+
},
|
|
26
|
+
[index],
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
return cloneElement(children, { selected });
|
|
30
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
2
|
+
import type { WithTimingConfig } from 'react-native-reanimated';
|
|
3
|
+
import Animated, { Easing, useAnimatedStyle, withTiming } from 'react-native-reanimated';
|
|
3
4
|
import { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';
|
|
4
5
|
import { useTheme } from '../styles';
|
|
5
6
|
import type TabIndicatorProps from './TabIndicatorProps';
|
|
@@ -7,14 +8,21 @@ import { defaultCoordinate } from './TabCoordinate';
|
|
|
7
8
|
|
|
8
9
|
type TabIndicatorStyles = NamedStylesStringUnion<'root' | 'disabled'>;
|
|
9
10
|
|
|
11
|
+
const INDICATOR_WIDTH = 10;
|
|
12
|
+
const INDICATOR_HEIGHT = 4;
|
|
13
|
+
|
|
14
|
+
const SCROLLABLE_TABS_INSET = 12 * 2;
|
|
15
|
+
|
|
10
16
|
const useStyles: UseStyles<TabIndicatorStyles> = function (): TabIndicatorStyles {
|
|
11
17
|
const theme = useTheme();
|
|
12
18
|
|
|
13
19
|
return {
|
|
14
20
|
root: {
|
|
15
21
|
backgroundColor: theme.palette.secondary.main,
|
|
22
|
+
left: 0,
|
|
16
23
|
bottom: 0,
|
|
17
|
-
|
|
24
|
+
width: INDICATOR_WIDTH,
|
|
25
|
+
height: INDICATOR_HEIGHT,
|
|
18
26
|
position: 'absolute',
|
|
19
27
|
},
|
|
20
28
|
disabled: {
|
|
@@ -23,12 +31,17 @@ const useStyles: UseStyles<TabIndicatorStyles> = function (): TabIndicatorStyles
|
|
|
23
31
|
};
|
|
24
32
|
};
|
|
25
33
|
|
|
34
|
+
const ANIMATION_CONFIG: Readonly<WithTimingConfig> = {
|
|
35
|
+
duration: 300,
|
|
36
|
+
easing: Easing.out(Easing.exp),
|
|
37
|
+
};
|
|
38
|
+
|
|
26
39
|
export default function TabIndicator(props: TabIndicatorProps) {
|
|
27
40
|
const {
|
|
28
41
|
coordinates,
|
|
29
42
|
disabled,
|
|
30
43
|
scrollable,
|
|
31
|
-
|
|
44
|
+
sharedIndex,
|
|
32
45
|
style,
|
|
33
46
|
...otherProps
|
|
34
47
|
} = props;
|
|
@@ -36,23 +49,22 @@ export default function TabIndicator(props: TabIndicatorProps) {
|
|
|
36
49
|
const styles = useStyles();
|
|
37
50
|
|
|
38
51
|
const animatedStyle = useAnimatedStyle(() => {
|
|
39
|
-
const
|
|
52
|
+
const index = sharedIndex.value;
|
|
40
53
|
|
|
41
|
-
const
|
|
42
|
-
const offset = rawScrollValue % 1;
|
|
54
|
+
const { x1, x2 } = coordinates[index] ?? defaultCoordinate;
|
|
43
55
|
|
|
44
|
-
const
|
|
45
|
-
const nextCoordinate = coordinates[index + 1] ?? defaultCoordinate;
|
|
56
|
+
const tabWidth = x2 - x1;
|
|
46
57
|
|
|
47
|
-
const
|
|
48
|
-
const x2 = (offset * nextCoordinate.x2 + (1 - offset) * coordinate.x2);
|
|
58
|
+
const translateX = x1 + (tabWidth - INDICATOR_WIDTH) / 2;
|
|
49
59
|
|
|
50
|
-
const
|
|
51
|
-
const
|
|
60
|
+
const inset = scrollable ? SCROLLABLE_TABS_INSET : 0;
|
|
61
|
+
const scaleX = (tabWidth - inset) / INDICATOR_WIDTH;
|
|
52
62
|
|
|
53
63
|
return {
|
|
54
|
-
|
|
55
|
-
|
|
64
|
+
transform: [
|
|
65
|
+
{ translateX: withTiming(translateX, ANIMATION_CONFIG) },
|
|
66
|
+
{ scaleX: withTiming(scaleX, ANIMATION_CONFIG) },
|
|
67
|
+
],
|
|
56
68
|
};
|
|
57
69
|
}, [coordinates, scrollable]);
|
|
58
70
|
|
|
@@ -20,7 +20,7 @@ export default interface TabIndicatorProps extends OverridableComponentProps<Vie
|
|
|
20
20
|
scrollable: boolean;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* Shared index value for using animated interpolation.
|
|
24
24
|
*/
|
|
25
|
-
|
|
25
|
+
sharedIndex: SharedValue<number>;
|
|
26
26
|
}> {}
|