Files
flxn-app/src/components/sheet/slide-panel/slide-panel-field.tsx
2025-09-16 09:24:21 -05:00

115 lines
2.7 KiB
TypeScript

import { Box, Text, UnstyledButton, Flex, Stack } from "@mantine/core";
import { CaretRightIcon } from "@phosphor-icons/react";
import React, { ComponentType, useContext } from "react";
import { SlidePanelContext } from "./slide-panel-context";
interface SlidePanelFieldProps {
key: string;
value?: any;
onChange?: (value: any) => void;
Component: ComponentType<any>;
title: string;
label?: string;
placeholder?: string;
formatValue?: (value: any) => string | React.ReactNode;
componentProps?: Record<string, any>;
withAsterisk?: boolean;
error?: string;
}
const SlidePanelField = ({
value,
onChange,
Component,
title,
label,
placeholder = "Select value",
withAsterisk = false,
formatValue,
componentProps,
error,
}: SlidePanelFieldProps) => {
const context = useContext(SlidePanelContext);
if (!context) {
throw new Error("SlidePanelField must be used within a SlidePanel");
}
const handleClick = () => {
if (!onChange) return;
context.openPanel({
title,
Component,
value,
onChange,
componentProps,
});
};
const displayValue = () => {
if (formatValue && value != null) {
return formatValue(value);
}
if (value != null) {
if (value instanceof Date) {
return value.toLocaleDateString();
}
return String(value);
}
return placeholder;
};
return (
<Box>
<UnstyledButton
onClick={handleClick}
p="sm"
style={{
width: "100%",
border: error
? "1px solid var(--mantine-color-error)"
: "1px solid var(--mantine-color-dimmed)",
borderRadius: "var(--mantine-radius-md)",
backgroundColor: "var(--mantine-color-body)",
textAlign: "left",
}}
>
<Flex justify="space-between" align="center">
<Stack>
<Text size="sm" fw={500}>
{label}
{withAsterisk && (
<Text
span
size="sm"
c="var(--mantine-color-error)"
fw={500}
ml={4}
>
*
</Text>
)}
</Text>
<Text size="sm" c="dimmed">
{displayValue()}
</Text>
</Stack>
<CaretRightIcon
size={24}
weight="thin"
style={{ marginRight: "12px" }}
/>
</Flex>
</UnstyledButton>
{error && (
<Text size="xs" c="var(--mantine-color-error)" fw={500} ml={4} mt={4}>
{error}
</Text>
)}
</Box>
);
};
export { SlidePanelField };