@ai-stack/payloadcms 3.76.0-beta.0 → 3.76.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/core/generateObject.js +1 -4
- package/dist/ai/core/generateObject.js.map +1 -1
- package/dist/ai/core/generateText.js +1 -5
- package/dist/ai/core/generateText.js.map +1 -1
- package/dist/ai/core/media/generateMedia.js +1 -4
- package/dist/ai/core/media/generateMedia.js.map +1 -1
- package/dist/ai/core/media/image/generateImage.js +4 -14
- package/dist/ai/core/media/image/generateImage.js.map +1 -1
- package/dist/ai/core/media/image/handlers/multimodal.js +21 -58
- package/dist/ai/core/media/image/handlers/multimodal.js.map +1 -1
- package/dist/ai/core/media/image/handlers/standard.js +17 -9
- package/dist/ai/core/media/image/handlers/standard.js.map +1 -1
- package/dist/ai/core/media/speech/generateSpeech.js +10 -11
- package/dist/ai/core/media/speech/generateSpeech.js.map +1 -1
- package/dist/ai/core/media/types.d.ts +3 -4
- package/dist/ai/core/media/types.js.map +1 -1
- package/dist/ai/core/streamObject.js +0 -3
- package/dist/ai/core/streamObject.js.map +1 -1
- package/dist/ai/core/streamText.js +1 -4
- package/dist/ai/core/streamText.js.map +1 -1
- package/dist/ai/core/types.d.ts +2 -2
- package/dist/ai/core/types.js.map +1 -1
- package/dist/ai/providers/blocks/anthropic.js +0 -42
- package/dist/ai/providers/blocks/anthropic.js.map +1 -1
- package/dist/ai/providers/blocks/elevenlabs.js +1 -106
- package/dist/ai/providers/blocks/elevenlabs.js.map +1 -1
- package/dist/ai/providers/blocks/fal.js +0 -118
- package/dist/ai/providers/blocks/fal.js.map +1 -1
- package/dist/ai/providers/blocks/google.js +2 -236
- package/dist/ai/providers/blocks/google.js.map +1 -1
- package/dist/ai/providers/blocks/openai-compatible.js +0 -144
- package/dist/ai/providers/blocks/openai-compatible.js.map +1 -1
- package/dist/ai/providers/blocks/openai.js +0 -200
- package/dist/ai/providers/blocks/openai.js.map +1 -1
- package/dist/ai/providers/blocks/xai.js +0 -53
- package/dist/ai/providers/blocks/xai.js.map +1 -1
- package/dist/ai/providers/index.d.ts +1 -1
- package/dist/ai/providers/index.js +0 -2
- package/dist/ai/providers/index.js.map +1 -1
- package/dist/ai/providers/registry.d.ts +24 -28
- package/dist/ai/providers/registry.js +186 -140
- package/dist/ai/providers/registry.js.map +1 -1
- package/dist/ai/providers/types.d.ts +12 -33
- package/dist/ai/providers/types.js +0 -1
- package/dist/ai/providers/types.js.map +1 -1
- package/dist/ai/schemas/lexicalJsonSchema.js +1 -1
- package/dist/ai/schemas/lexicalJsonSchema.js.map +1 -1
- package/dist/ai/utilities/filterEditorSchemaByNodes.js.map +1 -0
- package/dist/ai/utilities/generateFileNameByPrompt.js.map +1 -0
- package/dist/ai/utilities/isObjectSchema.js.map +1 -0
- package/dist/ai/utilities/nodeToSchemaMap.js.map +1 -0
- package/dist/ai/{prompts.d.ts → utilities/prompts.d.ts} +1 -1
- package/dist/ai/utilities/prompts.js.map +1 -0
- package/dist/ai/utilities/systemGenerate.js.map +1 -0
- package/dist/collections/AIJobs.js +3 -12
- package/dist/collections/AIJobs.js.map +1 -1
- package/dist/collections/AIProviders.d.ts +2 -0
- package/dist/collections/{AISettings.js → AIProviders.js} +54 -26
- package/dist/collections/AIProviders.js.map +1 -0
- package/dist/collections/Instructions.js +93 -57
- package/dist/collections/Instructions.js.map +1 -1
- package/dist/collections/shared.d.ts +30 -0
- package/dist/collections/shared.js +15 -0
- package/dist/collections/shared.js.map +1 -0
- package/dist/defaults.js +1 -1
- package/dist/defaults.js.map +1 -1
- package/dist/endpoints/fetchFields.js +15 -7
- package/dist/endpoints/fetchFields.js.map +1 -1
- package/dist/endpoints/fetchVoices.js +2 -2
- package/dist/endpoints/fetchVoices.js.map +1 -1
- package/dist/endpoints/generate.d.ts +7 -0
- package/dist/endpoints/generate.js +268 -0
- package/dist/endpoints/generate.js.map +1 -0
- package/dist/endpoints/index.js +9 -604
- package/dist/endpoints/index.js.map +1 -1
- package/dist/endpoints/promptMentions.d.ts +2 -0
- package/dist/endpoints/promptMentions.js +166 -0
- package/dist/endpoints/promptMentions.js.map +1 -0
- package/dist/endpoints/upload.d.ts +7 -0
- package/dist/endpoints/upload.js +294 -0
- package/dist/endpoints/upload.js.map +1 -0
- package/dist/endpoints/videogenWebhook.d.ts +7 -0
- package/dist/endpoints/videogenWebhook.js +132 -0
- package/dist/endpoints/videogenWebhook.js.map +1 -0
- package/dist/exports/client.d.ts +3 -2
- package/dist/exports/client.js +3 -2
- package/dist/exports/client.js.map +1 -1
- package/dist/exports/fields.d.ts +2 -1
- package/dist/exports/fields.js +2 -1
- package/dist/exports/fields.js.map +1 -1
- package/dist/fields/ArrayComposeField/ArrayComposeField.js +1 -1
- package/dist/fields/ArrayComposeField/ArrayComposeField.js.map +1 -1
- package/dist/fields/ArrayComposeField/ArrayComposeField.jsx +1 -1
- package/dist/fields/ComposeField/ComposeField.d.ts +1 -0
- package/dist/fields/ComposeField/ComposeField.js +18 -8
- package/dist/fields/ComposeField/ComposeField.js.map +1 -1
- package/dist/fields/ComposeField/ComposeField.jsx +12 -7
- package/dist/fields/PromptEditorField/feature.client.d.ts +1 -0
- package/dist/fields/PromptEditorField/feature.client.js +173 -0
- package/dist/fields/PromptEditorField/feature.client.js.map +1 -0
- package/dist/fields/PromptEditorField/feature.client.jsx +148 -0
- package/dist/fields/PromptEditorField/feature.server.d.ts +1 -0
- package/dist/fields/PromptEditorField/feature.server.js +30 -0
- package/dist/fields/PromptEditorField/feature.server.js.map +1 -0
- package/dist/fields/PromptField.d.ts +4 -0
- package/dist/fields/PromptField.js +18 -0
- package/dist/fields/PromptField.js.map +1 -0
- package/dist/fields/SelectField/SelectField.js +0 -1
- package/dist/fields/SelectField/SelectField.js.map +1 -1
- package/dist/fields/SelectField/SelectField.jsx +0 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/libraries/handlebars/helpers.js +2 -2
- package/dist/libraries/handlebars/helpers.js.map +1 -1
- package/dist/libraries/handlebars/replacePlaceholders.js +5 -1
- package/dist/libraries/handlebars/replacePlaceholders.js.map +1 -1
- package/dist/payload-ai.d.ts +5 -19
- package/dist/plugin.js +19 -22
- package/dist/plugin.js.map +1 -1
- package/dist/providers/FieldProvider/FieldProvider.js +10 -19
- package/dist/providers/FieldProvider/FieldProvider.js.map +1 -1
- package/dist/providers/FieldProvider/FieldProvider.jsx +7 -17
- package/dist/providers/InstructionsProvider/InstructionsProvider.js +4 -1
- package/dist/providers/InstructionsProvider/InstructionsProvider.js.map +1 -1
- package/dist/providers/InstructionsProvider/InstructionsProvider.jsx +3 -0
- package/dist/providers/InstructionsProvider/useInstructions.js +1 -1
- package/dist/providers/InstructionsProvider/useInstructions.js.map +1 -1
- package/dist/translations/de.json +47 -0
- package/dist/translations/en.json +45 -2
- package/dist/translations/es.json +45 -2
- package/dist/translations/fa.json +45 -2
- package/dist/translations/fr.json +46 -3
- package/dist/translations/hi.json +47 -0
- package/dist/translations/index.d.ts +88 -26
- package/dist/translations/index.js +18 -32
- package/dist/translations/index.js.map +1 -1
- package/dist/translations/ja.json +47 -0
- package/dist/translations/nb.json +47 -0
- package/dist/translations/nl.json +47 -0
- package/dist/translations/pl.json +45 -2
- package/dist/translations/pt.json +47 -0
- package/dist/translations/ru.json +45 -2
- package/dist/translations/th.json +47 -0
- package/dist/translations/translation-schema.json +184 -11
- package/dist/translations/uk.json +45 -2
- package/dist/translations/zh.json +47 -0
- package/dist/types.d.ts +57 -31
- package/dist/types.js.map +1 -1
- package/dist/ui/Compose/Compose.js +42 -79
- package/dist/ui/Compose/Compose.js.map +1 -1
- package/dist/ui/Compose/Compose.jsx +32 -86
- package/dist/ui/Compose/ComposePlaceholder.js +1 -1
- package/dist/ui/Compose/ComposePlaceholder.js.map +1 -1
- package/dist/ui/Compose/ComposePlaceholder.jsx +1 -1
- package/dist/ui/Compose/{compose.module.css → compose.module.scss} +3 -5
- package/dist/ui/Compose/hooks/menu/Item.d.ts +1 -1
- package/dist/ui/Compose/hooks/menu/Item.js +7 -3
- package/dist/ui/Compose/hooks/menu/Item.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/Item.jsx +11 -5
- package/dist/ui/Compose/hooks/menu/TranslateMenu.d.ts +5 -0
- package/dist/ui/Compose/hooks/menu/TranslateMenu.js +48 -5
- package/dist/ui/Compose/hooks/menu/TranslateMenu.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/TranslateMenu.jsx +44 -6
- package/dist/ui/Compose/hooks/menu/items.d.ts +8 -8
- package/dist/ui/Compose/hooks/menu/itemsMap.d.ts +2 -1
- package/dist/ui/Compose/hooks/menu/itemsMap.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/menu.module.scss +4 -1
- package/dist/ui/Compose/hooks/menu/types.d.ts +21 -0
- package/dist/ui/Compose/hooks/menu/types.js +3 -0
- package/dist/ui/Compose/hooks/menu/types.js.map +1 -0
- package/dist/ui/Compose/hooks/menu/useMenu.d.ts +2 -2
- package/dist/ui/Compose/hooks/menu/useMenu.js +45 -23
- package/dist/ui/Compose/hooks/menu/useMenu.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/useMenu.jsx +43 -23
- package/dist/ui/Compose/hooks/mergeGeneratedValue.d.ts +14 -0
- package/dist/ui/Compose/hooks/mergeGeneratedValue.js +38 -0
- package/dist/ui/Compose/hooks/mergeGeneratedValue.js.map +1 -0
- package/dist/ui/Compose/hooks/useActiveFieldTracking.js +34 -0
- package/dist/ui/Compose/hooks/useActiveFieldTracking.js.map +1 -1
- package/dist/ui/Compose/hooks/useGenerate.js +37 -12
- package/dist/ui/Compose/hooks/useGenerate.js.map +1 -1
- package/dist/ui/Compose/hooks/useGenerateUpload.js +67 -19
- package/dist/ui/Compose/hooks/useGenerateUpload.js.map +1 -1
- package/dist/ui/Compose/hooks/useStreamingUpdate.js +4 -4
- package/dist/ui/Compose/hooks/useStreamingUpdate.js.map +1 -1
- package/dist/ui/ConfigDashboard/configDashboard.module.css +94 -0
- package/dist/ui/ConfigDashboard/index.d.ts +2 -0
- package/dist/ui/ConfigDashboard/index.js +159 -0
- package/dist/ui/ConfigDashboard/index.js.map +1 -0
- package/dist/ui/ConfigDashboard/index.jsx +122 -0
- package/dist/ui/DynamicModelSelect/index.js +6 -27
- package/dist/ui/DynamicModelSelect/index.js.map +1 -1
- package/dist/ui/DynamicModelSelect/index.jsx +6 -29
- package/dist/ui/DynamicProviderSelect/index.js +6 -27
- package/dist/ui/DynamicProviderSelect/index.js.map +1 -1
- package/dist/ui/DynamicProviderSelect/index.jsx +6 -29
- package/dist/ui/DynamicVoiceSelect/index.js +34 -83
- package/dist/ui/DynamicVoiceSelect/index.js.map +1 -1
- package/dist/ui/DynamicVoiceSelect/index.jsx +16 -53
- package/dist/ui/GlobalProviderOptions/index.d.ts +2 -0
- package/dist/ui/GlobalProviderOptions/index.js +118 -0
- package/dist/ui/GlobalProviderOptions/index.js.map +1 -0
- package/dist/ui/GlobalProviderOptions/index.jsx +60 -0
- package/dist/ui/Icons/Icons.js +1 -1
- package/dist/ui/Icons/Icons.js.map +1 -1
- package/dist/ui/Icons/Icons.jsx +1 -1
- package/dist/ui/Icons/LottieAnimation.js +1 -1
- package/dist/ui/Icons/LottieAnimation.js.map +1 -1
- package/dist/ui/Icons/LottieAnimation.jsx +1 -1
- package/dist/ui/InstructionProviderOptions/ProviderOptionsTree.d.ts +12 -0
- package/dist/ui/InstructionProviderOptions/ProviderOptionsTree.js +166 -0
- package/dist/ui/InstructionProviderOptions/ProviderOptionsTree.js.map +1 -0
- package/dist/ui/InstructionProviderOptions/ProviderOptionsTree.jsx +83 -0
- package/dist/ui/InstructionProviderOptions/index.d.ts +2 -0
- package/dist/ui/InstructionProviderOptions/index.js +157 -0
- package/dist/ui/InstructionProviderOptions/index.js.map +1 -0
- package/dist/ui/InstructionProviderOptions/index.jsx +92 -0
- package/dist/ui/VoicesFetcher/index.js.map +1 -1
- package/dist/ui/hooks/useAISettings.d.ts +26 -0
- package/dist/ui/hooks/useAISettings.js +73 -0
- package/dist/ui/hooks/useAISettings.js.map +1 -0
- package/dist/ui/providerOptions/updateProviderOptionsValue.d.ts +6 -0
- package/dist/ui/providerOptions/updateProviderOptionsValue.js +50 -0
- package/dist/ui/providerOptions/updateProviderOptionsValue.js.map +1 -0
- package/dist/ui/shared/handleSelectChange.d.ts +5 -0
- package/dist/ui/shared/handleSelectChange.js +12 -0
- package/dist/ui/shared/handleSelectChange.js.map +1 -0
- package/dist/ui/shared/types.d.ts +11 -0
- package/dist/ui/shared/types.js +5 -0
- package/dist/ui/shared/types.js.map +1 -0
- package/dist/utilities/ai/resolveEffectiveInstructionSettings.d.ts +15 -0
- package/dist/utilities/ai/resolveEffectiveInstructionSettings.js +136 -0
- package/dist/utilities/ai/resolveEffectiveInstructionSettings.js.map +1 -0
- package/dist/{endpoints → utilities}/buildPromptUtils.js +14 -5
- package/dist/utilities/buildPromptUtils.js.map +1 -0
- package/dist/utilities/buildSmartPrompt.js +3 -3
- package/dist/utilities/buildSmartPrompt.js.map +1 -1
- package/dist/utilities/fields/fieldToJsonSchema.js.map +1 -0
- package/dist/utilities/fields/getFieldBySchemaPath.js.map +1 -0
- package/dist/utilities/fields/getFieldInfo.js.map +1 -0
- package/dist/utilities/{updateFieldsConfig.js → fields/updateFieldsConfig.js} +8 -3
- package/dist/utilities/fields/updateFieldsConfig.js.map +1 -0
- package/dist/utilities/images/extractImageData.js.map +1 -0
- package/dist/utilities/images/extractPromptAttachments.js.map +1 -0
- package/dist/utilities/{fetchImages.d.ts → images/fetchImages.d.ts} +1 -1
- package/dist/utilities/images/fetchImages.js +49 -0
- package/dist/utilities/images/fetchImages.js.map +1 -0
- package/dist/utilities/images/resolveImageReferences.js +183 -0
- package/dist/utilities/images/resolveImageReferences.js.map +1 -0
- package/dist/utilities/init/autoSetupProviders.d.ts +3 -0
- package/dist/utilities/init/autoSetupProviders.js +216 -0
- package/dist/utilities/init/autoSetupProviders.js.map +1 -0
- package/dist/utilities/lexical/editorSchemaValidator.js.map +1 -0
- package/dist/utilities/lexical/lexicalToHTML.js.map +1 -0
- package/dist/utilities/lexical/lexicalToPromptTemplate.d.ts +2 -0
- package/dist/utilities/lexical/lexicalToPromptTemplate.js +50 -0
- package/dist/utilities/lexical/lexicalToPromptTemplate.js.map +1 -0
- package/dist/utilities/lexical/setSafeLexicalState.js.map +1 -0
- package/dist/utilities/lexical/stringToLexicalJSON.d.ts +2 -0
- package/dist/utilities/lexical/stringToLexicalJSON.js +39 -0
- package/dist/utilities/lexical/stringToLexicalJSON.js.map +1 -0
- package/dist/utilities/sanitizeLog.d.ts +1 -0
- package/dist/utilities/sanitizeLog.js +39 -0
- package/dist/utilities/sanitizeLog.js.map +1 -0
- package/dist/utilities/seedProperties.js +37 -22
- package/dist/utilities/seedProperties.js.map +1 -1
- package/package.json +5 -2
- package/dist/ai/analyse.d.ts +0 -1
- package/dist/ai/analyse.js +0 -3
- package/dist/ai/analyse.js.map +0 -1
- package/dist/ai/index.d.ts +0 -11
- package/dist/ai/index.js +0 -25
- package/dist/ai/index.js.map +0 -1
- package/dist/ai/prompts.js.map +0 -1
- package/dist/ai/utils/filterEditorSchemaByNodes.js.map +0 -1
- package/dist/ai/utils/generateFileNameByPrompt.js.map +0 -1
- package/dist/ai/utils/isObjectSchema.js.map +0 -1
- package/dist/ai/utils/nodeToSchemaMap.js.map +0 -1
- package/dist/ai/utils/systemGenerate.js.map +0 -1
- package/dist/collections/AISettings.d.ts +0 -2
- package/dist/collections/AISettings.js.map +0 -1
- package/dist/endpoints/buildPromptUtils.js.map +0 -1
- package/dist/endpoints/chat.d.ts +0 -4
- package/dist/fields/PromptEditorField/PromptEditorField.d.ts +0 -3
- package/dist/fields/PromptEditorField/PromptEditorField.js +0 -217
- package/dist/fields/PromptEditorField/PromptEditorField.js.map +0 -1
- package/dist/fields/PromptEditorField/PromptEditorField.jsx +0 -160
- package/dist/ui/AIConfigDashboard/index.d.ts +0 -2
- package/dist/ui/AIConfigDashboard/index.js +0 -222
- package/dist/ui/AIConfigDashboard/index.js.map +0 -1
- package/dist/ui/AIConfigDashboard/index.jsx +0 -170
- package/dist/ui/ProviderOptionsEditor/index.d.ts +0 -7
- package/dist/ui/ProviderOptionsEditor/index.js +0 -291
- package/dist/ui/ProviderOptionsEditor/index.js.map +0 -1
- package/dist/ui/ProviderOptionsEditor/index.jsx +0 -210
- package/dist/utilities/editorSchemaValidator.js.map +0 -1
- package/dist/utilities/extractImageData.js.map +0 -1
- package/dist/utilities/extractPromptAttachments.js.map +0 -1
- package/dist/utilities/fetchImages.js +0 -38
- package/dist/utilities/fetchImages.js.map +0 -1
- package/dist/utilities/fieldToJsonSchema.js.map +0 -1
- package/dist/utilities/getFieldBySchemaPath.js.map +0 -1
- package/dist/utilities/getFieldInfo.js.map +0 -1
- package/dist/utilities/getProviderOptionsFields.d.ts +0 -16
- package/dist/utilities/getProviderOptionsFields.js +0 -80
- package/dist/utilities/getProviderOptionsFields.js.map +0 -1
- package/dist/utilities/isPluginActivated.d.ts +0 -2
- package/dist/utilities/isPluginActivated.js +0 -5
- package/dist/utilities/isPluginActivated.js.map +0 -1
- package/dist/utilities/lexicalToHTML.js.map +0 -1
- package/dist/utilities/resolveImageReferences.js +0 -167
- package/dist/utilities/resolveImageReferences.js.map +0 -1
- package/dist/utilities/schemaConverter.d.ts +0 -3
- package/dist/utilities/schemaConverter.js +0 -93
- package/dist/utilities/schemaConverter.js.map +0 -1
- package/dist/utilities/setSafeLexicalState.js.map +0 -1
- package/dist/utilities/updateFieldsConfig.js.map +0 -1
- /package/dist/ai/{utils → utilities}/filterEditorSchemaByNodes.d.ts +0 -0
- /package/dist/ai/{utils → utilities}/filterEditorSchemaByNodes.js +0 -0
- /package/dist/ai/{utils → utilities}/generateFileNameByPrompt.d.ts +0 -0
- /package/dist/ai/{utils → utilities}/generateFileNameByPrompt.js +0 -0
- /package/dist/ai/{utils → utilities}/isObjectSchema.d.ts +0 -0
- /package/dist/ai/{utils → utilities}/isObjectSchema.js +0 -0
- /package/dist/ai/{utils → utilities}/nodeToSchemaMap.d.ts +0 -0
- /package/dist/ai/{utils → utilities}/nodeToSchemaMap.js +0 -0
- /package/dist/ai/{prompts.js → utilities/prompts.js} +0 -0
- /package/dist/ai/{utils → utilities}/systemGenerate.d.ts +0 -0
- /package/dist/ai/{utils → utilities}/systemGenerate.js +0 -0
- /package/dist/ui/Icons/{icons.module.css → icons.module.scss} +0 -0
- /package/dist/{endpoints → utilities}/buildPromptUtils.d.ts +0 -0
- /package/dist/utilities/{fieldToJsonSchema.d.ts → fields/fieldToJsonSchema.d.ts} +0 -0
- /package/dist/utilities/{fieldToJsonSchema.js → fields/fieldToJsonSchema.js} +0 -0
- /package/dist/utilities/{getFieldBySchemaPath.d.ts → fields/getFieldBySchemaPath.d.ts} +0 -0
- /package/dist/utilities/{getFieldBySchemaPath.js → fields/getFieldBySchemaPath.js} +0 -0
- /package/dist/utilities/{getFieldInfo.d.ts → fields/getFieldInfo.d.ts} +0 -0
- /package/dist/utilities/{getFieldInfo.js → fields/getFieldInfo.js} +0 -0
- /package/dist/utilities/{updateFieldsConfig.d.ts → fields/updateFieldsConfig.d.ts} +0 -0
- /package/dist/utilities/{extractImageData.d.ts → images/extractImageData.d.ts} +0 -0
- /package/dist/utilities/{extractImageData.js → images/extractImageData.js} +0 -0
- /package/dist/utilities/{extractPromptAttachments.d.ts → images/extractPromptAttachments.d.ts} +0 -0
- /package/dist/utilities/{extractPromptAttachments.js → images/extractPromptAttachments.js} +0 -0
- /package/dist/utilities/{resolveImageReferences.d.ts → images/resolveImageReferences.d.ts} +0 -0
- /package/dist/utilities/{editorSchemaValidator.d.ts → lexical/editorSchemaValidator.d.ts} +0 -0
- /package/dist/utilities/{editorSchemaValidator.js → lexical/editorSchemaValidator.js} +0 -0
- /package/dist/utilities/{lexicalToHTML.d.ts → lexical/lexicalToHTML.d.ts} +0 -0
- /package/dist/utilities/{lexicalToHTML.js → lexical/lexicalToHTML.js} +0 -0
- /package/dist/utilities/{setSafeLexicalState.d.ts → lexical/setSafeLexicalState.d.ts} +0 -0
- /package/dist/utilities/{setSafeLexicalState.js → lexical/setSafeLexicalState.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/ui/Compose/hooks/menu/itemsMap.ts"],"sourcesContent":["import type React from 'react'\n\nimport type { ActionMenuItems
|
|
1
|
+
{"version":3,"sources":["../../../../../src/ui/Compose/hooks/menu/itemsMap.ts"],"sourcesContent":["import type React from 'react'\n\nimport type { ActionMenuItems } from '../../../../types.js'\nimport type { BaseItemProps } from './types.js'\n\nimport { Compose, Expand, Proofread, Rephrase, Settings, Simplify, Summarize } from './items.js'\nimport { MemoizedTranslateMenu, TranslateMenu } from './TranslateMenu.js'\n\ntype MenuItemsMapType = {\n component: React.FC<BaseItemProps>\n excludedFor?: string[]\n loadingText?: string\n name: ActionMenuItems\n}\n\nexport const menuItemsMap: MenuItemsMapType[] = [\n { name: 'Proofread', component: Proofread, excludedFor: ['upload', 'array'], loadingText: 'Proofreading' },\n { name: 'Rephrase', component: Rephrase, excludedFor: ['upload', 'array'], loadingText: 'Rephrasing' },\n {\n name: 'Translate',\n component: MemoizedTranslateMenu,\n excludedFor: ['upload', 'array'],\n loadingText: 'Translating',\n },\n { name: 'Expand', component: Expand, excludedFor: ['upload', 'text', 'array'], loadingText: 'Expanding' },\n {\n // Turned off - WIP\n name: 'Summarize',\n component: Summarize,\n excludedFor: ['upload', 'text', 'richText', 'array'],\n loadingText: 'Summarizing',\n },\n { name: 'Simplify', component: Simplify, excludedFor: ['upload', 'array'], loadingText: 'Simplifying' },\n { name: 'Compose', component: Compose, loadingText: 'Composing' },\n { name: 'Settings', component: Settings },\n]\n"],"names":["Compose","Expand","Proofread","Rephrase","Settings","Simplify","Summarize","MemoizedTranslateMenu","menuItemsMap","name","component","excludedFor","loadingText"],"mappings":"AAKA,SAASA,OAAO,EAAEC,MAAM,EAAEC,SAAS,EAAEC,QAAQ,EAAEC,QAAQ,EAAEC,QAAQ,EAAEC,SAAS,QAAQ,aAAY;AAChG,SAASC,qBAAqB,QAAuB,qBAAoB;AASzE,OAAO,MAAMC,eAAmC;IAC9C;QAAEC,MAAM;QAAaC,WAAWR;QAAWS,aAAa;YAAC;YAAU;SAAQ;QAAEC,aAAa;IAAe;IACzG;QAAEH,MAAM;QAAYC,WAAWP;QAAUQ,aAAa;YAAC;YAAU;SAAQ;QAAEC,aAAa;IAAa;IACrG;QACEH,MAAM;QACNC,WAAWH;QACXI,aAAa;YAAC;YAAU;SAAQ;QAChCC,aAAa;IACf;IACA;QAAEH,MAAM;QAAUC,WAAWT;QAAQU,aAAa;YAAC;YAAU;YAAQ;SAAQ;QAAEC,aAAa;IAAY;IACxG;QACE,mBAAmB;QACnBH,MAAM;QACNC,WAAWJ;QACXK,aAAa;YAAC;YAAU;YAAQ;YAAY;SAAQ;QACpDC,aAAa;IACf;IACA;QAAEH,MAAM;QAAYC,WAAWL;QAAUM,aAAa;YAAC;YAAU;SAAQ;QAAEC,aAAa;IAAc;IACtG;QAAEH,MAAM;QAAWC,WAAWV;QAASY,aAAa;IAAY;IAChE;QAAEH,MAAM;QAAYC,WAAWN;IAAS;CACzC,CAAA"}
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
.menu {
|
|
29
|
+
--popup-width: 150px;
|
|
30
|
+
|
|
29
31
|
display: flex;
|
|
30
32
|
gap: 1px;
|
|
31
33
|
flex-direction: column;
|
|
@@ -49,7 +51,7 @@
|
|
|
49
51
|
|
|
50
52
|
.subMenu {
|
|
51
53
|
position: absolute;
|
|
52
|
-
left: calc(var(--popup-width) +
|
|
54
|
+
left: calc(var(--popup-width) + 20px);
|
|
53
55
|
width: calc(var(--popup-width) + 12px);
|
|
54
56
|
top: 10px;
|
|
55
57
|
height: calc(100% - 16px);
|
|
@@ -85,6 +87,7 @@
|
|
|
85
87
|
color: var(--theme-elevation-800);
|
|
86
88
|
border-radius: 0;
|
|
87
89
|
-webkit-appearance: none;
|
|
90
|
+
appearance: none;
|
|
88
91
|
|
|
89
92
|
font-size: inherit !important;
|
|
90
93
|
height: auto !important;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CSSProperties, MouseEventHandler } from 'react';
|
|
2
|
+
export type ActionMenuEvents = 'onCompose' | 'onExpand' | 'onProofread' | 'onRephrase' | 'onSettings' | 'onSimplify' | 'onSummarize' | 'onTone' | 'onTranslate';
|
|
3
|
+
export type UseMenuEvents = {
|
|
4
|
+
[key in ActionMenuEvents]?: (data?: unknown) => void;
|
|
5
|
+
};
|
|
6
|
+
export type UseMenuOptions = {
|
|
7
|
+
isConfigAllowed: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type BaseItemProps<T = unknown> = {
|
|
10
|
+
children?: React.ReactNode;
|
|
11
|
+
className?: string;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
hideIcon?: boolean;
|
|
14
|
+
isActive?: boolean;
|
|
15
|
+
isMenu?: boolean;
|
|
16
|
+
onClick: (data?: unknown) => void;
|
|
17
|
+
onMouseEnter?: MouseEventHandler<T> | undefined;
|
|
18
|
+
onMouseLeave?: MouseEventHandler<T> | undefined;
|
|
19
|
+
style?: CSSProperties | undefined;
|
|
20
|
+
title?: string;
|
|
21
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../src/ui/Compose/hooks/menu/types.ts"],"sourcesContent":["import type { CSSProperties, MouseEventHandler } from 'react'\n\n\nexport type ActionMenuEvents =\n | 'onCompose'\n | 'onExpand'\n | 'onProofread'\n | 'onRephrase'\n | 'onSettings'\n | 'onSimplify'\n | 'onSummarize'\n | 'onTone'\n | 'onTranslate'\n\nexport type UseMenuEvents = {\n [key in ActionMenuEvents]?: (data?: unknown) => void\n}\n\nexport type UseMenuOptions = {\n isConfigAllowed: boolean\n}\n\nexport type BaseItemProps<T = unknown> = {\n children?: React.ReactNode\n className?: string\n disabled?: boolean\n hideIcon?: boolean\n isActive?: boolean\n isMenu?: boolean\n onClick: (data?: unknown) => void\n onMouseEnter?: MouseEventHandler<T> | undefined\n onMouseLeave?: MouseEventHandler<T> | undefined\n style?: CSSProperties | undefined\n title?: string\n}\n"],"names":[],"mappings":"AAsBA,WAYC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { UseMenuEvents, UseMenuOptions } from '
|
|
2
|
+
import type { UseMenuEvents, UseMenuOptions } from './types.js';
|
|
3
3
|
export declare const useMenu: (menuEvents: UseMenuEvents, options: UseMenuOptions) => {
|
|
4
|
-
ActiveComponent: ({ isLoading, loadingLabel, stop }: {
|
|
4
|
+
ActiveComponent: ({ isLoading, loadingLabel, stop, }: {
|
|
5
5
|
isLoading: boolean;
|
|
6
6
|
loadingLabel?: string;
|
|
7
7
|
stop: () => void;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
4
|
-
import { getSiblingData } from 'payload/shared';
|
|
3
|
+
import { useConfig, useField, useLocale, useTranslation } from '@payloadcms/ui';
|
|
5
4
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
6
5
|
import { useFieldProps } from '../../../../providers/FieldProvider/useFieldProps.js';
|
|
7
|
-
import { Compose, Proofread, Rephrase } from './items.js';
|
|
6
|
+
import { Compose, Proofread, Rephrase, Translate } from './items.js';
|
|
8
7
|
import { menuItemsMap } from './itemsMap.js';
|
|
9
8
|
import styles from './menu.module.scss';
|
|
10
9
|
const getActiveComponent = (ac)=>{
|
|
@@ -15,36 +14,47 @@ const getActiveComponent = (ac)=>{
|
|
|
15
14
|
return Proofread;
|
|
16
15
|
case 'Rephrase':
|
|
17
16
|
return Rephrase;
|
|
17
|
+
case 'Translate':
|
|
18
|
+
return Translate;
|
|
18
19
|
default:
|
|
19
20
|
return Rephrase;
|
|
20
21
|
}
|
|
21
22
|
};
|
|
22
23
|
export const useMenu = (menuEvents, options)=>{
|
|
23
24
|
const { field: { type: fieldType } = {}, path } = useFieldProps();
|
|
24
|
-
const {
|
|
25
|
+
const { value } = useField({
|
|
26
|
+
path: path || ''
|
|
27
|
+
});
|
|
28
|
+
const { config } = useConfig();
|
|
29
|
+
const locale = useLocale();
|
|
30
|
+
const { t } = useTranslation();
|
|
25
31
|
const [activeComponent, setActiveComponent] = useState('Rephrase');
|
|
26
|
-
// Check value
|
|
32
|
+
// Check value whenever it changes
|
|
27
33
|
useEffect(()=>{
|
|
28
34
|
let hasValue = false;
|
|
29
35
|
try {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
// But for now, simple truthiness covers most cases or at least defaults safely
|
|
36
|
-
if (fieldType === 'richText' && val && typeof val === 'object' && 'root' in val) {
|
|
37
|
-
// Basic lexical check could go here if needed
|
|
38
|
-
}
|
|
36
|
+
hasValue = value !== undefined && value !== null;
|
|
37
|
+
// For richTextFields, we might need a more robust check (e.g. check for root.children.length > 0)
|
|
38
|
+
// But for now, simple truthiness covers most cases or at least defaults safely
|
|
39
|
+
if (fieldType === 'richText' && value && typeof value === 'object' && 'root' in value) {
|
|
40
|
+
// Basic lexical check could go here if needed
|
|
39
41
|
}
|
|
40
42
|
} catch (e) {
|
|
41
43
|
// ignore
|
|
42
44
|
}
|
|
43
45
|
if (!hasValue) {
|
|
44
|
-
|
|
46
|
+
const defaultLocale = config?.localization ? config.localization.defaultLocale : undefined;
|
|
47
|
+
const translateItem = menuItemsMap.find((i)=>i.name === 'Translate');
|
|
48
|
+
const isTranslateExcluded = translateItem?.excludedFor?.includes(fieldType ?? '');
|
|
49
|
+
if (!isTranslateExcluded && locale?.code && defaultLocale && locale.code !== defaultLocale) {
|
|
50
|
+
setActiveComponent('Translate');
|
|
51
|
+
} else {
|
|
52
|
+
setActiveComponent('Compose');
|
|
53
|
+
}
|
|
45
54
|
return;
|
|
46
55
|
}
|
|
47
|
-
|
|
56
|
+
const rephraseItem = menuItemsMap.find((i)=>i.name === 'Rephrase');
|
|
57
|
+
if (rephraseItem?.excludedFor?.includes(fieldType ?? '')) {
|
|
48
58
|
setActiveComponent('Compose');
|
|
49
59
|
return;
|
|
50
60
|
}
|
|
@@ -52,8 +62,9 @@ export const useMenu = (menuEvents, options)=>{
|
|
|
52
62
|
setActiveComponent('Rephrase');
|
|
53
63
|
}, [
|
|
54
64
|
fieldType,
|
|
55
|
-
|
|
56
|
-
|
|
65
|
+
value,
|
|
66
|
+
locale?.code,
|
|
67
|
+
config?.localization
|
|
57
68
|
]);
|
|
58
69
|
const MemoizedActiveComponent = useMemo(()=>{
|
|
59
70
|
return ({ isLoading, loadingLabel, stop })=>{
|
|
@@ -65,7 +76,16 @@ export const useMenu = (menuEvents, options)=>{
|
|
|
65
76
|
if (!isLoading) {
|
|
66
77
|
const trigger = menuEvents[`on${activeComponent}`];
|
|
67
78
|
if (typeof trigger === 'function') {
|
|
68
|
-
|
|
79
|
+
const isEvent = data && typeof data === 'object' && 'nativeEvent' in data;
|
|
80
|
+
const actualData = isEvent ? undefined : data;
|
|
81
|
+
if (activeComponent === 'Translate' && !actualData) {
|
|
82
|
+
trigger({
|
|
83
|
+
locale: locale?.code,
|
|
84
|
+
translateFromDefault: true
|
|
85
|
+
});
|
|
86
|
+
} else {
|
|
87
|
+
trigger(actualData);
|
|
88
|
+
}
|
|
69
89
|
} else {
|
|
70
90
|
console.error('No trigger found for', activeComponent);
|
|
71
91
|
}
|
|
@@ -73,13 +93,15 @@ export const useMenu = (menuEvents, options)=>{
|
|
|
73
93
|
stop();
|
|
74
94
|
}
|
|
75
95
|
},
|
|
76
|
-
title: isLoading ? '
|
|
77
|
-
children: isLoading && (loadingLabel ?? activeItem.loadingText)
|
|
96
|
+
title: isLoading ? t('ai-plugin:general:clickToStop') : t(`ai-plugin:actions:${activeItem.name.toLowerCase()}`),
|
|
97
|
+
children: isLoading && (loadingLabel ?? (activeItem.loadingText ? t(`ai-plugin:actionLoading:${activeItem.loadingText.toLowerCase()}`) : null))
|
|
78
98
|
});
|
|
79
99
|
};
|
|
80
100
|
}, [
|
|
81
101
|
activeComponent,
|
|
82
|
-
menuEvents
|
|
102
|
+
menuEvents,
|
|
103
|
+
t,
|
|
104
|
+
locale?.code
|
|
83
105
|
]);
|
|
84
106
|
const filteredMenuItems = useMemo(()=>menuItemsMap.filter((i)=>{
|
|
85
107
|
if (i.name === 'Settings' && !options.isConfigAllowed) {
|
|
@@ -105,7 +127,7 @@ export const useMenu = (menuEvents, options)=>{
|
|
|
105
127
|
menuEvents[`on${i.name}`]?.(data);
|
|
106
128
|
onClose();
|
|
107
129
|
},
|
|
108
|
-
children: isLoading && i.loadingText
|
|
130
|
+
children: isLoading && i.loadingText && t(`ai-plugin:actionLoading:${i.loadingText.toLowerCase()}`)
|
|
109
131
|
}, i.name);
|
|
110
132
|
})
|
|
111
133
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/ui/Compose/hooks/menu/useMenu.tsx"],"sourcesContent":["'use client'\n\nimport { useForm } from '@payloadcms/ui'\nimport { getSiblingData } from 'payload/shared'\nimport React, { useEffect, useMemo, useState } from 'react'\n\nimport type { ActionMenuItems, UseMenuEvents, UseMenuOptions } from '../../../../types.js'\n\nimport { useFieldProps } from '../../../../providers/FieldProvider/useFieldProps.js'\nimport { Compose, Proofread, Rephrase } from './items.js'\nimport { menuItemsMap } from './itemsMap.js'\nimport styles from './menu.module.scss'\n\nconst getActiveComponent = (ac: ActionMenuItems) => {\n switch (ac) {\n case 'Compose':\n return Compose\n case 'Proofread':\n return Proofread\n case 'Rephrase':\n return Rephrase\n default:\n return Rephrase\n }\n}\n\nexport const useMenu = (menuEvents: UseMenuEvents, options: UseMenuOptions) => {\n const { field: { type: fieldType } = {}, path } = useFieldProps()\n const { getData } = useForm()\n const [activeComponent, setActiveComponent] = useState<ActionMenuItems>('Rephrase')\n\n // Check value once on mount or when path/type changes\n useEffect(() => {\n let hasValue = false\n\n try {\n const data = getData()\n if (path) {\n const val = getSiblingData(data, path)\n hasValue = val !== undefined && val !== null\n // For richTextFields, we might need a more robust check (e.g. check for root.children.length > 0)\n // But for now, simple truthiness covers most cases or at least defaults safely\n if (fieldType === 'richText' && val && typeof val === 'object' && 'root' in val) {\n // Basic lexical check could go here if needed\n }\n }\n } catch (e) {\n // ignore\n }\n\n if (!hasValue) {\n setActiveComponent('Compose')\n return\n }\n\n if (menuItemsMap.some((i) => i.excludedFor?.includes(fieldType ?? ''))) {\n setActiveComponent('Compose')\n return\n }\n\n // Default to Rephrase if value exists\n setActiveComponent('Rephrase')\n }, [fieldType, getData, path])\n\n const MemoizedActiveComponent = useMemo(() => {\n return ({ isLoading, loadingLabel, stop }: { isLoading: boolean; loadingLabel?: string; stop: () => void }) => {\n const ActiveComponent = getActiveComponent(activeComponent)\n const activeItem = menuItemsMap.find((i) => i.name === activeComponent)!\n return (\n <ActiveComponent\n hideIcon\n onClick={(data: unknown) => {\n if (!isLoading) {\n const trigger = menuEvents[`on${activeComponent}`]\n if (typeof trigger === 'function') {\n trigger(data)\n } else {\n console.error('No trigger found for', activeComponent)\n }\n } else {\n stop()\n }\n }}\n title={isLoading ? 'Click to stop' : activeItem.name}\n >\n {isLoading && (loadingLabel ?? activeItem.loadingText)}\n </ActiveComponent>\n )\n }\n }, [activeComponent, menuEvents])\n\n const filteredMenuItems = useMemo(\n () =>\n menuItemsMap.filter((i) => {\n if (i.name === 'Settings' && !options.isConfigAllowed) {\n return false\n } // Disable settings if a user role is not permitted\n return i.name !== activeComponent && !i.excludedFor?.includes(fieldType ?? '')\n }),\n [activeComponent, fieldType, options.isConfigAllowed],\n )\n\n const MemoizedMenu = useMemo(() => {\n return ({ isLoading, onClose }: { isLoading: boolean; onClose: () => void }) => (\n <div className={styles.menu}>\n {filteredMenuItems.map((i) => {\n const Action = i.component\n return (\n <Action\n disabled={isLoading}\n key={i.name}\n onClick={(data: unknown) => {\n if (i.name !== 'Settings') {\n setActiveComponent(i.name)\n }\n\n menuEvents[`on${i.name}`]?.(data)\n onClose()\n }}\n >\n {isLoading && i.loadingText}\n </Action>\n )\n })}\n </div>\n )\n }, [filteredMenuItems, menuEvents])\n\n return {\n ActiveComponent: MemoizedActiveComponent,\n Menu: MemoizedMenu,\n }\n}\n\n"],"names":["useForm","getSiblingData","React","useEffect","useMemo","useState","useFieldProps","Compose","Proofread","Rephrase","menuItemsMap","styles","getActiveComponent","ac","useMenu","menuEvents","options","field","type","fieldType","path","getData","activeComponent","setActiveComponent","hasValue","data","val","undefined","e","some","i","excludedFor","includes","MemoizedActiveComponent","isLoading","loadingLabel","stop","ActiveComponent","activeItem","find","name","hideIcon","onClick","trigger","console","error","title","loadingText","filteredMenuItems","filter","isConfigAllowed","MemoizedMenu","onClose","div","className","menu","map","Action","component","disabled","Menu"],"mappings":"AAAA;;AAEA,SAASA,OAAO,QAAQ,iBAAgB;AACxC,SAASC,cAAc,QAAQ,iBAAgB;AAC/C,OAAOC,SAASC,SAAS,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AAI3D,SAASC,aAAa,QAAQ,uDAAsD;AACpF,SAASC,OAAO,EAAEC,SAAS,EAAEC,QAAQ,QAAQ,aAAY;AACzD,SAASC,YAAY,QAAQ,gBAAe;AAC5C,OAAOC,YAAY,qBAAoB;AAEvC,MAAMC,qBAAqB,CAACC;IAC1B,OAAQA;QACN,KAAK;YACH,OAAON;QACT,KAAK;YACH,OAAOC;QACT,KAAK;YACH,OAAOC;QACT;YACE,OAAOA;IACX;AACF;AAEA,OAAO,MAAMK,UAAU,CAACC,YAA2BC;IACjD,MAAM,EAAEC,OAAO,EAAEC,MAAMC,SAAS,EAAE,GAAG,CAAC,CAAC,EAAEC,IAAI,EAAE,GAAGd;IAClD,MAAM,EAAEe,OAAO,EAAE,GAAGrB;IACpB,MAAM,CAACsB,iBAAiBC,mBAAmB,GAAGlB,SAA0B;IAExE,sDAAsD;IACtDF,UAAU;QACR,IAAIqB,WAAW;QAEf,IAAI;YACF,MAAMC,OAAOJ;YACb,IAAID,MAAM;gBACR,MAAMM,MAAMzB,eAAewB,MAAML;gBACjCI,WAAWE,QAAQC,aAAaD,QAAQ;gBACxC,kGAAkG;gBAClG,+EAA+E;gBAC/E,IAAIP,cAAc,cAAcO,OAAO,OAAOA,QAAQ,YAAY,UAAUA,KAAK;gBAC9E,8CAA8C;gBACjD;YACF;QACF,EAAE,OAAOE,GAAG;QACV,SAAS;QACX;QAEA,IAAI,CAACJ,UAAU;YACbD,mBAAmB;YACnB;QACF;QAEA,IAAIb,aAAamB,IAAI,CAAC,CAACC,IAAMA,EAAEC,WAAW,EAAEC,SAASb,aAAa,MAAM;YACtEI,mBAAmB;YACnB;QACF;QAEA,sCAAsC;QACtCA,mBAAmB;IACrB,GAAG;QAACJ;QAAWE;QAASD;KAAK;IAE7B,MAAMa,0BAA0B7B,QAAQ;QACtC,OAAO,CAAC,EAAE8B,SAAS,EAAEC,YAAY,EAAEC,IAAI,EAAmE;YACxG,MAAMC,kBAAkBzB,mBAAmBU;YAC3C,MAAMgB,aAAa5B,aAAa6B,IAAI,CAAC,CAACT,IAAMA,EAAEU,IAAI,KAAKlB;YACvD,qBACE,KAACe;gBACCI,QAAQ;gBACRC,SAAS,CAACjB;oBACR,IAAI,CAACS,WAAW;wBACd,MAAMS,UAAU5B,UAAU,CAAC,CAAC,EAAE,EAAEO,gBAAgB,CAAC,CAAC;wBAClD,IAAI,OAAOqB,YAAY,YAAY;4BACjCA,QAAQlB;wBACV,OAAO;4BACLmB,QAAQC,KAAK,CAAC,wBAAwBvB;wBACxC;oBACF,OAAO;wBACLc;oBACF;gBACF;gBACAU,OAAOZ,YAAY,kBAAkBI,WAAWE,IAAI;0BAEnDN,aAAcC,CAAAA,gBAAgBG,WAAWS,WAAW,AAAD;;QAG1D;IACF,GAAG;QAACzB;QAAiBP;KAAW;IAEhC,MAAMiC,oBAAoB5C,QACxB,IACEM,aAAauC,MAAM,CAAC,CAACnB;YACnB,IAAIA,EAAEU,IAAI,KAAK,cAAc,CAACxB,QAAQkC,eAAe,EAAE;gBACrD,OAAO;YACT,EAAE,mDAAmD;YACrD,OAAOpB,EAAEU,IAAI,KAAKlB,mBAAmB,CAACQ,EAAEC,WAAW,EAAEC,SAASb,aAAa;QAC7E,IACF;QAACG;QAAiBH;QAAWH,QAAQkC,eAAe;KAAC;IAGvD,MAAMC,eAAe/C,QAAQ;QAC3B,OAAO,CAAC,EAAE8B,SAAS,EAAEkB,OAAO,EAA+C,iBACzE,KAACC;gBAAIC,WAAW3C,OAAO4C,IAAI;0BACxBP,kBAAkBQ,GAAG,CAAC,CAAC1B;oBACtB,MAAM2B,SAAS3B,EAAE4B,SAAS;oBAC1B,qBACE,KAACD;wBACCE,UAAUzB;wBAEVQ,SAAS,CAACjB;4BACR,IAAIK,EAAEU,IAAI,KAAK,YAAY;gCACzBjB,mBAAmBO,EAAEU,IAAI;4BAC3B;4BAEAzB,UAAU,CAAC,CAAC,EAAE,EAAEe,EAAEU,IAAI,CAAC,CAAC,CAAC,GAAGf;4BAC5B2B;wBACF;kCAEClB,aAAaJ,EAAEiB,WAAW;uBAVtBjB,EAAEU,IAAI;gBAajB;;IAGN,GAAG;QAACQ;QAAmBjC;KAAW;IAElC,OAAO;QACLsB,iBAAiBJ;QACjB2B,MAAMT;IACR;AACF,EAAC"}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/ui/Compose/hooks/menu/useMenu.tsx"],"sourcesContent":["'use client'\n\nimport { useConfig, useField, useLocale, useTranslation } from '@payloadcms/ui'\nimport React, { useEffect, useMemo, useState } from 'react'\n\nimport type {\n PluginAITranslationKeys,\n PluginAITranslations,\n} from '../../../../translations/index.js'\nimport type { ActionMenuItems } from '../../../../types.js'\nimport type { UseMenuEvents, UseMenuOptions } from './types.js'\n\nimport { useFieldProps } from '../../../../providers/FieldProvider/useFieldProps.js'\nimport { Compose, Proofread, Rephrase, Translate } from './items.js'\nimport { menuItemsMap } from './itemsMap.js'\nimport styles from './menu.module.scss'\n\nconst getActiveComponent = (ac: ActionMenuItems) => {\n switch (ac) {\n case 'Compose':\n return Compose\n case 'Proofread':\n return Proofread\n case 'Rephrase':\n return Rephrase\n case 'Translate':\n return Translate\n default:\n return Rephrase\n }\n}\n\nexport const useMenu = (menuEvents: UseMenuEvents, options: UseMenuOptions) => {\n const { field: { type: fieldType } = {}, path } = useFieldProps()\n const { value } = useField<any>({ path: path || '' })\n const { config } = useConfig()\n const locale = useLocale()\n const { t } = useTranslation<PluginAITranslations, PluginAITranslationKeys>()\n const [activeComponent, setActiveComponent] = useState<ActionMenuItems>('Rephrase')\n\n // Check value whenever it changes\n useEffect(() => {\n let hasValue = false\n\n try {\n hasValue = value !== undefined && value !== null\n // For richTextFields, we might need a more robust check (e.g. check for root.children.length > 0)\n // But for now, simple truthiness covers most cases or at least defaults safely\n if (fieldType === 'richText' && value && typeof value === 'object' && 'root' in value) {\n // Basic lexical check could go here if needed\n }\n } catch (e) {\n // ignore\n }\n\n if (!hasValue) {\n const defaultLocale = config?.localization ? config.localization.defaultLocale : undefined\n const translateItem = menuItemsMap.find((i) => i.name === 'Translate')\n const isTranslateExcluded = translateItem?.excludedFor?.includes(fieldType ?? '')\n\n if (!isTranslateExcluded && locale?.code && defaultLocale && locale.code !== defaultLocale) {\n setActiveComponent('Translate')\n } else {\n setActiveComponent('Compose')\n }\n return\n }\n\n const rephraseItem = menuItemsMap.find((i) => i.name === 'Rephrase')\n if (rephraseItem?.excludedFor?.includes(fieldType ?? '')) {\n setActiveComponent('Compose')\n return\n }\n\n // Default to Rephrase if value exists\n setActiveComponent('Rephrase')\n }, [fieldType, value, locale?.code, config?.localization])\n\n const MemoizedActiveComponent = useMemo(() => {\n return ({\n isLoading,\n loadingLabel,\n stop,\n }: {\n isLoading: boolean\n loadingLabel?: string\n stop: () => void\n }) => {\n const ActiveComponent = getActiveComponent(activeComponent)\n const activeItem = menuItemsMap.find((i) => i.name === activeComponent)!\n return (\n <ActiveComponent\n hideIcon\n onClick={(data: unknown) => {\n if (!isLoading) {\n const trigger = menuEvents[`on${activeComponent}`]\n if (typeof trigger === 'function') {\n const isEvent = data && typeof data === 'object' && 'nativeEvent' in data\n const actualData = isEvent ? undefined : data\n\n if (activeComponent === 'Translate' && !actualData) {\n trigger({ locale: locale?.code, translateFromDefault: true })\n } else {\n trigger(actualData)\n }\n } else {\n console.error('No trigger found for', activeComponent)\n }\n } else {\n stop()\n }\n }}\n title={\n isLoading\n ? t('ai-plugin:general:clickToStop' as any)\n : t(`ai-plugin:actions:${activeItem.name.toLowerCase()}` as any)\n }\n >\n {isLoading &&\n (loadingLabel ??\n (activeItem.loadingText ? t(`ai-plugin:actionLoading:${activeItem.loadingText.toLowerCase()}` as any) : null))}\n </ActiveComponent>\n )\n }\n }, [activeComponent, menuEvents, t, locale?.code])\n\n const filteredMenuItems = useMemo(\n () =>\n menuItemsMap.filter((i) => {\n if (i.name === 'Settings' && !options.isConfigAllowed) {\n return false\n } // Disable settings if a user role is not permitted\n return i.name !== activeComponent && !i.excludedFor?.includes(fieldType ?? '')\n }),\n [activeComponent, fieldType, options.isConfigAllowed],\n )\n\n const MemoizedMenu = useMemo(() => {\n return ({ isLoading, onClose }: { isLoading: boolean; onClose: () => void }) => (\n <div className={styles.menu}>\n {filteredMenuItems.map((i) => {\n const Action = i.component\n return (\n <Action\n disabled={isLoading}\n key={i.name}\n onClick={(data: unknown) => {\n if (i.name !== 'Settings') {\n setActiveComponent(i.name)\n }\n\n menuEvents[`on${i.name}`]?.(data)\n onClose()\n }}\n >\n {isLoading && i.loadingText && t(`ai-plugin:actionLoading:${i.loadingText.toLowerCase()}` as any)}\n </Action>\n )\n })}\n </div>\n )\n }, [filteredMenuItems, menuEvents])\n\n return {\n ActiveComponent: MemoizedActiveComponent,\n Menu: MemoizedMenu,\n }\n}\n"],"names":["useConfig","useField","useLocale","useTranslation","React","useEffect","useMemo","useState","useFieldProps","Compose","Proofread","Rephrase","Translate","menuItemsMap","styles","getActiveComponent","ac","useMenu","menuEvents","options","field","type","fieldType","path","value","config","locale","t","activeComponent","setActiveComponent","hasValue","undefined","e","defaultLocale","localization","translateItem","find","i","name","isTranslateExcluded","excludedFor","includes","code","rephraseItem","MemoizedActiveComponent","isLoading","loadingLabel","stop","ActiveComponent","activeItem","hideIcon","onClick","data","trigger","isEvent","actualData","translateFromDefault","console","error","title","toLowerCase","loadingText","filteredMenuItems","filter","isConfigAllowed","MemoizedMenu","onClose","div","className","menu","map","Action","component","disabled","Menu"],"mappings":"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"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import {
|
|
3
|
-
import { getSiblingData } from 'payload/shared';
|
|
2
|
+
import { useConfig, useField, useLocale, useTranslation } from '@payloadcms/ui';
|
|
4
3
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
5
4
|
import { useFieldProps } from '../../../../providers/FieldProvider/useFieldProps.js';
|
|
6
|
-
import { Compose, Proofread, Rephrase } from './items.js';
|
|
5
|
+
import { Compose, Proofread, Rephrase, Translate } from './items.js';
|
|
7
6
|
import { menuItemsMap } from './itemsMap.js';
|
|
8
7
|
import styles from './menu.module.scss';
|
|
9
8
|
const getActiveComponent = (ac) => {
|
|
@@ -14,52 +13,69 @@ const getActiveComponent = (ac) => {
|
|
|
14
13
|
return Proofread;
|
|
15
14
|
case 'Rephrase':
|
|
16
15
|
return Rephrase;
|
|
16
|
+
case 'Translate':
|
|
17
|
+
return Translate;
|
|
17
18
|
default:
|
|
18
19
|
return Rephrase;
|
|
19
20
|
}
|
|
20
21
|
};
|
|
21
22
|
export const useMenu = (menuEvents, options) => {
|
|
22
23
|
const { field: { type: fieldType } = {}, path } = useFieldProps();
|
|
23
|
-
const {
|
|
24
|
+
const { value } = useField({ path: path || '' });
|
|
25
|
+
const { config } = useConfig();
|
|
26
|
+
const locale = useLocale();
|
|
27
|
+
const { t } = useTranslation();
|
|
24
28
|
const [activeComponent, setActiveComponent] = useState('Rephrase');
|
|
25
|
-
// Check value
|
|
29
|
+
// Check value whenever it changes
|
|
26
30
|
useEffect(() => {
|
|
27
31
|
let hasValue = false;
|
|
28
32
|
try {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
// But for now, simple truthiness covers most cases or at least defaults safely
|
|
35
|
-
if (fieldType === 'richText' && val && typeof val === 'object' && 'root' in val) {
|
|
36
|
-
// Basic lexical check could go here if needed
|
|
37
|
-
}
|
|
33
|
+
hasValue = value !== undefined && value !== null;
|
|
34
|
+
// For richTextFields, we might need a more robust check (e.g. check for root.children.length > 0)
|
|
35
|
+
// But for now, simple truthiness covers most cases or at least defaults safely
|
|
36
|
+
if (fieldType === 'richText' && value && typeof value === 'object' && 'root' in value) {
|
|
37
|
+
// Basic lexical check could go here if needed
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
catch (e) {
|
|
41
41
|
// ignore
|
|
42
42
|
}
|
|
43
43
|
if (!hasValue) {
|
|
44
|
-
|
|
44
|
+
const defaultLocale = config?.localization ? config.localization.defaultLocale : undefined;
|
|
45
|
+
const translateItem = menuItemsMap.find((i) => i.name === 'Translate');
|
|
46
|
+
const isTranslateExcluded = translateItem?.excludedFor?.includes(fieldType ?? '');
|
|
47
|
+
if (!isTranslateExcluded && locale?.code && defaultLocale && locale.code !== defaultLocale) {
|
|
48
|
+
setActiveComponent('Translate');
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
setActiveComponent('Compose');
|
|
52
|
+
}
|
|
45
53
|
return;
|
|
46
54
|
}
|
|
47
|
-
|
|
55
|
+
const rephraseItem = menuItemsMap.find((i) => i.name === 'Rephrase');
|
|
56
|
+
if (rephraseItem?.excludedFor?.includes(fieldType ?? '')) {
|
|
48
57
|
setActiveComponent('Compose');
|
|
49
58
|
return;
|
|
50
59
|
}
|
|
51
60
|
// Default to Rephrase if value exists
|
|
52
61
|
setActiveComponent('Rephrase');
|
|
53
|
-
}, [fieldType,
|
|
62
|
+
}, [fieldType, value, locale?.code, config?.localization]);
|
|
54
63
|
const MemoizedActiveComponent = useMemo(() => {
|
|
55
|
-
return ({ isLoading, loadingLabel, stop }) => {
|
|
64
|
+
return ({ isLoading, loadingLabel, stop, }) => {
|
|
56
65
|
const ActiveComponent = getActiveComponent(activeComponent);
|
|
57
66
|
const activeItem = menuItemsMap.find((i) => i.name === activeComponent);
|
|
58
67
|
return (<ActiveComponent hideIcon onClick={(data) => {
|
|
59
68
|
if (!isLoading) {
|
|
60
69
|
const trigger = menuEvents[`on${activeComponent}`];
|
|
61
70
|
if (typeof trigger === 'function') {
|
|
62
|
-
|
|
71
|
+
const isEvent = data && typeof data === 'object' && 'nativeEvent' in data;
|
|
72
|
+
const actualData = isEvent ? undefined : data;
|
|
73
|
+
if (activeComponent === 'Translate' && !actualData) {
|
|
74
|
+
trigger({ locale: locale?.code, translateFromDefault: true });
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
trigger(actualData);
|
|
78
|
+
}
|
|
63
79
|
}
|
|
64
80
|
else {
|
|
65
81
|
console.error('No trigger found for', activeComponent);
|
|
@@ -68,11 +84,15 @@ export const useMenu = (menuEvents, options) => {
|
|
|
68
84
|
else {
|
|
69
85
|
stop();
|
|
70
86
|
}
|
|
71
|
-
}} title={isLoading
|
|
72
|
-
|
|
87
|
+
}} title={isLoading
|
|
88
|
+
? t('ai-plugin:general:clickToStop')
|
|
89
|
+
: t(`ai-plugin:actions:${activeItem.name.toLowerCase()}`)}>
|
|
90
|
+
{isLoading &&
|
|
91
|
+
(loadingLabel ??
|
|
92
|
+
(activeItem.loadingText ? t(`ai-plugin:actionLoading:${activeItem.loadingText.toLowerCase()}`) : null))}
|
|
73
93
|
</ActiveComponent>);
|
|
74
94
|
};
|
|
75
|
-
}, [activeComponent, menuEvents]);
|
|
95
|
+
}, [activeComponent, menuEvents, t, locale?.code]);
|
|
76
96
|
const filteredMenuItems = useMemo(() => menuItemsMap.filter((i) => {
|
|
77
97
|
if (i.name === 'Settings' && !options.isConfigAllowed) {
|
|
78
98
|
return false;
|
|
@@ -90,7 +110,7 @@ export const useMenu = (menuEvents, options) => {
|
|
|
90
110
|
menuEvents[`on${i.name}`]?.(data);
|
|
91
111
|
onClose();
|
|
92
112
|
}}>
|
|
93
|
-
{isLoading && i.loadingText}
|
|
113
|
+
{isLoading && i.loadingText && t(`ai-plugin:actionLoading:${i.loadingText.toLowerCase()}`)}
|
|
94
114
|
</Action>);
|
|
95
115
|
})}
|
|
96
116
|
</div>);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type MergeGeneratedValueArgs = {
|
|
2
|
+
appendGenerated: boolean;
|
|
3
|
+
currentValue: unknown;
|
|
4
|
+
generatedValue: unknown;
|
|
5
|
+
hasMany: boolean;
|
|
6
|
+
max?: number;
|
|
7
|
+
maxRows?: number;
|
|
8
|
+
};
|
|
9
|
+
type MergeGeneratedValueResult = {
|
|
10
|
+
truncated: boolean;
|
|
11
|
+
value: unknown;
|
|
12
|
+
};
|
|
13
|
+
export declare const mergeGeneratedValue: ({ appendGenerated, currentValue, generatedValue, hasMany, max, maxRows, }: MergeGeneratedValueArgs) => MergeGeneratedValueResult;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const toArray = (value)=>{
|
|
2
|
+
if (Array.isArray(value)) {
|
|
3
|
+
return value;
|
|
4
|
+
}
|
|
5
|
+
if (value === null || value === undefined || value === '') {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
return [
|
|
9
|
+
value
|
|
10
|
+
];
|
|
11
|
+
};
|
|
12
|
+
export const mergeGeneratedValue = ({ appendGenerated, currentValue, generatedValue, hasMany, max, maxRows })=>{
|
|
13
|
+
if (!appendGenerated || !hasMany) {
|
|
14
|
+
return {
|
|
15
|
+
truncated: false,
|
|
16
|
+
value: generatedValue
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const current = toArray(currentValue);
|
|
20
|
+
const generated = toArray(generatedValue);
|
|
21
|
+
const merged = [
|
|
22
|
+
...current,
|
|
23
|
+
...generated
|
|
24
|
+
];
|
|
25
|
+
const limit = typeof maxRows === 'number' ? maxRows : typeof max === 'number' ? max : undefined;
|
|
26
|
+
if (typeof limit === 'number' && limit >= 0 && merged.length > limit) {
|
|
27
|
+
return {
|
|
28
|
+
truncated: true,
|
|
29
|
+
value: merged.slice(0, limit)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
truncated: false,
|
|
34
|
+
value: merged
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=mergeGeneratedValue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/ui/Compose/hooks/mergeGeneratedValue.ts"],"sourcesContent":["type MergeGeneratedValueArgs = {\n appendGenerated: boolean\n currentValue: unknown\n generatedValue: unknown\n hasMany: boolean\n max?: number\n maxRows?: number\n}\n\ntype MergeGeneratedValueResult = {\n truncated: boolean\n value: unknown\n}\n\nconst toArray = (value: unknown): unknown[] => {\n if (Array.isArray(value)) {\n return value\n }\n\n if (value === null || value === undefined || value === '') {\n return []\n }\n\n return [value]\n}\n\nexport const mergeGeneratedValue = ({\n appendGenerated,\n currentValue,\n generatedValue,\n hasMany,\n max,\n maxRows,\n}: MergeGeneratedValueArgs): MergeGeneratedValueResult => {\n if (!appendGenerated || !hasMany) {\n return {\n truncated: false,\n value: generatedValue,\n }\n }\n\n const current = toArray(currentValue)\n const generated = toArray(generatedValue)\n\n const merged = [...current, ...generated]\n const limit = typeof maxRows === 'number' ? maxRows : typeof max === 'number' ? max : undefined\n\n if (typeof limit === 'number' && limit >= 0 && merged.length > limit) {\n return {\n truncated: true,\n value: merged.slice(0, limit),\n }\n }\n\n return {\n truncated: false,\n value: merged,\n }\n}\n"],"names":["toArray","value","Array","isArray","undefined","mergeGeneratedValue","appendGenerated","currentValue","generatedValue","hasMany","max","maxRows","truncated","current","generated","merged","limit","length","slice"],"mappings":"AAcA,MAAMA,UAAU,CAACC;IACf,IAAIC,MAAMC,OAAO,CAACF,QAAQ;QACxB,OAAOA;IACT;IAEA,IAAIA,UAAU,QAAQA,UAAUG,aAAaH,UAAU,IAAI;QACzD,OAAO,EAAE;IACX;IAEA,OAAO;QAACA;KAAM;AAChB;AAEA,OAAO,MAAMI,sBAAsB,CAAC,EAClCC,eAAe,EACfC,YAAY,EACZC,cAAc,EACdC,OAAO,EACPC,GAAG,EACHC,OAAO,EACiB;IACxB,IAAI,CAACL,mBAAmB,CAACG,SAAS;QAChC,OAAO;YACLG,WAAW;YACXX,OAAOO;QACT;IACF;IAEA,MAAMK,UAAUb,QAAQO;IACxB,MAAMO,YAAYd,QAAQQ;IAE1B,MAAMO,SAAS;WAAIF;WAAYC;KAAU;IACzC,MAAME,QAAQ,OAAOL,YAAY,WAAWA,UAAU,OAAOD,QAAQ,WAAWA,MAAMN;IAEtF,IAAI,OAAOY,UAAU,YAAYA,SAAS,KAAKD,OAAOE,MAAM,GAAGD,OAAO;QACpE,OAAO;YACLJ,WAAW;YACXX,OAAOc,OAAOG,KAAK,CAAC,GAAGF;QACzB;IACF;IAEA,OAAO;QACLJ,WAAW;QACXX,OAAOc;IACT;AACF,EAAC"}
|
|
@@ -15,6 +15,8 @@ const fieldTypeCache = new WeakMap();
|
|
|
15
15
|
let pointerDownThrottleTimer = null;
|
|
16
16
|
let focusDebounceTimer = null;
|
|
17
17
|
let currentContainer = null;
|
|
18
|
+
let lastContainer = null // Track last valid container to restore if needed
|
|
19
|
+
;
|
|
18
20
|
let rafId = null // Track RAF to cancel if needed
|
|
19
21
|
;
|
|
20
22
|
/**
|
|
@@ -106,6 +108,8 @@ let rafId = null // Track RAF to cancel if needed
|
|
|
106
108
|
currentContainer?.classList.remove('ai-plugin-active');
|
|
107
109
|
if (next) {
|
|
108
110
|
next.classList.add('ai-plugin-active');
|
|
111
|
+
lastContainer = next // Update last known valid container
|
|
112
|
+
;
|
|
109
113
|
}
|
|
110
114
|
currentContainer = next;
|
|
111
115
|
};
|
|
@@ -113,6 +117,7 @@ const clearActiveContainer = ()=>{
|
|
|
113
117
|
if (currentContainer) {
|
|
114
118
|
currentContainer.classList.remove('ai-plugin-active');
|
|
115
119
|
currentContainer = null;
|
|
120
|
+
// Note: We do NOT clear lastContainer here, allowing restoration
|
|
116
121
|
}
|
|
117
122
|
// Cancel any pending RAF
|
|
118
123
|
if (rafId !== null) {
|
|
@@ -147,6 +152,23 @@ const isInteractiveElement = (element)=>{
|
|
|
147
152
|
}
|
|
148
153
|
return false;
|
|
149
154
|
};
|
|
155
|
+
// Helper for interactive menu check
|
|
156
|
+
const checkInteractiveMenu = (e)=>{
|
|
157
|
+
// Check global flag first (most reliable for mouse/hover interactions)
|
|
158
|
+
if (typeof window !== 'undefined' && window.__AI_MENU_INTERACTIVE) {
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
const target = e.target;
|
|
162
|
+
// Check target directly
|
|
163
|
+
if (target && target instanceof Element && (target.classList.contains('ai-interactive-menu') || target.hasAttribute('data-ai-interactive'))) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
// Fallback: Check DOM path (for keyboard or specific events)
|
|
167
|
+
const path = e.composedPath();
|
|
168
|
+
return path.some((el)=>{
|
|
169
|
+
return el instanceof Element && (el.classList.contains('ai-interactive-menu') || el.hasAttribute('data-ai-interactive'));
|
|
170
|
+
});
|
|
171
|
+
};
|
|
150
172
|
/**
|
|
151
173
|
* Handle focus events - only activate if focus is on an interactive element within .field-type
|
|
152
174
|
* Performance: Debounced by 10ms to handle rapid focus changes
|
|
@@ -163,6 +185,14 @@ const isInteractiveElement = (element)=>{
|
|
|
163
185
|
if (!isInteractiveElement(target)) {
|
|
164
186
|
return;
|
|
165
187
|
}
|
|
188
|
+
// Check for interactive menu elements using composedPath for robustness
|
|
189
|
+
if (typeof window !== 'undefined' && window.__AI_MENU_INTERACTIVE || checkInteractiveMenu(e)) {
|
|
190
|
+
// If we lost the active state (e.g. due to pointerDown clearing it), restore it
|
|
191
|
+
if (!currentContainer && lastContainer?.isConnected) {
|
|
192
|
+
setActiveContainer(lastContainer);
|
|
193
|
+
}
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
166
196
|
// Clear any pending debounce
|
|
167
197
|
if (focusDebounceTimer !== null) {
|
|
168
198
|
clearTimeout(focusDebounceTimer);
|
|
@@ -182,6 +212,10 @@ const isInteractiveElement = (element)=>{
|
|
|
182
212
|
if (!(target instanceof HTMLElement)) {
|
|
183
213
|
return;
|
|
184
214
|
}
|
|
215
|
+
// Check for interactive menu elements using composedPath
|
|
216
|
+
if (typeof window !== 'undefined' && window.__AI_MENU_INTERACTIVE || checkInteractiveMenu(e)) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
185
219
|
// Early exit if clicking within current container
|
|
186
220
|
if (currentContainer?.isConnected && currentContainer.contains(target)) {
|
|
187
221
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/ui/Compose/hooks/useActiveFieldTracking.ts"],"sourcesContent":["'use client'\n\nimport { useEffect } from 'react'\n\n/**\n * Allowed field type classes that should show the active state\n */\nconst ALLOWED_FIELD_TYPES = ['upload', 'text', 'textarea', 'rich-text-lexical']\n\n// Performance optimization: Cache container and field type lookups\nconst containerCache = new WeakMap<HTMLElement, HTMLElement | null>()\nconst fieldTypeCache = new WeakMap<HTMLElement, boolean>()\n\n// Performance optimization: Throttle/debounce timers\nlet pointerDownThrottleTimer: null | number = null\nlet focusDebounceTimer: null | number = null\n\nlet currentContainer: HTMLElement | null = null\nlet rafId: null | number = null // Track RAF to cancel if needed\n\n/**\n * Safely escape CSS selector values\n */\nconst cssEscape = (value: string): string => {\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {\n return CSS.escape(value)\n }\n return value.replace(/([ #;?%&,.+*~':\"!^$[\\]()=>|/@])/g, '\\\\$1')\n}\n\n/**\n * Find container from React Select dropdown elements\n * Performance: Early exit if not in a listbox/option element\n */\nconst findContainerFromReactSelect = (target: HTMLElement): HTMLElement | null => {\n // Early exit if element doesn't have role indicator for React Select\n const role = target.getAttribute('role')\n if (!role || !['listbox', 'option'].includes(role)) {\n return null\n }\n\n const listbox = target.closest<HTMLElement>('[role=\"listbox\"]')\n if (!listbox?.id) {\n return null\n }\n\n const id = cssEscape(listbox.id)\n const selector = `[aria-controls=\"${id}\"], [aria-owns=\"${id}\"]`\n const control = document.querySelector<HTMLElement>(selector)\n\n return control?.closest<HTMLElement>('.field-type') ?? null\n}\n\n/**\n * Check if a container has one of the allowed field type classes\n * Performance: Uses WeakMap cache to avoid repeated class list checks\n */\nconst isAllowedFieldType = (container: HTMLElement): boolean => {\n // Check cache first\n if (fieldTypeCache.has(container)) {\n return fieldTypeCache.get(container)!\n }\n\n // Compute and cache result\n const result = ALLOWED_FIELD_TYPES.some(\n (type) =>\n container.classList.contains(type) || container.classList.contains(`field-type-${type}`),\n )\n\n fieldTypeCache.set(container, result)\n return result\n}\n\n/**\n * Resolve the .field-type container for a given event target\n * Only returns containers that match allowed field types\n * Performance: Uses WeakMap cache to avoid repeated DOM traversals\n */\nconst resolveContainerFromTarget = (target: EventTarget | null): HTMLElement | null => {\n if (!(target instanceof HTMLElement)) {\n return null\n }\n\n // Check cache first\n if (containerCache.has(target)) {\n const cached = containerCache.get(target)!\n // Validate cache entry is still in DOM\n if (!cached || cached.isConnected) {\n return cached\n }\n // Invalidate stale cache entry\n containerCache.delete(target)\n }\n\n // Perform lookup\n let container = target.closest<HTMLElement>('.field-type')\n\n // Fall back to React Select logic if needed\n if (!container) {\n container = findContainerFromReactSelect(target)\n }\n\n // Validate field type and cache result\n const result = container && isAllowedFieldType(container) ? container : null\n containerCache.set(target, result)\n\n return result\n}\n\n/**\n * Update the active container and toggle CSS class\n * - Avoids acting on disconnected nodes\n * - Avoids redundant class work\n */\nconst setActiveContainer = (next: HTMLElement | null): void => {\n // Normalize both references against disconnected nodes\n if (currentContainer && !currentContainer.isConnected) {\n currentContainer = null\n }\n if (next && !next.isConnected) {\n next = null\n }\n\n if (currentContainer === next) {\n return\n }\n\n currentContainer?.classList.remove('ai-plugin-active')\n if (next) {\n next.classList.add('ai-plugin-active')\n }\n currentContainer = next\n}\n\nconst clearActiveContainer = (): void => {\n if (currentContainer) {\n currentContainer.classList.remove('ai-plugin-active')\n currentContainer = null\n }\n\n // Cancel any pending RAF\n if (rafId !== null) {\n cancelAnimationFrame(rafId)\n rafId = null\n }\n}\n\nconst isInteractiveElement = (element: HTMLElement): boolean => {\n const tagName = element.tagName.toLowerCase()\n const interactiveTags = ['input', 'textarea', 'select', 'button']\n\n if (interactiveTags.includes(tagName)) {\n return true\n }\n\n // Check for contenteditable\n if (element.isContentEditable) {\n return true\n }\n\n // Check for elements with role=\"textbox\" or role=\"combobox\" (React Select)\n const role = element.getAttribute('role')\n if (role && ['combobox', 'listbox', 'searchbox', 'textbox'].includes(role)) {\n return true\n }\n\n return false\n}\n\n/**\n * Handle focus events - only activate if focus is on an interactive element within .field-type\n * Performance: Debounced by 10ms to handle rapid focus changes\n */\nconst onFocusIn = (e: FocusEvent): void => {\n const target = e.target\n if (!(target instanceof HTMLElement)) {\n return\n }\n\n // Early exit if we're already inside the current container\n if (currentContainer?.isConnected && currentContainer.contains(target)) {\n return\n }\n\n // Only activate if the focused element is actually interactive\n if (!isInteractiveElement(target)) {\n return\n }\n\n // Clear any pending debounce\n if (focusDebounceTimer !== null) {\n clearTimeout(focusDebounceTimer)\n }\n\n // Debounce to reduce work during rapid focus changes (e.g., fast tabbing)\n focusDebounceTimer = window.setTimeout(() => {\n focusDebounceTimer = null\n const container = resolveContainerFromTarget(target)\n setActiveContainer(container)\n }, 10)\n}\n\n/**\n * Handle pointer/mouse events - only switch when clicking a different .field-type\n * Performance: Early exit for non-field clicks + 50ms throttling\n */\nconst onPointerDown = (e: PointerEvent): void => {\n const target = e.target\n if (!(target instanceof HTMLElement)) {\n return\n }\n\n // Early exit if clicking within current container\n if (currentContainer?.isConnected && currentContainer.contains(target)) {\n return\n }\n\n // Performance: Quick check before expensive traversal\n // If click is nowhere near a field, just clear active state\n if (!target.closest('.field-type')) {\n if (currentContainer) {\n setActiveContainer(null)\n }\n return\n }\n\n // Throttle to prevent excessive work on rapid clicking\n if (pointerDownThrottleTimer !== null) {\n return\n }\n\n const container = resolveContainerFromTarget(target)\n setActiveContainer(container)\n\n // Set throttle timer for 50ms\n pointerDownThrottleTimer = window.setTimeout(() => {\n pointerDownThrottleTimer = null\n }, 50)\n}\n\n/**\n * Handle keyboard navigation (Tab key)\n */\nconst onKeyDown = (e: KeyboardEvent): void => {\n if (e.key !== 'Tab') {\n return\n }\n\n // Cancel any pending RAF to prevent queuing\n if (rafId !== null) {\n cancelAnimationFrame(rafId)\n }\n\n // Defer until after focus has shifted\n rafId = requestAnimationFrame(() => {\n rafId = null\n const container = resolveContainerFromTarget(document.activeElement)\n setActiveContainer(container)\n })\n}\n\n/**\n * Handle visibility changes to properly cleanup when page is hidden\n */\nconst onVisibilityChange = (): void => {\n if (typeof document !== 'undefined' && document.hidden) {\n // Clear active state and cancel pending operations\n clearActiveContainer()\n }\n}\n\n/**\n * Initialize document-level listeners to track the active field container.\n * When a container is active, it receives the 'ai-plugin-active' class.\n */\nexport const useActiveFieldTracking = (): void => {\n useEffect(() => {\n if (typeof window === 'undefined') {\n return\n }\n\n const pluginWindow = window as {\n __aiComposeTracking?: boolean\n __aiComposeTrackingController?: AbortController\n __aiComposeTrackingCount?: number\n } & Window\n\n // Track number of mounted users of the hook\n pluginWindow.__aiComposeTrackingCount = (pluginWindow.__aiComposeTrackingCount ?? 0) + 1\n\n // Initialize listeners only once\n if (!pluginWindow.__aiComposeTracking) {\n const controller = new AbortController()\n pluginWindow.__aiComposeTrackingController = controller\n\n // Use capture for early handling\n document.addEventListener('focusin', onFocusIn, {\n capture: true,\n signal: controller.signal,\n })\n document.addEventListener('pointerdown', onPointerDown, {\n capture: true,\n passive: true,\n signal: controller.signal,\n })\n document.addEventListener('keydown', onKeyDown, {\n capture: true,\n signal: controller.signal,\n })\n document.addEventListener('visibilitychange', onVisibilityChange, {\n signal: controller.signal,\n })\n\n pluginWindow.__aiComposeTracking = true\n }\n\n return () => {\n // Decrement and cleanup when the last user unmounts\n pluginWindow.__aiComposeTrackingCount = (pluginWindow.__aiComposeTrackingCount ?? 1) - 1\n\n if ((pluginWindow.__aiComposeTrackingCount ?? 0) <= 0) {\n // Atomically remove all listeners\n pluginWindow.__aiComposeTrackingController?.abort()\n pluginWindow.__aiComposeTrackingController = undefined\n\n // Clear active state and cancel pending operations\n clearActiveContainer()\n\n // Reset all state\n pluginWindow.__aiComposeTracking = false\n pluginWindow.__aiComposeTrackingCount = 0\n }\n }\n }, [])\n}\n"],"names":["useEffect","ALLOWED_FIELD_TYPES","containerCache","WeakMap","fieldTypeCache","pointerDownThrottleTimer","focusDebounceTimer","currentContainer","rafId","cssEscape","value","CSS","escape","replace","findContainerFromReactSelect","target","role","getAttribute","includes","listbox","closest","id","selector","control","document","querySelector","isAllowedFieldType","container","has","get","result","some","type","classList","contains","set","resolveContainerFromTarget","HTMLElement","cached","isConnected","delete","setActiveContainer","next","remove","add","clearActiveContainer","cancelAnimationFrame","isInteractiveElement","element","tagName","toLowerCase","interactiveTags","isContentEditable","onFocusIn","e","clearTimeout","window","setTimeout","onPointerDown","onKeyDown","key","requestAnimationFrame","activeElement","onVisibilityChange","hidden","useActiveFieldTracking","pluginWindow","__aiComposeTrackingCount","__aiComposeTracking","controller","AbortController","__aiComposeTrackingController","addEventListener","capture","signal","passive","abort","undefined"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/ui/Compose/hooks/useActiveFieldTracking.ts"],"sourcesContent":["'use client'\n\nimport { useEffect } from 'react'\n\n/**\n * Allowed field type classes that should show the active state\n */\nconst ALLOWED_FIELD_TYPES = ['upload', 'text', 'textarea', 'rich-text-lexical']\n\n// Performance optimization: Cache container and field type lookups\nconst containerCache = new WeakMap<HTMLElement, HTMLElement | null>()\nconst fieldTypeCache = new WeakMap<HTMLElement, boolean>()\n\n// Performance optimization: Throttle/debounce timers\nlet pointerDownThrottleTimer: null | number = null\nlet focusDebounceTimer: null | number = null\n\nlet currentContainer: HTMLElement | null = null\nlet lastContainer: HTMLElement | null = null // Track last valid container to restore if needed\nlet rafId: null | number = null // Track RAF to cancel if needed\n\n/**\n * Safely escape CSS selector values\n */\nconst cssEscape = (value: string): string => {\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {\n return CSS.escape(value)\n }\n return value.replace(/([ #;?%&,.+*~':\"!^$[\\]()=>|/@])/g, '\\\\$1')\n}\n\n/**\n * Find container from React Select dropdown elements\n * Performance: Early exit if not in a listbox/option element\n */\nconst findContainerFromReactSelect = (target: HTMLElement): HTMLElement | null => {\n // Early exit if element doesn't have role indicator for React Select\n const role = target.getAttribute('role')\n if (!role || !['listbox', 'option'].includes(role)) {\n return null\n }\n\n const listbox = target.closest<HTMLElement>('[role=\"listbox\"]')\n if (!listbox?.id) {\n return null\n }\n\n const id = cssEscape(listbox.id)\n const selector = `[aria-controls=\"${id}\"], [aria-owns=\"${id}\"]`\n const control = document.querySelector<HTMLElement>(selector)\n\n return control?.closest<HTMLElement>('.field-type') ?? null\n}\n\n/**\n * Check if a container has one of the allowed field type classes\n * Performance: Uses WeakMap cache to avoid repeated class list checks\n */\nconst isAllowedFieldType = (container: HTMLElement): boolean => {\n // Check cache first\n if (fieldTypeCache.has(container)) {\n return fieldTypeCache.get(container)!\n }\n\n // Compute and cache result\n const result = ALLOWED_FIELD_TYPES.some(\n (type) =>\n container.classList.contains(type) || container.classList.contains(`field-type-${type}`),\n )\n\n fieldTypeCache.set(container, result)\n return result\n}\n\n/**\n * Resolve the .field-type container for a given event target\n * Only returns containers that match allowed field types\n * Performance: Uses WeakMap cache to avoid repeated DOM traversals\n */\nconst resolveContainerFromTarget = (target: EventTarget | null): HTMLElement | null => {\n if (!(target instanceof HTMLElement)) {\n return null\n }\n\n // Check cache first\n if (containerCache.has(target)) {\n const cached = containerCache.get(target)!\n // Validate cache entry is still in DOM\n if (!cached || cached.isConnected) {\n return cached\n }\n // Invalidate stale cache entry\n containerCache.delete(target)\n }\n\n // Perform lookup\n let container = target.closest<HTMLElement>('.field-type')\n\n // Fall back to React Select logic if needed\n if (!container) {\n container = findContainerFromReactSelect(target)\n }\n\n // Validate field type and cache result\n const result = container && isAllowedFieldType(container) ? container : null\n containerCache.set(target, result)\n\n return result\n}\n\n/**\n * Update the active container and toggle CSS class\n * - Avoids acting on disconnected nodes\n * - Avoids redundant class work\n */\nconst setActiveContainer = (next: HTMLElement | null): void => {\n // Normalize both references against disconnected nodes\n if (currentContainer && !currentContainer.isConnected) {\n currentContainer = null\n }\n if (next && !next.isConnected) {\n next = null\n }\n\n if (currentContainer === next) {\n return\n }\n\n currentContainer?.classList.remove('ai-plugin-active')\n if (next) {\n next.classList.add('ai-plugin-active')\n lastContainer = next // Update last known valid container\n }\n currentContainer = next\n}\n\nconst clearActiveContainer = (): void => {\n if (currentContainer) {\n currentContainer.classList.remove('ai-plugin-active')\n currentContainer = null\n // Note: We do NOT clear lastContainer here, allowing restoration\n }\n\n // Cancel any pending RAF\n if (rafId !== null) {\n cancelAnimationFrame(rafId)\n rafId = null\n }\n}\n\nconst isInteractiveElement = (element: HTMLElement): boolean => {\n const tagName = element.tagName.toLowerCase()\n const interactiveTags = ['input', 'textarea', 'select', 'button']\n\n if (interactiveTags.includes(tagName)) {\n return true\n }\n\n // Check for contenteditable\n if (element.isContentEditable) {\n return true\n }\n\n // Check for elements with role=\"textbox\" or role=\"combobox\" (React Select)\n const role = element.getAttribute('role')\n if (role && ['combobox', 'listbox', 'searchbox', 'textbox'].includes(role)) {\n return true\n }\n\n return false\n}\n\n// Helper for interactive menu check\nconst checkInteractiveMenu = (e: Event): boolean => {\n // Check global flag first (most reliable for mouse/hover interactions)\n if (typeof window !== 'undefined' && window.__AI_MENU_INTERACTIVE) {\n return true\n }\n\n const target = e.target as Element\n\n // Check target directly\n if (\n target &&\n target instanceof Element &&\n (target.classList.contains('ai-interactive-menu') || target.hasAttribute('data-ai-interactive'))\n ) {\n return true\n }\n\n // Fallback: Check DOM path (for keyboard or specific events)\n const path = e.composedPath()\n return path.some((el) => {\n return (\n el instanceof Element &&\n (el.classList.contains('ai-interactive-menu') || el.hasAttribute('data-ai-interactive'))\n )\n })\n}\n\n/**\n * Handle focus events - only activate if focus is on an interactive element within .field-type\n * Performance: Debounced by 10ms to handle rapid focus changes\n */\nconst onFocusIn = (e: FocusEvent): void => {\n const target = e.target\n if (!(target instanceof HTMLElement)) {\n return\n }\n\n // Early exit if we're already inside the current container\n if (currentContainer?.isConnected && currentContainer.contains(target)) {\n return\n }\n\n // Only activate if the focused element is actually interactive\n if (!isInteractiveElement(target)) {\n return\n }\n\n // Check for interactive menu elements using composedPath for robustness\n if (typeof window !== 'undefined' && window.__AI_MENU_INTERACTIVE || checkInteractiveMenu(e)) {\n // If we lost the active state (e.g. due to pointerDown clearing it), restore it\n if (!currentContainer && lastContainer?.isConnected) {\n setActiveContainer(lastContainer)\n }\n return\n }\n\n // Clear any pending debounce\n if (focusDebounceTimer !== null) {\n clearTimeout(focusDebounceTimer)\n }\n\n // Debounce to reduce work during rapid focus changes (e.g., fast tabbing)\n focusDebounceTimer = window.setTimeout(() => {\n focusDebounceTimer = null\n const container = resolveContainerFromTarget(target)\n setActiveContainer(container)\n }, 10)\n}\n\n/**\n * Handle pointer/mouse events - only switch when clicking a different .field-type\n * Performance: Early exit for non-field clicks + 50ms throttling\n */\nconst onPointerDown = (e: PointerEvent): void => {\n const target = e.target\n if (!(target instanceof HTMLElement)) {\n return\n }\n\n // Check for interactive menu elements using composedPath\n if (typeof window !== 'undefined' && window.__AI_MENU_INTERACTIVE || checkInteractiveMenu(e)) {\n return\n }\n\n // Early exit if clicking within current container\n if (currentContainer?.isConnected && currentContainer.contains(target)) {\n return\n }\n\n // Performance: Quick check before expensive traversal\n // If click is nowhere near a field, just clear active state\n if (!target.closest('.field-type')) {\n if (currentContainer) {\n setActiveContainer(null)\n }\n return\n }\n\n // Throttle to prevent excessive work on rapid clicking\n if (pointerDownThrottleTimer !== null) {\n return\n }\n\n const container = resolveContainerFromTarget(target)\n setActiveContainer(container)\n\n // Set throttle timer for 50ms\n pointerDownThrottleTimer = window.setTimeout(() => {\n pointerDownThrottleTimer = null\n }, 50)\n}\n\n/**\n * Handle keyboard navigation (Tab key)\n */\nconst onKeyDown = (e: KeyboardEvent): void => {\n if (e.key !== 'Tab') {\n return\n }\n\n // Cancel any pending RAF to prevent queuing\n if (rafId !== null) {\n cancelAnimationFrame(rafId)\n }\n\n // Defer until after focus has shifted\n rafId = requestAnimationFrame(() => {\n rafId = null\n const container = resolveContainerFromTarget(document.activeElement)\n setActiveContainer(container)\n })\n}\n\n/**\n * Handle visibility changes to properly cleanup when page is hidden\n */\nconst onVisibilityChange = (): void => {\n if (typeof document !== 'undefined' && document.hidden) {\n // Clear active state and cancel pending operations\n clearActiveContainer()\n }\n}\n\n/**\n * Initialize document-level listeners to track the active field container.\n * When a container is active, it receives the 'ai-plugin-active' class.\n */\nexport const useActiveFieldTracking = (): void => {\n useEffect(() => {\n if (typeof window === 'undefined') {\n return\n }\n\n const pluginWindow = window as {\n __aiComposeTracking?: boolean\n __aiComposeTrackingController?: AbortController\n __aiComposeTrackingCount?: number\n } & Window\n\n // Track number of mounted users of the hook\n pluginWindow.__aiComposeTrackingCount = (pluginWindow.__aiComposeTrackingCount ?? 0) + 1\n\n // Initialize listeners only once\n if (!pluginWindow.__aiComposeTracking) {\n const controller = new AbortController()\n pluginWindow.__aiComposeTrackingController = controller\n\n // Use capture for early handling\n document.addEventListener('focusin', onFocusIn, {\n capture: true,\n signal: controller.signal,\n })\n document.addEventListener('pointerdown', onPointerDown, {\n capture: true,\n passive: true,\n signal: controller.signal,\n })\n document.addEventListener('keydown', onKeyDown, {\n capture: true,\n signal: controller.signal,\n })\n document.addEventListener('visibilitychange', onVisibilityChange, {\n signal: controller.signal,\n })\n\n pluginWindow.__aiComposeTracking = true\n }\n\n return () => {\n // Decrement and cleanup when the last user unmounts\n pluginWindow.__aiComposeTrackingCount = (pluginWindow.__aiComposeTrackingCount ?? 1) - 1\n\n if ((pluginWindow.__aiComposeTrackingCount ?? 0) <= 0) {\n // Atomically remove all listeners\n pluginWindow.__aiComposeTrackingController?.abort()\n pluginWindow.__aiComposeTrackingController = undefined\n\n // Clear active state and cancel pending operations\n clearActiveContainer()\n\n // Reset all state\n pluginWindow.__aiComposeTracking = false\n pluginWindow.__aiComposeTrackingCount = 0\n }\n }\n }, [])\n}\n"],"names":["useEffect","ALLOWED_FIELD_TYPES","containerCache","WeakMap","fieldTypeCache","pointerDownThrottleTimer","focusDebounceTimer","currentContainer","lastContainer","rafId","cssEscape","value","CSS","escape","replace","findContainerFromReactSelect","target","role","getAttribute","includes","listbox","closest","id","selector","control","document","querySelector","isAllowedFieldType","container","has","get","result","some","type","classList","contains","set","resolveContainerFromTarget","HTMLElement","cached","isConnected","delete","setActiveContainer","next","remove","add","clearActiveContainer","cancelAnimationFrame","isInteractiveElement","element","tagName","toLowerCase","interactiveTags","isContentEditable","checkInteractiveMenu","e","window","__AI_MENU_INTERACTIVE","Element","hasAttribute","path","composedPath","el","onFocusIn","clearTimeout","setTimeout","onPointerDown","onKeyDown","key","requestAnimationFrame","activeElement","onVisibilityChange","hidden","useActiveFieldTracking","pluginWindow","__aiComposeTrackingCount","__aiComposeTracking","controller","AbortController","__aiComposeTrackingController","addEventListener","capture","signal","passive","abort","undefined"],"mappings":"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"}
|