@mvriu5/payload-ai 0.5.8 → 0.5.10

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.
Files changed (65) hide show
  1. package/README.md +62 -6
  2. package/dist/ai/{proposals.d.ts → proposalSigning.d.ts} +1 -1
  3. package/dist/ai/{proposals.js → proposalSigning.js} +6 -11
  4. package/dist/ai/providerOptions.d.ts +17 -1
  5. package/dist/ai/providerOptions.js +35 -7
  6. package/dist/ai/providerRuntime.d.ts +2 -2
  7. package/dist/ai/providerRuntime.js +50 -16
  8. package/dist/ai/sensitiveData.js +2 -6
  9. package/dist/components/AIInput.d.ts +2 -1
  10. package/dist/components/AIInput.js +327 -41
  11. package/dist/components/AIInput.module.css +41 -6
  12. package/dist/components/APIKeyField.d.ts +3 -0
  13. package/dist/components/{AIApiKeyField.js → APIKeyField.js} +3 -4
  14. package/dist/components/ActionToast.d.ts +30 -0
  15. package/dist/components/{AIActionProposalList.js → ActionToast.js} +78 -8
  16. package/dist/components/{AIActionProposalList.module.css → ActionToast.module.css} +49 -5
  17. package/dist/components/AuditLogList.d.ts +32 -0
  18. package/dist/components/AuditLogList.js +67 -0
  19. package/dist/components/AuditLogList.module.css +152 -0
  20. package/dist/components/DiffDialog.d.ts +19 -0
  21. package/dist/components/DiffDialog.js +396 -0
  22. package/dist/components/DiffDialog.module.css +333 -0
  23. package/dist/components/Icons.d.ts +9 -0
  24. package/dist/components/Icons.js +193 -0
  25. package/dist/components/MentionPopover.d.ts +19 -0
  26. package/dist/components/{CollectionMentionPopover.js → MentionPopover.js} +11 -4
  27. package/dist/components/{CollectionMentionPopover.module.css → MentionPopover.module.css} +0 -2
  28. package/dist/components/hooks/useAISettings.d.ts +6 -4
  29. package/dist/components/hooks/useAISettings.js +18 -3
  30. package/dist/components/hooks/useDocumentMentionSuggestions.d.ts +3 -3
  31. package/dist/components/hooks/useDocumentMentionSuggestions.js +2 -2
  32. package/dist/exports/client.d.ts +4 -2
  33. package/dist/exports/client.js +4 -2
  34. package/dist/handlers/applyActionHandler.d.ts +8 -0
  35. package/dist/handlers/applyActionHandler.js +563 -0
  36. package/dist/handlers/auditLogHandler.d.ts +6 -0
  37. package/dist/handlers/auditLogHandler.js +39 -0
  38. package/dist/handlers/chatHandler.d.ts +42 -0
  39. package/dist/handlers/chatHandler.js +634 -0
  40. package/dist/handlers/mentionSuggestionHandler.d.ts +7 -0
  41. package/dist/handlers/mentionSuggestionHandler.js +97 -0
  42. package/dist/handlers/proposalDiffHandler.d.ts +7 -0
  43. package/dist/handlers/proposalDiffHandler.js +208 -0
  44. package/dist/index.d.ts +6 -6
  45. package/dist/index.js +151 -8
  46. package/dist/payload/collectionPermissions.d.ts +14 -13
  47. package/dist/payload/collectionPermissions.js +3 -2
  48. package/dist/payload/normalizeData.d.ts +8 -0
  49. package/dist/payload/normalizeData.js +25 -3
  50. package/dist/payload/schemaContext.d.ts +79 -9
  51. package/dist/payload/schemaContext.js +231 -22
  52. package/dist/payload/shared.d.ts +33 -0
  53. package/dist/payload/shared.js +114 -0
  54. package/package.json +7 -2
  55. package/dist/components/AIActionProposalList.d.ts +0 -25
  56. package/dist/components/AIApiKeyField.d.ts +0 -2
  57. package/dist/components/CollectionMentionPopover.d.ts +0 -16
  58. package/dist/components/hooks/utils.d.ts +0 -1
  59. package/dist/components/hooks/utils.js +0 -3
  60. package/dist/endpoints/aiApplyActionEndpointHandler.d.ts +0 -7
  61. package/dist/endpoints/aiApplyActionEndpointHandler.js +0 -169
  62. package/dist/endpoints/aiChatEndpointHandler.d.ts +0 -35
  63. package/dist/endpoints/aiChatEndpointHandler.js +0 -321
  64. package/dist/endpoints/aiMentionSuggestionsEndpointHandler.d.ts +0 -7
  65. package/dist/endpoints/aiMentionSuggestionsEndpointHandler.js +0 -63
@@ -0,0 +1,333 @@
1
+ .dialogOverlay {
2
+ align-items: center;
3
+ background: rgba(0, 0, 0, 0.42);
4
+ display: flex;
5
+ inset: 0;
6
+ justify-content: center;
7
+ overflow: auto;
8
+ padding: 24px;
9
+ position: fixed;
10
+ z-index: 1100;
11
+ }
12
+
13
+ .dialog {
14
+ background: var(--theme-bg);
15
+ border: 1px solid var(--theme-elevation-150);
16
+ border-radius: 6px;
17
+ box-shadow: 0 20px 64px rgba(0, 0, 0, 0.26);
18
+ display: flex;
19
+ flex-direction: column;
20
+ gap: 16px;
21
+ max-height: min(760px, calc(100vh - 48px));
22
+ max-width: min(1120px, calc(100vw - 48px));
23
+ min-height: 0;
24
+ overflow: hidden;
25
+ padding: 16px;
26
+ width: 100%;
27
+ }
28
+
29
+ .dialogContent {
30
+ display: flex;
31
+ flex: 1 1 auto;
32
+ flex-direction: column;
33
+ gap: 16px;
34
+ min-height: 0;
35
+ overflow: auto;
36
+ }
37
+
38
+ .dialogHeader {
39
+ align-items: flex-start;
40
+ display: flex;
41
+ gap: 12px;
42
+ justify-content: space-between;
43
+ }
44
+
45
+ .dialogTitle {
46
+ color: var(--theme-text);
47
+ font-size: 14px;
48
+ font-weight: 600;
49
+ line-height: 1.4;
50
+ }
51
+
52
+ .meta {
53
+ color: var(--theme-elevation-600);
54
+ font-size: 12px;
55
+ line-height: 1.4;
56
+ margin-top: 2px;
57
+ }
58
+
59
+ .detailSection {
60
+ display: flex;
61
+ flex: 0 0 auto;
62
+ flex-direction: column;
63
+ gap: 10px;
64
+ }
65
+
66
+ .detailGrid {
67
+ column-gap: 12px;
68
+ display: grid;
69
+ grid-template-columns: max-content minmax(0, 1fr);
70
+ row-gap: 4px;
71
+ }
72
+
73
+ .detailLabel {
74
+ color: var(--theme-elevation-600);
75
+ font-size: 11px;
76
+ line-height: 1.2;
77
+ }
78
+
79
+ .detailValue {
80
+ color: var(--theme-text);
81
+ font-size: 12px;
82
+ line-height: 1.4;
83
+ min-width: 0;
84
+ overflow: hidden;
85
+ text-overflow: ellipsis;
86
+ white-space: nowrap;
87
+ }
88
+
89
+ .detailTextBlock {
90
+ display: flex;
91
+ flex-direction: column;
92
+ gap: 4px;
93
+ }
94
+
95
+ .detailText {
96
+ background: var(--theme-elevation-50);
97
+ border: 1px solid var(--theme-elevation-100);
98
+ border-radius: 4px;
99
+ color: var(--theme-text);
100
+ font-family: inherit;
101
+ font-size: 12px;
102
+ line-height: 1.5;
103
+ margin: 0;
104
+ max-height: 140px;
105
+ overflow: auto;
106
+ padding: 8px 10px;
107
+ white-space: pre-wrap;
108
+ word-break: break-word;
109
+ }
110
+
111
+ .closeButton {
112
+ align-items: center;
113
+ background: transparent;
114
+ border: 1px solid var(--theme-elevation-150);
115
+ border-radius: 4px;
116
+ color: var(--theme-text);
117
+ cursor: pointer;
118
+ display: inline-flex;
119
+ flex: 0 0 auto;
120
+ font: inherit;
121
+ height: 24px;
122
+ justify-content: center;
123
+ line-height: 24px;
124
+ min-height: 24px;
125
+ padding: 0;
126
+ text-decoration: none;
127
+ width: 24px;
128
+ }
129
+
130
+ .closeButton svg {
131
+ height: 12px;
132
+ width: 12px;
133
+ }
134
+
135
+ .diffShell {
136
+ border: 1px solid var(--theme-elevation-150);
137
+ border-radius: 0;
138
+ display: flex;
139
+ flex: 1 1 auto;
140
+ flex-direction: column;
141
+ min-height: 0;
142
+ min-width: 0;
143
+ overflow: hidden;
144
+ }
145
+
146
+ .diffSection {
147
+ display: flex;
148
+ flex: 0 0 calc(100% - 1px);
149
+ flex-direction: column;
150
+ gap: 6px;
151
+ min-height: calc(100% - 1px);
152
+ }
153
+
154
+ .diffSectionLabel {
155
+ color: var(--theme-elevation-700);
156
+ font-size: 12px;
157
+ font-weight: 600;
158
+ line-height: 1.3;
159
+ }
160
+
161
+ .diffHeaderGrid {
162
+ display: grid;
163
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
164
+ min-width: 100%;
165
+ position: sticky;
166
+ top: 0;
167
+ z-index: 1;
168
+ }
169
+
170
+ .diffPaneHeader {
171
+ background: var(--theme-elevation-50);
172
+ border-bottom: 1px solid var(--theme-elevation-150);
173
+ color: var(--theme-elevation-700);
174
+ font-size: 12px;
175
+ font-weight: 600;
176
+ line-height: 1.4;
177
+ min-width: 0;
178
+ overflow: hidden;
179
+ padding: 8px 10px;
180
+ }
181
+
182
+ .diffPaneHeader + .diffPaneHeader {
183
+ border-left: 1px solid var(--theme-elevation-150);
184
+ }
185
+
186
+ .diffScroll {
187
+ background: var(--theme-elevation-50);
188
+ color: var(--theme-text);
189
+ flex: 1 1 auto;
190
+ font-size: 12px;
191
+ line-height: 1.5;
192
+ min-height: 0;
193
+ overflow-x: hidden;
194
+ overflow-y: auto;
195
+ }
196
+
197
+ .diffRows {
198
+ display: grid;
199
+ font-family: monospace;
200
+ min-width: 100%;
201
+ padding: 0;
202
+ }
203
+
204
+ .diffRow {
205
+ display: grid;
206
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
207
+ min-width: 100%;
208
+ }
209
+
210
+ .diffLine {
211
+ display: block;
212
+ min-height: 18px;
213
+ min-width: 0;
214
+ overflow: hidden;
215
+ padding: 0;
216
+ text-overflow: clip;
217
+ white-space: pre;
218
+ }
219
+
220
+ .diffPathBadge {
221
+ background: rgba(255, 255, 255, 0.08);
222
+ border: 1px solid rgba(255, 255, 255, 0.16);
223
+ border-radius: 3px;
224
+ color: var(--theme-elevation-700);
225
+ display: block;
226
+ font-family: monospace;
227
+ font-size: 11px;
228
+ line-height: 18px;
229
+ margin: 2px 6px 1px;
230
+ max-width: calc(100% - 12px);
231
+ overflow: hidden;
232
+ padding: 0 6px;
233
+ text-overflow: ellipsis;
234
+ white-space: nowrap;
235
+ }
236
+
237
+ .diffLineContent {
238
+ display: inline-block;
239
+ min-width: var(--diff-line-width);
240
+ transform: translateX(var(--diff-line-offset));
241
+ }
242
+
243
+ .diffLine + .diffLine {
244
+ box-shadow: inset 1px 0 0 var(--theme-elevation-150);
245
+ }
246
+
247
+ .diffLineAdded {
248
+ background: rgba(39, 132, 90, 0.28);
249
+ border-left: 3px solid rgba(39, 132, 90, 0.92);
250
+ }
251
+
252
+ .diffLineRemoved {
253
+ background: rgba(160, 26, 26, 0.28);
254
+ border-left: 3px solid rgba(136, 18, 18, 0.96);
255
+ }
256
+
257
+ .diffLinePlaceholder {
258
+ background: var(--theme-elevation-50);
259
+ }
260
+
261
+ .diffCollapsedRow {
262
+ align-items: center;
263
+ background: var(--theme-elevation-100);
264
+ border: 0;
265
+ border-bottom: 1px solid var(--theme-elevation-150);
266
+ border-top: 1px solid var(--theme-elevation-150);
267
+ color: var(--theme-elevation-600);
268
+ cursor: pointer;
269
+ display: flex;
270
+ font: inherit;
271
+ font-family: monospace;
272
+ font-size: 12px;
273
+ gap: 8px;
274
+ grid-column: 1 / -1;
275
+ justify-content: center;
276
+ line-height: 24px;
277
+ min-height: 24px;
278
+ padding: 0 10px;
279
+ }
280
+
281
+ .diffCollapsedRow:hover {
282
+ background: var(--theme-elevation-150);
283
+ }
284
+
285
+ .diffCollapsedPath {
286
+ color: var(--theme-elevation-500);
287
+ min-width: 0;
288
+ overflow: hidden;
289
+ text-overflow: ellipsis;
290
+ white-space: nowrap;
291
+ }
292
+
293
+ .horizontalScroll {
294
+ flex: 0 0 auto;
295
+ height: 16px;
296
+ overflow-x: auto;
297
+ overflow-y: hidden;
298
+ }
299
+
300
+ .horizontalScrollSpacer {
301
+ height: 1px;
302
+ min-width: 100%;
303
+ width: calc(50% + var(--diff-line-width));
304
+ }
305
+
306
+ @media (max-width: 768px) {
307
+ .dialogOverlay {
308
+ padding: 12px;
309
+ }
310
+
311
+ .dialog {
312
+ max-height: calc(100vh - 24px);
313
+ max-width: calc(100vw - 24px);
314
+ }
315
+
316
+ .dialogHeader {
317
+ align-items: stretch;
318
+ flex-direction: column;
319
+ }
320
+
321
+ .detailGrid {
322
+ grid-template-columns: minmax(0, 1fr);
323
+ }
324
+
325
+ .closeButton {
326
+ align-self: flex-end;
327
+ }
328
+
329
+ .diffScroll {
330
+ min-height: 0;
331
+ }
332
+
333
+ }
@@ -3,3 +3,12 @@ export declare function MistralAiIcon(props: SVGProps<SVGSVGElement>): import("r
3
3
  export declare function OpenaiIcon(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
4
4
  export declare function ClaudeIcon(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
5
5
  export declare function GoogleGeminiIcon(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
6
+ export declare function OpenrouterIcon(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
7
+ export declare function FileDiff(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
8
+ export declare function Send(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
9
+ export declare function Apply(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
10
+ export declare function Reject(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
11
+ export declare function Collection(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
12
+ export declare function Document(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
13
+ export declare function Global(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
14
+ export declare function Block(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
@@ -51,6 +51,8 @@ export function OpenaiIcon(props) {
51
51
  return /*#__PURE__*/ React.createElement("svg", {
52
52
  xmlns: "http://www.w3.org/2000/svg",
53
53
  viewBox: "0 0 256 260",
54
+ fill: "currentColor",
55
+ stroke: "currentColor",
54
56
  ...props
55
57
  }, /*#__PURE__*/ React.createElement("path", {
56
58
  d: "M239.184 106.203a64.72 64.72 0 0 0-5.576-53.103C219.452 28.459 191 15.784 163.213 21.74A65.586 65.586 0 0 0 52.096 45.22a64.72 64.72 0 0 0-43.23 31.36c-14.31 24.602-11.061 55.634 8.033 76.74a64.67 64.67 0 0 0 5.525 53.102c14.174 24.65 42.644 37.324 70.446 31.36a64.72 64.72 0 0 0 48.754 21.744c28.481.025 53.714-18.361 62.414-45.481a64.77 64.77 0 0 0 43.229-31.36c14.137-24.558 10.875-55.423-8.083-76.483m-97.56 136.338a48.4 48.4 0 0 1-31.105-11.255l1.535-.87l51.67-29.825a8.6 8.6 0 0 0 4.247-7.367v-72.85l21.845 12.636c.218.111.37.32.409.563v60.367c-.056 26.818-21.783 48.545-48.601 48.601M37.158 197.93a48.35 48.35 0 0 1-5.781-32.589l1.534.921l51.722 29.826a8.34 8.34 0 0 0 8.441 0l63.181-36.425v25.221a.87.87 0 0 1-.358.665l-52.335 30.184c-23.257 13.398-52.97 5.431-66.404-17.803M23.549 85.38a48.5 48.5 0 0 1 25.58-21.333v61.39a8.29 8.29 0 0 0 4.195 7.316l62.874 36.272l-21.845 12.636a.82.82 0 0 1-.767 0L41.353 151.53c-23.211-13.454-31.171-43.144-17.804-66.405zm179.466 41.695l-63.08-36.63L161.73 77.86a.82.82 0 0 1 .768 0l52.233 30.184a48.6 48.6 0 0 1-7.316 87.635v-61.391a8.54 8.54 0 0 0-4.4-7.213m21.742-32.69l-1.535-.922l-51.619-30.081a8.39 8.39 0 0 0-8.492 0L99.98 99.808V74.587a.72.72 0 0 1 .307-.665l52.233-30.133a48.652 48.652 0 0 1 72.236 50.391zM88.061 139.097l-21.845-12.585a.87.87 0 0 1-.41-.614V65.685a48.652 48.652 0 0 1 79.757-37.346l-1.535.87l-51.67 29.825a8.6 8.6 0 0 0-4.246 7.367zm11.868-25.58L128.067 97.3l28.188 16.218v32.434l-28.086 16.218l-28.188-16.218z"
@@ -177,3 +179,194 @@ export function GoogleGeminiIcon(props) {
177
179
  d: "M348.374 72.76c-2.846-18.788-17.592-33.533-36.38-36.38c18.788-2.847 33.534-17.593 36.38-36.38c2.847 18.787 17.593 33.533 36.38 36.38c-18.787 2.847-33.533 17.592-36.38 36.38"
178
180
  }));
179
181
  }
182
+ export function OpenrouterIcon(props) {
183
+ return /*#__PURE__*/ React.createElement("svg", {
184
+ xmlns: "http://www.w3.org/2000/svg",
185
+ width: "512",
186
+ height: "512",
187
+ viewBox: "0 0 512 512",
188
+ fill: "currentColor",
189
+ stroke: "currentColor",
190
+ ...props
191
+ }, /*#__PURE__*/ React.createElement("g", {
192
+ clipPath: "url(#clip0_205_3)"
193
+ }, /*#__PURE__*/ React.createElement("path", {
194
+ d: "M3 248.945C18 248.945 76 236 106 219C136 202 136 202 198 158C276.497 102.293 332 120.945 423 120.945",
195
+ strokeWidth: "90"
196
+ }), /*#__PURE__*/ React.createElement("path", {
197
+ d: "M511 121.5L357.25 210.268L357.25 32.7324L511 121.5Z"
198
+ }), /*#__PURE__*/ React.createElement("path", {
199
+ d: "M0 249C15 249 73 261.945 103 278.945C133 295.945 133 295.945 195 339.945C273.497 395.652 329 377 420 377",
200
+ strokeWidth: "90"
201
+ }), /*#__PURE__*/ React.createElement("path", {
202
+ d: "M508 376.445L354.25 287.678L354.25 465.213L508 376.445Z"
203
+ })));
204
+ }
205
+ export function FileDiff(props) {
206
+ return /*#__PURE__*/ React.createElement("svg", {
207
+ xmlns: "http://www.w3.org/2000/svg",
208
+ viewBox: "0 0 24 24",
209
+ fill: "none",
210
+ stroke: "currentColor",
211
+ strokeWidth: 2,
212
+ strokeLinecap: "round",
213
+ strokeLinejoin: "round",
214
+ ...props
215
+ }, /*#__PURE__*/ React.createElement("path", {
216
+ stroke: "none",
217
+ d: "M0 0h24v24H0z",
218
+ fill: "none"
219
+ }), /*#__PURE__*/ React.createElement("path", {
220
+ d: "M14 3v4a1 1 0 0 0 1 1h4"
221
+ }), /*#__PURE__*/ React.createElement("path", {
222
+ d: "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2"
223
+ }), /*#__PURE__*/ React.createElement("path", {
224
+ d: "M12 10l0 4"
225
+ }), /*#__PURE__*/ React.createElement("path", {
226
+ d: "M10 12l4 0"
227
+ }), /*#__PURE__*/ React.createElement("path", {
228
+ d: "M10 17l4 0"
229
+ }));
230
+ }
231
+ export function Send(props) {
232
+ return /*#__PURE__*/ React.createElement("svg", {
233
+ xmlns: "http://www.w3.org/2000/svg",
234
+ viewBox: "0 0 24 24",
235
+ fill: "none",
236
+ stroke: "currentColor",
237
+ strokeWidth: 2,
238
+ strokeLinecap: "round",
239
+ strokeLinejoin: "round",
240
+ ...props
241
+ }, /*#__PURE__*/ React.createElement("path", {
242
+ stroke: "none",
243
+ d: "M0 0h24v24H0z",
244
+ fill: "none"
245
+ }), /*#__PURE__*/ React.createElement("path", {
246
+ d: "M10 14l11 -11"
247
+ }), /*#__PURE__*/ React.createElement("path", {
248
+ d: "M21 3l-6.5 18a.55 .55 0 0 1 -1 0l-3.5 -7l-7 -3.5a.55 .55 0 0 1 0 -1l18 -6.5"
249
+ }));
250
+ }
251
+ export function Apply(props) {
252
+ return /*#__PURE__*/ React.createElement("svg", {
253
+ xmlns: "http://www.w3.org/2000/svg",
254
+ viewBox: "0 0 24 24",
255
+ fill: "none",
256
+ stroke: "currentColor",
257
+ strokeWidth: 2,
258
+ strokeLinecap: "round",
259
+ strokeLinejoin: "round",
260
+ ...props
261
+ }, /*#__PURE__*/ React.createElement("path", {
262
+ stroke: "none",
263
+ d: "M0 0h24v24H0z",
264
+ fill: "none"
265
+ }), /*#__PURE__*/ React.createElement("path", {
266
+ d: "M5 12l5 5l10 -10"
267
+ }));
268
+ }
269
+ export function Reject(props) {
270
+ return /*#__PURE__*/ React.createElement("svg", {
271
+ xmlns: "http://www.w3.org/2000/svg",
272
+ viewBox: "0 0 24 24",
273
+ fill: "none",
274
+ stroke: "currentColor",
275
+ strokeWidth: 2,
276
+ strokeLinecap: "round",
277
+ strokeLinejoin: "round",
278
+ ...props
279
+ }, /*#__PURE__*/ React.createElement("path", {
280
+ stroke: "none",
281
+ d: "M0 0h24v24H0z",
282
+ fill: "none"
283
+ }), /*#__PURE__*/ React.createElement("path", {
284
+ d: "M18 6l-12 12"
285
+ }), /*#__PURE__*/ React.createElement("path", {
286
+ d: "M6 6l12 12"
287
+ }));
288
+ }
289
+ export function Collection(props) {
290
+ return /*#__PURE__*/ React.createElement("svg", {
291
+ xmlns: "http://www.w3.org/2000/svg",
292
+ viewBox: "0 0 24 24",
293
+ fill: "none",
294
+ stroke: "currentColor",
295
+ strokeWidth: 2,
296
+ strokeLinecap: "round",
297
+ strokeLinejoin: "round",
298
+ ...props
299
+ }, /*#__PURE__*/ React.createElement("path", {
300
+ stroke: "none",
301
+ d: "M0 0h24v24H0z",
302
+ fill: "none"
303
+ }), /*#__PURE__*/ React.createElement("path", {
304
+ d: "M5 4h4l3 3h7a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-11a2 2 0 0 1 2 -2"
305
+ }));
306
+ }
307
+ export function Document(props) {
308
+ return /*#__PURE__*/ React.createElement("svg", {
309
+ xmlns: "http://www.w3.org/2000/svg",
310
+ viewBox: "0 0 24 24",
311
+ fill: "none",
312
+ stroke: "currentColor",
313
+ strokeWidth: 2,
314
+ strokeLinecap: "round",
315
+ strokeLinejoin: "round",
316
+ ...props
317
+ }, /*#__PURE__*/ React.createElement("path", {
318
+ stroke: "none",
319
+ d: "M0 0h24v24H0z",
320
+ fill: "none"
321
+ }), /*#__PURE__*/ React.createElement("path", {
322
+ d: "M14 3v4a1 1 0 0 0 1 1h4"
323
+ }), /*#__PURE__*/ React.createElement("path", {
324
+ d: "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2"
325
+ }));
326
+ }
327
+ export function Global(props) {
328
+ return /*#__PURE__*/ React.createElement("svg", {
329
+ xmlns: "http://www.w3.org/2000/svg",
330
+ viewBox: "0 0 24 24",
331
+ fill: "none",
332
+ stroke: "currentColor",
333
+ strokeWidth: 2,
334
+ strokeLinecap: "round",
335
+ strokeLinejoin: "round",
336
+ ...props
337
+ }, /*#__PURE__*/ React.createElement("path", {
338
+ stroke: "none",
339
+ d: "M0 0h24v24H0z",
340
+ fill: "none"
341
+ }), /*#__PURE__*/ React.createElement("path", {
342
+ d: "M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0"
343
+ }), /*#__PURE__*/ React.createElement("path", {
344
+ d: "M3.6 9h16.8"
345
+ }), /*#__PURE__*/ React.createElement("path", {
346
+ d: "M3.6 15h16.8"
347
+ }), /*#__PURE__*/ React.createElement("path", {
348
+ d: "M11.5 3a17 17 0 0 0 0 18"
349
+ }), /*#__PURE__*/ React.createElement("path", {
350
+ d: "M12.5 3a17 17 0 0 1 0 18"
351
+ }));
352
+ }
353
+ export function Block(props) {
354
+ return /*#__PURE__*/ React.createElement("svg", {
355
+ xmlns: "http://www.w3.org/2000/svg",
356
+ viewBox: "0 0 24 24",
357
+ fill: "none",
358
+ stroke: "currentColor",
359
+ strokeWidth: 2,
360
+ strokeLinecap: "round",
361
+ strokeLinejoin: "round",
362
+ ...props
363
+ }, /*#__PURE__*/ React.createElement("path", {
364
+ stroke: "none",
365
+ d: "M0 0h24v24H0z",
366
+ fill: "none"
367
+ }), /*#__PURE__*/ React.createElement("path", {
368
+ d: "M14 4a1 1 0 0 1 1 -1h5a1 1 0 0 1 1 1v5a1 1 0 0 1 -1 1h-5a1 1 0 0 1 -1 -1l0 -5"
369
+ }), /*#__PURE__*/ React.createElement("path", {
370
+ d: "M3 14h12a2 2 0 0 1 2 2v3a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h3a2 2 0 0 1 2 2v12"
371
+ }));
372
+ }
@@ -0,0 +1,19 @@
1
+ import type { CSSProperties } from "react";
2
+ import type { RefObject } from "react";
3
+ export type MentionOption = {
4
+ collection?: string;
5
+ id?: string;
6
+ isDefault?: boolean;
7
+ label: string;
8
+ parent?: string;
9
+ slug: string;
10
+ type: "block" | "collection" | "doc" | "global" | "locale";
11
+ };
12
+ type MentionPopoverProps = {
13
+ containerRef?: RefObject<HTMLDivElement | null>;
14
+ suggestions: MentionOption[];
15
+ onSelect: (suggestion: MentionOption) => void;
16
+ style?: CSSProperties;
17
+ };
18
+ export declare const MentionPopover: ({ containerRef, onSelect, style, suggestions }: MentionPopoverProps) => import("react").JSX.Element | null;
19
+ export {};
@@ -1,11 +1,11 @@
1
- import styles from "./CollectionMentionPopover.module.css";
1
+ import styles from "./MentionPopover.module.css";
2
2
  const suggestionGroups = [
3
3
  {
4
4
  label: "Collections",
5
5
  type: "collection"
6
6
  },
7
7
  {
8
- label: "Collection items",
8
+ label: "Documents",
9
9
  type: "doc"
10
10
  },
11
11
  {
@@ -15,21 +15,27 @@ const suggestionGroups = [
15
15
  {
16
16
  label: "Blocks",
17
17
  type: "block"
18
+ },
19
+ {
20
+ label: "Locales",
21
+ type: "locale"
18
22
  }
19
23
  ];
20
24
  const getSuggestionTitle = (suggestion)=>{
21
25
  if (suggestion.type === "collection") return `@${suggestion.slug}`;
22
26
  if (suggestion.type === "global") return `@${suggestion.slug}`;
23
27
  if (suggestion.type === "block") return `@${suggestion.slug}`;
28
+ if (suggestion.type === "locale") return `@${suggestion.slug}`;
24
29
  return suggestion.label;
25
30
  };
26
31
  const getSuggestionLabel = (suggestion)=>{
27
32
  if (suggestion.type === "collection") return suggestion.label;
28
33
  if (suggestion.type === "global") return "global";
29
34
  if (suggestion.type === "block") return `${suggestion.parent} block`;
35
+ if (suggestion.type === "locale") return suggestion.isDefault ? "default locale" : "locale";
30
36
  return `${suggestion.collection} item`;
31
37
  };
32
- export const CollectionMentionPopover = ({ containerRef, onSelect, suggestions })=>{
38
+ export const MentionPopover = ({ containerRef, onSelect, style, suggestions })=>{
33
39
  if (suggestions.length === 0) return null;
34
40
  const onKeyDown = (event, suggestion)=>{
35
41
  if (event.key === "Enter" || event.key === " ") {
@@ -53,7 +59,8 @@ export const CollectionMentionPopover = ({ containerRef, onSelect, suggestions }
53
59
  };
54
60
  return /*#__PURE__*/ React.createElement("div", {
55
61
  className: styles.popover,
56
- ref: containerRef
62
+ ref: containerRef,
63
+ style: style
57
64
  }, suggestionGroups.map((group)=>{
58
65
  const groupSuggestions = suggestions.filter((s)=>s.type === group.type);
59
66
  if (groupSuggestions.length === 0) return null;
@@ -3,14 +3,12 @@
3
3
  border: 1px solid var(--theme-elevation-150);
4
4
  border-radius: 6px;
5
5
  box-shadow: 0 8px 24px rgb(0 0 0 / 12%);
6
- left: 0;
7
6
  max-height: 220px;
8
7
  max-width: calc(100% - 96px);
9
8
  min-width: 260px;
10
9
  overflow: auto;
11
10
  padding: 6px;
12
11
  position: absolute;
13
- top: calc(100% + 6px);
14
12
  z-index: 10;
15
13
  }
16
14
 
@@ -1,10 +1,12 @@
1
1
  import { type AIProvider } from "../../ai/providerOptions.js";
2
- export declare const useAISettings: ({ adminUserSlug, apiRoute, defaultModels, }: {
2
+ interface UseAISettingsOptions {
3
3
  adminUserSlug?: string;
4
4
  apiRoute: string;
5
5
  defaultModels: Record<AIProvider, string>;
6
- }) => {
6
+ }
7
+ export declare const useAISettings: ({ adminUserSlug, apiRoute, defaultModels }: UseAISettingsOptions) => {
7
8
  selectedModel: string;
8
- setSelectedModel: import("react").Dispatch<import("react").SetStateAction<string>>;
9
- settingsProvider: "claude" | "google" | "mistral" | "openai" | null;
9
+ setSelectedModel: (model: string) => void;
10
+ settingsProvider: "claude" | "google" | "mistral" | "openai" | "openrouter" | null;
10
11
  };
12
+ export {};
@@ -2,10 +2,25 @@
2
2
  import { formatAdminURL } from "payload/shared";
3
3
  import { useEffect, useState } from "react";
4
4
  import { isAIProvider } from "../../ai/providerOptions.js";
5
- import { isAbortError } from "./utils.js";
5
+ import { isAbortError } from "../../payload/shared.js";
6
+ const getStoredModelKey = (provider)=>`payload-ai:selected-model:${provider}`;
7
+ const getStoredModel = (provider)=>{
8
+ if (typeof window === "undefined") return null;
9
+ return window.localStorage.getItem(getStoredModelKey(provider));
10
+ };
11
+ const storeModel = (provider, model)=>{
12
+ if (typeof window === "undefined") return;
13
+ window.localStorage.setItem(getStoredModelKey(provider), model);
14
+ };
6
15
  export const useAISettings = ({ adminUserSlug, apiRoute, defaultModels })=>{
7
16
  const [settingsProvider, setSettingsProvider] = useState(null);
8
17
  const [selectedModel, setSelectedModel] = useState("");
18
+ const setStoredSelectedModel = (model)=>{
19
+ setSelectedModel(model);
20
+ if (settingsProvider && model) {
21
+ storeModel(settingsProvider, model);
22
+ }
23
+ };
9
24
  useEffect(()=>{
10
25
  if (!adminUserSlug) {
11
26
  setSettingsProvider(null);
@@ -34,7 +49,7 @@ export const useAISettings = ({ adminUserSlug, apiRoute, defaultModels })=>{
34
49
  return;
35
50
  }
36
51
  setSettingsProvider(provider);
37
- setSelectedModel(defaultModels[provider]);
52
+ setSelectedModel(getStoredModel(provider) || defaultModels[provider]);
38
53
  } catch (err) {
39
54
  if (isAbortError(err)) return;
40
55
  setSettingsProvider(null);
@@ -50,7 +65,7 @@ export const useAISettings = ({ adminUserSlug, apiRoute, defaultModels })=>{
50
65
  ]);
51
66
  return {
52
67
  selectedModel,
53
- setSelectedModel,
68
+ setSelectedModel: setStoredSelectedModel,
54
69
  settingsProvider
55
70
  };
56
71
  };