@mvriu5/payload-ai 0.5.6 → 0.5.9
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/README.md +52 -5
- package/dist/ai/providerOptions.d.ts +1 -14
- package/dist/ai/providerOptions.js +0 -23
- package/dist/ai/providerRuntime.d.ts +3 -2
- package/dist/ai/providerRuntime.js +6 -15
- package/dist/components/AIActionProposalList.d.ts +2 -1
- package/dist/components/AIActionProposalList.js +74 -6
- package/dist/components/AIActionProposalList.module.css +49 -5
- package/dist/components/AIApiKeyField.js +0 -8
- package/dist/components/AIInput.d.ts +1 -1
- package/dist/components/AIInput.js +156 -23
- package/dist/components/AIInput.module.css +185 -147
- package/dist/components/CollectionMentionPopover.d.ts +1 -1
- package/dist/components/DiffDialog.d.ts +12 -0
- package/dist/components/DiffDialog.js +310 -0
- package/dist/components/DiffDialog.module.css +249 -0
- package/dist/components/Icons.d.ts +9 -0
- package/dist/components/Icons.js +266 -0
- package/dist/components/RecentChangesList.d.ts +18 -0
- package/dist/components/RecentChangesList.js +66 -0
- package/dist/components/RecentChangesList.module.css +135 -0
- package/dist/components/hooks/useAISettings.d.ts +1 -1
- package/dist/endpoints/aiApplyActionEndpointHandler.d.ts +3 -1
- package/dist/endpoints/aiApplyActionEndpointHandler.js +209 -8
- package/dist/endpoints/aiChatEndpointHandler.d.ts +5 -1
- package/dist/endpoints/aiChatEndpointHandler.js +106 -21
- package/dist/endpoints/aiMentionSuggestionsEndpointHandler.d.ts +2 -1
- package/dist/endpoints/aiMentionSuggestionsEndpointHandler.js +7 -7
- package/dist/endpoints/aiProposalDiffEndpointHandler.d.ts +7 -0
- package/dist/endpoints/aiProposalDiffEndpointHandler.js +138 -0
- package/dist/endpoints/aiRecentChangesEndpointHandler.d.ts +6 -0
- package/dist/endpoints/aiRecentChangesEndpointHandler.js +35 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +140 -18
- package/dist/payload/collectionPermissions.d.ts +22 -0
- package/dist/payload/collectionPermissions.js +68 -0
- package/dist/payload/schemaContext.d.ts +46 -2
- package/dist/payload/schemaContext.js +105 -14
- package/package.json +113 -121
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ AI assistant plugin for Payload CMS. It adds an admin dashboard assistant that c
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
npm add @mvriu5/payload-ai
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
@@ -30,7 +30,7 @@ The plugin adds two fields to the configured Payload admin user collection:
|
|
|
30
30
|
- `aiProvider`
|
|
31
31
|
- `aiApiKey`
|
|
32
32
|
|
|
33
|
-
Users can select their provider and store their own API key in account settings.
|
|
33
|
+
Users can select their provider and optionally store their own API key in account settings. If no account-level key is set, the chat endpoint uses provider environment variables.
|
|
34
34
|
|
|
35
35
|
## Options
|
|
36
36
|
|
|
@@ -38,8 +38,14 @@ Users can select their provider and store their own API key in account settings.
|
|
|
38
38
|
import type { PayloadAiPluginOptions } from "payload-ai-plugin";
|
|
39
39
|
|
|
40
40
|
const options: PayloadAiPluginOptions = {
|
|
41
|
+
allowUserApiKeys: false,
|
|
41
42
|
collections: {
|
|
42
|
-
posts:
|
|
43
|
+
posts: {
|
|
44
|
+
read: true,
|
|
45
|
+
create: true,
|
|
46
|
+
update: true,
|
|
47
|
+
delete: false,
|
|
48
|
+
},
|
|
43
49
|
},
|
|
44
50
|
models: {
|
|
45
51
|
defaults: {
|
|
@@ -59,22 +65,63 @@ const options: PayloadAiPluginOptions = {
|
|
|
59
65
|
|
|
60
66
|
Restricts AI read and write proposals to enabled collection slugs. If omitted, all non-internal Payload collections are available.
|
|
61
67
|
|
|
68
|
+
Use `true` to enable all AI actions for a collection:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
payloadAiPlugin({
|
|
72
|
+
collections: {
|
|
73
|
+
posts: true,
|
|
74
|
+
},
|
|
75
|
+
})
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Use granular permissions to control each action:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
payloadAiPlugin({
|
|
82
|
+
collections: {
|
|
83
|
+
posts: {
|
|
84
|
+
read: true,
|
|
85
|
+
create: true,
|
|
86
|
+
update: true,
|
|
87
|
+
delete: false,
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
})
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`read` controls schema/context access, document search, and mentions. `create`, `update`, and `delete` control AI action proposals and server-side apply permissions.
|
|
94
|
+
|
|
62
95
|
### `models`
|
|
63
96
|
|
|
64
97
|
Overrides the model list shown in the admin UI and the default model per provider.
|
|
65
98
|
|
|
99
|
+
### `allowUserApiKeys`
|
|
100
|
+
|
|
101
|
+
Controls whether the plugin adds an `aiApiKey` field to the admin user collection.
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
payloadAiPlugin({
|
|
105
|
+
allowUserApiKeys: false,
|
|
106
|
+
})
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
When disabled, users can still select an AI provider, but API keys must come from environment variables.
|
|
110
|
+
|
|
66
111
|
### `disabled`
|
|
67
112
|
|
|
68
113
|
Disables endpoint and UI registration while keeping the plugin call in your config.
|
|
69
114
|
|
|
70
115
|
## Provider Environment Variables
|
|
71
116
|
|
|
72
|
-
|
|
117
|
+
API key priority is:
|
|
118
|
+
|
|
119
|
+
1. account-level API key, unless `allowUserApiKeys: false`
|
|
120
|
+
2. provider environment variables
|
|
73
121
|
|
|
74
122
|
- `OPENAI_API_KEY`, `OPENAI_MODEL`
|
|
75
123
|
- `ANTHROPIC_API_KEY`, `ANTHROPIC_MODEL`
|
|
76
124
|
- `GOOGLE_GENERATIVE_AI_API_KEY`, `GOOGLE_GENERATIVE_AI_MODEL`
|
|
77
|
-
- `GROQ_API_KEY`, `GROQ_MODEL`
|
|
78
125
|
- `MISTRAL_API_KEY`, `MISTRAL_MODEL`
|
|
79
126
|
|
|
80
127
|
`PAYLOAD_SECRET` is required for signing AI action proposals.
|
|
@@ -26,19 +26,6 @@ declare const aiProviderModels: {
|
|
|
26
26
|
readonly label: "Gemini 2.5 Pro";
|
|
27
27
|
readonly value: "gemini-2.5-pro";
|
|
28
28
|
}];
|
|
29
|
-
readonly groq: readonly [{
|
|
30
|
-
readonly label: "Llama 3.3 70B Versatile";
|
|
31
|
-
readonly value: "llama-3.3-70b-versatile";
|
|
32
|
-
}, {
|
|
33
|
-
readonly label: "Llama 3.1 8B Instant";
|
|
34
|
-
readonly value: "llama-3.1-8b-instant";
|
|
35
|
-
}, {
|
|
36
|
-
readonly label: "GPT OSS 120B";
|
|
37
|
-
readonly value: "openai/gpt-oss-120b";
|
|
38
|
-
}, {
|
|
39
|
-
readonly label: "GPT OSS 20B";
|
|
40
|
-
readonly value: "openai/gpt-oss-20b";
|
|
41
|
-
}];
|
|
42
29
|
readonly mistral: readonly [{
|
|
43
30
|
readonly label: "Mistral Small";
|
|
44
31
|
readonly value: "mistral-small-latest";
|
|
@@ -78,7 +65,7 @@ export type AIModelConfig = {
|
|
|
78
65
|
providers?: Partial<Record<AIProvider, AIProviderModelOption[]>>;
|
|
79
66
|
};
|
|
80
67
|
export declare const getResolvedAIModelConfig: (modelConfig?: AIModelConfig) => {
|
|
81
|
-
defaults: Record<"claude" | "google" | "
|
|
68
|
+
defaults: Record<"claude" | "google" | "mistral" | "openai", string>;
|
|
82
69
|
providers: AIProviderModels;
|
|
83
70
|
};
|
|
84
71
|
export declare const isAIProvider: (provider: string) => provider is AIProvider;
|
|
@@ -31,24 +31,6 @@ const aiProviderModels = {
|
|
|
31
31
|
value: "gemini-2.5-pro"
|
|
32
32
|
}
|
|
33
33
|
],
|
|
34
|
-
groq: [
|
|
35
|
-
{
|
|
36
|
-
label: "Llama 3.3 70B Versatile",
|
|
37
|
-
value: "llama-3.3-70b-versatile"
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
label: "Llama 3.1 8B Instant",
|
|
41
|
-
value: "llama-3.1-8b-instant"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
label: "GPT OSS 120B",
|
|
45
|
-
value: "openai/gpt-oss-120b"
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
label: "GPT OSS 20B",
|
|
49
|
-
value: "openai/gpt-oss-20b"
|
|
50
|
-
}
|
|
51
|
-
],
|
|
52
34
|
mistral: [
|
|
53
35
|
{
|
|
54
36
|
label: "Mistral Small",
|
|
@@ -95,10 +77,6 @@ export const aiProviders = [
|
|
|
95
77
|
label: "Google Gemini",
|
|
96
78
|
value: "google"
|
|
97
79
|
},
|
|
98
|
-
{
|
|
99
|
-
label: "Groq",
|
|
100
|
-
value: "groq"
|
|
101
|
-
},
|
|
102
80
|
{
|
|
103
81
|
label: "Mistral",
|
|
104
82
|
value: "mistral"
|
|
@@ -111,7 +89,6 @@ export const aiProviders = [
|
|
|
111
89
|
export const defaultAIModels = {
|
|
112
90
|
claude: aiProviderModels.claude[0].value,
|
|
113
91
|
google: aiProviderModels.google[0].value,
|
|
114
|
-
groq: aiProviderModels.groq[0].value,
|
|
115
92
|
mistral: aiProviderModels.mistral[0].value,
|
|
116
93
|
openai: aiProviderModels.openai[0].value
|
|
117
94
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { LanguageModel } from "ai";
|
|
2
|
-
import { type AIProvider } from "./providerOptions.js";
|
|
2
|
+
import { type AIProvider, type AIModelConfig } from "./providerOptions.js";
|
|
3
3
|
type ProviderConfig = {
|
|
4
4
|
apiKey?: string | null;
|
|
5
|
+
defaultModels?: AIModelConfig["defaults"];
|
|
5
6
|
model?: string | null;
|
|
6
7
|
provider: AIProvider;
|
|
7
8
|
};
|
|
@@ -10,7 +11,7 @@ type ModelConfig = {
|
|
|
10
11
|
model: string;
|
|
11
12
|
provider: AIProvider;
|
|
12
13
|
};
|
|
13
|
-
export declare const getProviderConfig: ({ apiKey, model, provider, }: ProviderConfig) => {
|
|
14
|
+
export declare const getProviderConfig: ({ apiKey, defaultModels, model, provider, }: ProviderConfig) => {
|
|
14
15
|
apiKey: string | undefined;
|
|
15
16
|
modelID: string;
|
|
16
17
|
};
|
|
@@ -1,37 +1,31 @@
|
|
|
1
1
|
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
2
2
|
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
3
|
-
import { createGroq } from "@ai-sdk/groq";
|
|
4
3
|
import { createMistral } from "@ai-sdk/mistral";
|
|
5
4
|
import { createOpenAI } from "@ai-sdk/openai";
|
|
6
5
|
import { defaultAIModels } from "./providerOptions.js";
|
|
7
|
-
export const getProviderConfig = ({ apiKey, model, provider })=>{
|
|
6
|
+
export const getProviderConfig = ({ apiKey, defaultModels, model, provider })=>{
|
|
7
|
+
const defaultModel = defaultModels?.[provider] || defaultAIModels[provider];
|
|
8
8
|
if (provider === "claude") {
|
|
9
9
|
return {
|
|
10
10
|
apiKey: apiKey || process.env.ANTHROPIC_API_KEY,
|
|
11
|
-
modelID: model || process.env.ANTHROPIC_MODEL ||
|
|
11
|
+
modelID: model || process.env.ANTHROPIC_MODEL || defaultModel
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
14
|
if (provider === "google") {
|
|
15
15
|
return {
|
|
16
16
|
apiKey: apiKey || process.env.GOOGLE_GENERATIVE_AI_API_KEY,
|
|
17
|
-
modelID: model || process.env.GOOGLE_GENERATIVE_AI_MODEL ||
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
if (provider === "groq") {
|
|
21
|
-
return {
|
|
22
|
-
apiKey: apiKey || process.env.GROQ_API_KEY,
|
|
23
|
-
modelID: model || process.env.GROQ_MODEL || defaultAIModels.groq
|
|
17
|
+
modelID: model || process.env.GOOGLE_GENERATIVE_AI_MODEL || defaultModel
|
|
24
18
|
};
|
|
25
19
|
}
|
|
26
20
|
if (provider === "mistral") {
|
|
27
21
|
return {
|
|
28
22
|
apiKey: apiKey || process.env.MISTRAL_API_KEY,
|
|
29
|
-
modelID: model || process.env.MISTRAL_MODEL ||
|
|
23
|
+
modelID: model || process.env.MISTRAL_MODEL || defaultModel
|
|
30
24
|
};
|
|
31
25
|
}
|
|
32
26
|
return {
|
|
33
27
|
apiKey: apiKey || process.env.OPENAI_API_KEY,
|
|
34
|
-
modelID: model || process.env.OPENAI_MODEL ||
|
|
28
|
+
modelID: model || process.env.OPENAI_MODEL || defaultModel
|
|
35
29
|
};
|
|
36
30
|
};
|
|
37
31
|
export const getModel = ({ apiKey, model, provider })=>{
|
|
@@ -41,9 +35,6 @@ export const getModel = ({ apiKey, model, provider })=>{
|
|
|
41
35
|
if (provider === "google") return createGoogleGenerativeAI({
|
|
42
36
|
apiKey
|
|
43
37
|
})(model);
|
|
44
|
-
if (provider === "groq") return createGroq({
|
|
45
|
-
apiKey
|
|
46
|
-
})(model);
|
|
47
38
|
if (provider === "mistral") return createMistral({
|
|
48
39
|
apiKey
|
|
49
40
|
})(model);
|
|
@@ -11,6 +11,7 @@ export type AIActionProposal = {
|
|
|
11
11
|
slug?: string;
|
|
12
12
|
};
|
|
13
13
|
type AIActionProposalListProps = {
|
|
14
|
+
apiRoute: string;
|
|
14
15
|
appliedProposalIndexes: number[];
|
|
15
16
|
description?: string;
|
|
16
17
|
error?: string;
|
|
@@ -21,5 +22,5 @@ type AIActionProposalListProps = {
|
|
|
21
22
|
onApply: (proposal: AIActionProposal, index: number) => void;
|
|
22
23
|
proposals: AIActionProposal[];
|
|
23
24
|
};
|
|
24
|
-
export declare const AIActionProposalList: ({ appliedProposalIndexes, description, error, getViewURL, isApplying, onDismiss, onDismissError, onApply, proposals
|
|
25
|
+
export declare const AIActionProposalList: ({ apiRoute, appliedProposalIndexes, description, error, getViewURL, isApplying, onDismiss, onDismissError, onApply, proposals }: AIActionProposalListProps) => import("react").JSX.Element | null;
|
|
25
26
|
export {};
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import styles from "./AIActionProposalList.module.css";
|
|
2
2
|
import { redactSensitiveData } from "../ai/sensitiveData.js";
|
|
3
|
+
import { formatAdminURL } from "payload/shared";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
import { DiffDialog } from "./DiffDialog.js";
|
|
6
|
+
import { Apply, FileDiff, Reject } from "./Icons.js";
|
|
3
7
|
const maxDescriptionLength = 220;
|
|
4
8
|
const getDescriptionPreview = (description)=>{
|
|
5
9
|
if (description.length <= maxDescriptionLength) return description;
|
|
@@ -15,10 +19,46 @@ const getSafeProposalDetails = (proposal)=>{
|
|
|
15
19
|
}
|
|
16
20
|
return redactedProposal;
|
|
17
21
|
};
|
|
18
|
-
export const AIActionProposalList = ({ appliedProposalIndexes, description, error, getViewURL, isApplying, onDismiss, onDismissError, onApply, proposals })=>{
|
|
22
|
+
export const AIActionProposalList = ({ apiRoute, appliedProposalIndexes, description, error, getViewURL, isApplying, onDismiss, onDismissError, onApply, proposals })=>{
|
|
23
|
+
const [activeDiff, setActiveDiff] = useState(null);
|
|
24
|
+
const [diffError, setDiffError] = useState("");
|
|
25
|
+
const [loadingDiffIndex, setLoadingDiffIndex] = useState(null);
|
|
19
26
|
if (proposals.length === 0 && !error && !description) return null;
|
|
20
27
|
const descriptionPreview = description ? getDescriptionPreview(description) : "";
|
|
21
28
|
const isDescriptionTruncated = Boolean(description) && descriptionPreview !== description;
|
|
29
|
+
const openDiff = async (proposal, index)=>{
|
|
30
|
+
setDiffError("");
|
|
31
|
+
setLoadingDiffIndex(index);
|
|
32
|
+
try {
|
|
33
|
+
const res = await fetch(formatAdminURL({
|
|
34
|
+
apiRoute,
|
|
35
|
+
path: "/ai-proposal-diff"
|
|
36
|
+
}), {
|
|
37
|
+
body: JSON.stringify({
|
|
38
|
+
proposal
|
|
39
|
+
}),
|
|
40
|
+
headers: {
|
|
41
|
+
"Content-Type": "application/json"
|
|
42
|
+
},
|
|
43
|
+
method: "POST"
|
|
44
|
+
});
|
|
45
|
+
const result = await res.json().catch(()=>null);
|
|
46
|
+
if (!res.ok || !result) {
|
|
47
|
+
throw new Error(result?.error || "Could not load proposal diff.");
|
|
48
|
+
}
|
|
49
|
+
setActiveDiff({
|
|
50
|
+
diff: {
|
|
51
|
+
after: result.after,
|
|
52
|
+
before: result.before
|
|
53
|
+
},
|
|
54
|
+
proposal
|
|
55
|
+
});
|
|
56
|
+
} catch (err) {
|
|
57
|
+
setDiffError(err instanceof Error ? err.message : "Could not load proposal diff.");
|
|
58
|
+
} finally{
|
|
59
|
+
setLoadingDiffIndex(null);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
22
62
|
return /*#__PURE__*/ React.createElement("div", {
|
|
23
63
|
className: styles.list
|
|
24
64
|
}, error && /*#__PURE__*/ React.createElement("div", {
|
|
@@ -73,22 +113,50 @@ export const AIActionProposalList = ({ appliedProposalIndexes, description, erro
|
|
|
73
113
|
className: styles.footer
|
|
74
114
|
}, /*#__PURE__*/ React.createElement("div", {
|
|
75
115
|
className: styles.viewAction
|
|
76
|
-
},
|
|
116
|
+
}, /*#__PURE__*/ React.createElement("button", {
|
|
77
117
|
className: styles.secondaryButton,
|
|
118
|
+
disabled: loadingDiffIndex === index,
|
|
119
|
+
onClick: ()=>void openDiff(proposal, index),
|
|
120
|
+
type: "button"
|
|
121
|
+
}, /*#__PURE__*/ React.createElement(FileDiff, {
|
|
122
|
+
height: 16,
|
|
123
|
+
width: 16
|
|
124
|
+
}), loadingDiffIndex === index ? "Loading" : "Review"), viewURL && /*#__PURE__*/ React.createElement("a", {
|
|
125
|
+
className: styles.ghostButton,
|
|
78
126
|
href: viewURL,
|
|
79
127
|
rel: "noreferrer noopener",
|
|
80
128
|
target: "_blank"
|
|
81
|
-
}, "
|
|
129
|
+
}, "Go to source")), /*#__PURE__*/ React.createElement("div", {
|
|
82
130
|
className: styles.actions
|
|
83
131
|
}, onDismiss && /*#__PURE__*/ React.createElement("button", {
|
|
84
132
|
className: styles.secondaryButton,
|
|
85
133
|
onClick: onDismiss,
|
|
86
134
|
type: "button"
|
|
87
|
-
},
|
|
135
|
+
}, /*#__PURE__*/ React.createElement(Reject, {
|
|
136
|
+
height: 16,
|
|
137
|
+
width: 16
|
|
138
|
+
})), /*#__PURE__*/ React.createElement("button", {
|
|
88
139
|
className: styles.button,
|
|
89
140
|
disabled: isApplying || isApplied,
|
|
90
141
|
onClick: ()=>onApply(proposal, index),
|
|
91
142
|
type: "button"
|
|
92
|
-
},
|
|
93
|
-
|
|
143
|
+
}, /*#__PURE__*/ React.createElement(Apply, {
|
|
144
|
+
height: 16,
|
|
145
|
+
width: 16
|
|
146
|
+
})))));
|
|
147
|
+
}), diffError ? /*#__PURE__*/ React.createElement("div", {
|
|
148
|
+
className: `${styles.item} ${styles.errorItem}`
|
|
149
|
+
}, /*#__PURE__*/ React.createElement("div", null, /*#__PURE__*/ React.createElement("div", {
|
|
150
|
+
className: styles.label
|
|
151
|
+
}, "Diff review failed"), /*#__PURE__*/ React.createElement("div", {
|
|
152
|
+
className: styles.description
|
|
153
|
+
}, diffError)), /*#__PURE__*/ React.createElement("button", {
|
|
154
|
+
className: styles.button,
|
|
155
|
+
onClick: ()=>setDiffError(""),
|
|
156
|
+
type: "button"
|
|
157
|
+
}, "Dismiss")) : null, activeDiff ? /*#__PURE__*/ React.createElement(DiffDialog, {
|
|
158
|
+
diff: activeDiff.diff,
|
|
159
|
+
onClose: ()=>setActiveDiff(null),
|
|
160
|
+
proposal: activeDiff.proposal
|
|
161
|
+
}) : null);
|
|
94
162
|
};
|
|
@@ -94,6 +94,7 @@
|
|
|
94
94
|
.viewAction {
|
|
95
95
|
align-items: center;
|
|
96
96
|
display: flex;
|
|
97
|
+
gap: 8px;
|
|
97
98
|
min-width: 0;
|
|
98
99
|
}
|
|
99
100
|
|
|
@@ -106,37 +107,74 @@
|
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
.button {
|
|
110
|
+
align-items: center;
|
|
109
111
|
background: var(--theme-text);
|
|
110
112
|
border: 0;
|
|
111
113
|
border-radius: 4px;
|
|
112
114
|
color: var(--theme-bg);
|
|
113
115
|
cursor: pointer;
|
|
116
|
+
display: inline-flex;
|
|
114
117
|
flex: 0 0 auto;
|
|
115
118
|
font: inherit;
|
|
116
|
-
|
|
119
|
+
gap: 6px;
|
|
120
|
+
justify-content: center;
|
|
121
|
+
line-height: 24px;
|
|
122
|
+
min-height: 24px;
|
|
117
123
|
padding: 0 14px;
|
|
118
124
|
}
|
|
119
125
|
|
|
120
126
|
.secondaryButton {
|
|
127
|
+
align-items: center;
|
|
121
128
|
background: transparent;
|
|
122
129
|
border: 1px solid var(--theme-elevation-150);
|
|
123
130
|
border-radius: 4px;
|
|
124
131
|
color: var(--theme-text);
|
|
125
132
|
cursor: pointer;
|
|
133
|
+
display: inline-flex;
|
|
126
134
|
flex: 0 0 auto;
|
|
127
135
|
font: inherit;
|
|
128
|
-
|
|
129
|
-
|
|
136
|
+
gap: 6px;
|
|
137
|
+
justify-content: center;
|
|
138
|
+
line-height: 24px;
|
|
139
|
+
min-height: 24px;
|
|
130
140
|
padding: 0 14px;
|
|
131
141
|
text-decoration: none;
|
|
132
142
|
}
|
|
133
143
|
|
|
144
|
+
.secondaryButton svg {
|
|
145
|
+
color: var(--theme-elevation-500);
|
|
146
|
+
flex: 0 0 auto;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.button svg {
|
|
150
|
+
flex: 0 0 auto;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.ghostButton {
|
|
154
|
+
background: transparent;
|
|
155
|
+
border: 0;
|
|
156
|
+
border-radius: 4px;
|
|
157
|
+
color: var(--theme-elevation-600);
|
|
158
|
+
cursor: pointer;
|
|
159
|
+
flex: 0 0 auto;
|
|
160
|
+
font: inherit;
|
|
161
|
+
line-height: 24px;
|
|
162
|
+
min-height: 24px;
|
|
163
|
+
padding: 0 10px;
|
|
164
|
+
text-decoration: none;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.ghostButton:hover {
|
|
168
|
+
text-decoration: underline;
|
|
169
|
+
}
|
|
170
|
+
|
|
134
171
|
.button:disabled {
|
|
135
172
|
cursor: not-allowed;
|
|
136
173
|
opacity: 0.45;
|
|
137
174
|
}
|
|
138
175
|
|
|
139
|
-
.secondaryButton:disabled
|
|
176
|
+
.secondaryButton:disabled,
|
|
177
|
+
.ghostButton:disabled {
|
|
140
178
|
cursor: not-allowed;
|
|
141
179
|
opacity: 0.45;
|
|
142
180
|
}
|
|
@@ -163,13 +201,19 @@
|
|
|
163
201
|
flex-direction: column;
|
|
164
202
|
}
|
|
165
203
|
|
|
204
|
+
.viewAction {
|
|
205
|
+
align-self: stretch;
|
|
206
|
+
flex-direction: column;
|
|
207
|
+
}
|
|
208
|
+
|
|
166
209
|
.footer {
|
|
167
210
|
align-items: stretch;
|
|
168
211
|
flex-direction: column;
|
|
169
212
|
}
|
|
170
213
|
|
|
171
214
|
.button,
|
|
172
|
-
.secondaryButton
|
|
215
|
+
.secondaryButton,
|
|
216
|
+
.ghostButton {
|
|
173
217
|
width: 100%;
|
|
174
218
|
}
|
|
175
219
|
}
|
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useField } from "@payloadcms/ui";
|
|
3
|
-
const getLabel = (label, fallback)=>{
|
|
4
|
-
if (typeof label === "string") return label;
|
|
5
|
-
if (label && typeof label === "object") {
|
|
6
|
-
const firstLabel = Object.values(label)[0];
|
|
7
|
-
if (typeof firstLabel === "string") return firstLabel;
|
|
8
|
-
}
|
|
9
|
-
return fallback;
|
|
10
|
-
};
|
|
11
3
|
const getFieldClassName = ({ className, isReadOnly, showError })=>[
|
|
12
4
|
"field-type",
|
|
13
5
|
"password",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AIInput: () => import("react
|
|
1
|
+
export declare const AIInput: () => import("react").JSX.Element;
|