@fountain-ui/core 2.0.0-beta.82 → 2.0.0-beta.83
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/Accordion/Accordion.js +9 -15
- package/build/commonjs/Accordion/Accordion.js.map +1 -1
- package/build/commonjs/Dialog/Dialog.js +59 -31
- package/build/commonjs/Dialog/Dialog.js.map +1 -1
- package/build/commonjs/Dialog/DialogProps.js.map +1 -1
- package/build/commonjs/Modal/AnimatedContainer/index.js +153 -0
- package/build/commonjs/Modal/AnimatedContainer/index.js.map +1 -0
- package/build/commonjs/Modal/Modal.js +41 -15
- package/build/commonjs/Modal/Modal.js.map +1 -1
- package/build/commonjs/Modal/ModalProps.js +12 -0
- package/build/commonjs/Modal/ModalProps.js.map +1 -1
- package/build/commonjs/Modal/index.js +8 -0
- package/build/commonjs/Modal/index.js.map +1 -1
- package/build/module/Accordion/Accordion.js +9 -15
- package/build/module/Accordion/Accordion.js.map +1 -1
- package/build/module/Dialog/Dialog.js +61 -31
- package/build/module/Dialog/Dialog.js.map +1 -1
- package/build/module/Dialog/DialogProps.js.map +1 -1
- package/build/module/Modal/AnimatedContainer/index.js +131 -0
- package/build/module/Modal/AnimatedContainer/index.js.map +1 -0
- package/build/module/Modal/Modal.js +41 -14
- package/build/module/Modal/Modal.js.map +1 -1
- package/build/module/Modal/ModalProps.js +5 -0
- package/build/module/Modal/ModalProps.js.map +1 -1
- package/build/module/Modal/index.js +1 -0
- package/build/module/Modal/index.js.map +1 -1
- package/build/typescript/Dialog/DialogProps.d.ts +6 -0
- package/build/typescript/Modal/AnimatedContainer/index.d.ts +5 -0
- package/build/typescript/Modal/ModalProps.d.ts +41 -8
- package/build/typescript/Modal/index.d.ts +2 -1
- package/package.json +2 -2
- package/src/Accordion/Accordion.tsx +6 -11
- package/src/Dialog/Dialog.tsx +70 -32
- package/src/Dialog/DialogProps.ts +7 -0
- package/src/Modal/AnimatedContainer/index.tsx +156 -0
- package/src/Modal/Modal.tsx +42 -18
- package/src/Modal/ModalProps.ts +51 -10
- package/src/Modal/index.ts +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","View","css","StyleSheet","useElevationStyle","
|
|
1
|
+
{"version":3,"names":["React","View","css","StyleSheet","useElevationStyle","AnimatedContainer","SimpleBackdrop","createModalCloseEvent","reason","metadata","Modal","props","animationStyle","backdropOpacity","children","closeAnimation","disableAnimation","hideBackdrop","initialOpacity","initialTranslateY","onClose","onEnter","onEnterProp","onEntered","onEnteredProp","onExit","onExitProp","onExited","onExitedProp","openAnimation","style","visible","otherProps","handleBackdropPress","exited","setExited","useState","elevationStyle","absoluteFill"],"sources":["Modal.tsx"],"sourcesContent":["import React from 'react';\nimport { View } from 'react-native';\nimport { css, StyleSheet } from '../styles';\nimport { useElevationStyle } from '../hooks';\nimport type ModalProps from './ModalProps';\nimport AnimatedContainer from './AnimatedContainer';\nimport SimpleBackdrop from './SimpleBackdrop';\n\nexport type ModalCloseReasonType = 'OUTSIDE_PRESS' | 'HARDWARE_BACK_PRESS' | 'CLOSE_BUTTON_PRESS' | 'UNKNOWN';\n\nexport interface ModalCloseEvent {\n metadata: {\n reason: ModalCloseReasonType\n };\n}\n\nexport const createModalCloseEvent = (reason: ModalCloseReasonType) => ({\n metadata: {\n reason,\n },\n});\n\nexport default function Modal(props: ModalProps) {\n const {\n animationStyle,\n backdropOpacity = 0.5,\n children,\n closeAnimation,\n disableAnimation = false,\n hideBackdrop = false,\n initialOpacity,\n initialTranslateY,\n onClose,\n onEnter: onEnterProp,\n onEntered: onEnteredProp,\n onExit: onExitProp,\n onExited: onExitedProp,\n openAnimation,\n style,\n visible,\n ...otherProps\n } = props;\n\n const handleBackdropPress = () => {\n if (onClose) {\n onClose(createModalCloseEvent('OUTSIDE_PRESS'));\n }\n };\n\n const [exited, setExited] = React.useState(true);\n\n const elevationStyle = useElevationStyle(6);\n\n const onEnter = () => {\n setExited(false);\n onEnterProp?.();\n };\n\n const onEntered = () => {\n onEnteredProp?.();\n };\n\n const onExit = () => {\n onExitProp?.();\n };\n\n const onExited = () => {\n setExited(true);\n onExitedProp?.();\n };\n\n if (!visible) {\n if (disableAnimation || exited) {\n return null;\n }\n }\n\n return (\n <View\n style={css([\n StyleSheet.absoluteFill,\n elevationStyle,\n style,\n ])}\n {...otherProps}\n >\n {(!hideBackdrop && visible) ? (\n <SimpleBackdrop\n onPress={handleBackdropPress}\n opacity={backdropOpacity}\n />\n ) : null}\n\n {!disableAnimation ? (\n <AnimatedContainer\n children={children}\n closeAnimation={closeAnimation}\n initialOpacity={initialOpacity}\n initialTranslateY={initialTranslateY}\n onEnter={onEnter}\n onEntered={onEntered}\n onExit={onExit}\n onExited={onExited}\n openAnimation={openAnimation}\n style={animationStyle}\n visible={visible}\n />\n ) : children}\n </View>\n );\n};\n"],"mappings":";;AAAA,OAAOA,KAAP,MAAkB,OAAlB;AACA,SAASC,IAAT,QAAqB,cAArB;AACA,SAASC,GAAT,EAAcC,UAAd,QAAgC,WAAhC;AACA,SAASC,iBAAT,QAAkC,UAAlC;AAEA,OAAOC,iBAAP,MAA8B,qBAA9B;AACA,OAAOC,cAAP,MAA2B,kBAA3B;AAUA,OAAO,MAAMC,qBAAqB,GAAIC,MAAD,KAAmC;EACpEC,QAAQ,EAAE;IACND;EADM;AAD0D,CAAnC,CAA9B;AAMP,eAAe,SAASE,KAAT,CAAeC,KAAf,EAAkC;EAC7C,MAAM;IACFC,cADE;IAEFC,eAAe,GAAG,GAFhB;IAGFC,QAHE;IAIFC,cAJE;IAKFC,gBAAgB,GAAG,KALjB;IAMFC,YAAY,GAAG,KANb;IAOFC,cAPE;IAQFC,iBARE;IASFC,OATE;IAUFC,OAAO,EAAEC,WAVP;IAWFC,SAAS,EAAEC,aAXT;IAYFC,MAAM,EAAEC,UAZN;IAaFC,QAAQ,EAAEC,YAbR;IAcFC,aAdE;IAeFC,KAfE;IAgBFC,OAhBE;IAiBF,GAAGC;EAjBD,IAkBFrB,KAlBJ;;EAoBA,MAAMsB,mBAAmB,GAAG,MAAM;IAC9B,IAAIb,OAAJ,EAAa;MACTA,OAAO,CAACb,qBAAqB,CAAC,eAAD,CAAtB,CAAP;IACH;EACJ,CAJD;;EAMA,MAAM,CAAC2B,MAAD,EAASC,SAAT,IAAsBnC,KAAK,CAACoC,QAAN,CAAe,IAAf,CAA5B;EAEA,MAAMC,cAAc,GAAGjC,iBAAiB,CAAC,CAAD,CAAxC;;EAEA,MAAMiB,OAAO,GAAG,MAAM;IAClBc,SAAS,CAAC,KAAD,CAAT;IACAb,WAAW,SAAX,IAAAA,WAAW,WAAX,YAAAA,WAAW;EACd,CAHD;;EAKA,MAAMC,SAAS,GAAG,MAAM;IACpBC,aAAa,SAAb,IAAAA,aAAa,WAAb,YAAAA,aAAa;EAChB,CAFD;;EAIA,MAAMC,MAAM,GAAG,MAAM;IACjBC,UAAU,SAAV,IAAAA,UAAU,WAAV,YAAAA,UAAU;EACb,CAFD;;EAIA,MAAMC,QAAQ,GAAG,MAAM;IACnBQ,SAAS,CAAC,IAAD,CAAT;IACAP,YAAY,SAAZ,IAAAA,YAAY,WAAZ,YAAAA,YAAY;EACf,CAHD;;EAKA,IAAI,CAACG,OAAL,EAAc;IACV,IAAIf,gBAAgB,IAAIkB,MAAxB,EAAgC;MAC5B,OAAO,IAAP;IACH;EACJ;;EAED,oBACI,oBAAC,IAAD;IACI,KAAK,EAAEhC,GAAG,CAAC,CACPC,UAAU,CAACmC,YADJ,EAEPD,cAFO,EAGPP,KAHO,CAAD;EADd,GAMQE,UANR,GAQM,CAACf,YAAD,IAAiBc,OAAlB,gBACG,oBAAC,cAAD;IACI,OAAO,EAAEE,mBADb;IAEI,OAAO,EAAEpB;EAFb,EADH,GAKG,IAbR,EAeK,CAACG,gBAAD,gBACG,oBAAC,iBAAD;IACI,QAAQ,EAAEF,QADd;IAEI,cAAc,EAAEC,cAFpB;IAGI,cAAc,EAAEG,cAHpB;IAII,iBAAiB,EAAEC,iBAJvB;IAKI,OAAO,EAAEE,OALb;IAMI,SAAS,EAAEE,SANf;IAOI,MAAM,EAAEE,MAPZ;IAQI,QAAQ,EAAEE,QARd;IASI,aAAa,EAAEE,aATnB;IAUI,KAAK,EAAEjB,cAVX;IAWI,OAAO,EAAEmB;EAXb,EADH,GAcGjB,QA7BR,CADJ;AAiCH;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["ModalProps.ts"],"sourcesContent":["import React from 'react';\nimport type { ViewProps } from 'react-native';\nimport type { ComponentProps, OverridableComponentProps } from '../types';\nimport { ModalCloseEvent } from './Modal';\n\nexport default interface ModalProps extends OverridableComponentProps<ViewProps, {\n /**\n * Style object provided to animation component.\n */\n animationStyle?: ComponentProps['style'];\n\n /**\n * Opacity for backdrop.\n * @default 0.5\n */\n backdropOpacity?: number;\n\n /**\n * A single child content element.\n */\n children: React.ReactElement;\n\n /**\n * If `true`, the animation is disabled.\n * @default false\n */\n disableAnimation?: boolean;\n\n /**\n *
|
|
1
|
+
{"version":3,"names":["ANIMATION_TYPE"],"sources":["ModalProps.ts"],"sourcesContent":["import React from 'react';\nimport type { ViewProps } from 'react-native';\nimport { Animated } from 'react-native';\nimport type { ComponentProps, OverridableComponentProps } from '../types';\nimport { ModalCloseEvent } from './Modal';\n\nexport const enum ANIMATION_TYPE {\n SLIDE = 'slide',\n FADE = 'fade',\n}\n\nexport type AnimationUnit = Omit<Animated.TimingAnimationConfig, 'useNativeDriver'> & {\n /**\n * Type of animation used when the dialog opens and closes.\n */\n type: ANIMATION_TYPE;\n}\n\nexport default interface ModalProps extends OverridableComponentProps<ViewProps, {\n /**\n * Style object provided to animation component.\n */\n animationStyle?: ComponentProps['style'];\n\n /**\n * Opacity for backdrop.\n * @default 0.5\n */\n backdropOpacity?: number;\n\n /**\n * A single child content element.\n */\n children: React.ReactElement;\n\n /**\n * If `true`, the animation is disabled.\n * @default false\n */\n disableAnimation?: boolean;\n\n /**\n * Animation used when the modal closes.\n */\n closeAnimation?: AnimationUnit[] | undefined;\n\n /**\n * If `true`, the backdrop is not rendered.\n * @default false\n */\n hideBackdrop?: boolean;\n\n /**\n * Set the initial value of opacity for animating.\n */\n initialOpacity?: number | undefined;\n\n /**\n * Set the initial value of transition y for animating.\n */\n initialTranslateY?: number | undefined;\n\n /**\n * Callback fired when the component requests to be closed.\n */\n onClose?: (event?: ModalCloseEvent) => void;\n\n /**\n * Callback fired when the enter animation will start.\n */\n onEnter?: () => void | undefined;\n\n /**\n * Callback fired when the enter animation is completed.\n */\n onEntered?: () => void | undefined;\n\n /**\n * Callback fired when the exit animation will start.\n */\n onExit?: () => void | undefined;\n\n /**\n * Callback fired when the exit animation is completed.\n */\n onExited?: () => void | undefined;\n\n /**\n * Animation used when the modal opens.\n */\n openAnimation?: AnimationUnit[] | undefined;\n\n /**\n * If `true`, the modal is visible.\n */\n visible: boolean;\n}> {}\n"],"mappings":"AAMA,WAAkBA,cAAlB;;WAAkBA,c;EAAAA,c;EAAAA,c;GAAAA,c,KAAAA,c"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["default","createModalCloseEvent"],"sources":["index.ts"],"sourcesContent":["export { default, createModalCloseEvent } from './Modal';\nexport type { ModalCloseEvent } from './Modal';\nexport type { default as ModalProps } from './ModalProps';\n"],"mappings":"AAAA,SAASA,OAAT,EAAkBC,qBAAlB,QAA+C,SAA/C"}
|
|
1
|
+
{"version":3,"names":["default","createModalCloseEvent","ANIMATION_TYPE"],"sources":["index.ts"],"sourcesContent":["export { default, createModalCloseEvent } from './Modal';\nexport type { ModalCloseEvent } from './Modal';\nexport type { default as ModalProps, AnimationUnit } from './ModalProps';\nexport { ANIMATION_TYPE } from './ModalProps';\n"],"mappings":"AAAA,SAASA,OAAT,EAAkBC,qBAAlB,QAA+C,SAA/C;AAGA,SAASC,cAAT,QAA+B,cAA/B"}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ModalProps } from '../Modal';
|
|
3
3
|
import type { OverridableComponentProps } from '../types';
|
|
4
|
+
import { ANIMATION_TYPE } from '../Modal';
|
|
4
5
|
export default interface DialogProps extends OverridableComponentProps<ModalProps, {
|
|
6
|
+
/**
|
|
7
|
+
* Type of animation used when the dialog opens and closes.
|
|
8
|
+
* @default 'slide'
|
|
9
|
+
*/
|
|
10
|
+
animationType?: ANIMATION_TYPE;
|
|
5
11
|
/**
|
|
6
12
|
* Dialog children, usually the included sub-components.
|
|
7
13
|
*/
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type ModalProps from '../ModalProps';
|
|
3
|
+
declare type AnimatedContainerProps = Pick<ModalProps, 'children' | 'closeAnimation' | 'initialOpacity' | 'initialTranslateY' | 'onEnter' | 'onEntered' | 'onExit' | 'onExited' | 'openAnimation' | 'style' | 'visible'>;
|
|
4
|
+
export default function AnimatedContainer(props: AnimatedContainerProps): JSX.Element;
|
|
5
|
+
export {};
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ViewProps } from 'react-native';
|
|
3
|
+
import { Animated } from 'react-native';
|
|
3
4
|
import type { ComponentProps, OverridableComponentProps } from '../types';
|
|
4
5
|
import { ModalCloseEvent } from './Modal';
|
|
6
|
+
export declare const enum ANIMATION_TYPE {
|
|
7
|
+
SLIDE = "slide",
|
|
8
|
+
FADE = "fade"
|
|
9
|
+
}
|
|
10
|
+
export declare type AnimationUnit = Omit<Animated.TimingAnimationConfig, 'useNativeDriver'> & {
|
|
11
|
+
/**
|
|
12
|
+
* Type of animation used when the dialog opens and closes.
|
|
13
|
+
*/
|
|
14
|
+
type: ANIMATION_TYPE;
|
|
15
|
+
};
|
|
5
16
|
export default interface ModalProps extends OverridableComponentProps<ViewProps, {
|
|
6
17
|
/**
|
|
7
18
|
* Style object provided to animation component.
|
|
@@ -22,24 +33,46 @@ export default interface ModalProps extends OverridableComponentProps<ViewProps,
|
|
|
22
33
|
*/
|
|
23
34
|
disableAnimation?: boolean;
|
|
24
35
|
/**
|
|
25
|
-
*
|
|
26
|
-
* @default 300
|
|
27
|
-
*/
|
|
28
|
-
enterDuration?: number;
|
|
29
|
-
/**
|
|
30
|
-
* The number of milliseconds to exit animation.
|
|
31
|
-
* @default 150
|
|
36
|
+
* Animation used when the modal closes.
|
|
32
37
|
*/
|
|
33
|
-
|
|
38
|
+
closeAnimation?: AnimationUnit[] | undefined;
|
|
34
39
|
/**
|
|
35
40
|
* If `true`, the backdrop is not rendered.
|
|
36
41
|
* @default false
|
|
37
42
|
*/
|
|
38
43
|
hideBackdrop?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Set the initial value of opacity for animating.
|
|
46
|
+
*/
|
|
47
|
+
initialOpacity?: number | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Set the initial value of transition y for animating.
|
|
50
|
+
*/
|
|
51
|
+
initialTranslateY?: number | undefined;
|
|
39
52
|
/**
|
|
40
53
|
* Callback fired when the component requests to be closed.
|
|
41
54
|
*/
|
|
42
55
|
onClose?: (event?: ModalCloseEvent) => void;
|
|
56
|
+
/**
|
|
57
|
+
* Callback fired when the enter animation will start.
|
|
58
|
+
*/
|
|
59
|
+
onEnter?: () => void | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Callback fired when the enter animation is completed.
|
|
62
|
+
*/
|
|
63
|
+
onEntered?: () => void | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Callback fired when the exit animation will start.
|
|
66
|
+
*/
|
|
67
|
+
onExit?: () => void | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Callback fired when the exit animation is completed.
|
|
70
|
+
*/
|
|
71
|
+
onExited?: () => void | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Animation used when the modal opens.
|
|
74
|
+
*/
|
|
75
|
+
openAnimation?: AnimationUnit[] | undefined;
|
|
43
76
|
/**
|
|
44
77
|
* If `true`, the modal is visible.
|
|
45
78
|
*/
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { default, createModalCloseEvent } from './Modal';
|
|
2
2
|
export type { ModalCloseEvent } from './Modal';
|
|
3
|
-
export type { default as ModalProps } from './ModalProps';
|
|
3
|
+
export type { default as ModalProps, AnimationUnit } from './ModalProps';
|
|
4
|
+
export { ANIMATION_TYPE } from './ModalProps';
|
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.83",
|
|
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": "ade918bdbf6082ea7d61be5749d28ff0c6c3300b"
|
|
71
71
|
}
|
|
@@ -26,14 +26,10 @@ type AccordionStyles = NamedStylesStringUnion<
|
|
|
26
26
|
| 'contentView'
|
|
27
27
|
>;
|
|
28
28
|
|
|
29
|
-
const CONTENT_Y_START = 10;
|
|
30
|
-
const CONTENT_Y_END = 0;
|
|
31
|
-
|
|
32
29
|
const ROTATE_HIDE_DEGREE = 0;
|
|
33
30
|
const ROTATE_SHOW_DEGREE = 180;
|
|
34
|
-
const ANIMATION_CONFIG: Readonly<WithTimingConfig> = { duration:
|
|
35
|
-
const INITIAL_EXPANDED_DELAY_MILLIS =
|
|
36
|
-
const CONTENT_TRANSLATEY_DELAY_MILLIS = 300;
|
|
31
|
+
const ANIMATION_CONFIG: Readonly<WithTimingConfig> = { duration: 200 };
|
|
32
|
+
const INITIAL_EXPANDED_DELAY_MILLIS = 100;
|
|
37
33
|
const CONTENT_OPACITY_DELAY_MILLIS = 200;
|
|
38
34
|
|
|
39
35
|
const useStyles: UseStyles<AccordionStyles> = function (): AccordionStyles {
|
|
@@ -47,6 +43,7 @@ const useStyles: UseStyles<AccordionStyles> = function (): AccordionStyles {
|
|
|
47
43
|
paddingHorizontal: theme.spacing(4),
|
|
48
44
|
paddingVertical: theme.spacing(3.5),
|
|
49
45
|
alignItems: 'center',
|
|
46
|
+
height: 64,
|
|
50
47
|
},
|
|
51
48
|
titleColumn: { flexShrink: 1 },
|
|
52
49
|
subtitle: {
|
|
@@ -85,7 +82,6 @@ export default function Accordion(props: AccordionProps) {
|
|
|
85
82
|
|
|
86
83
|
const rotate = useSharedValue(ROTATE_HIDE_DEGREE);
|
|
87
84
|
const animatedOpacity = useSharedValue(0);
|
|
88
|
-
const animatedContentY = useSharedValue(CONTENT_Y_START);
|
|
89
85
|
|
|
90
86
|
const animatedHeight = useSharedValue(0);
|
|
91
87
|
const [contentHeight, setContentHeight] = useState(0);
|
|
@@ -100,7 +96,6 @@ export default function Accordion(props: AccordionProps) {
|
|
|
100
96
|
}), []);
|
|
101
97
|
|
|
102
98
|
const animatedContentStyle = useAnimatedStyle(() => ({
|
|
103
|
-
transform: [{ translateY: animatedContentY.value }],
|
|
104
99
|
opacity: animatedOpacity.value,
|
|
105
100
|
}), []);
|
|
106
101
|
|
|
@@ -126,9 +121,6 @@ export default function Accordion(props: AccordionProps) {
|
|
|
126
121
|
animatedOpacity.value = isExpanded
|
|
127
122
|
? withDelay(CONTENT_OPACITY_DELAY_MILLIS, withTiming(1, ANIMATION_CONFIG))
|
|
128
123
|
: withTiming(0, ANIMATION_CONFIG);
|
|
129
|
-
animatedContentY.value = isExpanded
|
|
130
|
-
? withDelay(CONTENT_TRANSLATEY_DELAY_MILLIS, withTiming(CONTENT_Y_END, ANIMATION_CONFIG))
|
|
131
|
-
: withDelay(ANIMATION_CONFIG.duration as number, withTiming(CONTENT_Y_START, { duration: 0 }));
|
|
132
124
|
}, [isExpanded, contentHeight]);
|
|
133
125
|
|
|
134
126
|
return (
|
|
@@ -143,6 +135,7 @@ export default function Accordion(props: AccordionProps) {
|
|
|
143
135
|
children={title}
|
|
144
136
|
color={'textPrimary'}
|
|
145
137
|
numberOfLines={1}
|
|
138
|
+
disableFontScaling={true}
|
|
146
139
|
/>
|
|
147
140
|
|
|
148
141
|
{subTitle ? (
|
|
@@ -153,6 +146,8 @@ export default function Accordion(props: AccordionProps) {
|
|
|
153
146
|
style={styles.subtitle}
|
|
154
147
|
color={'tertiary'}
|
|
155
148
|
children={subTitle}
|
|
149
|
+
numberOfLines={1}
|
|
150
|
+
disableFontScaling={true}
|
|
156
151
|
/>
|
|
157
152
|
</React.Fragment>
|
|
158
153
|
) : null}
|
package/src/Dialog/Dialog.tsx
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import { useWindowDimensions
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { useWindowDimensions } from 'react-native';
|
|
3
3
|
import { css, NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';
|
|
4
4
|
import Column from '../Column';
|
|
5
|
-
import Modal from '../Modal';
|
|
5
|
+
import Modal, { ANIMATION_TYPE, AnimationUnit } from '../Modal';
|
|
6
6
|
import Paper from '../Paper';
|
|
7
|
-
import { useAnimatedValue } from '../hooks';
|
|
8
|
-
import { isNotAndroid12 } from '../utils';
|
|
9
7
|
import { useTheme } from '../styles';
|
|
10
8
|
import type DialogProps from './DialogProps';
|
|
11
9
|
|
|
@@ -22,9 +20,6 @@ type DialogStyles = NamedStylesStringUnion<DialogStyleKeys>;
|
|
|
22
20
|
|
|
23
21
|
const DIALOG_MAX_WIDTH = 328;
|
|
24
22
|
|
|
25
|
-
const fadeDuration = 300;
|
|
26
|
-
const fadeAnimationDelay = 50;
|
|
27
|
-
|
|
28
23
|
const useStyles: UseStyles<DialogStyles> = function (): DialogStyles {
|
|
29
24
|
const theme = useTheme();
|
|
30
25
|
|
|
@@ -40,6 +35,7 @@ const useStyles: UseStyles<DialogStyles> = function (): DialogStyles {
|
|
|
40
35
|
zIndex: theme.zIndex.dialog,
|
|
41
36
|
},
|
|
42
37
|
paper: {
|
|
38
|
+
borderRadius: theme.shape.roundnessExtra,
|
|
43
39
|
margin,
|
|
44
40
|
maxWidth: DIALOG_MAX_WIDTH,
|
|
45
41
|
overflow: 'hidden',
|
|
@@ -68,6 +64,7 @@ const useStyles: UseStyles<DialogStyles> = function (): DialogStyles {
|
|
|
68
64
|
|
|
69
65
|
export default function Dialog(props: DialogProps) {
|
|
70
66
|
const {
|
|
67
|
+
animationType = ANIMATION_TYPE.SLIDE,
|
|
71
68
|
children,
|
|
72
69
|
fullScreen = false,
|
|
73
70
|
onClose,
|
|
@@ -78,38 +75,80 @@ export default function Dialog(props: DialogProps) {
|
|
|
78
75
|
} = props;
|
|
79
76
|
|
|
80
77
|
const styles = useStyles();
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if(
|
|
86
|
-
|
|
87
|
-
toValue:
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
78
|
+
|
|
79
|
+
const { height: screenHeight } = useWindowDimensions();
|
|
80
|
+
|
|
81
|
+
const closeAnimation = useMemo<AnimationUnit[]>(() => {
|
|
82
|
+
if (animationType === ANIMATION_TYPE.FADE) {
|
|
83
|
+
return [{
|
|
84
|
+
toValue: 0,
|
|
85
|
+
type: ANIMATION_TYPE.FADE,
|
|
86
|
+
}];
|
|
87
|
+
} else if (animationType === ANIMATION_TYPE.SLIDE && !fullScreen) {
|
|
88
|
+
return [
|
|
89
|
+
{
|
|
90
|
+
toValue: screenHeight,
|
|
91
|
+
type: ANIMATION_TYPE.SLIDE,
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
duration: 150,
|
|
95
|
+
toValue: 0,
|
|
96
|
+
type: ANIMATION_TYPE.FADE,
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return [{
|
|
102
|
+
duration: 150,
|
|
103
|
+
toValue: screenHeight,
|
|
104
|
+
type: ANIMATION_TYPE.SLIDE,
|
|
105
|
+
}];
|
|
106
|
+
}, [animationType, fullScreen, screenHeight]);
|
|
107
|
+
|
|
108
|
+
const openAnimation = useMemo<AnimationUnit[]>(() => {
|
|
109
|
+
if (animationType === ANIMATION_TYPE.FADE) {
|
|
110
|
+
return [{
|
|
111
|
+
toValue: 1,
|
|
112
|
+
type: ANIMATION_TYPE.FADE,
|
|
113
|
+
}];
|
|
114
|
+
} else if (animationType === ANIMATION_TYPE.SLIDE && !fullScreen) {
|
|
115
|
+
return [
|
|
116
|
+
{
|
|
117
|
+
toValue: 0,
|
|
118
|
+
type: ANIMATION_TYPE.SLIDE,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
delay: 50,
|
|
122
|
+
duration: 150,
|
|
123
|
+
toValue: 1,
|
|
124
|
+
type: ANIMATION_TYPE.FADE,
|
|
125
|
+
},
|
|
126
|
+
];
|
|
93
127
|
}
|
|
94
|
-
|
|
128
|
+
|
|
129
|
+
return [{
|
|
130
|
+
toValue: 0,
|
|
131
|
+
type: ANIMATION_TYPE.SLIDE,
|
|
132
|
+
}];
|
|
133
|
+
}, [animationType, fullScreen]);
|
|
134
|
+
|
|
135
|
+
const initialOpacity = animationType === ANIMATION_TYPE.SLIDE && fullScreen ? 1 : undefined;
|
|
136
|
+
|
|
137
|
+
const initialTranslateY = animationType === ANIMATION_TYPE.FADE ? 0 : undefined;
|
|
95
138
|
|
|
96
139
|
return (
|
|
97
140
|
<Modal
|
|
98
141
|
animationStyle={fullScreen ? styles.animationFullScreen : styles.animation}
|
|
142
|
+
closeAnimation={closeAnimation}
|
|
143
|
+
initialOpacity={initialOpacity}
|
|
144
|
+
initialTranslateY={initialTranslateY}
|
|
99
145
|
onClose={onClose}
|
|
100
|
-
|
|
146
|
+
openAnimation={openAnimation}
|
|
101
147
|
visible={visible}
|
|
102
148
|
style={styles.root}
|
|
103
149
|
{...otherProps}
|
|
104
150
|
>
|
|
105
|
-
<
|
|
106
|
-
needsOffscreenAlphaCompositing={true}
|
|
107
|
-
style={{
|
|
108
|
-
height: fullScreen ? '100%' : 'auto',
|
|
109
|
-
width: fullScreen ? '100%' : 'auto',
|
|
110
|
-
opacity: fullScreen ? 1 : animatedOpacity,
|
|
111
|
-
}}
|
|
112
|
-
>
|
|
151
|
+
<React.Fragment>
|
|
113
152
|
{topElement ? (
|
|
114
153
|
<Column style={fullScreen ? undefined : styles.topElementSize}>
|
|
115
154
|
<Column style={styles.topElementPosition}>
|
|
@@ -122,14 +161,13 @@ export default function Dialog(props: DialogProps) {
|
|
|
122
161
|
elevation={6}
|
|
123
162
|
square={fullScreen}
|
|
124
163
|
style={css([
|
|
125
|
-
{ borderRadius: fullScreen ? undefined : theme.shape.roundnessExtra },
|
|
126
164
|
fullScreen ? styles.paperFullScreen : styles.paper,
|
|
127
165
|
style,
|
|
128
166
|
])}
|
|
129
167
|
>
|
|
130
168
|
{children}
|
|
131
169
|
</Paper>
|
|
132
|
-
</
|
|
170
|
+
</React.Fragment>
|
|
133
171
|
</Modal>
|
|
134
172
|
);
|
|
135
173
|
};
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ModalProps } from '../Modal';
|
|
3
3
|
import type { OverridableComponentProps } from '../types';
|
|
4
|
+
import { ANIMATION_TYPE } from '../Modal';
|
|
4
5
|
|
|
5
6
|
export default interface DialogProps extends OverridableComponentProps<ModalProps, {
|
|
7
|
+
/**
|
|
8
|
+
* Type of animation used when the dialog opens and closes.
|
|
9
|
+
* @default 'slide'
|
|
10
|
+
*/
|
|
11
|
+
animationType?: ANIMATION_TYPE;
|
|
12
|
+
|
|
6
13
|
/**
|
|
7
14
|
* Dialog children, usually the included sub-components.
|
|
8
15
|
*/
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import React, { useCallback, useEffect } from 'react';
|
|
2
|
+
import { Animated, Easing, Platform, useWindowDimensions } from 'react-native';
|
|
3
|
+
import * as R from 'ramda';
|
|
4
|
+
import { useAnimatedValue } from '../../hooks';
|
|
5
|
+
import { isNotAndroid12 } from '../../utils';
|
|
6
|
+
import type ModalProps from '../ModalProps';
|
|
7
|
+
import { ANIMATION_TYPE, AnimationUnit } from '../ModalProps';
|
|
8
|
+
|
|
9
|
+
type AnimatedContainerProps = Pick<ModalProps,
|
|
10
|
+
| 'children'
|
|
11
|
+
| 'closeAnimation'
|
|
12
|
+
| 'initialOpacity'
|
|
13
|
+
| 'initialTranslateY'
|
|
14
|
+
| 'onEnter'
|
|
15
|
+
| 'onEntered'
|
|
16
|
+
| 'onExit'
|
|
17
|
+
| 'onExited'
|
|
18
|
+
| 'openAnimation'
|
|
19
|
+
| 'style'
|
|
20
|
+
| 'visible'>
|
|
21
|
+
|
|
22
|
+
const DEFAULT_ANIMATION_CONFIG = {
|
|
23
|
+
duration: 300,
|
|
24
|
+
useNativeDriver: isNotAndroid12,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default function AnimatedContainer(props: AnimatedContainerProps) {
|
|
28
|
+
const {
|
|
29
|
+
children,
|
|
30
|
+
closeAnimation,
|
|
31
|
+
initialOpacity,
|
|
32
|
+
initialTranslateY,
|
|
33
|
+
onEnter,
|
|
34
|
+
onEntered,
|
|
35
|
+
onExit,
|
|
36
|
+
onExited,
|
|
37
|
+
openAnimation,
|
|
38
|
+
style,
|
|
39
|
+
visible,
|
|
40
|
+
} = props;
|
|
41
|
+
|
|
42
|
+
const { height: screenHeight } = useWindowDimensions();
|
|
43
|
+
|
|
44
|
+
const opacity = useAnimatedValue(initialOpacity ?? 0);
|
|
45
|
+
|
|
46
|
+
const translateY = useAnimatedValue(initialTranslateY ?? screenHeight);
|
|
47
|
+
|
|
48
|
+
const convertToCompositeAnimation = useCallback((animationUnit: AnimationUnit) => {
|
|
49
|
+
const {
|
|
50
|
+
type,
|
|
51
|
+
...others
|
|
52
|
+
} = animationUnit;
|
|
53
|
+
|
|
54
|
+
switch (type) {
|
|
55
|
+
case ANIMATION_TYPE.FADE:
|
|
56
|
+
return Animated.timing(opacity, {
|
|
57
|
+
...others,
|
|
58
|
+
useNativeDriver: isNotAndroid12,
|
|
59
|
+
});
|
|
60
|
+
case ANIMATION_TYPE.SLIDE:
|
|
61
|
+
default:
|
|
62
|
+
const easing = others.toValue === screenHeight
|
|
63
|
+
? Easing.in(Easing.ease)
|
|
64
|
+
: Platform.OS === 'web'
|
|
65
|
+
? Easing.bezier(0.16, 1, 0.3, 1)
|
|
66
|
+
: Easing.out(Easing.exp);
|
|
67
|
+
|
|
68
|
+
return Animated.timing(translateY, {
|
|
69
|
+
...others,
|
|
70
|
+
easing,
|
|
71
|
+
useNativeDriver: isNotAndroid12,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}, [screenHeight]);
|
|
75
|
+
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (visible) {
|
|
78
|
+
onEnter?.();
|
|
79
|
+
|
|
80
|
+
if (R.isNil(openAnimation)) {
|
|
81
|
+
opacity.setValue(1);
|
|
82
|
+
|
|
83
|
+
Animated.timing(translateY, {
|
|
84
|
+
...DEFAULT_ANIMATION_CONFIG,
|
|
85
|
+
easing: Platform.OS === 'web'
|
|
86
|
+
? Easing.bezier(0.16, 1, 0.3, 1)
|
|
87
|
+
: Easing.out(Easing.exp),
|
|
88
|
+
toValue: 0,
|
|
89
|
+
}).start(({ finished }) => {
|
|
90
|
+
if (finished) {
|
|
91
|
+
onEntered?.();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
} else {
|
|
95
|
+
const convertedAnimation = openAnimation.map((animationUnit) => {
|
|
96
|
+
return convertToCompositeAnimation({
|
|
97
|
+
...DEFAULT_ANIMATION_CONFIG,
|
|
98
|
+
...animationUnit,
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
Animated.parallel(convertedAnimation).start(({ finished }) => {
|
|
103
|
+
if (finished) {
|
|
104
|
+
onEntered?.();
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
onExit?.();
|
|
110
|
+
|
|
111
|
+
if (R.isNil(closeAnimation)) {
|
|
112
|
+
opacity.setValue(1);
|
|
113
|
+
|
|
114
|
+
Animated.timing(translateY, {
|
|
115
|
+
...DEFAULT_ANIMATION_CONFIG,
|
|
116
|
+
easing: Easing.in(Easing.ease),
|
|
117
|
+
toValue: screenHeight,
|
|
118
|
+
}).start(({ finished }) => {
|
|
119
|
+
if (finished) {
|
|
120
|
+
onExited?.();
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
} else {
|
|
124
|
+
const convertedAnimation = closeAnimation.map((animationUnit) => {
|
|
125
|
+
return convertToCompositeAnimation({
|
|
126
|
+
...DEFAULT_ANIMATION_CONFIG,
|
|
127
|
+
...animationUnit,
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
Animated.parallel(convertedAnimation).start(({ finished }) => {
|
|
132
|
+
if (finished) {
|
|
133
|
+
onExited?.();
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}, [convertToCompositeAnimation, visible]);
|
|
139
|
+
|
|
140
|
+
const animatedStyle = {
|
|
141
|
+
opacity,
|
|
142
|
+
transform: [{ translateY }],
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<Animated.View
|
|
147
|
+
pointerEvents={'box-none'}
|
|
148
|
+
style={[
|
|
149
|
+
animatedStyle,
|
|
150
|
+
style,
|
|
151
|
+
]}
|
|
152
|
+
>
|
|
153
|
+
{children}
|
|
154
|
+
</Animated.View>
|
|
155
|
+
);
|
|
156
|
+
}
|