UNPKG

@ai-stack/payloadcms

Version:

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

142 lines (141 loc) 5.22 kB
'use client'; import { useEditorConfigContext } from '@payloadcms/richtext-lexical/client'; import { Popup, useDocumentDrawer, useField } from '@payloadcms/ui'; import React, { useCallback, useMemo, useState } from 'react'; import { PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js'; import { setSafeLexicalState } from '../../utilities/setSafeLexicalState.js'; import { PluginIcon } from '../Icons/Icons.js'; import styles from './compose.module.css'; import { useMenu } from './hooks/menu/useMenu.js'; import { useActiveFieldTracking } from './hooks/useActiveFieldTracking.js'; import { useGenerate } from './hooks/useGenerate.js'; import { UndoRedoActions } from './UndoRedoActions.js'; export const Compose = ({ descriptionProps, instructionId, isConfigAllowed }) => { const [DocumentDrawer, _, { closeDrawer, openDrawer }] = useDocumentDrawer({ id: instructionId, collectionSlug: PLUGIN_INSTRUCTIONS_TABLE, }); const pathFromContext = descriptionProps?.path; const { editor: lexicalEditor } = useEditorConfigContext(); // Initialize global active-field tracking useActiveFieldTracking(); const [isProcessing, setIsProcessing] = useState(false); const { generate, isLoading, stop } = useGenerate({ instructionId }); const { ActiveComponent, Menu } = useMenu({ onCompose: () => { console.log('Composing...'); setIsProcessing(true); generate({ action: 'Compose', }) .catch((reason) => { console.error('Compose : ', reason); }) .finally(() => { setIsProcessing(false); }); }, onExpand: () => { console.log('Expanding...'); generate({ action: 'Expand', }) .catch((reason) => { console.error('Compose : ', reason); }) .finally(() => { setIsProcessing(false); }); }, onProofread: () => { console.log('Proofreading...'); generate({ action: 'Proofread', }) .catch((reason) => { console.error('Compose : ', reason); }) .finally(() => { setIsProcessing(false); }); }, onRephrase: () => { console.log('Rephrasing...'); generate({ action: 'Rephrase', }) .catch((reason) => { console.error('Compose : ', reason); }) .finally(() => { setIsProcessing(false); }); }, onSettings: isConfigAllowed ? openDrawer : undefined, onSimplify: () => { console.log('Simplifying...'); generate({ action: 'Simplify', }) .catch((reason) => { console.error('Compose : ', reason); }) .finally(() => { setIsProcessing(false); }); }, onSummarize: () => { console.log('Summarizing...'); generate({ action: 'Summarize', }) .catch((reason) => { console.error('Compose : ', reason); }) .finally(() => { setIsProcessing(false); }); }, onTranslate: (data) => { console.log('Translating...'); generate({ action: 'Translate', params: data, }) .catch((reason) => { console.error('Compose : ', reason); }) .finally(() => { setIsProcessing(false); }); }, }, { isConfigAllowed, }); const { setValue } = useField({ path: pathFromContext, }); const setIfValueIsLexicalState = useCallback((val) => { if (val && typeof val === 'object' && 'root' in val && lexicalEditor) { setSafeLexicalState(JSON.stringify(val), lexicalEditor); } // DO NOT PROVIDE lexicalEditor as a dependency, it freaks out and does not update the editor after first undo/redo }, []); const popupRender = useCallback(({ close }) => { return <Menu isLoading={isProcessing || isLoading} onClose={close}/>; }, [isProcessing, isLoading, Menu]); const memoizedPopup = useMemo(() => { return (<Popup button={<PluginIcon isLoading={isProcessing || isLoading}/>} render={popupRender} verticalAlign="bottom"/>); }, [popupRender, isProcessing, isLoading]); return (<label className={`payloadai-compose__actions ${styles.actions}`} onClick={(e) => e.preventDefault()} role="presentation"> <DocumentDrawer onSave={() => { closeDrawer(); }}/> {memoizedPopup} <ActiveComponent isLoading={isProcessing || isLoading} stop={stop}/> <UndoRedoActions onChange={(val) => { setValue(val); setIfValueIsLexicalState(val); }}/> </label>); };