@mvriu5/payload-ai 1.2.0 → 1.3.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/README.md +42 -0
- package/dist/components/Icons.d.ts +0 -8
- package/dist/components/Icons.js +4 -216
- package/dist/components/{ActionToast.d.ts → action-toast/ActionToast.d.ts} +1 -2
- package/dist/components/{ActionToast.js → action-toast/ActionToast.js} +25 -34
- package/dist/components/{ActionToast.module.css → action-toast/ActionToast.module.css} +0 -79
- package/dist/components/ai-input/AIInput.js +433 -0
- package/dist/components/{AIInput.module.css → ai-input/AIInput.module.css} +111 -43
- package/dist/components/ai-input/badge.d.ts +14 -0
- package/dist/components/ai-input/badge.js +85 -0
- package/dist/components/{AuditLogList.d.ts → audit-log-list/AuditLogList.d.ts} +4 -8
- package/dist/components/{AuditLogList.js → audit-log-list/AuditLogList.js} +49 -21
- package/dist/components/{AuditLogList.module.css → audit-log-list/AuditLogList.module.css} +11 -65
- package/dist/components/dashboard/Dashboard.d.ts +2 -0
- package/dist/components/dashboard/Dashboard.js +15 -0
- package/dist/components/dashboard/Dashboard.module.css +13 -0
- package/dist/components/{DiffDialog.d.ts → diff-dialog/DiffDialog.d.ts} +2 -2
- package/dist/components/{DiffDialog.js → diff-dialog/DiffDialog.js} +200 -189
- package/dist/components/{DiffDialog.module.css → diff-dialog/DiffDialog.module.css} +17 -35
- package/dist/components/hooks/useAIChatStream.d.ts +39 -0
- package/dist/components/hooks/useAIChatStream.js +217 -0
- package/dist/components/hooks/useAISettings.js +26 -25
- package/dist/components/hooks/useAuditLog.d.ts +11 -0
- package/dist/components/hooks/useAuditLog.js +41 -0
- package/dist/components/hooks/useDocumentMentionSuggestions.d.ts +1 -1
- package/dist/components/hooks/useDocumentMentionSuggestions.js +31 -27
- package/dist/components/hooks/useMentions.d.ts +58 -0
- package/dist/components/hooks/useMentions.js +276 -0
- package/dist/components/hooks/usePluginConfig.d.ts +52 -0
- package/dist/components/hooks/usePluginConfig.js +20 -0
- package/dist/components/{MentionPopover.d.ts → mention-popover/MentionPopover.d.ts} +2 -4
- package/dist/components/{MentionPopover.js → mention-popover/MentionPopover.js} +1 -8
- package/dist/components/{MentionPopover.module.css → mention-popover/MentionPopover.module.css} +1 -1
- package/dist/exports/client.d.ts +2 -2
- package/dist/exports/client.js +2 -2
- package/dist/handlers/applyActionHandler.js +27 -7
- package/dist/handlers/chatHandler.js +302 -58
- package/dist/handlers/mediaUploadHandler.d.ts +7 -0
- package/dist/handlers/mediaUploadHandler.js +99 -0
- package/dist/handlers/mentionSuggestionHandler.js +16 -14
- package/dist/handlers/proposalDiffHandler.js +41 -29
- package/dist/index.d.ts +6 -0
- package/dist/index.js +39 -7
- package/dist/payload/collectionPermissions.js +3 -1
- package/dist/payload/normalizeData.d.ts +0 -6
- package/dist/payload/normalizeData.js +25 -13
- package/dist/payload/proposalData.js +4 -1
- package/dist/payload/schemaContext.js +98 -43
- package/package.json +6 -6
- package/dist/components/AIInput.js +0 -896
- /package/dist/components/{AIInput.d.ts → ai-input/AIInput.d.ts} +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const appendSvgPath = (svg, d)=>{
|
|
2
|
+
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
3
|
+
path.setAttribute("d", d);
|
|
4
|
+
svg.append(path);
|
|
5
|
+
};
|
|
6
|
+
const createBadgeIcon = (type, styles)=>{
|
|
7
|
+
if (type === "locale") return null;
|
|
8
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
9
|
+
svg.setAttribute("aria-hidden", "true");
|
|
10
|
+
svg.setAttribute("class", styles.badgeIcon);
|
|
11
|
+
svg.setAttribute("fill", "none");
|
|
12
|
+
svg.setAttribute("stroke", "currentColor");
|
|
13
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
14
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
15
|
+
svg.setAttribute("stroke-width", "2");
|
|
16
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
17
|
+
if (type === "collection") {
|
|
18
|
+
appendSvgPath(svg, "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");
|
|
19
|
+
}
|
|
20
|
+
if (type === "doc") {
|
|
21
|
+
appendSvgPath(svg, "M14 3v4a1 1 0 0 0 1 1h4");
|
|
22
|
+
appendSvgPath(svg, "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2");
|
|
23
|
+
}
|
|
24
|
+
if (type === "global") {
|
|
25
|
+
appendSvgPath(svg, "M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0");
|
|
26
|
+
appendSvgPath(svg, "M3.6 9h16.8");
|
|
27
|
+
appendSvgPath(svg, "M3.6 15h16.8");
|
|
28
|
+
appendSvgPath(svg, "M11.5 3a17 17 0 0 0 0 18");
|
|
29
|
+
appendSvgPath(svg, "M12.5 3a17 17 0 0 1 0 18");
|
|
30
|
+
}
|
|
31
|
+
return svg;
|
|
32
|
+
};
|
|
33
|
+
export const createBadgePrefix = (suggestion, styles)=>{
|
|
34
|
+
const prefix = document.createElement("span");
|
|
35
|
+
const icon = createBadgeIcon(suggestion.type, styles);
|
|
36
|
+
prefix.className = styles.prefix;
|
|
37
|
+
if (icon) {
|
|
38
|
+
prefix.append(icon);
|
|
39
|
+
}
|
|
40
|
+
if (suggestion.type === "doc") {
|
|
41
|
+
prefix.append(document.createTextNode(`${suggestion.collection || "document"}:`));
|
|
42
|
+
} else if (suggestion.type === "locale") {
|
|
43
|
+
prefix.textContent = "locale:";
|
|
44
|
+
}
|
|
45
|
+
return prefix;
|
|
46
|
+
};
|
|
47
|
+
export const getTextNodeAtOffset = (element, offset)=>{
|
|
48
|
+
const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
|
|
49
|
+
let currentOffset = 0;
|
|
50
|
+
let node = walker.nextNode();
|
|
51
|
+
while(node){
|
|
52
|
+
const nextOffset = currentOffset + (node.textContent?.length || 0);
|
|
53
|
+
if (offset <= nextOffset) {
|
|
54
|
+
return {
|
|
55
|
+
node,
|
|
56
|
+
offset: offset - currentOffset
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
currentOffset = nextOffset;
|
|
60
|
+
node = walker.nextNode();
|
|
61
|
+
}
|
|
62
|
+
const textNode = document.createTextNode("");
|
|
63
|
+
element.append(textNode);
|
|
64
|
+
return {
|
|
65
|
+
node: textNode,
|
|
66
|
+
offset: 0
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
export const replaceTextRangeWithBadge = ({ badge, editor, end, start })=>{
|
|
70
|
+
const startPosition = getTextNodeAtOffset(editor, start);
|
|
71
|
+
const endPosition = getTextNodeAtOffset(editor, end);
|
|
72
|
+
const range = document.createRange();
|
|
73
|
+
const trailingSpace = document.createTextNode(" ");
|
|
74
|
+
range.setStart(startPosition.node, startPosition.offset);
|
|
75
|
+
range.setEnd(endPosition.node, endPosition.offset);
|
|
76
|
+
range.deleteContents();
|
|
77
|
+
range.insertNode(trailingSpace);
|
|
78
|
+
range.insertNode(badge);
|
|
79
|
+
const selection = window.getSelection();
|
|
80
|
+
const caretRange = document.createRange();
|
|
81
|
+
caretRange.setStartAfter(trailingSpace);
|
|
82
|
+
caretRange.collapse(true);
|
|
83
|
+
selection?.removeAllRanges();
|
|
84
|
+
selection?.addRange(caretRange);
|
|
85
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ActionProposal } from "
|
|
2
|
-
import { type ProposalDiff } from "
|
|
1
|
+
import type { ActionProposal } from "../action-toast/ActionToast.js";
|
|
2
|
+
import { type ProposalDiff } from "../diff-dialog/DiffDialog.js";
|
|
3
3
|
export type AppliedChange = {
|
|
4
4
|
action?: ActionProposal["action"] | null;
|
|
5
5
|
additions: number;
|
|
@@ -19,14 +19,10 @@ export type AppliedChange = {
|
|
|
19
19
|
userLabel?: string | null;
|
|
20
20
|
url?: string | null;
|
|
21
21
|
};
|
|
22
|
-
type AuditLogListProps = {
|
|
23
|
-
allChangesURL?: string;
|
|
24
|
-
changes: AppliedChange[];
|
|
25
|
-
};
|
|
26
22
|
export type ActiveDiff = {
|
|
27
23
|
change: AppliedChange | null;
|
|
28
24
|
diff: ProposalDiff;
|
|
29
25
|
proposal: ActionProposal;
|
|
30
26
|
};
|
|
31
|
-
|
|
32
|
-
export
|
|
27
|
+
declare const AuditLogList: () => import("react").JSX.Element;
|
|
28
|
+
export default AuditLogList;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from "react";
|
|
3
|
-
import { ExternalLinkIcon } from "@payloadcms/ui";
|
|
4
|
-
import { DiffDialog } from "
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { Button, ExternalLinkIcon, useConfig } from "@payloadcms/ui";
|
|
5
|
+
import { DiffDialog } from "../diff-dialog/DiffDialog.js";
|
|
5
6
|
import styles from "./AuditLogList.module.css";
|
|
7
|
+
import { useAuditLog } from "../hooks/useAuditLog.js";
|
|
6
8
|
const getChangeProposal = (change)=>({
|
|
7
9
|
action: change.action || "update",
|
|
8
10
|
collection: change.collection || undefined,
|
|
@@ -10,8 +12,24 @@ const getChangeProposal = (change)=>({
|
|
|
10
12
|
label: change.title,
|
|
11
13
|
slug: change.slug || undefined
|
|
12
14
|
});
|
|
13
|
-
|
|
15
|
+
const AuditLogList = ()=>{
|
|
16
|
+
const { config } = useConfig();
|
|
17
|
+
const { loadRecentChanges, allChangesURL, appliedChanges: changes } = useAuditLog({
|
|
18
|
+
adminRoute: config.routes.admin,
|
|
19
|
+
apiRoute: config.routes.api
|
|
20
|
+
});
|
|
14
21
|
const [activeDiff, setActiveDiff] = useState(null);
|
|
22
|
+
useEffect(()=>{
|
|
23
|
+
const refresh = ()=>{
|
|
24
|
+
void loadRecentChanges().catch(()=>undefined);
|
|
25
|
+
};
|
|
26
|
+
window.addEventListener("payload-ai:audit-log-updated", refresh);
|
|
27
|
+
return ()=>{
|
|
28
|
+
window.removeEventListener("payload-ai:audit-log-updated", refresh);
|
|
29
|
+
};
|
|
30
|
+
}, [
|
|
31
|
+
loadRecentChanges
|
|
32
|
+
]);
|
|
15
33
|
return /*#__PURE__*/ _jsxs("aside", {
|
|
16
34
|
className: styles.recentChanges,
|
|
17
35
|
children: [
|
|
@@ -22,9 +40,15 @@ export const RecentChangesList = ({ allChangesURL, changes })=>{
|
|
|
22
40
|
className: styles.title,
|
|
23
41
|
children: "Recent changes"
|
|
24
42
|
}),
|
|
25
|
-
allChangesURL && /*#__PURE__*/ _jsx(
|
|
26
|
-
|
|
27
|
-
|
|
43
|
+
allChangesURL && /*#__PURE__*/ _jsx(Button, {
|
|
44
|
+
url: allChangesURL,
|
|
45
|
+
el: "anchor",
|
|
46
|
+
"aria-labelabel": "View all",
|
|
47
|
+
margin: false,
|
|
48
|
+
buttonStyle: "tab",
|
|
49
|
+
size: "small",
|
|
50
|
+
disabled: !changes || changes.length <= 0,
|
|
51
|
+
newTab: true,
|
|
28
52
|
children: "View all"
|
|
29
53
|
})
|
|
30
54
|
]
|
|
@@ -34,22 +58,25 @@ export const RecentChangesList = ({ allChangesURL, changes })=>{
|
|
|
34
58
|
children: changes.length === 0 ? /*#__PURE__*/ _jsx("div", {
|
|
35
59
|
className: styles.empty,
|
|
36
60
|
children: "No changes yet."
|
|
37
|
-
}) : changes.slice(0,
|
|
61
|
+
}) : changes.slice(0, 8).map((change, index)=>/*#__PURE__*/ _jsxs("div", {
|
|
38
62
|
className: styles.item,
|
|
39
63
|
children: [
|
|
40
64
|
/*#__PURE__*/ _jsxs("div", {
|
|
41
65
|
className: styles.titleRow,
|
|
42
66
|
children: [
|
|
67
|
+
change.url && /*#__PURE__*/ _jsx(Button, {
|
|
68
|
+
url: change.url,
|
|
69
|
+
el: "anchor",
|
|
70
|
+
buttonStyle: "tab",
|
|
71
|
+
size: "small",
|
|
72
|
+
"aria-label": "Open change",
|
|
73
|
+
newTab: true,
|
|
74
|
+
margin: false,
|
|
75
|
+
children: /*#__PURE__*/ _jsx(ExternalLinkIcon, {})
|
|
76
|
+
}),
|
|
43
77
|
/*#__PURE__*/ _jsx("div", {
|
|
44
78
|
className: styles.itemTitle,
|
|
45
79
|
children: change.title
|
|
46
|
-
}),
|
|
47
|
-
change.url && /*#__PURE__*/ _jsx("a", {
|
|
48
|
-
className: styles.ghostButton,
|
|
49
|
-
href: change.url,
|
|
50
|
-
rel: "noreferrer noopener",
|
|
51
|
-
target: "_blank",
|
|
52
|
-
children: /*#__PURE__*/ _jsx(ExternalLinkIcon, {})
|
|
53
80
|
})
|
|
54
81
|
]
|
|
55
82
|
}),
|
|
@@ -72,12 +99,13 @@ export const RecentChangesList = ({ allChangesURL, changes })=>{
|
|
|
72
99
|
})
|
|
73
100
|
]
|
|
74
101
|
}),
|
|
75
|
-
/*#__PURE__*/ _jsx(
|
|
76
|
-
|
|
102
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
103
|
+
buttonStyle: "tab",
|
|
104
|
+
size: "small",
|
|
105
|
+
"aria-label": "Open review",
|
|
106
|
+
margin: false,
|
|
77
107
|
onClick: ()=>{
|
|
78
|
-
if (change.before === undefined || change.after === undefined)
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
108
|
+
if (change.before === undefined || change.after === undefined) return;
|
|
81
109
|
setActiveDiff({
|
|
82
110
|
change,
|
|
83
111
|
diff: {
|
|
@@ -87,7 +115,6 @@ export const RecentChangesList = ({ allChangesURL, changes })=>{
|
|
|
87
115
|
proposal: getChangeProposal(change)
|
|
88
116
|
});
|
|
89
117
|
},
|
|
90
|
-
type: "button",
|
|
91
118
|
children: "Review"
|
|
92
119
|
})
|
|
93
120
|
]
|
|
@@ -102,3 +129,4 @@ export const RecentChangesList = ({ allChangesURL, changes })=>{
|
|
|
102
129
|
]
|
|
103
130
|
});
|
|
104
131
|
};
|
|
132
|
+
export default AuditLogList;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
.recentChanges {
|
|
2
|
+
width: 100%;
|
|
3
|
+
max-width: none;
|
|
2
4
|
border: 1px solid var(--theme-elevation-150);
|
|
3
5
|
border-radius: 8px;
|
|
4
6
|
display: flex;
|
|
@@ -16,19 +18,6 @@
|
|
|
16
18
|
margin-bottom: 10px;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
.headerGhostButton {
|
|
20
|
-
color: var(--theme-elevation-500);
|
|
21
|
-
flex: 0 0 auto;
|
|
22
|
-
font-size: 12px;
|
|
23
|
-
line-height: 24px;
|
|
24
|
-
min-height: 24px;
|
|
25
|
-
text-decoration: none;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
.headerGhostButton:hover {
|
|
29
|
-
text-decoration: underline;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
21
|
.title {
|
|
33
22
|
font-size: 14px;
|
|
34
23
|
line-height: 1.3;
|
|
@@ -39,8 +28,8 @@
|
|
|
39
28
|
display: flex;
|
|
40
29
|
flex: 1 1 auto;
|
|
41
30
|
flex-direction: column;
|
|
42
|
-
gap:
|
|
43
|
-
max-height:
|
|
31
|
+
gap: 4px;
|
|
32
|
+
max-height: 300px;
|
|
44
33
|
min-height: 0;
|
|
45
34
|
overflow: auto;
|
|
46
35
|
padding-right: 2px;
|
|
@@ -54,12 +43,15 @@
|
|
|
54
43
|
|
|
55
44
|
.item {
|
|
56
45
|
align-items: center;
|
|
57
|
-
border: 1px solid var(--theme-elevation-100);
|
|
58
|
-
border-radius: 4px;
|
|
46
|
+
border-bottom: 1px solid var(--theme-elevation-100);
|
|
59
47
|
display: grid;
|
|
60
48
|
gap: 8px;
|
|
49
|
+
padding: 0px 0px 4px 0px;
|
|
61
50
|
grid-template-columns: minmax(0, 1fr) auto auto;
|
|
62
|
-
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.item:last-child {
|
|
54
|
+
border-bottom: none;
|
|
63
55
|
}
|
|
64
56
|
|
|
65
57
|
.titleRow {
|
|
@@ -73,7 +65,7 @@
|
|
|
73
65
|
color: var(--theme-text);
|
|
74
66
|
flex: 0 1 auto;
|
|
75
67
|
font-size: 12px;
|
|
76
|
-
font-weight:
|
|
68
|
+
font-weight: 400;
|
|
77
69
|
line-height: 1.4;
|
|
78
70
|
min-width: 0;
|
|
79
71
|
overflow: hidden;
|
|
@@ -104,49 +96,3 @@
|
|
|
104
96
|
background: rgba(160, 26, 26, 0.16);
|
|
105
97
|
color: #a01a1a;
|
|
106
98
|
}
|
|
107
|
-
|
|
108
|
-
.button {
|
|
109
|
-
align-items: center;
|
|
110
|
-
background: var(--theme-elevation-0);
|
|
111
|
-
border: 1px solid var(--theme-elevation-150);
|
|
112
|
-
border-radius: 4px;
|
|
113
|
-
color: var(--theme-text);
|
|
114
|
-
cursor: pointer;
|
|
115
|
-
display: inline-flex;
|
|
116
|
-
font-size: 12px;
|
|
117
|
-
gap: 6px;
|
|
118
|
-
justify-content: center;
|
|
119
|
-
line-height: 24px;
|
|
120
|
-
min-height: 24px;
|
|
121
|
-
padding: 0 10px;
|
|
122
|
-
text-align: center;
|
|
123
|
-
text-decoration: none;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
.button:disabled {
|
|
127
|
-
color: var(--theme-elevation-400);
|
|
128
|
-
cursor: not-allowed;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.button svg {
|
|
132
|
-
color: var(--theme-elevation-500);
|
|
133
|
-
flex: 0 0 auto;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
.ghostButton {
|
|
137
|
-
color: var(--theme-elevation-500);
|
|
138
|
-
flex: 0 0 auto;
|
|
139
|
-
font-size: 12px;
|
|
140
|
-
line-height: 18px;
|
|
141
|
-
text-decoration: none;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.ghostButton:hover {
|
|
145
|
-
text-decoration: underline;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
@media (max-width: 768px) {
|
|
149
|
-
.list {
|
|
150
|
-
max-height: 220px;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import AIInput from "../ai-input/AIInput.js";
|
|
4
|
+
import AuditLogList from "../audit-log-list/AuditLogList.js";
|
|
5
|
+
import styles from "./Dashboard.module.css";
|
|
6
|
+
const Dashboard = ()=>{
|
|
7
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
8
|
+
className: styles.dashboard,
|
|
9
|
+
children: [
|
|
10
|
+
/*#__PURE__*/ _jsx(AIInput, {}),
|
|
11
|
+
/*#__PURE__*/ _jsx(AuditLogList, {})
|
|
12
|
+
]
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
export default Dashboard;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ActionProposal } from "
|
|
2
|
-
import type { AppliedChange } from "
|
|
1
|
+
import type { ActionProposal } from "../action-toast/ActionToast.js";
|
|
2
|
+
import type { AppliedChange } from "../audit-log-list/AuditLogList.js";
|
|
3
3
|
export type ProposalDiff = {
|
|
4
4
|
after: unknown;
|
|
5
5
|
before: unknown;
|