@lookiero/checkout 0.2.23 → 0.2.24

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.
@@ -2,30 +2,34 @@ import { useI18nMessage } from "@lookiero/i18n-react";
2
2
  import React, { useCallback, useState } from "react";
3
3
  import { useIntl } from "react-intl";
4
4
  import { TouchableHighlight, View } from "react-native";
5
- import { useSafeAreaInsets } from "react-native-safe-area-context";
6
5
  import { RETURN_QUESTIONS_PREFIX } from "../../../../../i18n/i18n";
7
6
  import { Modal } from "../../../../../shared/components/layouts/modal/Modal";
7
+ import { ButtonIcon } from "../../../../../shared/components/molecules/buttonIcon/ButtonIcon";
8
8
  import { InputField } from "../../../../../shared/components/molecules/inputField/InputField";
9
- import { theme } from "../../../../../theme/theme";
10
- import { useReturnQuestionFeedback } from "../../behaviors/useReturnQuestionFeedback";
11
- import { feedbackForReturnQuestion } from "../../util/returnQuestionFeedback";
9
+ import { useReturnQuestionFeedback, useReturnQuestionFeedbackForId } from "../../behaviors/useReturnQuestionFeedback";
10
+ import { deepestReturnQuestionWithFeedbackForReturnQuestion, feedbackForReturnQuestion, } from "../../util/returnQuestionFeedback";
12
11
  import { style, containerUnderlayColor } from "./HostSelectReturnQuestionItem.style";
13
- const { spaceXL } = theme();
14
12
  const HostSelectReturnQuestionItem = ({ returnQuestion, children, portalHostName, }) => {
15
- const { bottom: safeAreaInsetBottom } = useSafeAreaInsets();
16
13
  const placeholderText = useI18nMessage({ id: returnQuestion.placeholder, prefix: RETURN_QUESTIONS_PREFIX });
17
14
  const [modalVisible, setModalVisible] = useState(false);
18
15
  const handleOnPress = useCallback(() => setModalVisible(true), []);
19
16
  const handleOnModalClose = useCallback(() => setModalVisible(false), []);
20
17
  const feedback = useReturnQuestionFeedback();
18
+ const { onChange } = useReturnQuestionFeedbackForId({ id: returnQuestion.id });
21
19
  const intl = useIntl();
22
20
  const translate = useCallback((returnQuestionName) => intl.formatMessage({ id: `${RETURN_QUESTIONS_PREFIX}${returnQuestionName}`, defaultMessage: returnQuestionName }), [intl]);
23
21
  const inputValue = feedbackForReturnQuestion({ feedback, returnQuestion, translate }).join(" / ");
22
+ const deepestReturnQuestionWithFeedback = deepestReturnQuestionWithFeedbackForReturnQuestion({
23
+ feedback,
24
+ returnQuestion,
25
+ });
26
+ const handleOnBackButtonPress = useCallback(() => deepestReturnQuestionWithFeedback &&
27
+ onChange({ returnQuestionId: deepestReturnQuestionWithFeedback.id, returnQuestionFeedback: undefined }), [deepestReturnQuestionWithFeedback, onChange]);
24
28
  return (React.createElement(React.Fragment, null,
25
29
  React.createElement(TouchableHighlight, { style: style.container, onPress: handleOnPress, underlayColor: containerUnderlayColor },
26
30
  React.createElement(View, { pointerEvents: "none" },
27
31
  React.createElement(InputField, { label: placeholderText || "", value: inputValue, icon: "arrow-down", editable: false }))),
28
- React.createElement(Modal, { visible: modalVisible, onClose: handleOnModalClose, portalHostName: portalHostName },
29
- React.createElement(View, { style: [style.modalContent, { paddingBottom: spaceXL + safeAreaInsetBottom }] }, children))));
32
+ React.createElement(Modal, { visible: modalVisible, onClose: handleOnModalClose, portalHostName: portalHostName, header: deepestReturnQuestionWithFeedback && (React.createElement(ButtonIcon, { name: "arrow-left", onPress: handleOnBackButtonPress, testID: "modal-back-button" })), scroll: true },
33
+ React.createElement(View, { style: style.modalContent }, children))));
30
34
  };
31
35
  export { HostSelectReturnQuestionItem };
@@ -1,33 +1,27 @@
1
1
  import { Text } from "@lookiero/aurora-next/build/components/primitives/Text/Text";
2
2
  import { useI18nMessage } from "@lookiero/i18n-react";
3
- import React, { useCallback } from "react";
3
+ import { animated, useSpring } from "@react-spring/native";
4
+ import React, { useCallback, useState } from "react";
5
+ import { View } from "react-native";
4
6
  import { RETURN_QUESTIONS_PREFIX } from "../../../../../i18n/i18n";
5
- import { ButtonIcon } from "../../../../../shared/components/molecules/buttonIcon/ButtonIcon";
6
7
  import ReturnQuestion from "../../ReturnQuestion";
7
8
  import { useReturnQuestionFeedbackForId } from "../../behaviors/useReturnQuestionFeedback";
8
9
  import { style } from "./HostStackReturnQuestionItem.style";
9
10
  const HostStackReturnQuestionItem = ({ returnQuestion, children, portalHostName, }) => {
10
11
  const titleText = useI18nMessage({ id: returnQuestion.name, prefix: RETURN_QUESTIONS_PREFIX });
11
- const { feedback, onChange } = useReturnQuestionFeedbackForId({ id: returnQuestion.id });
12
+ const { feedback } = useReturnQuestionFeedbackForId({ id: returnQuestion.id });
12
13
  const feedbackReturnQuestion = feedback
13
14
  ? returnQuestion.children?.find((returnQuestion) => returnQuestion.id === feedback)
14
15
  : undefined;
15
16
  const feedbackText = useI18nMessage({ id: feedbackReturnQuestion?.name, prefix: RETURN_QUESTIONS_PREFIX });
16
- const handleOnBackButtonPress = useCallback(() => {
17
- onChange({ returnQuestionId: returnQuestion.id, returnQuestionFeedback: undefined });
18
- }, [onChange, returnQuestion.id]);
19
- const questionTitle = titleText && (React.createElement(Text, { level: 2, style: style.title }, titleText));
20
- if (feedbackReturnQuestion) {
21
- return (React.createElement(React.Fragment, null,
22
- React.createElement(ButtonIcon, { name: "arrow-left", style: { icon: style.backButton }, onPress: handleOnBackButtonPress }),
23
- questionTitle,
24
- React.createElement(Text, { level: 3, style: style.feedback }, feedbackText),
25
- feedbackReturnQuestion.children?.map((childReturnQuestion) => (React.createElement(ReturnQuestion, { key: childReturnQuestion.id, returnQuestion: childReturnQuestion, returnQuestionParentId: feedbackReturnQuestion.id, portalHostName: portalHostName })))));
26
- }
27
- else {
28
- return (React.createElement(React.Fragment, null,
29
- questionTitle,
30
- children));
31
- }
17
+ const [stackHeight, setStackHeight] = useState();
18
+ const handleOnLayout = useCallback(({ nativeEvent: { layout: { height }, }, }) => setStackHeight(height), []);
19
+ const stackSyle = useSpring({ height: stackHeight });
20
+ return (React.createElement(animated.View, { style: stackSyle },
21
+ React.createElement(View, { onLayout: handleOnLayout },
22
+ titleText && (React.createElement(Text, { level: 2, style: style.title }, titleText)),
23
+ feedbackReturnQuestion ? (React.createElement(React.Fragment, null,
24
+ React.createElement(Text, { level: 3, style: style.feedback }, feedbackText),
25
+ feedbackReturnQuestion.children?.map((childReturnQuestion) => (React.createElement(ReturnQuestion, { key: childReturnQuestion.id, returnQuestion: childReturnQuestion, returnQuestionParentId: feedbackReturnQuestion.id, portalHostName: portalHostName }))))) : (children))));
32
26
  };
33
27
  export { HostStackReturnQuestionItem };
@@ -1,10 +1,4 @@
1
1
  declare const style: {
2
- backButton: {
3
- position: "absolute";
4
- top: number;
5
- left: number;
6
- zIndex: number;
7
- };
8
2
  title: {
9
3
  marginVertical: number;
10
4
  textAlign: "center";
@@ -1,16 +1,7 @@
1
1
  import { StyleSheet } from "react-native";
2
2
  import { theme } from "../../../../../theme/theme";
3
- const { colorGrayscaleL, spaceS, spaceM, spaceL, iconSize } = theme();
4
- const headerPadding = spaceM;
5
- const buttonIconPadding = spaceS;
6
- const backButtonTop = (iconSize + headerPadding + buttonIconPadding * 2) * -1;
3
+ const { colorGrayscaleL, spaceM, spaceL } = theme();
7
4
  const style = StyleSheet.create({
8
- backButton: {
9
- position: "absolute",
10
- top: backButtonTop,
11
- left: spaceM,
12
- zIndex: 20,
13
- },
14
5
  title: {
15
6
  marginVertical: spaceL,
16
7
  textAlign: "center",
@@ -10,4 +10,13 @@ interface RecursiveFeedbackForReturnQuestionFunction {
10
10
  (args: RecursiveFeedbackForReturnQuestionFunctionArgs): string[];
11
11
  }
12
12
  declare const feedbackForReturnQuestion: RecursiveFeedbackForReturnQuestionFunction;
13
- export { feedbackForReturnQuestion };
13
+ interface RecursiveDeepestReturnQuestionWithFeedbackFunctionArgs {
14
+ readonly feedback: FeedbackProjection | undefined;
15
+ readonly returnQuestion: ReturnQuestionProjection;
16
+ readonly deepestReturnQuestion?: ReturnQuestionProjection;
17
+ }
18
+ interface RecursiveDeepestReturnQuestionWithFeedbackFunction {
19
+ (args: RecursiveDeepestReturnQuestionWithFeedbackFunctionArgs): ReturnQuestionProjection | undefined;
20
+ }
21
+ declare const deepestReturnQuestionWithFeedbackForReturnQuestion: RecursiveDeepestReturnQuestionWithFeedbackFunction;
22
+ export { feedbackForReturnQuestion, deepestReturnQuestionWithFeedbackForReturnQuestion };
@@ -7,25 +7,52 @@ const feedbackForReturnQuestion = ({ feedback, returnQuestion, translate, acc =
7
7
  const returnQuestionId = Object.keys(feedback).find((id) => id === returnQuestion.id);
8
8
  if (returnQuestionId) {
9
9
  const returnQuestionFeedback = feedback[returnQuestionId];
10
- if (returnQuestionFeedback !== undefined) {
11
- if (isUuid(returnQuestionFeedback)) {
12
- const feebackReturnQuestionChild = returnQuestion.children?.find((childReturnQuestion) => childReturnQuestion.id === returnQuestionFeedback);
13
- if (feebackReturnQuestionChild) {
14
- return [
15
- ...acc,
16
- translate(feebackReturnQuestionChild?.name),
17
- ...feedbackForReturnQuestion({ feedback, returnQuestion: feebackReturnQuestionChild, translate, acc }),
18
- ];
19
- }
20
- return acc;
10
+ if (isUuid(returnQuestionFeedback)) {
11
+ const feebackReturnQuestionChild = returnQuestion.children?.find((childReturnQuestion) => childReturnQuestion.id === returnQuestionFeedback);
12
+ if (feebackReturnQuestionChild) {
13
+ return [
14
+ ...acc,
15
+ translate(feebackReturnQuestionChild?.name),
16
+ ...feedbackForReturnQuestion({ feedback, returnQuestion: feebackReturnQuestionChild, translate, acc }),
17
+ ];
21
18
  }
22
- return [...acc, returnQuestionFeedback];
19
+ return acc;
23
20
  }
24
- return acc;
21
+ return [...acc, returnQuestionFeedback];
25
22
  }
26
23
  return (returnQuestion.children?.reduce((acc, childReturnQuestion) => [
27
24
  ...acc,
28
25
  ...feedbackForReturnQuestion({ feedback, returnQuestion: childReturnQuestion, translate, acc }),
29
26
  ], []) || []);
30
27
  };
31
- export { feedbackForReturnQuestion };
28
+ const deepestReturnQuestionWithFeedbackForReturnQuestion = ({ feedback, returnQuestion, deepestReturnQuestion, }) => {
29
+ if (!feedback) {
30
+ return;
31
+ }
32
+ const returnQuestionId = Object.keys(feedback).find((id) => id === returnQuestion.id);
33
+ if (returnQuestionId) {
34
+ const returnQuestionFeedback = feedback[returnQuestionId];
35
+ if (isUuid(returnQuestionFeedback)) {
36
+ const feebackReturnQuestionChild = returnQuestion.children?.find((childReturnQuestion) => childReturnQuestion.id === returnQuestionFeedback);
37
+ if (feebackReturnQuestionChild) {
38
+ return deepestReturnQuestionWithFeedbackForReturnQuestion({
39
+ feedback,
40
+ returnQuestion: feebackReturnQuestionChild,
41
+ deepestReturnQuestion: returnQuestion,
42
+ });
43
+ }
44
+ return returnQuestion;
45
+ }
46
+ return returnQuestion;
47
+ }
48
+ const feebackReturnQuestionChild = returnQuestion.children?.find((childReturnQuestion) => Object.keys(feedback).find((id) => id === childReturnQuestion.id));
49
+ if (feebackReturnQuestionChild) {
50
+ return deepestReturnQuestionWithFeedbackForReturnQuestion({
51
+ feedback,
52
+ returnQuestion: feebackReturnQuestionChild,
53
+ deepestReturnQuestion: feebackReturnQuestionChild,
54
+ });
55
+ }
56
+ return deepestReturnQuestion;
57
+ };
58
+ export { feedbackForReturnQuestion, deepestReturnQuestionWithFeedbackForReturnQuestion };
@@ -9,6 +9,7 @@ interface ModalProps {
9
9
  readonly onClose?: () => void;
10
10
  readonly header?: ReactNode;
11
11
  readonly portalHostName?: string;
12
+ readonly scroll?: boolean;
12
13
  readonly size?: Partial<Record<ScreenSize, ColumnSize>>;
13
14
  readonly style?: Partial<Record<ModalStyle, ViewProps>>;
14
15
  }
@@ -1,14 +1,14 @@
1
1
  import { Portal } from "@gorhom/portal";
2
2
  import { animated, useTransition } from "@react-spring/native";
3
- import React, { useCallback, useState } from "react";
4
- import { Dimensions, Platform, TouchableWithoutFeedback, View } from "react-native";
3
+ import React, { useCallback, useMemo, useState } from "react";
4
+ import { Dimensions, Platform, ScrollView, TouchableWithoutFeedback, View, } from "react-native";
5
5
  import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context";
6
6
  import { useScreenSize } from "../../../hooks/useScreenSize";
7
7
  import { ButtonIcon } from "../../molecules/buttonIcon/ButtonIcon";
8
8
  import { Row } from "../row/Row";
9
9
  import { style } from "./Modal.style";
10
10
  const TRANSITION_MODAL_SCALE = 0.9;
11
- const Modal = ({ children, visible, header, portalHostName, onClose, size = { M: "2/3", L: "1/3" }, style: customStyle, }) => {
11
+ const Modal = ({ children, visible, header, portalHostName, onClose, size = { M: "2/3", L: "1/3" }, style: customStyle, scroll = false, }) => {
12
12
  const { height: screenHeight } = Dimensions.get("screen");
13
13
  const { top: safeAreaInsetTop, bottom: safeAreaInsetBottom } = useSafeAreaInsets();
14
14
  const screenSizeWithoutInsets = screenHeight - safeAreaInsetTop;
@@ -37,6 +37,7 @@ const Modal = ({ children, visible, header, portalHostName, onClose, size = { M:
37
37
  : { modalOpacity: 0, overlayOpacity: 0, modalTranslateY: 0, modalScale: TRANSITION_MODAL_SCALE },
38
38
  unique: true,
39
39
  });
40
+ const ModalContentView = useMemo(() => (scroll ? ScrollView : View), [scroll]);
40
41
  return (React.createElement(Portal, { hostName: portalHostName }, transitions(({ modalOpacity, overlayOpacity, modalTranslateY, modalScale }, item) => item && (React.createElement(View, { style: style.container, pointerEvents: visible ? "auto" : "none", testID: "modal" },
41
42
  React.createElement(TouchableWithoutFeedback, { onPress: visible ? onClose : undefined },
42
43
  React.createElement(animated.View, { style: [style.overlay, { opacity: overlayOpacity }, customStyle?.overlay] })),
@@ -54,7 +55,8 @@ const Modal = ({ children, visible, header, portalHostName, onClose, size = { M:
54
55
  ], onLayout: handleOnModalLayout, pointerEvents: visible ? "auto" : "none" },
55
56
  (header || onClose) && (React.createElement(View, { style: [style.header, customStyle?.header] },
56
57
  React.createElement(View, null, header),
57
- onClose && (React.createElement(ButtonIcon, { style: { button: [style.closeButton, customStyle?.closeButton] }, name: "close", onPress: onClose })))),
58
- children))))))));
58
+ onClose && (React.createElement(ButtonIcon, { style: { button: customStyle?.closeButton }, name: "close", onPress: onClose })))),
59
+ React.createElement(ModalContentView, null,
60
+ React.createElement(View, { style: { paddingBottom: safeAreaInsetBottom } }, children))))))))));
59
61
  };
60
62
  export { Modal };
@@ -42,8 +42,5 @@ declare const style: {
42
42
  padding: number;
43
43
  flexDirection: "row";
44
44
  };
45
- closeButton: {
46
- alignSelf: "flex-end";
47
- };
48
45
  };
49
46
  export { style };
@@ -55,8 +55,5 @@ const style = StyleSheet.create({
55
55
  padding: spaceM,
56
56
  flexDirection: "row",
57
57
  },
58
- closeButton: {
59
- alignSelf: "flex-end",
60
- },
61
58
  });
62
59
  export { style };
@@ -1,14 +1,16 @@
1
1
  import { FC } from "react";
2
- import { StyleProp, ViewStyle } from "react-native";
2
+ import { StyleProp, TouchableHighlightProps, ViewStyle } from "react-native";
3
3
  import { IconName, IconStyle } from "../../atoms/icon/Icon";
4
4
  interface ButtonIconStyle {
5
5
  readonly button: StyleProp<ViewStyle>;
6
6
  readonly icon: IconStyle;
7
7
  }
8
- interface ButtonIconProps {
8
+ interface ButtonIconBaseProps {
9
9
  readonly name: IconName;
10
+ readonly testID?: string;
10
11
  readonly style?: Partial<ButtonIconStyle>;
11
- readonly onPress: () => void;
12
+ }
13
+ interface ButtonIconProps extends Omit<TouchableHighlightProps, keyof ButtonIconBaseProps>, ButtonIconBaseProps {
12
14
  }
13
15
  declare const ButtonIcon: FC<ButtonIconProps>;
14
16
  export { ButtonIcon };
@@ -2,6 +2,6 @@ import React from "react";
2
2
  import { TouchableHighlight } from "react-native";
3
3
  import { Icon } from "../../atoms/icon/Icon";
4
4
  import { buttonIconUnderlayColor, style } from "./ButtonIcon.style";
5
- const ButtonIcon = ({ name, style: customStyle, onPress }) => (React.createElement(TouchableHighlight, { style: [style.buttonIcon, customStyle?.button], onPress: onPress, underlayColor: buttonIconUnderlayColor, testID: "button-icon" },
5
+ const ButtonIcon = ({ name, style: customStyle, testID = "button-icon", onPress, ...restProps }) => (React.createElement(TouchableHighlight, { style: [style.buttonIcon, customStyle?.button], onPress: onPress, underlayColor: buttonIconUnderlayColor, testID: testID, ...restProps },
6
6
  React.createElement(Icon, { name: name, style: customStyle?.icon })));
7
7
  export { ButtonIcon };
@@ -1,7 +1,6 @@
1
1
  import { PortalHost } from "@gorhom/portal";
2
2
  import React from "react";
3
- import { ScrollView, View } from "react-native";
4
- import { useSafeAreaInsets } from "react-native-safe-area-context";
3
+ import { View } from "react-native";
5
4
  import { ReturnQuestionType, } from "../../../../../../projection/returnQuestion/returnQuestion";
6
5
  import { ReturnQuestions } from "../../../../components/organisms/returnQuestions/ReturnQuestions";
7
6
  import { ReturnQuestionFeedbackProvider } from "../../../../components/organisms/returnQuestions/behaviors/useReturnQuestionFeedback";
@@ -12,9 +11,7 @@ import { HostStackReturnQuestionItem } from "../../../../components/organisms/re
12
11
  import { OptionReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/optionReturnQuestionItem/OptionReturnQuestionItem";
13
12
  import { TextareaReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/textareaReturnQuestionItem/TextareaReturnQuestionItem";
14
13
  import { Modal } from "../../../../shared/components/layouts/modal/Modal";
15
- import { theme } from "../../../../theme/theme";
16
14
  import { style } from "./ReturnQuestionsForm.style";
17
- const { spaceXL } = theme();
18
15
  const RETURN_QUESTION_FORM_PORTAL_HOST_NAME = "return-question-form-portal";
19
16
  const returnQuestionItems = {
20
17
  [ReturnQuestionType.HOST_DEFAULT]: HostDefaultReturnQuestionItem,
@@ -24,14 +21,10 @@ const returnQuestionItems = {
24
21
  [ReturnQuestionType.TEXTAREA]: TextareaReturnQuestionItem,
25
22
  [ReturnQuestionType.OPTION]: OptionReturnQuestionItem,
26
23
  };
27
- const ReturnQuestionsForm = ({ feedback, returnQuestions, onClose, visible }) => {
28
- const { bottom: safeAreaInsetBottom } = useSafeAreaInsets();
29
- return (React.createElement(ReturnQuestionFeedbackProvider, { feedback: feedback },
30
- React.createElement(ReturnQuestionItemProvider, { returnQuestionItems: returnQuestionItems },
31
- React.createElement(PortalHost, { name: RETURN_QUESTION_FORM_PORTAL_HOST_NAME }),
32
- React.createElement(Modal, { visible: visible, onClose: onClose, portalHostName: RETURN_QUESTION_FORM_PORTAL_HOST_NAME },
33
- React.createElement(ScrollView, null,
34
- React.createElement(View, { style: [style.returnQuestionsContainer, { paddingBottom: spaceXL + safeAreaInsetBottom }] },
35
- React.createElement(ReturnQuestions, { returnQuestions: returnQuestions, portalHostName: RETURN_QUESTION_FORM_PORTAL_HOST_NAME })))))));
36
- };
24
+ const ReturnQuestionsForm = ({ feedback, returnQuestions, onClose, visible }) => (React.createElement(ReturnQuestionFeedbackProvider, { feedback: feedback },
25
+ React.createElement(ReturnQuestionItemProvider, { returnQuestionItems: returnQuestionItems },
26
+ React.createElement(PortalHost, { name: RETURN_QUESTION_FORM_PORTAL_HOST_NAME }),
27
+ React.createElement(Modal, { visible: visible, onClose: onClose, portalHostName: RETURN_QUESTION_FORM_PORTAL_HOST_NAME, scroll: true },
28
+ React.createElement(View, { style: style.returnQuestionsContainer },
29
+ React.createElement(ReturnQuestions, { returnQuestions: returnQuestions, portalHostName: RETURN_QUESTION_FORM_PORTAL_HOST_NAME }))))));
37
30
  export { ReturnQuestionsForm };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lookiero/checkout",
3
- "version": "0.2.23",
3
+ "version": "0.2.24",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [