@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.
Files changed (51) hide show
  1. package/README.md +42 -0
  2. package/dist/components/Icons.d.ts +0 -8
  3. package/dist/components/Icons.js +4 -216
  4. package/dist/components/{ActionToast.d.ts → action-toast/ActionToast.d.ts} +1 -2
  5. package/dist/components/{ActionToast.js → action-toast/ActionToast.js} +25 -34
  6. package/dist/components/{ActionToast.module.css → action-toast/ActionToast.module.css} +0 -79
  7. package/dist/components/ai-input/AIInput.js +433 -0
  8. package/dist/components/{AIInput.module.css → ai-input/AIInput.module.css} +111 -43
  9. package/dist/components/ai-input/badge.d.ts +14 -0
  10. package/dist/components/ai-input/badge.js +85 -0
  11. package/dist/components/{AuditLogList.d.ts → audit-log-list/AuditLogList.d.ts} +4 -8
  12. package/dist/components/{AuditLogList.js → audit-log-list/AuditLogList.js} +49 -21
  13. package/dist/components/{AuditLogList.module.css → audit-log-list/AuditLogList.module.css} +11 -65
  14. package/dist/components/dashboard/Dashboard.d.ts +2 -0
  15. package/dist/components/dashboard/Dashboard.js +15 -0
  16. package/dist/components/dashboard/Dashboard.module.css +13 -0
  17. package/dist/components/{DiffDialog.d.ts → diff-dialog/DiffDialog.d.ts} +2 -2
  18. package/dist/components/{DiffDialog.js → diff-dialog/DiffDialog.js} +200 -189
  19. package/dist/components/{DiffDialog.module.css → diff-dialog/DiffDialog.module.css} +17 -35
  20. package/dist/components/hooks/useAIChatStream.d.ts +39 -0
  21. package/dist/components/hooks/useAIChatStream.js +217 -0
  22. package/dist/components/hooks/useAISettings.js +26 -25
  23. package/dist/components/hooks/useAuditLog.d.ts +11 -0
  24. package/dist/components/hooks/useAuditLog.js +41 -0
  25. package/dist/components/hooks/useDocumentMentionSuggestions.d.ts +1 -1
  26. package/dist/components/hooks/useDocumentMentionSuggestions.js +31 -27
  27. package/dist/components/hooks/useMentions.d.ts +58 -0
  28. package/dist/components/hooks/useMentions.js +276 -0
  29. package/dist/components/hooks/usePluginConfig.d.ts +52 -0
  30. package/dist/components/hooks/usePluginConfig.js +20 -0
  31. package/dist/components/{MentionPopover.d.ts → mention-popover/MentionPopover.d.ts} +2 -4
  32. package/dist/components/{MentionPopover.js → mention-popover/MentionPopover.js} +1 -8
  33. package/dist/components/{MentionPopover.module.css → mention-popover/MentionPopover.module.css} +1 -1
  34. package/dist/exports/client.d.ts +2 -2
  35. package/dist/exports/client.js +2 -2
  36. package/dist/handlers/applyActionHandler.js +27 -7
  37. package/dist/handlers/chatHandler.js +302 -58
  38. package/dist/handlers/mediaUploadHandler.d.ts +7 -0
  39. package/dist/handlers/mediaUploadHandler.js +99 -0
  40. package/dist/handlers/mentionSuggestionHandler.js +16 -14
  41. package/dist/handlers/proposalDiffHandler.js +41 -29
  42. package/dist/index.d.ts +6 -0
  43. package/dist/index.js +39 -7
  44. package/dist/payload/collectionPermissions.js +3 -1
  45. package/dist/payload/normalizeData.d.ts +0 -6
  46. package/dist/payload/normalizeData.js +25 -13
  47. package/dist/payload/proposalData.js +4 -1
  48. package/dist/payload/schemaContext.js +98 -43
  49. package/package.json +6 -6
  50. package/dist/components/AIInput.js +0 -896
  51. /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 "./ActionToast.js";
2
- import { type ProposalDiff } from "./DiffDialog.js";
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
- export declare const RecentChangesList: ({ allChangesURL, changes }: AuditLogListProps) => import("react").JSX.Element;
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 "./DiffDialog.js";
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
- export const RecentChangesList = ({ allChangesURL, changes })=>{
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("a", {
26
- className: styles.headerGhostButton,
27
- href: allChangesURL,
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, 10).map((change, index)=>/*#__PURE__*/ _jsxs("div", {
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("button", {
76
- className: styles.button,
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: 8px;
43
- max-height: 260px;
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
- padding: 4px 4px 4px 8px;
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: 600;
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,2 @@
1
+ declare const Dashboard: () => import("react").JSX.Element;
2
+ export default Dashboard;
@@ -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;
@@ -0,0 +1,13 @@
1
+ .dashboard {
2
+ display: flex;
3
+ flex-direction: row;
4
+ gap: 16px;
5
+ align-items: flex-start;
6
+ }
7
+
8
+ @media (max-width: 600px) {
9
+ .dashboard {
10
+ flex-direction: column;
11
+ align-items: stretch;
12
+ }
13
+ }
@@ -1,5 +1,5 @@
1
- import type { ActionProposal } from "./ActionToast.js";
2
- import type { AppliedChange } from "./AuditLogList.js";
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;