Element functions are now split into multiple file and started the ground work for onPress support
This commit is contained in:
15
front/components/GtkUI/Element.tsx
Normal file
15
front/components/GtkUI/Element.tsx
Normal file
@@ -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 IconButton from "../IconButton";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { RawElement } from "./RawElement";
|
||||
import { Element } from "./Element";
|
||||
|
||||
import {
|
||||
Box,
|
||||
@@ -14,91 +16,18 @@ import {
|
||||
Divider,
|
||||
Switch,
|
||||
Popover,
|
||||
Pressable,
|
||||
useBreakpointValue,
|
||||
Select,
|
||||
} from "native-base";
|
||||
|
||||
type ElementType = "custom" | "default" | "text" | "toggle" | "dropdown";
|
||||
|
||||
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 = {
|
||||
export type ElementProps = {
|
||||
title: string;
|
||||
icon?: React.ReactNode;
|
||||
type?: ElementType | "custom";
|
||||
helperText?: string;
|
||||
description?: string;
|
||||
disabled?: boolean;
|
||||
onPress?: () => void;
|
||||
data?:
|
||||
| ElementTextProps
|
||||
| ElementToggleProps
|
||||
@@ -106,117 +35,6 @@ type ElementProps = {
|
||||
| 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 = {
|
||||
elements: ElementProps[];
|
||||
style?: StyleProp<ViewStyle>;
|
||||
|
||||
79
front/components/GtkUI/ElementTypes.tsx
Normal file
79
front/components/GtkUI/ElementTypes.tsx
Normal file
@@ -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>
|
||||
);
|
||||
};
|
||||
126
front/components/GtkUI/RawElement.tsx
Normal file
126
front/components/GtkUI/RawElement.tsx
Normal file
@@ -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",
|
||||
title: "Email",
|
||||
onPress: () => {
|
||||
console.log("Go to email settings");
|
||||
},
|
||||
data: {
|
||||
text: user.email || "Aucun email associé",
|
||||
onPress: () => {
|
||||
console.log("Go to email settings");
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user