@ai-stack/payloadcms 3.2.26 → 3.68.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/{LICENSE.md → LICENSE} +1 -1
- package/README.md +218 -229
- package/dist/access/checkAccess.d.ts +4 -0
- package/dist/access/checkAccess.js +20 -0
- package/dist/access/checkAccess.js.map +1 -0
- package/dist/ai/core/generateObject.d.ts +7 -0
- package/dist/ai/core/generateObject.js +35 -0
- package/dist/ai/core/generateObject.js.map +1 -0
- package/dist/ai/core/generateText.d.ts +7 -0
- package/dist/ai/core/generateText.js +31 -0
- package/dist/ai/core/generateText.js.map +1 -0
- package/dist/ai/core/index.d.ts +11 -0
- package/dist/ai/core/index.js +10 -0
- package/dist/ai/core/index.js.map +1 -0
- package/dist/ai/core/media/generateMedia.d.ts +7 -0
- package/dist/ai/core/media/generateMedia.js +50 -0
- package/dist/ai/core/media/generateMedia.js.map +1 -0
- package/dist/ai/core/media/image/generateImage.d.ts +6 -0
- package/dist/ai/core/media/image/generateImage.js +41 -0
- package/dist/ai/core/media/image/generateImage.js.map +1 -0
- package/dist/ai/core/media/image/handlers/multimodal.d.ts +7 -0
- package/dist/ai/core/media/image/handlers/multimodal.js +100 -0
- package/dist/ai/core/media/image/handlers/multimodal.js.map +1 -0
- package/dist/ai/core/media/image/handlers/standard.d.ts +7 -0
- package/dist/ai/core/media/image/handlers/standard.js +28 -0
- package/dist/ai/core/media/image/handlers/standard.js.map +1 -0
- package/dist/ai/core/media/image/index.d.ts +2 -0
- package/dist/ai/core/media/image/index.js +3 -0
- package/dist/ai/core/media/image/index.js.map +1 -0
- package/dist/ai/core/media/index.d.ts +2 -0
- package/dist/ai/core/media/index.js +3 -0
- package/dist/ai/core/media/index.js.map +1 -0
- package/dist/ai/core/media/speech/generateSpeech.d.ts +5 -0
- package/dist/ai/core/media/speech/generateSpeech.js +55 -0
- package/dist/ai/core/media/speech/generateSpeech.js.map +1 -0
- package/dist/ai/core/media/speech/index.d.ts +2 -0
- package/dist/ai/core/media/speech/index.js +3 -0
- package/dist/ai/core/media/speech/index.js.map +1 -0
- package/dist/ai/core/media/types.d.ts +74 -0
- package/dist/ai/core/media/types.js +5 -0
- package/dist/ai/core/media/types.js.map +1 -0
- package/dist/ai/core/media/utils.d.ts +11 -0
- package/dist/ai/core/media/utils.js +34 -0
- package/dist/ai/core/media/utils.js.map +1 -0
- package/dist/ai/core/media/video/generateVideo.d.ts +6 -0
- package/dist/ai/core/media/video/generateVideo.js +32 -0
- package/dist/ai/core/media/video/generateVideo.js.map +1 -0
- package/dist/ai/core/media/video/index.d.ts +2 -0
- package/dist/ai/core/media/video/index.js +3 -0
- package/dist/ai/core/media/video/index.js.map +1 -0
- package/dist/ai/core/streamObject.d.ts +7 -0
- package/dist/ai/core/streamObject.js +54 -0
- package/dist/ai/core/streamObject.js.map +1 -0
- package/dist/ai/core/streamText.d.ts +7 -0
- package/dist/ai/core/streamText.js +30 -0
- package/dist/ai/core/streamText.js.map +1 -0
- package/dist/ai/core/types.d.ts +85 -0
- package/dist/ai/core/types.js +5 -0
- package/dist/ai/core/types.js.map +1 -0
- package/dist/ai/index.d.ts +11 -0
- package/dist/ai/index.js +25 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/providers/blocks/anthropic.d.ts +2 -0
- package/dist/ai/providers/blocks/anthropic.js +223 -0
- package/dist/ai/providers/blocks/anthropic.js.map +1 -0
- package/dist/ai/providers/blocks/elevenlabs.d.ts +2 -0
- package/dist/ai/providers/blocks/elevenlabs.js +449 -0
- package/dist/ai/providers/blocks/elevenlabs.js.map +1 -0
- package/dist/ai/providers/blocks/fal.d.ts +2 -0
- package/dist/ai/providers/blocks/fal.js +312 -0
- package/dist/ai/providers/blocks/fal.js.map +1 -0
- package/dist/ai/providers/blocks/google.d.ts +2 -0
- package/dist/ai/providers/blocks/google.js +623 -0
- package/dist/ai/providers/blocks/google.js.map +1 -0
- package/dist/ai/providers/blocks/index.d.ts +2 -0
- package/dist/ai/providers/blocks/index.js +18 -0
- package/dist/ai/providers/blocks/index.js.map +1 -0
- package/dist/ai/providers/blocks/openai-compatible.d.ts +2 -0
- package/dist/ai/providers/blocks/openai-compatible.js +308 -0
- package/dist/ai/providers/blocks/openai-compatible.js.map +1 -0
- package/dist/ai/providers/blocks/openai.d.ts +2 -0
- package/dist/ai/providers/blocks/openai.js +600 -0
- package/dist/ai/providers/blocks/openai.js.map +1 -0
- package/dist/ai/providers/blocks/xai.d.ts +2 -0
- package/dist/ai/providers/blocks/xai.js +247 -0
- package/dist/ai/providers/blocks/xai.js.map +1 -0
- package/dist/ai/providers/icons.d.ts +7 -0
- package/dist/ai/providers/icons.js +9 -0
- package/dist/ai/providers/icons.js.map +1 -0
- package/dist/ai/providers/index.d.ts +2 -0
- package/dist/ai/providers/index.js +6 -0
- package/dist/ai/providers/index.js.map +1 -0
- package/dist/ai/providers/registry.d.ts +40 -0
- package/dist/ai/providers/registry.js +267 -0
- package/dist/ai/providers/registry.js.map +1 -0
- package/dist/ai/providers/types.d.ts +115 -0
- package/dist/ai/providers/types.js +4 -0
- package/dist/ai/providers/types.js.map +1 -0
- package/dist/ai/utils/systemGenerate.d.ts +1 -1
- package/dist/ai/utils/systemGenerate.js +19 -19
- package/dist/ai/utils/systemGenerate.js.map +1 -1
- package/dist/collections/AIJobs.d.ts +2 -0
- package/dist/collections/AIJobs.js +81 -0
- package/dist/collections/AIJobs.js.map +1 -0
- package/dist/collections/AISettings.d.ts +2 -0
- package/dist/collections/AISettings.js +279 -0
- package/dist/collections/AISettings.js.map +1 -0
- package/dist/collections/Instructions.js +224 -50
- package/dist/collections/Instructions.js.map +1 -1
- package/dist/defaults.d.ts +3 -0
- package/dist/defaults.js +3 -0
- package/dist/defaults.js.map +1 -1
- package/dist/endpoints/buildPromptUtils.d.ts +19 -0
- package/dist/endpoints/buildPromptUtils.js +114 -0
- package/dist/endpoints/buildPromptUtils.js.map +1 -0
- package/dist/endpoints/chat.d.ts +4 -0
- package/dist/endpoints/fetchFields.js +0 -7
- package/dist/endpoints/fetchFields.js.map +1 -1
- package/dist/endpoints/fetchVoices.d.ts +2 -0
- package/dist/endpoints/fetchVoices.js +79 -0
- package/dist/endpoints/fetchVoices.js.map +1 -0
- package/dist/endpoints/index.js +339 -232
- package/dist/endpoints/index.js.map +1 -1
- package/dist/exports/client.d.ts +9 -0
- package/dist/exports/client.js +9 -0
- package/dist/exports/client.js.map +1 -1
- package/dist/exports/fields.d.ts +1 -0
- package/dist/exports/fields.js +1 -0
- package/dist/exports/fields.js.map +1 -1
- package/dist/fields/ArrayComposeField/ArrayComposeField.d.ts +15 -0
- package/dist/fields/ArrayComposeField/ArrayComposeField.js +87 -0
- package/dist/fields/ArrayComposeField/ArrayComposeField.js.map +1 -0
- package/dist/fields/ArrayComposeField/ArrayComposeField.jsx +73 -0
- package/dist/fields/ComposeField/ComposeField.js +2 -2
- package/dist/fields/ComposeField/ComposeField.js.map +1 -1
- package/dist/fields/ComposeField/ComposeField.jsx +2 -2
- package/dist/fields/PromptEditorField/PromptEditorField.js +162 -16
- package/dist/fields/PromptEditorField/PromptEditorField.js.map +1 -1
- package/dist/fields/PromptEditorField/PromptEditorField.jsx +123 -5
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/init.js +63 -65
- package/dist/init.js.map +1 -1
- package/dist/payload-ai.d.ts +149 -0
- package/dist/plugin.js +94 -46
- package/dist/plugin.js.map +1 -1
- package/dist/providers/InstructionsProvider/InstructionsProvider.js +38 -7
- package/dist/providers/InstructionsProvider/InstructionsProvider.js.map +1 -1
- package/dist/providers/InstructionsProvider/InstructionsProvider.jsx +30 -4
- package/dist/providers/InstructionsProvider/context.d.ts +1 -0
- package/dist/providers/InstructionsProvider/context.js +1 -0
- package/dist/providers/InstructionsProvider/context.js.map +1 -1
- package/dist/providers/InstructionsProvider/useInstructions.js +30 -10
- package/dist/providers/InstructionsProvider/useInstructions.js.map +1 -1
- package/dist/styles.d.ts +11 -0
- package/dist/types/handlebars-async-helpers.d.ts +1 -0
- package/dist/types/handlebars-dist-handlebars.d.ts +1 -0
- package/dist/types/react-mentions.d.ts +1 -0
- package/dist/types.d.ts +6 -16
- package/dist/types.js.map +1 -1
- package/dist/ui/AIConfigDashboard/index.d.ts +2 -0
- package/dist/ui/AIConfigDashboard/index.js +46 -0
- package/dist/ui/AIConfigDashboard/index.js.map +1 -0
- package/dist/ui/AIConfigDashboard/index.jsx +24 -0
- package/dist/ui/ApiKeyStatusIndicator/index.d.ts +6 -0
- package/dist/ui/ApiKeyStatusIndicator/index.js +39 -0
- package/dist/ui/ApiKeyStatusIndicator/index.js.map +1 -0
- package/dist/ui/ApiKeyStatusIndicator/index.jsx +29 -0
- package/dist/ui/Compose/Compose.d.ts +2 -2
- package/dist/ui/Compose/Compose.js +118 -92
- package/dist/ui/Compose/Compose.js.map +1 -1
- package/dist/ui/Compose/Compose.jsx +113 -103
- package/dist/ui/Compose/ComposePlaceholder.d.ts +7 -0
- package/dist/ui/Compose/ComposePlaceholder.js +78 -0
- package/dist/ui/Compose/ComposePlaceholder.js.map +1 -0
- package/dist/ui/Compose/ComposePlaceholder.jsx +66 -0
- package/dist/ui/Compose/UndoRedoActions.d.ts +2 -2
- package/dist/ui/Compose/UndoRedoActions.js +11 -6
- package/dist/ui/Compose/UndoRedoActions.js.map +1 -1
- package/dist/ui/Compose/UndoRedoActions.jsx +8 -6
- package/dist/ui/Compose/compose.module.css +57 -17
- package/dist/ui/Compose/hooks/menu/itemsMap.js +13 -7
- package/dist/ui/Compose/hooks/menu/itemsMap.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/useMenu.d.ts +2 -1
- package/dist/ui/Compose/hooks/menu/useMenu.js +28 -17
- package/dist/ui/Compose/hooks/menu/useMenu.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/useMenu.jsx +27 -14
- package/dist/ui/Compose/hooks/useActiveFieldTracking.js +69 -10
- package/dist/ui/Compose/hooks/useActiveFieldTracking.js.map +1 -1
- package/dist/ui/Compose/hooks/useGenerate.d.ts +3 -0
- package/dist/ui/Compose/hooks/useGenerate.js +71 -11
- package/dist/ui/Compose/hooks/useGenerate.js.map +1 -1
- package/dist/ui/Compose/hooks/useHistory.d.ts +0 -1
- package/dist/ui/Compose/hooks/useHistory.js +113 -26
- package/dist/ui/Compose/hooks/useHistory.js.map +1 -1
- package/dist/ui/DynamicModelSelect/index.d.ts +7 -0
- package/dist/ui/DynamicModelSelect/index.js +231 -0
- package/dist/ui/DynamicModelSelect/index.js.map +1 -0
- package/dist/ui/DynamicModelSelect/index.jsx +207 -0
- package/dist/ui/DynamicProviderSelect/index.d.ts +7 -0
- package/dist/ui/DynamicProviderSelect/index.js +101 -0
- package/dist/ui/DynamicProviderSelect/index.js.map +1 -0
- package/dist/ui/DynamicProviderSelect/index.jsx +90 -0
- package/dist/ui/DynamicVoiceSelect/index.d.ts +7 -0
- package/dist/ui/DynamicVoiceSelect/index.js +156 -0
- package/dist/ui/DynamicVoiceSelect/index.js.map +1 -0
- package/dist/ui/DynamicVoiceSelect/index.jsx +102 -0
- package/dist/ui/EncryptedTextField/index.d.ts +8 -0
- package/dist/ui/EncryptedTextField/index.js +74 -0
- package/dist/ui/EncryptedTextField/index.js.map +1 -0
- package/dist/ui/EncryptedTextField/index.jsx +35 -0
- package/dist/ui/Icons/LottieAnimation.js +3 -1
- package/dist/ui/Icons/LottieAnimation.js.map +1 -1
- package/dist/ui/Icons/LottieAnimation.jsx +2 -1
- package/dist/ui/ModelRowLabel/index.d.ts +6 -0
- package/dist/ui/ModelRowLabel/index.js +41 -0
- package/dist/ui/ModelRowLabel/index.js.map +1 -0
- package/dist/ui/ModelRowLabel/index.jsx +26 -0
- package/dist/ui/ProviderOptionsEditor/index.d.ts +7 -0
- package/dist/ui/ProviderOptionsEditor/index.js +291 -0
- package/dist/ui/ProviderOptionsEditor/index.js.map +1 -0
- package/dist/ui/ProviderOptionsEditor/index.jsx +210 -0
- package/dist/ui/VoicesFetcher/index.d.ts +7 -0
- package/dist/ui/VoicesFetcher/index.js +118 -0
- package/dist/ui/VoicesFetcher/index.js.map +1 -0
- package/dist/ui/VoicesFetcher/index.jsx +79 -0
- package/dist/utilities/buildSmartPrompt.d.ts +22 -0
- package/dist/utilities/buildSmartPrompt.js +143 -0
- package/dist/utilities/buildSmartPrompt.js.map +1 -0
- package/dist/utilities/encryption.d.ts +2 -0
- package/dist/utilities/encryption.js +47 -0
- package/dist/utilities/encryption.js.map +1 -0
- package/dist/utilities/extractImageData.d.ts +9 -0
- package/dist/utilities/extractImageData.js +12 -2
- package/dist/utilities/extractImageData.js.map +1 -1
- package/dist/utilities/fetchImages.d.ts +14 -0
- package/dist/utilities/fetchImages.js +38 -0
- package/dist/utilities/fetchImages.js.map +1 -0
- package/dist/utilities/fieldToJsonSchema.d.ts +2 -1
- package/dist/utilities/fieldToJsonSchema.js +66 -3
- package/dist/utilities/fieldToJsonSchema.js.map +1 -1
- package/dist/utilities/getFieldBySchemaPath.d.ts +2 -2
- package/dist/utilities/getFieldBySchemaPath.js +15 -0
- package/dist/utilities/getFieldBySchemaPath.js.map +1 -1
- package/dist/utilities/getProviderOptionsFields.d.ts +16 -0
- package/dist/utilities/getProviderOptionsFields.js +80 -0
- package/dist/utilities/getProviderOptionsFields.js.map +1 -0
- package/dist/utilities/isPluginActivated.js +1 -2
- package/dist/utilities/isPluginActivated.js.map +1 -1
- package/dist/utilities/lexicalToHTML.js.map +1 -1
- package/dist/utilities/resolveImageReferences.d.ts +30 -0
- package/dist/utilities/resolveImageReferences.js +167 -0
- package/dist/utilities/resolveImageReferences.js.map +1 -0
- package/dist/utilities/schemaConverter.d.ts +3 -0
- package/dist/utilities/schemaConverter.js +93 -0
- package/dist/utilities/schemaConverter.js.map +1 -0
- package/dist/utilities/setSafeLexicalState.d.ts +1 -3
- package/dist/utilities/setSafeLexicalState.js +1 -1
- package/dist/utilities/setSafeLexicalState.js.map +1 -1
- package/dist/utilities/updateFieldsConfig.js +27 -43
- package/dist/utilities/updateFieldsConfig.js.map +1 -1
- package/package.json +23 -24
- package/dist/ai/models/anthropic/index.d.ts +0 -2
- package/dist/ai/models/anthropic/index.js +0 -129
- package/dist/ai/models/anthropic/index.js.map +0 -1
- package/dist/ai/models/elevenLabs/generateVoice.d.ts +0 -8
- package/dist/ai/models/elevenLabs/generateVoice.js +0 -20
- package/dist/ai/models/elevenLabs/generateVoice.js.map +0 -1
- package/dist/ai/models/elevenLabs/index.d.ts +0 -2
- package/dist/ai/models/elevenLabs/index.js +0 -133
- package/dist/ai/models/elevenLabs/index.js.map +0 -1
- package/dist/ai/models/elevenLabs/voices.d.ts +0 -8
- package/dist/ai/models/elevenLabs/voices.js +0 -24
- package/dist/ai/models/elevenLabs/voices.js.map +0 -1
- package/dist/ai/models/generateObject.d.ts +0 -11
- package/dist/ai/models/generateObject.js +0 -22
- package/dist/ai/models/generateObject.js.map +0 -1
- package/dist/ai/models/google/generateImage.d.ts +0 -9
- package/dist/ai/models/google/generateImage.js +0 -27
- package/dist/ai/models/google/generateImage.js.map +0 -1
- package/dist/ai/models/google/index.d.ts +0 -2
- package/dist/ai/models/google/index.js +0 -201
- package/dist/ai/models/google/index.js.map +0 -1
- package/dist/ai/models/index.d.ts +0 -2
- package/dist/ai/models/index.js +0 -13
- package/dist/ai/models/index.js.map +0 -1
- package/dist/ai/models/openai/generateImage.d.ts +0 -5
- package/dist/ai/models/openai/generateImage.js +0 -31
- package/dist/ai/models/openai/generateImage.js.map +0 -1
- package/dist/ai/models/openai/generateVoice.d.ts +0 -6
- package/dist/ai/models/openai/generateVoice.js +0 -19
- package/dist/ai/models/openai/generateVoice.js.map +0 -1
- package/dist/ai/models/openai/index.d.ts +0 -2
- package/dist/ai/models/openai/index.js +0 -428
- package/dist/ai/models/openai/index.js.map +0 -1
- package/dist/ai/models/openai/openai.d.ts +0 -1
- package/dist/ai/models/openai/openai.js +0 -8
- package/dist/ai/models/openai/openai.js.map +0 -1
- package/dist/ai/utils/editImagesWithOpenAI.d.ts +0 -10
- package/dist/ai/utils/editImagesWithOpenAI.js +0 -37
- package/dist/ai/utils/editImagesWithOpenAI.js.map +0 -1
- package/dist/styles.d.js +0 -2
- package/dist/styles.d.js.map +0 -1
- package/dist/types/handlebars-async-helpers.d.js +0 -2
- package/dist/types/handlebars-async-helpers.d.js.map +0 -1
- package/dist/types/handlebars-dist-handlebars.d.js +0 -2
- package/dist/types/handlebars-dist-handlebars.d.js.map +0 -1
- package/dist/types/react-mentions.d.js +0 -2
- package/dist/types/react-mentions.d.js.map +0 -1
- package/dist/utilities/getGenerationModels.d.ts +0 -2
- package/dist/utilities/getGenerationModels.js +0 -10
- package/dist/utilities/getGenerationModels.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { FieldDescription, FieldLabel, useField } from '@payloadcms/ui';
|
|
3
|
+
import { FieldDescription, FieldLabel, useConfig, useField } from '@payloadcms/ui';
|
|
4
4
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
5
5
|
import { Mention, MentionsInput } from 'react-mentions/dist/react-mentions.cjs.js';
|
|
6
6
|
import { useInstructions } from '../../providers/InstructionsProvider/useInstructions.js';
|
|
@@ -12,13 +12,141 @@ export const PromptEditorField = (props)=>{
|
|
|
12
12
|
});
|
|
13
13
|
const [localValue, setLocalValue] = useState(payloadValue || '');
|
|
14
14
|
const hasInitialized = useRef(false);
|
|
15
|
-
const { promptEditorSuggestions } = useInstructions();
|
|
15
|
+
const { activeCollection, promptEditorSuggestions } = useInstructions();
|
|
16
|
+
const { config } = useConfig();
|
|
16
17
|
const suggestions = useMemo(()=>promptEditorSuggestions.map((suggestion)=>({
|
|
17
18
|
id: suggestion,
|
|
18
19
|
display: suggestion
|
|
19
20
|
})), [
|
|
20
21
|
promptEditorSuggestions
|
|
21
22
|
]);
|
|
23
|
+
// Extract document ID from URL if available (to get specific filenames)
|
|
24
|
+
const [documentData, setDocumentData] = useState(null);
|
|
25
|
+
useEffect(()=>{
|
|
26
|
+
// Only run in browser
|
|
27
|
+
if (typeof window === 'undefined') {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// Allow time for verify window.location is stable (unlikely to change but good practice)
|
|
31
|
+
const segments = window.location.pathname.split('/');
|
|
32
|
+
const collectionsIndex = segments.indexOf('collections');
|
|
33
|
+
if (collectionsIndex > -1 && segments.length > collectionsIndex + 2) {
|
|
34
|
+
const urlCollectionSlug = segments[collectionsIndex + 1];
|
|
35
|
+
const urlId = segments[collectionsIndex + 2];
|
|
36
|
+
// Only fetch if we are editing instructions for the same collection we are viewing
|
|
37
|
+
// and we haven't fetched yet (or ID changed)
|
|
38
|
+
if (urlCollectionSlug === activeCollection && urlId && urlId !== 'create') {
|
|
39
|
+
const fetchDocument = async ()=>{
|
|
40
|
+
try {
|
|
41
|
+
const response = await fetch(`${String(config.serverURL)}${String(config.routes.api)}/${String(urlCollectionSlug)}/${String(urlId)}`);
|
|
42
|
+
if (response.ok) {
|
|
43
|
+
const data = await response.json();
|
|
44
|
+
setDocumentData(data);
|
|
45
|
+
}
|
|
46
|
+
} catch (_err) {
|
|
47
|
+
// Ignore error
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
void fetchDocument();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}, [
|
|
54
|
+
activeCollection,
|
|
55
|
+
config
|
|
56
|
+
]);
|
|
57
|
+
// Extract all upload fields from the current collection schema
|
|
58
|
+
const imageFieldSuggestions = useMemo(()=>{
|
|
59
|
+
const suggestions = [];
|
|
60
|
+
// Use activeCollection from context which holds the target collection slug
|
|
61
|
+
const targetSlug = activeCollection;
|
|
62
|
+
if (!targetSlug || !config?.collections) {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
const collection = config.collections.find((c)=>c.slug === targetSlug);
|
|
66
|
+
if (!collection?.fields) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
const uploadFields = [];
|
|
70
|
+
// Recursive function to find upload fields
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
72
|
+
const findUploadFields = (fields, prefix = '')=>{
|
|
73
|
+
for (const field of fields){
|
|
74
|
+
if (field.type === 'upload' && field.name) {
|
|
75
|
+
const fieldPath = prefix ? `${prefix}.${String(field.name)}` : String(field.name);
|
|
76
|
+
uploadFields.push({
|
|
77
|
+
name: fieldPath,
|
|
78
|
+
hasMany: field.hasMany === true
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// Check nested fields in groups, arrays, etc.
|
|
82
|
+
if (field.fields && Array.isArray(field.fields)) {
|
|
83
|
+
const newPrefix = field.name ? prefix ? `${prefix}.${String(field.name)}` : String(field.name) : prefix;
|
|
84
|
+
findUploadFields(field.fields, newPrefix);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
findUploadFields(collection.fields);
|
|
89
|
+
// Add generic field names (base suggestions) - ONLY for single uploads (not hasMany arrays)
|
|
90
|
+
uploadFields.forEach(({ name, hasMany })=>{
|
|
91
|
+
// User requested to hide the array itself for hasMany fields
|
|
92
|
+
if (!hasMany) {
|
|
93
|
+
suggestions.push({
|
|
94
|
+
id: name,
|
|
95
|
+
display: name
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
// If we have document data, add specific filename suggestions
|
|
100
|
+
if (documentData) {
|
|
101
|
+
uploadFields.forEach(({ name, hasMany })=>{
|
|
102
|
+
const value = documentData[name] // Note: nested access logic simplified for now
|
|
103
|
+
;
|
|
104
|
+
// Helper to extract filename from media doc (which might be ID or object)
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
106
|
+
const getFilename = (item)=>{
|
|
107
|
+
if (typeof item === 'object' && item && (item.filename || item.name)) {
|
|
108
|
+
return item.filename || item.name;
|
|
109
|
+
}
|
|
110
|
+
// If it's just an ID, we can't show filename without populating.
|
|
111
|
+
// Assuming compose view usually fetches with depth > 0 or we rely on what we have.
|
|
112
|
+
return null;
|
|
113
|
+
};
|
|
114
|
+
if (value) {
|
|
115
|
+
if (hasMany && Array.isArray(value)) {
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
117
|
+
value.forEach((item)=>{
|
|
118
|
+
const fname = getFilename(item);
|
|
119
|
+
if (fname) {
|
|
120
|
+
const suggestion = `${name}:${fname}`;
|
|
121
|
+
suggestions.push({
|
|
122
|
+
id: suggestion,
|
|
123
|
+
display: suggestion
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
} else if (!hasMany) {
|
|
128
|
+
// Single image - we already added the base name above.
|
|
129
|
+
// We can optionally add the specific filename too if desired,
|
|
130
|
+
// but user request focused on arrays.
|
|
131
|
+
// Adding the specific filename option for Single images too as it's explicit.
|
|
132
|
+
const fname = getFilename(value);
|
|
133
|
+
if (fname) {
|
|
134
|
+
const suggestion = `${name}:${fname}`;
|
|
135
|
+
suggestions.push({
|
|
136
|
+
id: suggestion,
|
|
137
|
+
display: suggestion
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return suggestions;
|
|
145
|
+
}, [
|
|
146
|
+
activeCollection,
|
|
147
|
+
config,
|
|
148
|
+
documentData
|
|
149
|
+
]);
|
|
22
150
|
useEffect(()=>{
|
|
23
151
|
if (!hasInitialized.current || payloadValue === '') {
|
|
24
152
|
setLocalValue(payloadValue || '');
|
|
@@ -28,8 +156,13 @@ export const PromptEditorField = (props)=>{
|
|
|
28
156
|
payloadValue
|
|
29
157
|
]);
|
|
30
158
|
const handleChange = useCallback((e)=>{
|
|
31
|
-
|
|
32
|
-
|
|
159
|
+
const newValue = e.target.value;
|
|
160
|
+
setLocalValue(newValue);
|
|
161
|
+
// Also update Payload value immediately to prevent loss when Save is clicked
|
|
162
|
+
setValue(newValue);
|
|
163
|
+
}, [
|
|
164
|
+
setValue
|
|
165
|
+
]);
|
|
33
166
|
const handleBlur = useCallback(()=>{
|
|
34
167
|
setValue(localValue);
|
|
35
168
|
}, [
|
|
@@ -37,28 +170,41 @@ export const PromptEditorField = (props)=>{
|
|
|
37
170
|
setValue
|
|
38
171
|
]);
|
|
39
172
|
const displayTransform = useCallback((id)=>`{{ ${id} }}`, []);
|
|
173
|
+
const imageDisplayTransform = useCallback((id)=>`@${id}`, []);
|
|
40
174
|
return /*#__PURE__*/ _jsxs("div", {
|
|
41
175
|
className: "field-type textarea",
|
|
42
176
|
children: [
|
|
43
177
|
/*#__PURE__*/ _jsx(FieldLabel, {
|
|
44
178
|
label: field.label
|
|
45
179
|
}),
|
|
46
|
-
/*#__PURE__*/
|
|
180
|
+
/*#__PURE__*/ _jsxs(MentionsInput, {
|
|
47
181
|
onBlur: handleBlur,
|
|
48
182
|
onChange: handleChange,
|
|
49
|
-
placeholder: "Type
|
|
183
|
+
placeholder: "Type {{ for fields }} or @imageField for images. For specific images use @imageField:filename.jpg",
|
|
50
184
|
style: defaultStyle,
|
|
51
185
|
value: localValue,
|
|
52
|
-
children:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
186
|
+
children: [
|
|
187
|
+
/*#__PURE__*/ _jsx(Mention, {
|
|
188
|
+
data: suggestions,
|
|
189
|
+
displayTransform: displayTransform,
|
|
190
|
+
markup: "{{__id__}}",
|
|
191
|
+
style: {
|
|
192
|
+
backgroundColor: 'var(--theme-elevation-100)',
|
|
193
|
+
padding: '2px 0'
|
|
194
|
+
},
|
|
195
|
+
trigger: "{"
|
|
196
|
+
}),
|
|
197
|
+
/*#__PURE__*/ _jsx(Mention, {
|
|
198
|
+
data: imageFieldSuggestions,
|
|
199
|
+
displayTransform: imageDisplayTransform,
|
|
200
|
+
markup: "@__id__",
|
|
201
|
+
style: {
|
|
202
|
+
backgroundColor: 'var(--theme-elevation-150)',
|
|
203
|
+
padding: '2px 0'
|
|
204
|
+
},
|
|
205
|
+
trigger: "@"
|
|
206
|
+
})
|
|
207
|
+
]
|
|
62
208
|
}),
|
|
63
209
|
/*#__PURE__*/ _jsx(FieldDescription, {
|
|
64
210
|
description: field?.admin?.description,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/fields/PromptEditorField/PromptEditorField.tsx"],"sourcesContent":["'use client'\n\nimport type { TextareaFieldClientProps } from 'payload'\n\nimport { FieldDescription, FieldLabel, useField } from '@payloadcms/ui'\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { Mention, MentionsInput } from 'react-mentions/dist/react-mentions.cjs.js'\n\nimport { useInstructions } from '../../providers/InstructionsProvider/useInstructions.js'\nimport { defaultStyle } from './defaultStyle.js'\n\nexport const PromptEditorField: React.FC<TextareaFieldClientProps> = (props) => {\n const { field, path: pathFromContext } = props\n const { setValue, value: payloadValue } = useField<string>({\n path: pathFromContext,\n })\n\n const [localValue, setLocalValue] = useState(payloadValue || '')\n const hasInitialized = useRef(false)\n\n const { promptEditorSuggestions } = useInstructions()\n\n const suggestions = useMemo(\n () =>\n promptEditorSuggestions.map((suggestion: string) => ({\n id: suggestion,\n display: suggestion,\n })),\n [promptEditorSuggestions],\n )\n\n useEffect(() => {\n if (!hasInitialized.current || payloadValue === '') {\n setLocalValue(payloadValue || '')\n hasInitialized.current = true\n }\n }, [payloadValue])\n\n const handleChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setLocalValue(e.target.value)\n }, [])\n\n const handleBlur = useCallback(() => {\n setValue(localValue)\n }, [localValue, setValue])\n\n const displayTransform = useCallback((id: string) => `{{ ${id} }}`, [])\n\n return (\n <div className=\"field-type textarea\">\n <FieldLabel label={field.label} />\n <MentionsInput\n onBlur={handleBlur}\n onChange={handleChange}\n placeholder=\"Type your prompt using {{ fieldName }} variables...\"\n style={defaultStyle}\n value={localValue}\n >\n <Mention\n data={suggestions}\n displayTransform={displayTransform}\n markup=\"{{__id__}}\"\n style={{\n backgroundColor: 'var(--theme-elevation-100)',\n padding: '2px 0',\n }}\n trigger=\"{\"\n />\n </MentionsInput>\n <FieldDescription description={field?.admin?.description} path=\"\" />\n </div>\n )\n}\n"],"names":["FieldDescription","FieldLabel","useField","React","useCallback","useEffect","useMemo","useRef","useState","Mention","MentionsInput","useInstructions","defaultStyle","PromptEditorField","props","field","path","pathFromContext","setValue","value","payloadValue","localValue","setLocalValue","hasInitialized","promptEditorSuggestions","suggestions","map","suggestion","id","display","current","handleChange","e","target","handleBlur","displayTransform","div","className","label","onBlur","onChange","placeholder","style","data","markup","backgroundColor","padding","trigger","description","admin"],"mappings":"AAAA;;AAIA,SAASA,gBAAgB,EAAEC,UAAU,EAAEC,QAAQ,QAAQ,iBAAgB;AACvE,OAAOC,SAASC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AAChF,SAASC,OAAO,EAAEC,aAAa,QAAQ,4CAA2C;AAElF,SAASC,eAAe,QAAQ,0DAAyD;AACzF,SAASC,YAAY,QAAQ,oBAAmB;AAEhD,OAAO,MAAMC,oBAAwD,CAACC;IACpE,MAAM,EAAEC,KAAK,EAAEC,MAAMC,eAAe,EAAE,GAAGH;IACzC,MAAM,EAAEI,QAAQ,EAAEC,OAAOC,YAAY,EAAE,GAAGlB,SAAiB;QACzDc,MAAMC;IACR;IAEA,MAAM,CAACI,YAAYC,cAAc,GAAGd,SAASY,gBAAgB;IAC7D,MAAMG,iBAAiBhB,OAAO;IAE9B,MAAM,EAAEiB,uBAAuB,EAAE,GAAGb;IAEpC,MAAMc,cAAcnB,QAClB,IACEkB,wBAAwBE,GAAG,CAAC,CAACC,aAAwB,CAAA;gBACnDC,IAAID;gBACJE,SAASF;YACX,CAAA,IACF;QAACH;KAAwB;IAG3BnB,UAAU;QACR,IAAI,CAACkB,eAAeO,OAAO,IAAIV,iBAAiB,IAAI;YAClDE,cAAcF,gBAAgB;YAC9BG,eAAeO,OAAO,GAAG;QAC3B;IACF,GAAG;QAACV;KAAa;IAEjB,MAAMW,eAAe3B,YAAY,CAAC4B;QAChCV,cAAcU,EAAEC,MAAM,CAACd,KAAK;IAC9B,GAAG,EAAE;IAEL,MAAMe,aAAa9B,YAAY;QAC7Bc,SAASG;IACX,GAAG;QAACA;QAAYH;KAAS;IAEzB,MAAMiB,mBAAmB/B,YAAY,CAACwB,KAAe,CAAC,GAAG,EAAEA,GAAG,GAAG,CAAC,EAAE,EAAE;IAEtE,qBACE,MAACQ;QAAIC,WAAU;;0BACb,KAACpC;gBAAWqC,OAAOvB,MAAMuB,KAAK;;0BAC9B,KAAC5B;gBACC6B,QAAQL;gBACRM,UAAUT;gBACVU,aAAY;gBACZC,OAAO9B;gBACPO,OAAOE;0BAEP,cAAA,KAACZ;oBACCkC,MAAMlB;oBACNU,kBAAkBA;oBAClBS,QAAO;oBACPF,OAAO;wBACLG,iBAAiB;wBACjBC,SAAS;oBACX;oBACAC,SAAQ;;;0BAGZ,KAAC/C;gBAAiBgD,aAAajC,OAAOkC,OAAOD;gBAAahC,MAAK;;;;AAGrE,EAAC"}
|
|
1
|
+
{"version":3,"sources":["../../../src/fields/PromptEditorField/PromptEditorField.tsx"],"sourcesContent":["'use client'\n\nimport type { TextareaFieldClientProps } from 'payload'\n\nimport { FieldDescription, FieldLabel, useConfig, useField } from '@payloadcms/ui'\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { Mention, MentionsInput } from 'react-mentions/dist/react-mentions.cjs.js'\n\nimport { useInstructions } from '../../providers/InstructionsProvider/useInstructions.js'\nimport { defaultStyle } from './defaultStyle.js'\n\nexport const PromptEditorField: React.FC<TextareaFieldClientProps> = (props) => {\n const { field, path: pathFromContext } = props\n const { setValue, value: payloadValue } = useField<string>({\n path: pathFromContext,\n })\n\n const [localValue, setLocalValue] = useState(payloadValue || '')\n const hasInitialized = useRef(false)\n\n const { activeCollection, promptEditorSuggestions } = useInstructions()\n const { config } = useConfig()\n\n const suggestions = useMemo(\n () =>\n promptEditorSuggestions.map((suggestion: string) => ({\n id: suggestion,\n display: suggestion,\n })),\n [promptEditorSuggestions],\n )\n\n // Extract document ID from URL if available (to get specific filenames)\n const [documentData, setDocumentData] = useState<null | Record<string, unknown>>(null)\n \n useEffect(() => {\n // Only run in browser\n if (typeof window === 'undefined') {\n return\n }\n\n // Allow time for verify window.location is stable (unlikely to change but good practice)\n const segments = window.location.pathname.split('/')\n const collectionsIndex = segments.indexOf('collections')\n \n if (collectionsIndex > -1 && segments.length > collectionsIndex + 2) {\n const urlCollectionSlug = segments[collectionsIndex + 1]\n const urlId = segments[collectionsIndex + 2]\n\n // Only fetch if we are editing instructions for the same collection we are viewing\n // and we haven't fetched yet (or ID changed)\n if (urlCollectionSlug === activeCollection && urlId && urlId !== 'create') {\n const fetchDocument = async () => {\n try {\n \n const response = await fetch(`${String(config.serverURL)}${String(config.routes.api)}/${String(urlCollectionSlug)}/${String(urlId)}`)\n if (response.ok) {\n const data = await response.json()\n setDocumentData(data)\n }\n } catch (_err) {\n // Ignore error\n }\n }\n void fetchDocument()\n }\n }\n }, [activeCollection, config])\n\n // Extract all upload fields from the current collection schema\n const imageFieldSuggestions = useMemo(() => {\n const suggestions: { display: string; id: string }[] = []\n \n // Use activeCollection from context which holds the target collection slug\n const targetSlug = activeCollection\n \n if (!targetSlug || !config?.collections) {\n return []\n }\n\n const collection = config.collections.find((c) => c.slug === targetSlug)\n if (!collection?.fields) {\n return []\n }\n\n const uploadFields: { hasMany: boolean; name: string }[] = []\n\n // Recursive function to find upload fields\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const findUploadFields = (fields: any[], prefix = ''): void => {\n for (const field of fields) {\n if (field.type === 'upload' && field.name) {\n const fieldPath = prefix ? `${prefix}.${String(field.name)}` : String(field.name)\n uploadFields.push({ name: fieldPath, hasMany: field.hasMany === true })\n }\n // Check nested fields in groups, arrays, etc.\n if (field.fields && Array.isArray(field.fields)) {\n const newPrefix = field.name ? (prefix ? `${prefix}.${String(field.name)}` : String(field.name)) : prefix\n findUploadFields(field.fields, newPrefix)\n }\n }\n }\n\n findUploadFields(collection.fields)\n \n // Add generic field names (base suggestions) - ONLY for single uploads (not hasMany arrays)\n uploadFields.forEach(({ name, hasMany }) => {\n // User requested to hide the array itself for hasMany fields\n if (!hasMany) {\n suggestions.push({ id: name, display: name })\n }\n })\n\n // If we have document data, add specific filename suggestions\n if (documentData) {\n uploadFields.forEach(({ name, hasMany }) => {\n const value = documentData[name] // Note: nested access logic simplified for now\n \n // Helper to extract filename from media doc (which might be ID or object)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const getFilename = (item: any): null | string => {\n if (typeof item === 'object' && item && (item.filename || item.name)) {\n return item.filename || item.name\n }\n // If it's just an ID, we can't show filename without populating. \n // Assuming compose view usually fetches with depth > 0 or we rely on what we have.\n return null\n }\n\n if (value) {\n if (hasMany && Array.isArray(value)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value.forEach((item: any) => {\n const fname = getFilename(item)\n if (fname) {\n const suggestion = `${name}:${fname}`\n suggestions.push({ id: suggestion, display: suggestion })\n }\n })\n } else if (!hasMany) {\n // Single image - we already added the base name above.\n // We can optionally add the specific filename too if desired, \n // but user request focused on arrays.\n // Adding the specific filename option for Single images too as it's explicit.\n const fname = getFilename(value)\n if (fname) {\n const suggestion = `${name}:${fname}`\n suggestions.push({ id: suggestion, display: suggestion })\n }\n }\n }\n })\n }\n \n return suggestions\n }, [activeCollection, config, documentData])\n\n useEffect(() => {\n if (!hasInitialized.current || payloadValue === '') {\n setLocalValue(payloadValue || '')\n hasInitialized.current = true\n }\n }, [payloadValue])\n\n const handleChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newValue = e.target.value\n setLocalValue(newValue)\n // Also update Payload value immediately to prevent loss when Save is clicked\n setValue(newValue)\n }, [setValue])\n\n const handleBlur = useCallback(() => {\n setValue(localValue)\n }, [localValue, setValue])\n\n const displayTransform = useCallback((id: string) => `{{ ${id} }}`, [])\n const imageDisplayTransform = useCallback((id: string) => `@${id}`, [])\n\n return (\n <div className=\"field-type textarea\">\n <FieldLabel label={field.label} />\n <MentionsInput\n onBlur={handleBlur}\n onChange={handleChange}\n placeholder=\"Type {{ for fields }} or @imageField for images. For specific images use @imageField:filename.jpg\"\n style={defaultStyle}\n value={localValue}\n >\n <Mention\n data={suggestions}\n displayTransform={displayTransform}\n markup=\"{{__id__}}\"\n style={{\n backgroundColor: 'var(--theme-elevation-100)',\n padding: '2px 0',\n }}\n trigger=\"{\"\n />\n <Mention\n data={imageFieldSuggestions}\n displayTransform={imageDisplayTransform}\n markup=\"@__id__\"\n style={{\n backgroundColor: 'var(--theme-elevation-150)',\n padding: '2px 0',\n }}\n trigger=\"@\"\n />\n </MentionsInput>\n <FieldDescription description={field?.admin?.description} path=\"\" />\n </div>\n )\n}\n"],"names":["FieldDescription","FieldLabel","useConfig","useField","React","useCallback","useEffect","useMemo","useRef","useState","Mention","MentionsInput","useInstructions","defaultStyle","PromptEditorField","props","field","path","pathFromContext","setValue","value","payloadValue","localValue","setLocalValue","hasInitialized","activeCollection","promptEditorSuggestions","config","suggestions","map","suggestion","id","display","documentData","setDocumentData","window","segments","location","pathname","split","collectionsIndex","indexOf","length","urlCollectionSlug","urlId","fetchDocument","response","fetch","String","serverURL","routes","api","ok","data","json","_err","imageFieldSuggestions","targetSlug","collections","collection","find","c","slug","fields","uploadFields","findUploadFields","prefix","type","name","fieldPath","push","hasMany","Array","isArray","newPrefix","forEach","getFilename","item","filename","fname","current","handleChange","e","newValue","target","handleBlur","displayTransform","imageDisplayTransform","div","className","label","onBlur","onChange","placeholder","style","markup","backgroundColor","padding","trigger","description","admin"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { FieldDescription, FieldLabel, useField } from '@payloadcms/ui';
|
|
2
|
+
import { FieldDescription, FieldLabel, useConfig, useField } from '@payloadcms/ui';
|
|
3
3
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { Mention, MentionsInput } from 'react-mentions/dist/react-mentions.cjs.js';
|
|
5
5
|
import { useInstructions } from '../../providers/InstructionsProvider/useInstructions.js';
|
|
@@ -11,11 +11,121 @@ export const PromptEditorField = (props) => {
|
|
|
11
11
|
});
|
|
12
12
|
const [localValue, setLocalValue] = useState(payloadValue || '');
|
|
13
13
|
const hasInitialized = useRef(false);
|
|
14
|
-
const { promptEditorSuggestions } = useInstructions();
|
|
14
|
+
const { activeCollection, promptEditorSuggestions } = useInstructions();
|
|
15
|
+
const { config } = useConfig();
|
|
15
16
|
const suggestions = useMemo(() => promptEditorSuggestions.map((suggestion) => ({
|
|
16
17
|
id: suggestion,
|
|
17
18
|
display: suggestion,
|
|
18
19
|
})), [promptEditorSuggestions]);
|
|
20
|
+
// Extract document ID from URL if available (to get specific filenames)
|
|
21
|
+
const [documentData, setDocumentData] = useState(null);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
// Only run in browser
|
|
24
|
+
if (typeof window === 'undefined') {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
// Allow time for verify window.location is stable (unlikely to change but good practice)
|
|
28
|
+
const segments = window.location.pathname.split('/');
|
|
29
|
+
const collectionsIndex = segments.indexOf('collections');
|
|
30
|
+
if (collectionsIndex > -1 && segments.length > collectionsIndex + 2) {
|
|
31
|
+
const urlCollectionSlug = segments[collectionsIndex + 1];
|
|
32
|
+
const urlId = segments[collectionsIndex + 2];
|
|
33
|
+
// Only fetch if we are editing instructions for the same collection we are viewing
|
|
34
|
+
// and we haven't fetched yet (or ID changed)
|
|
35
|
+
if (urlCollectionSlug === activeCollection && urlId && urlId !== 'create') {
|
|
36
|
+
const fetchDocument = async () => {
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetch(`${String(config.serverURL)}${String(config.routes.api)}/${String(urlCollectionSlug)}/${String(urlId)}`);
|
|
39
|
+
if (response.ok) {
|
|
40
|
+
const data = await response.json();
|
|
41
|
+
setDocumentData(data);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (_err) {
|
|
45
|
+
// Ignore error
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
void fetchDocument();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}, [activeCollection, config]);
|
|
52
|
+
// Extract all upload fields from the current collection schema
|
|
53
|
+
const imageFieldSuggestions = useMemo(() => {
|
|
54
|
+
const suggestions = [];
|
|
55
|
+
// Use activeCollection from context which holds the target collection slug
|
|
56
|
+
const targetSlug = activeCollection;
|
|
57
|
+
if (!targetSlug || !config?.collections) {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
const collection = config.collections.find((c) => c.slug === targetSlug);
|
|
61
|
+
if (!collection?.fields) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
const uploadFields = [];
|
|
65
|
+
// Recursive function to find upload fields
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
|
+
const findUploadFields = (fields, prefix = '') => {
|
|
68
|
+
for (const field of fields) {
|
|
69
|
+
if (field.type === 'upload' && field.name) {
|
|
70
|
+
const fieldPath = prefix ? `${prefix}.${String(field.name)}` : String(field.name);
|
|
71
|
+
uploadFields.push({ name: fieldPath, hasMany: field.hasMany === true });
|
|
72
|
+
}
|
|
73
|
+
// Check nested fields in groups, arrays, etc.
|
|
74
|
+
if (field.fields && Array.isArray(field.fields)) {
|
|
75
|
+
const newPrefix = field.name ? (prefix ? `${prefix}.${String(field.name)}` : String(field.name)) : prefix;
|
|
76
|
+
findUploadFields(field.fields, newPrefix);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
findUploadFields(collection.fields);
|
|
81
|
+
// Add generic field names (base suggestions) - ONLY for single uploads (not hasMany arrays)
|
|
82
|
+
uploadFields.forEach(({ name, hasMany }) => {
|
|
83
|
+
// User requested to hide the array itself for hasMany fields
|
|
84
|
+
if (!hasMany) {
|
|
85
|
+
suggestions.push({ id: name, display: name });
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
// If we have document data, add specific filename suggestions
|
|
89
|
+
if (documentData) {
|
|
90
|
+
uploadFields.forEach(({ name, hasMany }) => {
|
|
91
|
+
const value = documentData[name]; // Note: nested access logic simplified for now
|
|
92
|
+
// Helper to extract filename from media doc (which might be ID or object)
|
|
93
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
94
|
+
const getFilename = (item) => {
|
|
95
|
+
if (typeof item === 'object' && item && (item.filename || item.name)) {
|
|
96
|
+
return item.filename || item.name;
|
|
97
|
+
}
|
|
98
|
+
// If it's just an ID, we can't show filename without populating.
|
|
99
|
+
// Assuming compose view usually fetches with depth > 0 or we rely on what we have.
|
|
100
|
+
return null;
|
|
101
|
+
};
|
|
102
|
+
if (value) {
|
|
103
|
+
if (hasMany && Array.isArray(value)) {
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
105
|
+
value.forEach((item) => {
|
|
106
|
+
const fname = getFilename(item);
|
|
107
|
+
if (fname) {
|
|
108
|
+
const suggestion = `${name}:${fname}`;
|
|
109
|
+
suggestions.push({ id: suggestion, display: suggestion });
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
else if (!hasMany) {
|
|
114
|
+
// Single image - we already added the base name above.
|
|
115
|
+
// We can optionally add the specific filename too if desired,
|
|
116
|
+
// but user request focused on arrays.
|
|
117
|
+
// Adding the specific filename option for Single images too as it's explicit.
|
|
118
|
+
const fname = getFilename(value);
|
|
119
|
+
if (fname) {
|
|
120
|
+
const suggestion = `${name}:${fname}`;
|
|
121
|
+
suggestions.push({ id: suggestion, display: suggestion });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return suggestions;
|
|
128
|
+
}, [activeCollection, config, documentData]);
|
|
19
129
|
useEffect(() => {
|
|
20
130
|
if (!hasInitialized.current || payloadValue === '') {
|
|
21
131
|
setLocalValue(payloadValue || '');
|
|
@@ -23,19 +133,27 @@ export const PromptEditorField = (props) => {
|
|
|
23
133
|
}
|
|
24
134
|
}, [payloadValue]);
|
|
25
135
|
const handleChange = useCallback((e) => {
|
|
26
|
-
|
|
27
|
-
|
|
136
|
+
const newValue = e.target.value;
|
|
137
|
+
setLocalValue(newValue);
|
|
138
|
+
// Also update Payload value immediately to prevent loss when Save is clicked
|
|
139
|
+
setValue(newValue);
|
|
140
|
+
}, [setValue]);
|
|
28
141
|
const handleBlur = useCallback(() => {
|
|
29
142
|
setValue(localValue);
|
|
30
143
|
}, [localValue, setValue]);
|
|
31
144
|
const displayTransform = useCallback((id) => `{{ ${id} }}`, []);
|
|
145
|
+
const imageDisplayTransform = useCallback((id) => `@${id}`, []);
|
|
32
146
|
return (<div className="field-type textarea">
|
|
33
147
|
<FieldLabel label={field.label}/>
|
|
34
|
-
<MentionsInput onBlur={handleBlur} onChange={handleChange} placeholder="Type
|
|
148
|
+
<MentionsInput onBlur={handleBlur} onChange={handleChange} placeholder="Type {{ for fields }} or @imageField for images. For specific images use @imageField:filename.jpg" style={defaultStyle} value={localValue}>
|
|
35
149
|
<Mention data={suggestions} displayTransform={displayTransform} markup="{{__id__}}" style={{
|
|
36
150
|
backgroundColor: 'var(--theme-elevation-100)',
|
|
37
151
|
padding: '2px 0',
|
|
38
152
|
}} trigger="{"/>
|
|
153
|
+
<Mention data={imageFieldSuggestions} displayTransform={imageDisplayTransform} markup="@__id__" style={{
|
|
154
|
+
backgroundColor: 'var(--theme-elevation-150)',
|
|
155
|
+
padding: '2px 0',
|
|
156
|
+
}} trigger="@"/>
|
|
39
157
|
</MentionsInput>
|
|
40
158
|
<FieldDescription description={field?.admin?.description} path=""/>
|
|
41
159
|
</div>);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export type { GenerateArgs } from './ai/index.js';
|
|
1
2
|
export { defaultPrompts, defaultSeedPrompts } from './ai/prompts.js';
|
|
2
3
|
export { PayloadAiPluginLexicalEditorFeature } from './fields/LexicalEditor/feature.server.js';
|
|
4
|
+
export type {} from './payload-ai.d.ts';
|
|
3
5
|
export { payloadAiPlugin } from './plugin.js';
|
|
6
|
+
export { fieldToJsonSchema } from './utilities/fieldToJsonSchema.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { defaultPrompts, defaultSeedPrompts } from './ai/prompts.js';
|
|
2
2
|
export { PayloadAiPluginLexicalEditorFeature } from './fields/LexicalEditor/feature.server.js';
|
|
3
3
|
export { payloadAiPlugin } from './plugin.js';
|
|
4
|
+
export { fieldToJsonSchema } from './utilities/fieldToJsonSchema.js';
|
|
4
5
|
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { defaultPrompts, defaultSeedPrompts } from './ai/prompts.js'\n\nexport { PayloadAiPluginLexicalEditorFeature } from './fields/LexicalEditor/feature.server.js'\nexport { payloadAiPlugin } from './plugin.js'\n"],"names":["defaultPrompts","defaultSeedPrompts","PayloadAiPluginLexicalEditorFeature","payloadAiPlugin"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type { GenerateArgs } from './ai/index.js'\n\nexport { defaultPrompts, defaultSeedPrompts } from './ai/prompts.js'\n\nexport { PayloadAiPluginLexicalEditorFeature } from './fields/LexicalEditor/feature.server.js'\n// Re-export to ensure payload.ai module augmentation is included\nexport type {} from './payload-ai.d.ts'\n\nexport { payloadAiPlugin } from './plugin.js'\nexport { fieldToJsonSchema } from './utilities/fieldToJsonSchema.js'\n"],"names":["defaultPrompts","defaultSeedPrompts","PayloadAiPluginLexicalEditorFeature","payloadAiPlugin","fieldToJsonSchema"],"mappings":"AAEA,SAASA,cAAc,EAAEC,kBAAkB,QAAQ,kBAAiB;AAEpE,SAASC,mCAAmC,QAAQ,2CAA0C;AAI9F,SAASC,eAAe,QAAQ,cAAa;AAC7C,SAASC,iBAAiB,QAAQ,mCAAkC"}
|
package/dist/init.js
CHANGED
|
@@ -1,7 +1,33 @@
|
|
|
1
1
|
import { defaultSeedPrompts } from './ai/prompts.js';
|
|
2
|
-
import { systemGenerate } from './ai/utils/systemGenerate.js';
|
|
3
2
|
import { PLUGIN_INSTRUCTIONS_TABLE } from './defaults.js';
|
|
4
|
-
|
|
3
|
+
// Defined capabilities mapping for init
|
|
4
|
+
const CAPABILITY_MAP = [
|
|
5
|
+
{
|
|
6
|
+
id: 'text',
|
|
7
|
+
fields: [
|
|
8
|
+
'text',
|
|
9
|
+
'textarea'
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: 'richtext',
|
|
14
|
+
fields: [
|
|
15
|
+
'richText'
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: 'image',
|
|
20
|
+
fields: [
|
|
21
|
+
'upload'
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: 'array',
|
|
26
|
+
fields: [
|
|
27
|
+
'array'
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
];
|
|
5
31
|
export const init = async (payload, fieldSchemaPaths, pluginConfig)=>{
|
|
6
32
|
if (!pluginConfig.generatePromptOnInit) {
|
|
7
33
|
return;
|
|
@@ -10,20 +36,14 @@ export const init = async (payload, fieldSchemaPaths, pluginConfig)=>{
|
|
|
10
36
|
payload.logger.info(`— AI Plugin: Initializing...`);
|
|
11
37
|
}
|
|
12
38
|
const paths = Object.keys(fieldSchemaPaths);
|
|
13
|
-
// Note: schema-path is globally unique, so we create one entry per path regardless of localization
|
|
14
|
-
// Localization info is kept for potential future use or debugging
|
|
15
|
-
const _isLocalized = pluginConfig._localization?.enabled && pluginConfig._localization.locales.length > 0;
|
|
16
|
-
const _locales = pluginConfig._localization?.locales || [];
|
|
17
39
|
// Get all instructions for faster initialization
|
|
18
|
-
// Query with locale: 'all' to get entries from all locales when localization is enabled
|
|
19
40
|
const { docs: allInstructions } = await payload.find({
|
|
20
41
|
collection: PLUGIN_INSTRUCTIONS_TABLE,
|
|
21
42
|
depth: 0,
|
|
22
|
-
locale: 'all',
|
|
23
43
|
pagination: false,
|
|
24
44
|
select: {
|
|
25
|
-
id: true,
|
|
26
45
|
'field-type': true,
|
|
46
|
+
'model-id': true,
|
|
27
47
|
'schema-path': true
|
|
28
48
|
}
|
|
29
49
|
});
|
|
@@ -31,7 +51,6 @@ export const init = async (payload, fieldSchemaPaths, pluginConfig)=>{
|
|
|
31
51
|
for(let i = 0; i < paths.length; i++){
|
|
32
52
|
const path = paths[i];
|
|
33
53
|
const { type: fieldType, label: fieldLabel, relationTo } = fieldSchemaPaths[path];
|
|
34
|
-
// Find existing entry for this path (schema-path is globally unique, not per locale)
|
|
35
54
|
let instructions = allInstructions.find((entry)=>entry['schema-path'] === path);
|
|
36
55
|
if (!instructions) {
|
|
37
56
|
let seed;
|
|
@@ -54,18 +73,21 @@ export const init = async (payload, fieldSchemaPaths, pluginConfig)=>{
|
|
|
54
73
|
}
|
|
55
74
|
continue;
|
|
56
75
|
}
|
|
57
|
-
|
|
76
|
+
// Empty prompt - smart fallback will generate a contextual prompt at runtime
|
|
77
|
+
const generatedPrompt = '';
|
|
58
78
|
if ('prompt' in seed) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
79
|
+
// Prompt generation currently disabled during migration to AI SDK Providers
|
|
80
|
+
// TODO: Re-enable using a default provider from AI Settings if available
|
|
81
|
+
/*
|
|
82
|
+
generatedPrompt = await systemGenerate(
|
|
83
|
+
{
|
|
84
|
+
prompt: seed.prompt,
|
|
85
|
+
system: seed.system,
|
|
86
|
+
},
|
|
87
|
+
undefined // No generateTextFn currently
|
|
88
|
+
)
|
|
89
|
+
*/ }
|
|
90
|
+
const modelForId = CAPABILITY_MAP.find((a)=>a.fields.includes(fieldType));
|
|
69
91
|
const data = {
|
|
70
92
|
'model-id': modelForId?.id,
|
|
71
93
|
prompt: generatedPrompt,
|
|
@@ -79,44 +101,12 @@ export const init = async (payload, fieldSchemaPaths, pluginConfig)=>{
|
|
|
79
101
|
prompt: generatedPrompt,
|
|
80
102
|
...seed.data
|
|
81
103
|
}, `Prompt seeded for "${path}" field`);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
// Handle unique constraint violation - entry might already exist for another locale
|
|
89
|
-
const error = err;
|
|
90
|
-
if (error?.name === 'ValidationError' && error?.data?.errors?.some((e)=>e.path === 'schema-path')) {
|
|
91
|
-
// Try to find the existing entry across all locales
|
|
92
|
-
const { docs } = await payload.find({
|
|
93
|
-
collection: PLUGIN_INSTRUCTIONS_TABLE,
|
|
94
|
-
limit: 1,
|
|
95
|
-
locale: 'all',
|
|
96
|
-
select: {
|
|
97
|
-
id: true,
|
|
98
|
-
'field-type': true,
|
|
99
|
-
'schema-path': true
|
|
100
|
-
},
|
|
101
|
-
where: {
|
|
102
|
-
'schema-path': {
|
|
103
|
-
equals: path
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
const existingEntry = docs[0];
|
|
108
|
-
if (existingEntry) {
|
|
109
|
-
instructions = existingEntry;
|
|
110
|
-
if (pluginConfig.debugging) {
|
|
111
|
-
payload.logger.info(`— AI Plugin: Entry already exists for ${path}, using existing entry`);
|
|
112
|
-
}
|
|
113
|
-
} else {
|
|
114
|
-
payload.logger.error(err, `— AI Plugin: Error creating Compose settings for ${path}`);
|
|
115
|
-
}
|
|
116
|
-
} else {
|
|
117
|
-
payload.logger.error(err, `— AI Plugin: Error creating Compose settings for ${path}`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
104
|
+
instructions = await payload.create({
|
|
105
|
+
collection: PLUGIN_INSTRUCTIONS_TABLE,
|
|
106
|
+
data
|
|
107
|
+
}).catch((err)=>{
|
|
108
|
+
payload.logger.error(err, '— AI Plugin: Error creating Compose settings-');
|
|
109
|
+
});
|
|
120
110
|
if (instructions?.id) {
|
|
121
111
|
fieldInstructionsMap[path] = {
|
|
122
112
|
id: instructions.id,
|
|
@@ -124,17 +114,25 @@ export const init = async (payload, fieldSchemaPaths, pluginConfig)=>{
|
|
|
124
114
|
};
|
|
125
115
|
}
|
|
126
116
|
} else {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
payload.logger.warn(`— AI Plugin: Field
|
|
117
|
+
const modelForId = CAPABILITY_MAP.find((a)=>a.fields.includes(fieldType));
|
|
118
|
+
if (instructions['field-type'] !== fieldType || !instructions['model-id']) {
|
|
119
|
+
payload.logger.warn(`— AI Plugin: Field config mismatch for ${path}! Updating...`);
|
|
120
|
+
const updateData = {
|
|
121
|
+
'field-type': fieldType
|
|
122
|
+
};
|
|
123
|
+
// Only set model-id if it's missing or we have a better default
|
|
124
|
+
if (!instructions['model-id'] && modelForId?.id) {
|
|
125
|
+
updateData['model-id'] = modelForId.id;
|
|
126
|
+
}
|
|
130
127
|
await payload.update({
|
|
131
128
|
id: instructions.id,
|
|
132
129
|
collection: PLUGIN_INSTRUCTIONS_TABLE,
|
|
133
|
-
data:
|
|
134
|
-
'field-type': fieldType
|
|
135
|
-
}
|
|
130
|
+
data: updateData
|
|
136
131
|
});
|
|
137
132
|
instructions['field-type'] = fieldType;
|
|
133
|
+
if (updateData['model-id']) {
|
|
134
|
+
instructions['model-id'] = updateData['model-id'];
|
|
135
|
+
}
|
|
138
136
|
}
|
|
139
137
|
fieldInstructionsMap[path] = {
|
|
140
138
|
id: instructions.id,
|