@tactics/toddle-styleguide 5.4.45 → 5.4.47
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/babel.config.js +3 -1
- package/package.json +8 -5
- package/src/components/atoms/backdrop/backdrop.component.tsx +10 -20
- package/src/components/atoms/check-switch/check-switch.component.tsx +16 -8
- package/src/components/molecules/swipe/swipe.component.native.tsx +1 -0
- package/src/components/molecules/swipe/swipe.styles.d.ts +1 -0
- package/src/components/molecules/swipe/swipe.styles.js +1 -0
- package/src/components/templates/popover/components/modal/modal.component.d.ts +2 -2
- package/src/components/templates/popover/components/modal/modal.component.tsx +18 -24
- package/src/components/templates/popover/popover.component.tsx +1 -1
- package/src/components/templates/popover-action/popover-action.component.tsx +31 -21
package/babel.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tactics/toddle-styleguide",
|
|
3
|
-
"version": "5.4.
|
|
3
|
+
"version": "5.4.47",
|
|
4
4
|
"main": "index.tsx",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"prepublish": "tsc",
|
|
@@ -64,7 +64,9 @@
|
|
|
64
64
|
"react-native-web": "~0.21.0",
|
|
65
65
|
"react-native-wheel-picker-expo": "^0.5.4",
|
|
66
66
|
"react-native-wheely": "^0.6.0",
|
|
67
|
-
"typescript": "~5.9.3"
|
|
67
|
+
"typescript": "~5.9.3",
|
|
68
|
+
"react-native-reanimated": "~4.1.6",
|
|
69
|
+
"react-native-worklets": "0.5.1"
|
|
68
70
|
},
|
|
69
71
|
"resolutions": {
|
|
70
72
|
"@react-native-picker/picker": "2.11.1"
|
|
@@ -82,11 +84,12 @@
|
|
|
82
84
|
},
|
|
83
85
|
"scripts": {
|
|
84
86
|
"preinstall": "npx only-allow pnpm",
|
|
85
|
-
"start": "./node_modules/.bin/tsc && ./node_modules/.bin/expo start",
|
|
87
|
+
"start": "./node_modules/.bin/tsc && ./node_modules/.bin/expo start -c",
|
|
86
88
|
"format": "./node_modules/.bin/prettier --write src/.",
|
|
87
89
|
"types": "./node_modules/.bin/tsc index.tsx --declaration --allowJs --emitDeclarationOnly --esModuleInterop --jsx react-native --skipLibCheck --target es5",
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
+
"prebuild": "npx expo prebuild --clean",
|
|
91
|
+
"android": "npx expo run:android",
|
|
92
|
+
"ios": "npx expo run:ios",
|
|
90
93
|
"release:patch": "pnpm version patch --git-tag-version=false",
|
|
91
94
|
"release:minor": "pnpm version minor --git-tag-version=false",
|
|
92
95
|
"release:major": "pnpm version major --git-tag-version=false"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {useContext,
|
|
2
|
+
import {useContext, useEffect, useRef} from 'react';
|
|
3
3
|
|
|
4
4
|
import {ThemeCtx} from '../../../context/theme.context';
|
|
5
5
|
import {Animated} from 'react-native';
|
|
@@ -12,34 +12,24 @@ type PopoverBackdropProps = {
|
|
|
12
12
|
|
|
13
13
|
const Backdrop = ({isVisible, touchBackDrop}: PopoverBackdropProps) => {
|
|
14
14
|
const context = useContext(ThemeCtx);
|
|
15
|
-
const opacity =
|
|
15
|
+
const opacity = useRef(new Animated.Value(0)).current;
|
|
16
16
|
|
|
17
17
|
const styles = Stylesheet(context);
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
useEffect(() => {
|
|
20
20
|
Animated.timing(opacity, {
|
|
21
|
-
toValue: 0.75,
|
|
22
|
-
duration:
|
|
21
|
+
toValue: isVisible ? 0.75 : 0,
|
|
22
|
+
duration: isVisible ? 120 : 300,
|
|
23
23
|
useNativeDriver: true,
|
|
24
24
|
}).start();
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const close = () => {
|
|
28
|
-
Animated.timing(opacity, {
|
|
29
|
-
toValue: 0,
|
|
30
|
-
duration: 600,
|
|
31
|
-
useNativeDriver: true,
|
|
32
|
-
}).start();
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
if (isVisible) {
|
|
36
|
-
open();
|
|
37
|
-
} else {
|
|
38
|
-
close();
|
|
39
|
-
}
|
|
25
|
+
}, [isVisible, opacity]);
|
|
40
26
|
|
|
41
27
|
return (
|
|
42
28
|
<Animated.View
|
|
29
|
+
accessible={true}
|
|
30
|
+
accessibilityRole="button"
|
|
31
|
+
accessibilityLabel="Close modal"
|
|
32
|
+
onAccessibilityTap={() => (touchBackDrop ? touchBackDrop(false) : null)}
|
|
43
33
|
onTouchStart={() => (touchBackDrop ? touchBackDrop(false) : null)}
|
|
44
34
|
style={[styles.element, {opacity: opacity}]}
|
|
45
35
|
/>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {useContext, useRef} from 'react';
|
|
2
|
+
import {useContext, useEffect, useRef} from 'react';
|
|
3
3
|
|
|
4
4
|
import {View, Animated, Pressable, Easing} from 'react-native';
|
|
5
5
|
import {ThemeCtx} from '../../../context/theme.context';
|
|
@@ -21,12 +21,14 @@ export const Check = ({value, onToggle}: CheckProps) => {
|
|
|
21
21
|
outputRange: [0, 27],
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
Animated.timing(positionButton, {
|
|
26
|
+
toValue: value ? 1 : 0,
|
|
27
|
+
duration: 200,
|
|
28
|
+
easing: Easing.linear,
|
|
29
|
+
useNativeDriver: true,
|
|
30
|
+
}).start();
|
|
31
|
+
}, [value, positionButton]);
|
|
30
32
|
|
|
31
33
|
const animatedStyle = {
|
|
32
34
|
transform: [
|
|
@@ -38,7 +40,13 @@ export const Check = ({value, onToggle}: CheckProps) => {
|
|
|
38
40
|
|
|
39
41
|
return (
|
|
40
42
|
<View style={styles.container}>
|
|
41
|
-
<Pressable
|
|
43
|
+
<Pressable
|
|
44
|
+
onPress={onToggle}
|
|
45
|
+
accessible={true}
|
|
46
|
+
accessibilityRole="switch"
|
|
47
|
+
accessibilityState={{ checked: value }}
|
|
48
|
+
accessibilityLabel="Toggle"
|
|
49
|
+
>
|
|
42
50
|
<View style={styles.toggleContainer}>
|
|
43
51
|
<Animated.View style={[styles.thumbStyle, animatedStyle]} />
|
|
44
52
|
</View>
|
|
@@ -6,7 +6,7 @@ type PopoverModalProps = {
|
|
|
6
6
|
isVisible: boolean;
|
|
7
7
|
children: React.ReactNode;
|
|
8
8
|
windowHeight: number;
|
|
9
|
-
|
|
9
|
+
disableScrollContent?: boolean;
|
|
10
10
|
};
|
|
11
|
-
declare const Modal: ({ isVisible, title, subtitle, onClose, children, windowHeight,
|
|
11
|
+
declare const Modal: ({ isVisible, title, subtitle, onClose, children, windowHeight, disableScrollContent, }: PopoverModalProps) => React.JSX.Element;
|
|
12
12
|
export { Modal as Modal };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {useContext,
|
|
2
|
+
import {useContext, useEffect, useRef, useState} from 'react';
|
|
3
3
|
import {Animated, View} from 'react-native';
|
|
4
4
|
import {Stylesheet} from './modal.styles';
|
|
5
5
|
import {Close} from './close/close.component';
|
|
@@ -14,7 +14,7 @@ type PopoverModalProps = {
|
|
|
14
14
|
isVisible: boolean;
|
|
15
15
|
children: React.ReactNode;
|
|
16
16
|
windowHeight: number;
|
|
17
|
-
|
|
17
|
+
disableScrollContent?: boolean;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
const Modal = ({
|
|
@@ -24,7 +24,7 @@ const Modal = ({
|
|
|
24
24
|
onClose,
|
|
25
25
|
children,
|
|
26
26
|
windowHeight,
|
|
27
|
-
|
|
27
|
+
disableScrollContent,
|
|
28
28
|
}: PopoverModalProps) => {
|
|
29
29
|
// Keep element and window size in local state.
|
|
30
30
|
const [elementSize, setElementSize] = useState({width: 0, height: 0});
|
|
@@ -40,32 +40,23 @@ const Modal = ({
|
|
|
40
40
|
|
|
41
41
|
const saveHeight = elementHeight > maxHeight ? maxHeight : elementHeight;
|
|
42
42
|
|
|
43
|
-
const translateY =
|
|
44
|
-
() => new Animated.Value(translateYStartingPoint),
|
|
45
|
-
[translateYStartingPoint]
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
const open = () => {
|
|
49
|
-
Animated.timing(translateY, {
|
|
50
|
-
toValue: translateYStartingPoint - saveHeight,
|
|
51
|
-
duration: 500,
|
|
52
|
-
useNativeDriver: true,
|
|
53
|
-
}).start();
|
|
54
|
-
};
|
|
43
|
+
const translateY = useRef(new Animated.Value(translateYStartingPoint)).current;
|
|
55
44
|
|
|
56
|
-
|
|
45
|
+
// Animate when visibility changes
|
|
46
|
+
useEffect(() => {
|
|
57
47
|
Animated.timing(translateY, {
|
|
58
|
-
toValue: translateYStartingPoint,
|
|
48
|
+
toValue: isVisible ? translateYStartingPoint - saveHeight : translateYStartingPoint,
|
|
59
49
|
duration: 500,
|
|
60
50
|
useNativeDriver: true,
|
|
61
51
|
}).start();
|
|
62
|
-
};
|
|
52
|
+
}, [isVisible, saveHeight, translateYStartingPoint, translateY]);
|
|
63
53
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
54
|
+
// If height changes while visible, jump to new position without replaying from bottom
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (!isVisible) return;
|
|
57
|
+
// @ts-ignore setValue exists on Animated.Value
|
|
58
|
+
translateY.setValue(translateYStartingPoint - saveHeight);
|
|
59
|
+
}, [saveHeight, translateYStartingPoint, isVisible, translateY]);
|
|
69
60
|
|
|
70
61
|
const transform = [{translateY: translateY}];
|
|
71
62
|
|
|
@@ -76,11 +67,14 @@ const Modal = ({
|
|
|
76
67
|
const {width, height} = event.nativeEvent.layout;
|
|
77
68
|
setElementSize({width: width, height: height});
|
|
78
69
|
}}
|
|
70
|
+
accessibilityViewIsModal={true}
|
|
71
|
+
importantForAccessibility="yes"
|
|
72
|
+
accessibilityLabel={title}
|
|
79
73
|
>
|
|
80
74
|
<Close onPress={onClose} />
|
|
81
75
|
<Animated.View style={styles.inner}>
|
|
82
76
|
{title ? <Heading title={title} subtitle={subtitle} /> : null}
|
|
83
|
-
{
|
|
77
|
+
{disableScrollContent ? (
|
|
84
78
|
<View>{children}</View>
|
|
85
79
|
) : (
|
|
86
80
|
<ScrollContent>{children}</ScrollContent>
|
|
@@ -49,16 +49,20 @@ export const PopOverAction = ({
|
|
|
49
49
|
index: number,
|
|
50
50
|
layout: LayoutChangeEvent['nativeEvent']['layout']
|
|
51
51
|
) => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
// Ignore zero-height layouts which can occur before content renders,
|
|
53
|
+
// otherwise the sheet may collapse and appear to lose content.
|
|
54
|
+
if (layout?.height && layout.height > 0) {
|
|
55
|
+
setChildDimensions((prev) => {
|
|
56
|
+
const updated = [...prev];
|
|
57
|
+
updated[index] = layout;
|
|
58
|
+
return updated;
|
|
59
|
+
});
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
// Ensure element size is known for the currently visible child so the animation can open
|
|
62
|
+
// even if Swipe never emits onIndexChange (e.g., only one child or Swipe not implemented yet).
|
|
63
|
+
if (index === currentChildIndex) {
|
|
64
|
+
setElementSize({ width: layout.width, height: layout.height });
|
|
65
|
+
}
|
|
62
66
|
}
|
|
63
67
|
};
|
|
64
68
|
|
|
@@ -115,14 +119,11 @@ export const PopOverAction = ({
|
|
|
115
119
|
const styles = Stylesheet(context);
|
|
116
120
|
|
|
117
121
|
const elementHeight = Math.round(elementSize.height);
|
|
118
|
-
const maxHeight = Math.round(windowHeight * 0.
|
|
122
|
+
const maxHeight = Math.round(windowHeight * 0.9);
|
|
119
123
|
const translateYStartingPoint = windowHeight;
|
|
120
124
|
const saveHeight = elementHeight > maxHeight ? maxHeight : elementHeight;
|
|
121
125
|
|
|
122
|
-
const translateY =
|
|
123
|
-
() => new Animated.Value(translateYStartingPoint),
|
|
124
|
-
[translateYStartingPoint]
|
|
125
|
-
);
|
|
126
|
+
const translateY = React.useRef(new Animated.Value(translateYStartingPoint)).current;
|
|
126
127
|
|
|
127
128
|
const open = () => {
|
|
128
129
|
Animated.timing(translateY, {
|
|
@@ -143,7 +144,17 @@ export const PopOverAction = ({
|
|
|
143
144
|
useEffect(() => {
|
|
144
145
|
if (isVisible) open();
|
|
145
146
|
else close();
|
|
146
|
-
}, [isVisible
|
|
147
|
+
}, [isVisible]);
|
|
148
|
+
|
|
149
|
+
// When the content height changes while the popover is open, adjust the position
|
|
150
|
+
// instantly to match the new height instead of replaying the open animation.
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
if (!isVisible) return;
|
|
153
|
+
// Jump to the new position without animating from the bottom again
|
|
154
|
+
translateY.stopAnimation?.(() => {});
|
|
155
|
+
// @ts-ignore - setValue exists on Animated.Value
|
|
156
|
+
translateY.setValue(translateYStartingPoint - saveHeight);
|
|
157
|
+
}, [saveHeight, isVisible, translateYStartingPoint]);
|
|
147
158
|
|
|
148
159
|
const transform = [{ translateY }];
|
|
149
160
|
|
|
@@ -153,13 +164,12 @@ export const PopOverAction = ({
|
|
|
153
164
|
pointerEvents={isVisible ? 'box-none' : 'none'}
|
|
154
165
|
>
|
|
155
166
|
<Backdrop isVisible={isVisible} touchBackDrop={touchBackDrop} />
|
|
156
|
-
|
|
157
167
|
<Animated.View
|
|
158
|
-
style={[
|
|
159
|
-
|
|
160
|
-
{
|
|
161
|
-
{
|
|
162
|
-
|
|
168
|
+
style={[styles.slidePanelContainer, {maxHeight: maxHeight}, {transform: transform}]}
|
|
169
|
+
onLayout={(event) => {
|
|
170
|
+
const {width, height} = event.nativeEvent.layout;
|
|
171
|
+
setElementSize({width: width, height: height});
|
|
172
|
+
}}
|
|
163
173
|
>
|
|
164
174
|
<Swipe onIndexChange={handleChildIndexChange}>
|
|
165
175
|
{renderChildrenWithLayout(children, handleChildLayout)}
|