diff --git a/package.json b/package.json index 6a5469457..2fbcf5ff4 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "dockerode": "^3.3.2", "embla-carousel-react": "^7.0.0", "fily-publish-gridstack": "^0.0.13", - "framer-motion": "^6.5.1", + "framer-motion": "^9.0.2", "i18next": "^21.9.1", "i18next-browser-languagedetector": "^6.1.5", "i18next-http-backend": "^1.4.1", diff --git a/src/components/Dashboard/Tiles/Widgets/DraggableList.tsx b/src/components/Dashboard/Tiles/Widgets/DraggableList.tsx new file mode 100644 index 000000000..ae6d68998 --- /dev/null +++ b/src/components/Dashboard/Tiles/Widgets/DraggableList.tsx @@ -0,0 +1,119 @@ +import { Collapse, createStyles, Stack, Text } from '@mantine/core'; +import { IconChevronDown, IconGripVertical } from '@tabler/icons'; +import { Reorder, useDragControls } from 'framer-motion'; +import { FC, ReactNode, useState } from 'react'; +import { IDraggableListInputValue } from '../../../../widgets/widgets'; + +const useStyles = createStyles((theme) => ({ + container: { + display: 'flex', + flexDirection: 'column', + borderRadius: theme.radius.md, + border: `1px solid ${ + theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[2] + }`, + backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.white, + marginBottom: theme.spacing.xs, + gap: theme.spacing.xs, + }, + row: { + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + padding: '12px 16px', + gap: theme.spacing.sm, + }, + middle: { + flexGrow: 1, + }, + symbol: { + fontSize: 16, + }, + clickableIcons: { + color: theme.colorScheme === 'dark' ? theme.colors.dark[1] : theme.colors.gray[6], + cursor: 'pointer', + userSelect: 'none', + transition: 'transform .3s ease-in-out', + }, + rotate: { + transform: 'rotate(180deg)', + }, + collapseContent: { + padding: '12px 16px', + }, +})); + +type DraggableListParams = { + value: IDraggableListInputValue['defaultValue']; + onChange: (value: IDraggableListInputValue['defaultValue']) => void; + labels: Record; + children?: Record; +}; + +export const DraggableList: FC = (props) => { + const keys = props.value.map((v) => v.key); + + return ( +
+ + props.onChange(order.map((key) => props.value.find((v) => v.key === key)!)) + } + as="div" + > + {props.value.map((item) => ( + + {props.children?.[item.key]} + + ))} + +
+ ); +}; + +const ListItem: FC<{ + item: IDraggableListInputValue['defaultValue'][number]; + label: string; +}> = (props) => { + const { classes, cx } = useStyles(); + const controls = useDragControls(); + + const [showContent, setShowContent] = useState(false); + const hasContent = props.children != null && Object.keys(props.children).length !== 0; + + return ( + +
+
+ controls.start(e)} + size={18} + stroke={1.5} + /> + +
+ {props.label} +
+ + {hasContent && ( + setShowContent(!showContent)} + size={18} + stroke={1.5} + /> + )} +
+ + {hasContent && ( + + {props.children} + + )} +
+
+ ); +}; diff --git a/src/components/Dashboard/Tiles/Widgets/WidgetsEditModal.tsx b/src/components/Dashboard/Tiles/Widgets/WidgetsEditModal.tsx index 62a2550a4..3d53a395a 100644 --- a/src/components/Dashboard/Tiles/Widgets/WidgetsEditModal.tsx +++ b/src/components/Dashboard/Tiles/Widgets/WidgetsEditModal.tsx @@ -3,24 +3,25 @@ import { Button, Group, MultiSelect, + NumberInput, + Select, + Slider, Stack, Switch, - TextInput, Text, - NumberInput, - Slider, - Select, + TextInput, } from '@mantine/core'; import { ContextModalProps } from '@mantine/modals'; import { IconAlertTriangle } from '@tabler/icons'; import { Trans, useTranslation } from 'next-i18next'; -import { useState } from 'react'; -import Widgets from '../../../../widgets'; -import type { IWidgetOptionValue } from '../../../../widgets/widgets'; +import { FC, useState } from 'react'; import { useConfigContext } from '../../../../config/provider'; import { useConfigStore } from '../../../../config/store'; -import { IWidget } from '../../../../widgets/widgets'; import { useColorTheme } from '../../../../tools/color'; +import Widgets from '../../../../widgets'; +import type { IDraggableListInputValue, IWidgetOptionValue } from '../../../../widgets/widgets'; +import { IWidget } from '../../../../widgets/widgets'; +import { DraggableList } from './DraggableList'; export type WidgetEditModalInnerProps = { widgetId: string; @@ -93,7 +94,17 @@ export const WidgetsEditModal = ({ ); } - return WidgetOptionTypeSwitch(option, index, t, key, value, handleChange); + + return ( + + ); })}