UNPKG

@ai-stack/payloadcms

Version:

<p align="center"> <img alt="Payload AI Plugin" src="assets/payload-ai-intro.gif" width="100%" /> </p>

93 lines (92 loc) 3.96 kB
'use client'; import { useField, useTranslation } from '@payloadcms/ui'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useFieldProps } from '../../../../providers/FieldProvider/useFieldProps.js'; import { Compose, Proofread, Rephrase } from './items.js'; import { menuItemsMap } from './itemsMap.js'; import styles from './menu.module.scss'; const getActiveComponent = (ac) => { switch (ac) { case 'Compose': return Compose; case 'Proofread': return Proofread; case 'Rephrase': return Rephrase; default: return Rephrase; } }; export const useMenu = (menuEvents, options) => { const { field: { type: fieldType } = {}, path: pathFromContext } = useFieldProps(); const field = useField({ path: pathFromContext ?? '' }); const { t } = useTranslation(); const [activeComponent, setActiveComponent] = useState('Rephrase'); const { initialValue, value } = field; useEffect(() => { if (!value) { setActiveComponent('Compose'); return; } if (menuItemsMap.some((i) => i.excludedFor?.includes(fieldType ?? ''))) { setActiveComponent('Compose'); return; } if (typeof value === 'string' && value !== initialValue) { setActiveComponent('Proofread'); } else { setActiveComponent('Rephrase'); } }, [initialValue, value, fieldType]); const renderLabel = useCallback((key) => <span className={styles.text}>{t(key)}</span>, [t]); const MemoizedActiveComponent = useMemo(() => { return ({ isLoading, stop }) => { const ActiveComponent = getActiveComponent(activeComponent); const activeItem = menuItemsMap.find((i) => i.name === activeComponent); const loadingKey = activeItem.loadingKey ?? activeItem.labelKey; return (<ActiveComponent hideIcon onClick={(data) => { if (!isLoading) { const trigger = menuEvents[`on${activeComponent}`]; if (typeof trigger === 'function') { trigger(data); } else { console.error('No trigger found for', activeComponent); } } else { stop(); } }} title={isLoading ? t('ai-plugin:clickToStop') : t(activeItem.labelKey)}> {isLoading ? t(loadingKey) : renderLabel(activeItem.labelKey)} </ActiveComponent>); }; }, [activeComponent, menuEvents, renderLabel, t]); const filteredMenuItems = useMemo(() => menuItemsMap.filter((i) => { if (i.name === 'Settings' && !options.isConfigAllowed) { return false; } // Disable settings if a user role is not permitted return i.name !== activeComponent && !i.excludedFor?.includes(fieldType ?? ''); }), [activeComponent, fieldType, options.isConfigAllowed]); const MemoizedMenu = useMemo(() => { return ({ isLoading, onClose }) => (<div className={styles.menu}> {filteredMenuItems.map((i) => { const Action = i.component; return (<Action disabled={isLoading} key={i.name} onClick={(data) => { if (i.name !== 'Settings') { setActiveComponent(i.name); } menuEvents[`on${i.name}`]?.(data); onClose(); }}> {isLoading && i.loadingKey ? t(i.loadingKey) : renderLabel(i.labelKey)} </Action>); })} </div>); }, [filteredMenuItems, menuEvents, renderLabel, t]); return { ActiveComponent: MemoizedActiveComponent, Menu: MemoizedMenu, }; };