mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-19 16:06:02 +01:00
* feat: Support image Tag in buttons in my server. ox_lib is heavily used. most of sample use cases for this is. Food image, Ingredients, Vehicle Parts, etc.. i believe font awesome is not enough for some use cases. i did suggest this on v3 pending PR. but it seems gets ignored. here i am gonna try to push this PR. to use this. icon must be not existing in the options. if both icon and image is in options, nothing will appear. image in metadata will still appear normaly. * tweak(web/menu): resize render image comparable to FA * refactor(web/context): use icon prop for images * refactor(web/list): use icon prop for images --------- Co-authored-by: Luke <39926192+LukeWasTakenn@users.noreply.github.com>
138 lines
4.1 KiB
TypeScript
138 lines
4.1 KiB
TypeScript
import { Box, Group, Stack, Text, Progress, Image } from '@mantine/core';
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
import React, { forwardRef } from 'react';
|
|
import CustomCheckbox from './CustomCheckbox';
|
|
import type { MenuItem } from '../../../typings';
|
|
import { createStyles } from '@mantine/core';
|
|
import { isIconUrl } from '../../../utils/isIconUrl';
|
|
import { IconProp } from '@fortawesome/fontawesome-svg-core';
|
|
|
|
interface Props {
|
|
item: MenuItem;
|
|
index: number;
|
|
scrollIndex: number;
|
|
checked: boolean;
|
|
}
|
|
|
|
const useStyles = createStyles((theme, params: { iconColor?: string }) => ({
|
|
buttonContainer: {
|
|
backgroundColor: theme.colors.dark[6],
|
|
borderRadius: theme.radius.md,
|
|
padding: 2,
|
|
height: 60,
|
|
scrollMargin: 8,
|
|
'&:focus': {
|
|
backgroundColor: theme.colors.dark[4],
|
|
outline: 'none',
|
|
},
|
|
},
|
|
iconImage: {
|
|
maxWidth: 32,
|
|
},
|
|
buttonWrapper: {
|
|
paddingLeft: 5,
|
|
paddingRight: 12,
|
|
height: '100%',
|
|
},
|
|
iconContainer: {
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
width: 32,
|
|
height: 32,
|
|
},
|
|
icon: {
|
|
fontSize: 24,
|
|
color: params.iconColor || theme.colors.dark[2],
|
|
},
|
|
label: {
|
|
color: theme.colors.dark[2],
|
|
textTransform: 'uppercase',
|
|
fontSize: 12,
|
|
verticalAlign: 'middle',
|
|
},
|
|
chevronIcon: {
|
|
fontSize: 14,
|
|
color: theme.colors.dark[2],
|
|
},
|
|
scrollIndexValue: {
|
|
color: theme.colors.dark[2],
|
|
textTransform: 'uppercase',
|
|
fontSize: 14,
|
|
},
|
|
progressStack: {
|
|
width: '100%',
|
|
marginRight: 5,
|
|
},
|
|
progressLabel: {
|
|
verticalAlign: 'middle',
|
|
marginBottom: 3,
|
|
},
|
|
}));
|
|
|
|
const ListItem = forwardRef<Array<HTMLDivElement | null>, Props>(({ item, index, scrollIndex, checked }, ref) => {
|
|
const { classes } = useStyles({ iconColor: item.iconColor });
|
|
|
|
return (
|
|
<Box
|
|
tabIndex={index}
|
|
className={classes.buttonContainer}
|
|
key={`item-${index}`}
|
|
ref={(element: HTMLDivElement) => {
|
|
if (ref)
|
|
// @ts-ignore i cba
|
|
return (ref.current = [...ref.current, element]);
|
|
}}
|
|
>
|
|
<Group spacing={15} noWrap className={classes.buttonWrapper}>
|
|
{item.icon && (
|
|
<Box className={classes.iconContainer}>
|
|
{typeof item.icon === 'string' && isIconUrl(item.icon) ? (
|
|
<img src={item.icon} alt="Missing image" className={classes.iconImage} />
|
|
) : (
|
|
<FontAwesomeIcon icon={item.icon as IconProp} className={classes.icon} fixedWidth />
|
|
)}
|
|
</Box>
|
|
)}
|
|
{Array.isArray(item.values) ? (
|
|
<Group position="apart" w="100%">
|
|
<Stack spacing={0} justify="space-between">
|
|
<Text className={classes.label}>{item.label}</Text>
|
|
<Text>
|
|
{typeof item.values[scrollIndex] === 'object'
|
|
? // @ts-ignore for some reason even checking the type TS still thinks it's a string
|
|
item.values[scrollIndex].label
|
|
: item.values[scrollIndex]}
|
|
</Text>
|
|
</Stack>
|
|
<Group spacing={1} position="center">
|
|
<FontAwesomeIcon icon="chevron-left" className={classes.chevronIcon} />
|
|
<Text className={classes.scrollIndexValue}>
|
|
{scrollIndex + 1}/{item.values.length}
|
|
</Text>
|
|
<FontAwesomeIcon icon="chevron-right" className={classes.chevronIcon} />
|
|
</Group>
|
|
</Group>
|
|
) : item.checked !== undefined ? (
|
|
<Group position="apart" w="100%">
|
|
<Text>{item.label}</Text>
|
|
<CustomCheckbox checked={checked}></CustomCheckbox>
|
|
</Group>
|
|
) : item.progress !== undefined ? (
|
|
<Stack className={classes.progressStack} spacing={0}>
|
|
<Text className={classes.progressLabel}>{item.label}</Text>
|
|
<Progress
|
|
value={item.progress}
|
|
color={item.colorScheme || 'dark.0'}
|
|
styles={(theme) => ({ root: { backgroundColor: theme.colors.dark[3] } })}
|
|
/>
|
|
</Stack>
|
|
) : (
|
|
<Text>{item.label}</Text>
|
|
)}
|
|
</Group>
|
|
</Box>
|
|
);
|
|
});
|
|
|
|
export default React.memo(ListItem);
|