Element functions are now split into multiple file and started the ground work for onPress support
This commit is contained in:
@@ -0,0 +1,15 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { ElementProps } from "./ElementList";
|
||||||
|
import { RawElement } from "./RawElement";
|
||||||
|
import { Pressable } from "native-base";
|
||||||
|
|
||||||
|
export const Element = (props: ElementProps) => {
|
||||||
|
if (props.type === "text" && props.data?.onPress) {
|
||||||
|
return (
|
||||||
|
<Pressable onPress={props.data.onPress}>
|
||||||
|
<RawElement {...props} />
|
||||||
|
</Pressable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <RawElement {...props} />;
|
||||||
|
};
|
||||||
@@ -2,6 +2,8 @@ import React from "react";
|
|||||||
import { StyleProp, ViewStyle } from "react-native";
|
import { StyleProp, ViewStyle } from "react-native";
|
||||||
import IconButton from "../IconButton";
|
import IconButton from "../IconButton";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { RawElement } from "./RawElement";
|
||||||
|
import { Element } from "./Element";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
@@ -14,91 +16,18 @@ import {
|
|||||||
Divider,
|
Divider,
|
||||||
Switch,
|
Switch,
|
||||||
Popover,
|
Popover,
|
||||||
|
Pressable,
|
||||||
useBreakpointValue,
|
useBreakpointValue,
|
||||||
Select,
|
Select,
|
||||||
} from "native-base";
|
} from "native-base";
|
||||||
|
|
||||||
type ElementType = "custom" | "default" | "text" | "toggle" | "dropdown";
|
export type ElementProps = {
|
||||||
|
|
||||||
type DropdownOption = {
|
|
||||||
label: string;
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ElementTextProps = {
|
|
||||||
text: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ElementToggleProps = {
|
|
||||||
onToggle: (value: boolean) => void;
|
|
||||||
value: boolean;
|
|
||||||
defaultValue?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ElementDropdownProps = {
|
|
||||||
options: DropdownOption[];
|
|
||||||
onSelect: (value: string) => void;
|
|
||||||
value: string;
|
|
||||||
defaultValue?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getElementTextNode = ({ text }: ElementTextProps, disabled: boolean) => {
|
|
||||||
return (
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
opacity: disabled ? 0.4 : 0.6,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{text}
|
|
||||||
</Text>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getElementToggleNode = (
|
|
||||||
{ onToggle, value, defaultValue }: ElementToggleProps,
|
|
||||||
disabled: boolean
|
|
||||||
) => {
|
|
||||||
return (
|
|
||||||
<Switch
|
|
||||||
onToggle={onToggle}
|
|
||||||
isChecked={value ?? false}
|
|
||||||
defaultIsChecked={defaultValue}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getElementDropdownNode = (
|
|
||||||
{ options, onSelect, value, defaultValue }: ElementDropdownProps,
|
|
||||||
disabled: boolean
|
|
||||||
) => {
|
|
||||||
return (
|
|
||||||
<Select
|
|
||||||
selectedValue={value}
|
|
||||||
onValueChange={onSelect}
|
|
||||||
defaultValue={defaultValue}
|
|
||||||
variant="filled"
|
|
||||||
isDisabled={disabled}
|
|
||||||
>
|
|
||||||
{options.map((option) => (
|
|
||||||
<Select.Item
|
|
||||||
key={option.label}
|
|
||||||
label={option.label}
|
|
||||||
value={option.value}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
type ElementProps = {
|
|
||||||
title: string;
|
title: string;
|
||||||
icon?: React.ReactNode;
|
icon?: React.ReactNode;
|
||||||
type?: ElementType | "custom";
|
type?: ElementType | "custom";
|
||||||
helperText?: string;
|
helperText?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
onPress?: () => void;
|
|
||||||
data?:
|
data?:
|
||||||
| ElementTextProps
|
| ElementTextProps
|
||||||
| ElementToggleProps
|
| ElementToggleProps
|
||||||
@@ -106,117 +35,6 @@ type ElementProps = {
|
|||||||
| React.ReactNode;
|
| React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Element = ({
|
|
||||||
title,
|
|
||||||
icon,
|
|
||||||
type,
|
|
||||||
helperText,
|
|
||||||
description,
|
|
||||||
disabled,
|
|
||||||
onPress,
|
|
||||||
node,
|
|
||||||
data,
|
|
||||||
}: ElementProps) => {
|
|
||||||
const screenSize = useBreakpointValue({ base: "small", md: "big" });
|
|
||||||
const isSmallScreen = screenSize === "small";
|
|
||||||
return (
|
|
||||||
<Row
|
|
||||||
style={{
|
|
||||||
width: "100%",
|
|
||||||
height: 45,
|
|
||||||
padding: 15,
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
style={{
|
|
||||||
flexGrow: 1,
|
|
||||||
opacity: disabled ? 0.6 : 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{icon}
|
|
||||||
<Column>
|
|
||||||
<Text isTruncated maxW={"95%"}>
|
|
||||||
{title}
|
|
||||||
</Text>
|
|
||||||
{description && (
|
|
||||||
<Text
|
|
||||||
isTruncated
|
|
||||||
maxW={"90%"}
|
|
||||||
style={{
|
|
||||||
opacity: 0.6,
|
|
||||||
fontSize: 12,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{description}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</Column>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<Row
|
|
||||||
style={{
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{helperText && (
|
|
||||||
<Popover
|
|
||||||
trigger={(triggerProps) => (
|
|
||||||
<Button
|
|
||||||
{...triggerProps}
|
|
||||||
color="gray.500"
|
|
||||||
leftIcon={
|
|
||||||
<Icon
|
|
||||||
as={Ionicons}
|
|
||||||
size={"md"}
|
|
||||||
name="help-circle-outline"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
variant="ghost"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Popover.Content
|
|
||||||
accessibilityLabel={`Additionnal information for ${title}`}
|
|
||||||
style={{
|
|
||||||
maxWidth: isSmallScreen ? "90vw" : "20vw",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Popover.Arrow />
|
|
||||||
<Popover.Body>{helperText}</Popover.Body>
|
|
||||||
</Popover.Content>
|
|
||||||
</Popover>
|
|
||||||
)}
|
|
||||||
{(() => {
|
|
||||||
switch (type) {
|
|
||||||
case "text":
|
|
||||||
return getElementTextNode(
|
|
||||||
data as ElementTextProps,
|
|
||||||
disabled ?? false
|
|
||||||
);
|
|
||||||
case "toggle":
|
|
||||||
return getElementToggleNode(
|
|
||||||
data as ElementToggleProps,
|
|
||||||
disabled ?? false
|
|
||||||
);
|
|
||||||
case "dropdown":
|
|
||||||
return getElementDropdownNode(
|
|
||||||
data as ElementDropdownProps,
|
|
||||||
disabled ?? false
|
|
||||||
);
|
|
||||||
case "custom":
|
|
||||||
return data as React.ReactNode;
|
|
||||||
default:
|
|
||||||
return <Text>Unknown type</Text>;
|
|
||||||
}
|
|
||||||
})()}
|
|
||||||
</Row>
|
|
||||||
</Box>
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
type ElementListProps = {
|
type ElementListProps = {
|
||||||
elements: ElementProps[];
|
elements: ElementProps[];
|
||||||
style?: StyleProp<ViewStyle>;
|
style?: StyleProp<ViewStyle>;
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import {
|
||||||
|
Select,
|
||||||
|
Switch,
|
||||||
|
Text,
|
||||||
|
} from "native-base";
|
||||||
|
|
||||||
|
export type ElementType = "custom" | "default" | "text" | "toggle" | "dropdown";
|
||||||
|
|
||||||
|
export type DropdownOption = {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ElementTextProps = {
|
||||||
|
text: string;
|
||||||
|
onPress?: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ElementToggleProps = {
|
||||||
|
onToggle: (value: boolean) => void;
|
||||||
|
value: boolean;
|
||||||
|
defaultValue?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ElementDropdownProps = {
|
||||||
|
options: DropdownOption[];
|
||||||
|
onSelect: (value: string) => void;
|
||||||
|
value: string;
|
||||||
|
defaultValue?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getElementTextNode = ({ text }: ElementTextProps, disabled: boolean) => {
|
||||||
|
return (
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
opacity: disabled ? 0.4 : 0.6,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getElementToggleNode = (
|
||||||
|
{ onToggle, value, defaultValue }: ElementToggleProps,
|
||||||
|
disabled: boolean
|
||||||
|
) => {
|
||||||
|
return (
|
||||||
|
<Switch
|
||||||
|
onToggle={onToggle}
|
||||||
|
isChecked={value ?? false}
|
||||||
|
defaultIsChecked={defaultValue}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getElementDropdownNode = (
|
||||||
|
{ options, onSelect, value, defaultValue }: ElementDropdownProps,
|
||||||
|
disabled: boolean
|
||||||
|
) => {
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
selectedValue={value}
|
||||||
|
onValueChange={onSelect}
|
||||||
|
defaultValue={defaultValue}
|
||||||
|
variant="filled"
|
||||||
|
isDisabled={disabled}
|
||||||
|
>
|
||||||
|
{options.map((option) => (
|
||||||
|
<Select.Item
|
||||||
|
key={option.label}
|
||||||
|
label={option.label}
|
||||||
|
value={option.value}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Column,
|
||||||
|
Divider,
|
||||||
|
Icon,
|
||||||
|
Popover,
|
||||||
|
Row,
|
||||||
|
Text,
|
||||||
|
useBreakpointValue,
|
||||||
|
} from "native-base";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { ElementProps } from "./ElementList";
|
||||||
|
import {
|
||||||
|
getElementDropdownNode,
|
||||||
|
getElementTextNode,
|
||||||
|
getElementToggleNode,
|
||||||
|
ElementDropdownProps,
|
||||||
|
ElementTextProps,
|
||||||
|
ElementToggleProps,
|
||||||
|
} from "./ElementTypes";
|
||||||
|
|
||||||
|
export const RawElement = (
|
||||||
|
{ title, icon, type, helperText, description, disabled, data }: ElementProps,
|
||||||
|
isHovered: boolean
|
||||||
|
) => {
|
||||||
|
const screenSize = useBreakpointValue({ base: "small", md: "big" });
|
||||||
|
const isSmallScreen = screenSize === "small";
|
||||||
|
return (
|
||||||
|
<Row
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: 45,
|
||||||
|
padding: 15,
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
style={{
|
||||||
|
flexGrow: 1,
|
||||||
|
opacity: disabled ? 0.6 : 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{icon}
|
||||||
|
<Column>
|
||||||
|
<Text isTruncated maxW={"95%"}>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
{description && (
|
||||||
|
<Text
|
||||||
|
isTruncated
|
||||||
|
maxW={"90%"}
|
||||||
|
style={{
|
||||||
|
opacity: 0.6,
|
||||||
|
fontSize: 12,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{description}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</Column>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Row
|
||||||
|
style={{
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{helperText && (
|
||||||
|
<Popover
|
||||||
|
trigger={(triggerProps) => (
|
||||||
|
<Button
|
||||||
|
{...triggerProps}
|
||||||
|
color="gray.500"
|
||||||
|
leftIcon={
|
||||||
|
<Icon
|
||||||
|
as={Ionicons}
|
||||||
|
size={"md"}
|
||||||
|
name="help-circle-outline"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
variant="ghost"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Popover.Content
|
||||||
|
accessibilityLabel={`Additionnal information for ${title}`}
|
||||||
|
style={{
|
||||||
|
maxWidth: isSmallScreen ? "90vw" : "20vw",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Popover.Arrow />
|
||||||
|
<Popover.Body>{helperText}</Popover.Body>
|
||||||
|
</Popover.Content>
|
||||||
|
</Popover>
|
||||||
|
)}
|
||||||
|
{(() => {
|
||||||
|
switch (type) {
|
||||||
|
case "text":
|
||||||
|
return getElementTextNode(
|
||||||
|
data as ElementTextProps,
|
||||||
|
disabled ?? false
|
||||||
|
);
|
||||||
|
case "toggle":
|
||||||
|
return getElementToggleNode(
|
||||||
|
data as ElementToggleProps,
|
||||||
|
disabled ?? false
|
||||||
|
);
|
||||||
|
case "dropdown":
|
||||||
|
return getElementDropdownNode(
|
||||||
|
data as ElementDropdownProps,
|
||||||
|
disabled ?? false
|
||||||
|
);
|
||||||
|
case "custom":
|
||||||
|
return data as React.ReactNode;
|
||||||
|
default:
|
||||||
|
return <Text>Unknown type</Text>;
|
||||||
|
}
|
||||||
|
})()}
|
||||||
|
</Row>
|
||||||
|
</Box>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -90,11 +90,11 @@ const ProfileSettings = ({ navigation }: { navigation: any }) => {
|
|||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
title: "Email",
|
title: "Email",
|
||||||
onPress: () => {
|
|
||||||
console.log("Go to email settings");
|
|
||||||
},
|
|
||||||
data: {
|
data: {
|
||||||
text: user.email || "Aucun email associé",
|
text: user.email || "Aucun email associé",
|
||||||
|
onPress: () => {
|
||||||
|
console.log("Go to email settings");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user