/* eslint-disable react-refresh/only-export-components */ import { type MenuItemProps, type MenuProps } from '@mantine/core'; import { getUUID } from '@warkypublic/artemis-kit'; import { createSyncStore } from '@warkypublic/zustandsyncstore'; import { produce } from 'immer'; import { type ReactNode } from 'react'; export interface MantineBetterMenuInstance { id: string; items?: Array; menuProps?: MenuProps; renderer?: ReactNode; visible: boolean; x: number; y: number; } export interface MantineBetterMenuInstanceItem extends Partial { id?: string; isDivider?: boolean; items?: Array; label?: string; onClick?: (e?: React.MouseEvent) => void; onClickAsync?: () => Promise; renderer?: | ((props: MantineBetterMenuInstanceItem & Record) => ReactNode) | ReactNode; } export interface MantineBetterMenuStoreProps { menus?: Array; providerID?: string; width?: number; } export type MantineBetterMenuStoreState = MantineBetterMenuStoreProps & MantineBetterMenuStoreStateOnly; export interface MantineBetterMenuStoreStateOnly { hide: (id: string) => void; menus: Array; setInstanceState: ( instanceID: string, key: K, value: MantineBetterMenuInstance[K] ) => void; setState: ( key: K, value: Partial ) => void; show: (id: string, options?: Partial) => void; } const { Provider: MantineBetterMenusStoreProvider, useStore: useMantineBetterMenus } = createSyncStore( (set, get) => ({ hide: (id: string) => { const s = get(); s.setInstanceState(id, 'visible', false); }, menus: [], setInstanceState: (id, key, value) => { //@ts-expect-error Type instantiation is excessively deep and possibly infinite. set( produce((state: MantineBetterMenuStoreState) => { const idx = state?.menus?.findIndex((m: MantineBetterMenuInstance) => m.id === id); if (idx >= 0) { state.menus[idx][key] = value; } }) ); }, setState: (key, value) => { set( produce((state) => { state[key] = value; }) ); }, show: (id: string, options?: Partial>) => { const s = get(); const menuIndex = s.menus.findIndex((m) => m.id === id); const menu: Partial = s.menus[menuIndex] ? { ...s.menus[menuIndex] } : {}; Object.assign(menu, options); menu.id = menu.id ?? id; menu.visible = !(menu.visible ?? false); if (menuIndex < 0) { s.setState('menus', [...s.menus, menu as MantineBetterMenuInstance]); } else { set( produce((state: MantineBetterMenuStoreState) => { if (!state.menus) { state.menus = []; } state.menus[menuIndex] = { ...state.menus[menuIndex], ...menu }; }) ); } }, }), (props) => { return { providerID: props.providerID ?? `MenuStore-${getUUID()}`, }; } ); export { MantineBetterMenusStoreProvider, useMantineBetterMenus };