payload-discussions 0.0.1
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 +82 -0
- package/dist/components/CommentForm.d.ts +10 -0
- package/dist/components/CommentForm.d.ts.map +1 -0
- package/dist/components/CommentForm.js +71 -0
- package/dist/components/CommentForm.js.map +1 -0
- package/dist/components/CommentForm.module.css.js +16 -0
- package/dist/components/CommentForm.module.css.js.map +1 -0
- package/dist/components/CommentItem.d.ts +11 -0
- package/dist/components/CommentItem.d.ts.map +1 -0
- package/dist/components/CommentItem.js +77 -0
- package/dist/components/CommentItem.js.map +1 -0
- package/dist/components/CommentItem.module.css.js +22 -0
- package/dist/components/CommentItem.module.css.js.map +1 -0
- package/dist/components/CommentList.d.ts +11 -0
- package/dist/components/CommentList.d.ts.map +1 -0
- package/dist/components/CommentList.js +24 -0
- package/dist/components/CommentList.js.map +1 -0
- package/dist/components/CommentList.module.css.js +10 -0
- package/dist/components/CommentList.module.css.js.map +1 -0
- package/dist/components/Discussions.d.ts +10 -0
- package/dist/components/Discussions.d.ts.map +1 -0
- package/dist/components/Discussions.js +67 -0
- package/dist/components/Discussions.js.map +1 -0
- package/dist/components/Discussions.module.css.js +8 -0
- package/dist/components/Discussions.module.css.js.map +1 -0
- package/dist/components/DiscussionsCell.d.ts +4 -0
- package/dist/components/DiscussionsCell.d.ts.map +1 -0
- package/dist/components/DiscussionsCell.js +11 -0
- package/dist/components/DiscussionsCell.js.map +1 -0
- package/dist/components/DiscussionsField.d.ts +4 -0
- package/dist/components/DiscussionsField.d.ts.map +1 -0
- package/dist/components/DiscussionsField.js +37 -0
- package/dist/components/DiscussionsField.js.map +1 -0
- package/dist/const.d.ts +2 -0
- package/dist/const.d.ts.map +1 -0
- package/dist/endpoints/create-comment.d.ts +5 -0
- package/dist/endpoints/create-comment.d.ts.map +1 -0
- package/dist/endpoints/create-comment.js +40 -0
- package/dist/endpoints/create-comment.js.map +1 -0
- package/dist/endpoints/create-reply.d.ts +5 -0
- package/dist/endpoints/create-reply.d.ts.map +1 -0
- package/dist/endpoints/create-reply.js +36 -0
- package/dist/endpoints/create-reply.js.map +1 -0
- package/dist/entities.d.ts +4 -0
- package/dist/entities.d.ts.map +1 -0
- package/dist/entities.js +41 -0
- package/dist/entities.js.map +1 -0
- package/dist/exports/client.d.ts +2 -0
- package/dist/exports/client.d.ts.map +1 -0
- package/dist/exports/client.js +2 -0
- package/dist/exports/client.js.map +1 -0
- package/dist/exports/rsc.d.ts +3 -0
- package/dist/exports/rsc.d.ts.map +1 -0
- package/dist/exports/rsc.js +7 -0
- package/dist/exports/rsc.js.map +1 -0
- package/dist/hooks.d.ts +40 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +55 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/payload-types.d.ts +246 -0
- package/dist/payload-types.d.ts.map +1 -0
- package/dist/procedures.d.ts +13 -0
- package/dist/procedures.d.ts.map +1 -0
- package/dist/procedures.js +18 -0
- package/dist/procedures.js.map +1 -0
- package/dist/styles.css +1 -0
- package/dist/types.d.ts +24 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -0
- package/dist/utitls/populate-comment.d.ts +5 -0
- package/dist/utitls/populate-comment.d.ts.map +1 -0
- package/dist/utitls/populate-comment.js +30 -0
- package/dist/utitls/populate-comment.js.map +1 -0
- package/package.json +81 -0
package/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# payload-discussions
|
|
2
|
+
|
|
3
|
+
Threaded comment discussions with nested replies and author tracking for Payload CMS.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/payload-discussions)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Attach threaded discussions to any collection or global in Payload. Comments support nested replies, are linked to authenticated users, and are automatically cleaned up when parent documents are deleted or restored. A ready-made sidebar component integrates directly into the admin panel.
|
|
11
|
+
|
|
12
|
+
**Features**
|
|
13
|
+
|
|
14
|
+
- **Threaded replies** -- nested comment threads with configurable maximum depth.
|
|
15
|
+
- **Sidebar UI** -- a field component that renders discussions in the Payload admin sidebar.
|
|
16
|
+
- **Lifecycle handling** -- comments follow their parent document through soft-delete, permanent delete, and restore.
|
|
17
|
+
- **Collection & global support** -- attach discussions to any combination of collections and globals.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
pnpm add payload-discussions
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// payload.config.ts
|
|
29
|
+
import { buildConfig } from 'payload';
|
|
30
|
+
import { discussionsPlugin } from 'payload-discussions';
|
|
31
|
+
|
|
32
|
+
export default buildConfig({
|
|
33
|
+
// ...
|
|
34
|
+
plugins: [
|
|
35
|
+
discussionsPlugin({
|
|
36
|
+
collections: ['posts', 'pages'],
|
|
37
|
+
globals: ['settings'],
|
|
38
|
+
}),
|
|
39
|
+
],
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Options
|
|
44
|
+
|
|
45
|
+
| Option | Type | Default | Description |
|
|
46
|
+
|--------|------|---------|-------------|
|
|
47
|
+
| `collections` | `CollectionSlug[]` | `[]` | Collections to add the discussions field to. |
|
|
48
|
+
| `globals` | `GlobalSlug[]` | `[]` | Globals to add the discussions field to. |
|
|
49
|
+
| `maxCommentDepth` | `number` | `5` | Maximum nesting depth for reply threads. |
|
|
50
|
+
| `collectionSlug` | `CollectionSlug` | `"comments"` | Slug used for the auto-created comments collection. |
|
|
51
|
+
|
|
52
|
+
## Contributing
|
|
53
|
+
|
|
54
|
+
This plugin lives in the [payload-plugins](https://github.com/davincicoding-org/payload-plugins) monorepo.
|
|
55
|
+
|
|
56
|
+
### Development
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
pnpm install
|
|
60
|
+
|
|
61
|
+
# watch this plugin for changes
|
|
62
|
+
pnpm --filter payload-discussions dev
|
|
63
|
+
|
|
64
|
+
# run the Payload dev app (in a second terminal)
|
|
65
|
+
pnpm --filter sandbox dev
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The `sandbox/` directory is a Next.js + Payload app that imports plugins via `workspace:*` — use it to test changes locally.
|
|
69
|
+
|
|
70
|
+
### Code quality
|
|
71
|
+
|
|
72
|
+
- **Formatting & linting** — handled by [Biome](https://biomejs.dev/), enforced on commit via husky + lint-staged.
|
|
73
|
+
- **Commits** — must follow [Conventional Commits](https://www.conventionalcommits.org/) with a valid scope (e.g. `fix(payload-discussions): ...`).
|
|
74
|
+
- **Changesets** — please include a [changeset](https://github.com/changesets/changesets) in your PR by running `pnpm release`.
|
|
75
|
+
|
|
76
|
+
### Issues & PRs
|
|
77
|
+
|
|
78
|
+
Bug reports and feature requests are welcome — [open an issue](https://github.com/davincicoding-org/payload-plugins/issues).
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
MIT
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface CommentFormProps {
|
|
2
|
+
onSubmit: (content: string) => Promise<void>;
|
|
3
|
+
onCancel?: () => void;
|
|
4
|
+
placeholder?: string;
|
|
5
|
+
submitLabel?: string;
|
|
6
|
+
autoFocus?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function CommentForm({ onSubmit, onCancel, placeholder, submitLabel, autoFocus, }: CommentFormProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=CommentForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentForm.d.ts","sourceRoot":"","sources":["../../src/components/CommentForm.tsx"],"names":[],"mappings":"AAKA,UAAU,gBAAgB;IACxB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,QAAQ,EACR,WAAkC,EAClC,WAAsB,EACtB,SAAiB,GAClB,EAAE,gBAAgB,2CAoElB"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as u, jsx as r } from "react/jsx-runtime";
|
|
3
|
+
import { useState as f, useRef as v, useEffect as S } from "react";
|
|
4
|
+
import n from "./CommentForm.module.css.js";
|
|
5
|
+
function N({
|
|
6
|
+
onSubmit: b,
|
|
7
|
+
onCancel: o,
|
|
8
|
+
placeholder: d = "Write a comment...",
|
|
9
|
+
submitLabel: y = "Submit",
|
|
10
|
+
autoFocus: a = !1
|
|
11
|
+
}) {
|
|
12
|
+
const [s, l] = f(""), [e, c] = f(!1), i = v(null);
|
|
13
|
+
S(() => {
|
|
14
|
+
a && (i.current?.focus(), i.current?.scrollIntoView({
|
|
15
|
+
behavior: "smooth",
|
|
16
|
+
block: "nearest"
|
|
17
|
+
}));
|
|
18
|
+
}, [a]);
|
|
19
|
+
const m = async () => {
|
|
20
|
+
if (!(!s.trim() || e)) {
|
|
21
|
+
c(!0);
|
|
22
|
+
try {
|
|
23
|
+
await b(s.trim()), l("");
|
|
24
|
+
} finally {
|
|
25
|
+
c(!1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}, h = (t) => {
|
|
29
|
+
t.key === "Enter" && (t.metaKey || t.ctrlKey) && (t.preventDefault(), m());
|
|
30
|
+
}, p = !s.trim() || e;
|
|
31
|
+
return /* @__PURE__ */ u("div", { className: n.form, children: [
|
|
32
|
+
/* @__PURE__ */ r(
|
|
33
|
+
"textarea",
|
|
34
|
+
{
|
|
35
|
+
className: n.textarea,
|
|
36
|
+
disabled: e,
|
|
37
|
+
onChange: (t) => l(t.target.value),
|
|
38
|
+
onKeyDown: h,
|
|
39
|
+
placeholder: d,
|
|
40
|
+
ref: i,
|
|
41
|
+
value: s
|
|
42
|
+
}
|
|
43
|
+
),
|
|
44
|
+
/* @__PURE__ */ u("div", { className: n.footer, children: [
|
|
45
|
+
o && /* @__PURE__ */ r(
|
|
46
|
+
"button",
|
|
47
|
+
{
|
|
48
|
+
className: n.cancelButton,
|
|
49
|
+
disabled: e,
|
|
50
|
+
onClick: o,
|
|
51
|
+
type: "button",
|
|
52
|
+
children: "Cancel"
|
|
53
|
+
}
|
|
54
|
+
),
|
|
55
|
+
/* @__PURE__ */ r(
|
|
56
|
+
"button",
|
|
57
|
+
{
|
|
58
|
+
className: n.submitButton,
|
|
59
|
+
disabled: p,
|
|
60
|
+
onClick: m,
|
|
61
|
+
type: "button",
|
|
62
|
+
children: e ? "Submitting..." : y
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
] })
|
|
66
|
+
] });
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
N as CommentForm
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=CommentForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentForm.js","sources":["../../src/components/CommentForm.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport styles from './CommentForm.module.css';\n\ninterface CommentFormProps {\n onSubmit: (content: string) => Promise<void>;\n onCancel?: () => void;\n placeholder?: string;\n submitLabel?: string;\n autoFocus?: boolean;\n}\n\nexport function CommentForm({\n onSubmit,\n onCancel,\n placeholder = 'Write a comment...',\n submitLabel = 'Submit',\n autoFocus = false,\n}: CommentFormProps) {\n const [content, setContent] = useState('');\n const [isSubmitting, setIsSubmitting] = useState(false);\n const inputRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n if (!autoFocus) return;\n inputRef.current?.focus();\n inputRef.current?.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n });\n }, [autoFocus]);\n\n const handleSubmit = async () => {\n if (!content.trim() || isSubmitting) return;\n\n setIsSubmitting(true);\n try {\n await onSubmit(content.trim());\n setContent('');\n } finally {\n setIsSubmitting(false);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n const isDisabled = !content.trim() || isSubmitting;\n\n return (\n <div className={styles.form}>\n <textarea\n className={styles.textarea}\n disabled={isSubmitting}\n onChange={(e) => setContent(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n ref={inputRef}\n value={content}\n />\n <div className={styles.footer}>\n {onCancel && (\n <button\n className={styles.cancelButton}\n disabled={isSubmitting}\n onClick={onCancel}\n type=\"button\"\n >\n Cancel\n </button>\n )}\n <button\n className={styles.submitButton}\n disabled={isDisabled}\n onClick={handleSubmit}\n type=\"button\"\n >\n {isSubmitting ? 'Submitting...' : submitLabel}\n </button>\n </div>\n </div>\n );\n}\n"],"names":["CommentForm","onSubmit","onCancel","placeholder","submitLabel","autoFocus","content","setContent","useState","isSubmitting","setIsSubmitting","inputRef","useRef","useEffect","handleSubmit","handleKeyDown","e","isDisabled","jsxs","styles","jsx"],"mappings":";;;;AAaO,SAASA,EAAY;AAAA,EAC1B,UAAAC;AAAA,EACA,UAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,aAAAC,IAAc;AAAA,EACd,WAAAC,IAAY;AACd,GAAqB;AACnB,QAAM,CAACC,GAASC,CAAU,IAAIC,EAAS,EAAE,GACnC,CAACC,GAAcC,CAAe,IAAIF,EAAS,EAAK,GAChDG,IAAWC,EAA4B,IAAI;AAEjD,EAAAC,EAAU,MAAM;AACd,IAAKR,MACLM,EAAS,SAAS,MAAA,GAClBA,EAAS,SAAS,eAAe;AAAA,MAC/B,UAAU;AAAA,MACV,OAAO;AAAA,IAAA,CACR;AAAA,EACH,GAAG,CAACN,CAAS,CAAC;AAEd,QAAMS,IAAe,YAAY;AAC/B,QAAI,GAACR,EAAQ,KAAA,KAAUG,IAEvB;AAAA,MAAAC,EAAgB,EAAI;AACpB,UAAI;AACF,cAAMT,EAASK,EAAQ,MAAM,GAC7BC,EAAW,EAAE;AAAA,MACf,UAAA;AACE,QAAAG,EAAgB,EAAK;AAAA,MACvB;AAAA;AAAA,EACF,GAEMK,IAAgB,CAACC,MAAgD;AACrE,IAAIA,EAAE,QAAQ,YAAYA,EAAE,WAAWA,EAAE,aACvCA,EAAE,eAAA,GACFF,EAAA;AAAA,EAEJ,GAEMG,IAAa,CAACX,EAAQ,KAAA,KAAUG;AAEtC,SACE,gBAAAS,EAAC,OAAA,EAAI,WAAWC,EAAO,MACrB,UAAA;AAAA,IAAA,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWD,EAAO;AAAA,QAClB,UAAUV;AAAA,QACV,UAAU,CAACO,MAAMT,EAAWS,EAAE,OAAO,KAAK;AAAA,QAC1C,WAAWD;AAAA,QACX,aAAAZ;AAAA,QACA,KAAKQ;AAAA,QACL,OAAOL;AAAA,MAAA;AAAA,IAAA;AAAA,IAET,gBAAAY,EAAC,OAAA,EAAI,WAAWC,EAAO,QACpB,UAAA;AAAA,MAAAjB,KACC,gBAAAkB;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAWD,EAAO;AAAA,UAClB,UAAUV;AAAA,UACV,SAASP;AAAA,UACT,MAAK;AAAA,UACN,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAIH,gBAAAkB;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAWD,EAAO;AAAA,UAClB,UAAUF;AAAA,UACV,SAASH;AAAA,UACT,MAAK;AAAA,UAEJ,cAAe,kBAAkBV;AAAA,QAAA;AAAA,MAAA;AAAA,IACpC,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const t = "_form_1lmwf_1", o = "_textarea_1lmwf_7", e = "_footer_1lmwf_20", n = "_cancelButton_1lmwf_29", _ = "_submitButton_1lmwf_37", c = {
|
|
2
|
+
form: t,
|
|
3
|
+
textarea: o,
|
|
4
|
+
footer: e,
|
|
5
|
+
cancelButton: n,
|
|
6
|
+
submitButton: _
|
|
7
|
+
};
|
|
8
|
+
export {
|
|
9
|
+
n as cancelButton,
|
|
10
|
+
c as default,
|
|
11
|
+
e as footer,
|
|
12
|
+
t as form,
|
|
13
|
+
_ as submitButton,
|
|
14
|
+
o as textarea
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=CommentForm.module.css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentForm.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Comment } from '../payload-types';
|
|
2
|
+
import { PopulatedComment } from '../types';
|
|
3
|
+
export interface CommentItemProps {
|
|
4
|
+
comment: PopulatedComment;
|
|
5
|
+
depth?: number;
|
|
6
|
+
onReply: (parentId: Comment['id'], content: string) => Promise<void>;
|
|
7
|
+
forceCollapse?: boolean;
|
|
8
|
+
maxDepth: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function CommentItem({ comment, depth, onReply, forceCollapse, maxDepth, }: CommentItemProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=CommentItem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentItem.d.ts","sourceRoot":"","sources":["../../src/components/CommentItem.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAGjD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,KAAS,EACT,OAAO,EACP,aAAa,EACb,QAAQ,GACT,EAAE,gBAAgB,2CAqGlB"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as o, jsx as s } from "react/jsx-runtime";
|
|
3
|
+
import { useTranslation as F, formatTimeToNow as S } from "@payloadcms/ui";
|
|
4
|
+
import { useState as p } from "react";
|
|
5
|
+
import { CommentForm as g } from "./CommentForm.js";
|
|
6
|
+
import e from "./CommentItem.module.css.js";
|
|
7
|
+
function k({
|
|
8
|
+
comment: l,
|
|
9
|
+
depth: a = 0,
|
|
10
|
+
onReply: d,
|
|
11
|
+
forceCollapse: m,
|
|
12
|
+
maxDepth: u
|
|
13
|
+
}) {
|
|
14
|
+
const { i18n: R } = F(), [h, i] = p(!1), [r, f] = p(a === 0), [y, c] = p(!1), n = l.replies ?? [], N = a < u, b = m ? !1 : h ? !0 : n.length === 0 ? !1 : r, w = async (t) => {
|
|
15
|
+
await d(l.id, t), i(!1), f(!0), c(!1);
|
|
16
|
+
}, C = () => {
|
|
17
|
+
c(!0), i(!0);
|
|
18
|
+
}, v = () => {
|
|
19
|
+
i(!1), c(!1);
|
|
20
|
+
};
|
|
21
|
+
return /* @__PURE__ */ o("div", { children: [
|
|
22
|
+
/* @__PURE__ */ o("div", { className: e.bubble, children: [
|
|
23
|
+
/* @__PURE__ */ o("div", { className: e.header, children: [
|
|
24
|
+
/* @__PURE__ */ s("span", { className: e.author, children: l.author?.displayName || "Unknown" }),
|
|
25
|
+
/* @__PURE__ */ s("span", { children: S({ date: l.createdAt, i18n: R }) })
|
|
26
|
+
] }),
|
|
27
|
+
/* @__PURE__ */ s("div", { className: e.content, children: l.content })
|
|
28
|
+
] }),
|
|
29
|
+
N && !m && /* @__PURE__ */ o("div", { className: e.actions, children: [
|
|
30
|
+
/* @__PURE__ */ s(
|
|
31
|
+
"button",
|
|
32
|
+
{
|
|
33
|
+
className: e.actionButton,
|
|
34
|
+
onClick: C,
|
|
35
|
+
type: "button",
|
|
36
|
+
children: "Reply"
|
|
37
|
+
}
|
|
38
|
+
),
|
|
39
|
+
n.length > 0 && /* @__PURE__ */ s(
|
|
40
|
+
"button",
|
|
41
|
+
{
|
|
42
|
+
className: e.actionButton,
|
|
43
|
+
onClick: () => f((t) => !t),
|
|
44
|
+
type: "button",
|
|
45
|
+
children: `${r ? "Hide Replies" : "Show Replies"} (${n.length})`
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
] }),
|
|
49
|
+
b && /* @__PURE__ */ o("div", { className: e.replies, children: [
|
|
50
|
+
n.length > 0 && r && /* @__PURE__ */ s("div", { className: e.repliesList, children: n.map((t) => /* @__PURE__ */ s(
|
|
51
|
+
k,
|
|
52
|
+
{
|
|
53
|
+
comment: t,
|
|
54
|
+
depth: a + 1,
|
|
55
|
+
forceCollapse: y,
|
|
56
|
+
maxDepth: u,
|
|
57
|
+
onReply: d
|
|
58
|
+
},
|
|
59
|
+
t.id
|
|
60
|
+
)) }),
|
|
61
|
+
h && /* @__PURE__ */ s(
|
|
62
|
+
g,
|
|
63
|
+
{
|
|
64
|
+
autoFocus: !0,
|
|
65
|
+
onCancel: v,
|
|
66
|
+
onSubmit: w,
|
|
67
|
+
placeholder: "Write a reply...",
|
|
68
|
+
submitLabel: "Reply"
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
] })
|
|
72
|
+
] });
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
k as CommentItem
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=CommentItem.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentItem.js","sources":["../../src/components/CommentItem.tsx"],"sourcesContent":["'use client';\n\nimport { formatTimeToNow, useTranslation } from '@payloadcms/ui';\nimport { useState } from 'react';\nimport type { Comment } from '@/payload-types';\nimport type { PopulatedComment } from '../types';\nimport { CommentForm } from './CommentForm';\nimport styles from './CommentItem.module.css';\nexport interface CommentItemProps {\n comment: PopulatedComment;\n depth?: number;\n onReply: (parentId: Comment['id'], content: string) => Promise<void>;\n forceCollapse?: boolean;\n maxDepth: number;\n}\n\nexport function CommentItem({\n comment,\n depth = 0,\n onReply,\n forceCollapse,\n maxDepth,\n}: CommentItemProps) {\n const { i18n } = useTranslation();\n const [showReplyForm, setShowReplyForm] = useState(false);\n const [showReplies, setShowReplies] = useState(depth === 0);\n const [forceCollapseReplies, setForceCollapseReplies] = useState(false);\n\n const replies = comment.replies ?? [];\n const canReply = depth < maxDepth;\n\n const isExpanded = (() => {\n if (forceCollapse) return false;\n if (showReplyForm) return true;\n if (replies.length === 0) return false;\n\n return showReplies;\n })();\n\n const handleReply = async (content: string) => {\n await onReply(comment.id, content);\n setShowReplyForm(false);\n setShowReplies(true);\n setForceCollapseReplies(false);\n };\n\n const handleOpenReplyForm = () => {\n setForceCollapseReplies(true);\n setShowReplyForm(true);\n };\n\n const handleCloseReplyForm = () => {\n setShowReplyForm(false);\n setForceCollapseReplies(false);\n };\n\n return (\n <div>\n <div className={styles.bubble}>\n <div className={styles.header}>\n <span className={styles.author}>\n {comment.author?.displayName || 'Unknown'}\n </span>\n <span>{formatTimeToNow({ date: comment.createdAt, i18n })}</span>\n </div>\n\n <div className={styles.content}>{comment.content}</div>\n </div>\n\n {canReply && !forceCollapse && (\n <div className={styles.actions}>\n <button\n className={styles.actionButton}\n onClick={handleOpenReplyForm}\n type=\"button\"\n >\n Reply\n </button>\n\n {replies.length > 0 && (\n <button\n className={styles.actionButton}\n onClick={() => setShowReplies((current) => !current)}\n type=\"button\"\n >\n {`${showReplies ? 'Hide Replies' : `Show Replies`} (${\n replies.length\n })`}\n </button>\n )}\n </div>\n )}\n\n {isExpanded && (\n <div className={styles.replies}>\n {replies.length > 0 && showReplies && (\n <div className={styles.repliesList}>\n {replies.map((reply) => (\n <CommentItem\n comment={reply}\n depth={depth + 1}\n forceCollapse={forceCollapseReplies}\n key={reply.id}\n maxDepth={maxDepth}\n onReply={onReply}\n />\n ))}\n </div>\n )}\n\n {showReplyForm && (\n <CommentForm\n autoFocus\n onCancel={handleCloseReplyForm}\n onSubmit={handleReply}\n placeholder=\"Write a reply...\"\n submitLabel=\"Reply\"\n />\n )}\n </div>\n )}\n </div>\n );\n}\n"],"names":["CommentItem","comment","depth","onReply","forceCollapse","maxDepth","i18n","useTranslation","showReplyForm","setShowReplyForm","useState","showReplies","setShowReplies","forceCollapseReplies","setForceCollapseReplies","replies","canReply","isExpanded","handleReply","content","handleOpenReplyForm","handleCloseReplyForm","jsxs","styles","jsx","formatTimeToNow","current","reply","CommentForm"],"mappings":";;;;;;AAgBO,SAASA,EAAY;AAAA,EAC1B,SAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,SAAAC;AAAA,EACA,eAAAC;AAAA,EACA,UAAAC;AACF,GAAqB;AACnB,QAAM,EAAE,MAAAC,EAAA,IAASC,EAAA,GACX,CAACC,GAAeC,CAAgB,IAAIC,EAAS,EAAK,GAClD,CAACC,GAAaC,CAAc,IAAIF,EAASR,MAAU,CAAC,GACpD,CAACW,GAAsBC,CAAuB,IAAIJ,EAAS,EAAK,GAEhEK,IAAUd,EAAQ,WAAW,CAAA,GAC7Be,IAAWd,IAAQG,GAEnBY,IACAb,IAAsB,KACtBI,IAAsB,KACtBO,EAAQ,WAAW,IAAU,KAE1BJ,GAGHO,IAAc,OAAOC,MAAoB;AAC7C,UAAMhB,EAAQF,EAAQ,IAAIkB,CAAO,GACjCV,EAAiB,EAAK,GACtBG,EAAe,EAAI,GACnBE,EAAwB,EAAK;AAAA,EAC/B,GAEMM,IAAsB,MAAM;AAChC,IAAAN,EAAwB,EAAI,GAC5BL,EAAiB,EAAI;AAAA,EACvB,GAEMY,IAAuB,MAAM;AACjC,IAAAZ,EAAiB,EAAK,GACtBK,EAAwB,EAAK;AAAA,EAC/B;AAEA,2BACG,OAAA,EACC,UAAA;AAAA,IAAA,gBAAAQ,EAAC,OAAA,EAAI,WAAWC,EAAO,QACrB,UAAA;AAAA,MAAA,gBAAAD,EAAC,OAAA,EAAI,WAAWC,EAAO,QACrB,UAAA;AAAA,QAAA,gBAAAC,EAAC,UAAK,WAAWD,EAAO,QACrB,UAAAtB,EAAQ,QAAQ,eAAe,UAAA,CAClC;AAAA,QACA,gBAAAuB,EAAC,UAAM,UAAAC,EAAgB,EAAE,MAAMxB,EAAQ,WAAW,MAAAK,EAAA,CAAM,EAAA,CAAE;AAAA,MAAA,GAC5D;AAAA,wBAEC,OAAA,EAAI,WAAWiB,EAAO,SAAU,YAAQ,QAAA,CAAQ;AAAA,IAAA,GACnD;AAAA,IAECP,KAAY,CAACZ,uBACX,OAAA,EAAI,WAAWmB,EAAO,SACrB,UAAA;AAAA,MAAA,gBAAAC;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAWD,EAAO;AAAA,UAClB,SAASH;AAAA,UACT,MAAK;AAAA,UACN,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAIAL,EAAQ,SAAS,KAChB,gBAAAS;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAWD,EAAO;AAAA,UAClB,SAAS,MAAMX,EAAe,CAACc,MAAY,CAACA,CAAO;AAAA,UACnD,MAAK;AAAA,UAEJ,aAAGf,IAAc,iBAAiB,cAAc,KAC/CI,EAAQ,MACV;AAAA,QAAA;AAAA,MAAA;AAAA,IACF,GAEJ;AAAA,IAGDE,KACC,gBAAAK,EAAC,OAAA,EAAI,WAAWC,EAAO,SACpB,UAAA;AAAA,MAAAR,EAAQ,SAAS,KAAKJ,KACrB,gBAAAa,EAAC,OAAA,EAAI,WAAWD,EAAO,aACpB,UAAAR,EAAQ,IAAI,CAACY,MACZ,gBAAAH;AAAA,QAACxB;AAAA,QAAA;AAAA,UACC,SAAS2B;AAAA,UACT,OAAOzB,IAAQ;AAAA,UACf,eAAeW;AAAA,UAEf,UAAAR;AAAA,UACA,SAAAF;AAAA,QAAA;AAAA,QAFKwB,EAAM;AAAA,MAAA,CAId,GACH;AAAA,MAGDnB,KACC,gBAAAgB;AAAA,QAACI;AAAA,QAAA;AAAA,UACC,WAAS;AAAA,UACT,UAAUP;AAAA,UACV,UAAUH;AAAA,UACV,aAAY;AAAA,UACZ,aAAY;AAAA,QAAA;AAAA,MAAA;AAAA,IACd,EAAA,CAEJ;AAAA,EAAA,GAEJ;AAEJ;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const t = "_bubble_1o6c7_1", o = "_header_1o6c7_9", e = "_author_1o6c7_18", c = "_content_1o6c7_23", n = "_actions_1o6c7_29", s = "_actionButton_1o6c7_37", _ = "_replies_1o6c7_46", i = "_repliesList_1o6c7_57", a = {
|
|
2
|
+
bubble: t,
|
|
3
|
+
header: o,
|
|
4
|
+
author: e,
|
|
5
|
+
content: c,
|
|
6
|
+
actions: n,
|
|
7
|
+
actionButton: s,
|
|
8
|
+
replies: _,
|
|
9
|
+
repliesList: i
|
|
10
|
+
};
|
|
11
|
+
export {
|
|
12
|
+
s as actionButton,
|
|
13
|
+
n as actions,
|
|
14
|
+
e as author,
|
|
15
|
+
t as bubble,
|
|
16
|
+
c as content,
|
|
17
|
+
a as default,
|
|
18
|
+
o as header,
|
|
19
|
+
_ as replies,
|
|
20
|
+
i as repliesList
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=CommentItem.module.css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentItem.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { EntityID } from '@repo/common';
|
|
2
|
+
import { PopulatedComment } from '../types';
|
|
3
|
+
interface CommentListProps {
|
|
4
|
+
comments: PopulatedComment[];
|
|
5
|
+
isLoading?: boolean;
|
|
6
|
+
onReply: (parentId: EntityID, content: string) => Promise<void>;
|
|
7
|
+
maxDepth: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function CommentList({ comments, isLoading, onReply, maxDepth, }: CommentListProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=CommentList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentList.d.ts","sourceRoot":"","sources":["../../src/components/CommentList.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAIjD,UAAU,gBAAgB;IACxB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,SAAiB,EACjB,OAAO,EACP,QAAQ,GACT,EAAE,gBAAgB,2CAyBlB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as e } from "react/jsx-runtime";
|
|
3
|
+
import { CommentItem as s } from "./CommentItem.js";
|
|
4
|
+
import t from "./CommentList.module.css.js";
|
|
5
|
+
function d({
|
|
6
|
+
comments: r,
|
|
7
|
+
isLoading: m = !1,
|
|
8
|
+
onReply: o,
|
|
9
|
+
maxDepth: l
|
|
10
|
+
}) {
|
|
11
|
+
return m ? /* @__PURE__ */ e("div", { className: t.placeholder, children: "Loading comments..." }) : r.length === 0 ? /* @__PURE__ */ e("div", { className: t.placeholder, children: "No comments yet. Be the first to comment!" }) : /* @__PURE__ */ e("div", { className: t.list, children: r.map((i) => /* @__PURE__ */ e(
|
|
12
|
+
s,
|
|
13
|
+
{
|
|
14
|
+
comment: i,
|
|
15
|
+
maxDepth: l,
|
|
16
|
+
onReply: o
|
|
17
|
+
},
|
|
18
|
+
i.id
|
|
19
|
+
)) });
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
d as CommentList
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=CommentList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentList.js","sources":["../../src/components/CommentList.tsx"],"sourcesContent":["'use client';\n\nimport type { EntityID } from '@repo/common';\nimport type { PopulatedComment } from '../types';\nimport { CommentItem } from './CommentItem';\nimport styles from './CommentList.module.css';\n\ninterface CommentListProps {\n comments: PopulatedComment[];\n isLoading?: boolean;\n onReply: (parentId: EntityID, content: string) => Promise<void>;\n maxDepth: number;\n}\n\nexport function CommentList({\n comments,\n isLoading = false,\n onReply,\n maxDepth,\n}: CommentListProps) {\n if (isLoading) {\n return <div className={styles.placeholder}>Loading comments...</div>;\n }\n\n if (comments.length === 0) {\n return (\n <div className={styles.placeholder}>\n No comments yet. Be the first to comment!\n </div>\n );\n }\n\n return (\n <div className={styles.list}>\n {comments.map((comment) => (\n <CommentItem\n comment={comment}\n key={comment.id}\n maxDepth={maxDepth}\n onReply={onReply}\n />\n ))}\n </div>\n );\n}\n"],"names":["CommentList","comments","isLoading","onReply","maxDepth","jsx","styles","comment","CommentItem"],"mappings":";;;;AAcO,SAASA,EAAY;AAAA,EAC1B,UAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,SAAAC;AAAA,EACA,UAAAC;AACF,GAAqB;AACnB,SAAIF,IACK,gBAAAG,EAAC,OAAA,EAAI,WAAWC,EAAO,aAAa,UAAA,uBAAmB,IAG5DL,EAAS,WAAW,IAEpB,gBAAAI,EAAC,OAAA,EAAI,WAAWC,EAAO,aAAa,UAAA,6CAEpC,IAKF,gBAAAD,EAAC,SAAI,WAAWC,EAAO,MACpB,UAAAL,EAAS,IAAI,CAACM,MACb,gBAAAF;AAAA,IAACG;AAAA,IAAA;AAAA,MACC,SAAAD;AAAA,MAEA,UAAAH;AAAA,MACA,SAAAD;AAAA,IAAA;AAAA,IAFKI,EAAQ;AAAA,EAAA,CAIhB,GACH;AAEJ;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentList.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PopulatedComment } from '../types';
|
|
2
|
+
interface DiscussionsClientProps {
|
|
3
|
+
initialComments: PopulatedComment[];
|
|
4
|
+
documentId: number | string;
|
|
5
|
+
documentCollectionSlug: string;
|
|
6
|
+
maxDepth: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function DiscussionsClient({ initialComments, documentId, documentCollectionSlug, maxDepth, }: DiscussionsClientProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=Discussions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Discussions.d.ts","sourceRoot":"","sources":["../../src/components/Discussions.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAKjD,UAAU,sBAAsB;IAC9B,eAAe,EAAE,gBAAgB,EAAE,CAAC;IACpC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,eAAe,EACf,UAAU,EACV,sBAAsB,EACtB,QAAQ,GACT,EAAE,sBAAsB,2CA0DxB"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as R, jsx as a } from "react/jsx-runtime";
|
|
3
|
+
import { useConfig as b } from "@payloadcms/ui";
|
|
4
|
+
import { useState as h, useCallback as g } from "react";
|
|
5
|
+
import { ENDPOINTS as i } from "../procedures.js";
|
|
6
|
+
import { CommentForm as x } from "./CommentForm.js";
|
|
7
|
+
import { CommentList as L } from "./CommentList.js";
|
|
8
|
+
import N from "./Discussions.module.css.js";
|
|
9
|
+
function E({
|
|
10
|
+
initialComments: p,
|
|
11
|
+
documentId: c,
|
|
12
|
+
documentCollectionSlug: u,
|
|
13
|
+
maxDepth: f
|
|
14
|
+
}) {
|
|
15
|
+
const {
|
|
16
|
+
config: {
|
|
17
|
+
routes: { api: t }
|
|
18
|
+
}
|
|
19
|
+
} = b(), [d, m] = h(p), C = async (o) => {
|
|
20
|
+
const s = await i.createComment.call(t, {
|
|
21
|
+
documentCollectionSlug: u,
|
|
22
|
+
documentId: c,
|
|
23
|
+
content: o
|
|
24
|
+
});
|
|
25
|
+
m((n) => [s, ...n]);
|
|
26
|
+
}, y = g(
|
|
27
|
+
async (o, s) => {
|
|
28
|
+
const n = await i.createReply.call(t, {
|
|
29
|
+
parentId: o,
|
|
30
|
+
content: s
|
|
31
|
+
}), r = (l) => l.map(
|
|
32
|
+
(e) => e.id === o ? {
|
|
33
|
+
...e,
|
|
34
|
+
replies: [...e.replies || [], n]
|
|
35
|
+
} : {
|
|
36
|
+
...e,
|
|
37
|
+
replies: e.replies ? r(e.replies) : null
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
m((l) => r(l));
|
|
41
|
+
},
|
|
42
|
+
[t]
|
|
43
|
+
);
|
|
44
|
+
return /* @__PURE__ */ R("div", { className: N.root, children: [
|
|
45
|
+
/* @__PURE__ */ a(
|
|
46
|
+
x,
|
|
47
|
+
{
|
|
48
|
+
onSubmit: C,
|
|
49
|
+
placeholder: "Add a comment...",
|
|
50
|
+
submitLabel: "Comment"
|
|
51
|
+
}
|
|
52
|
+
),
|
|
53
|
+
/* @__PURE__ */ a(
|
|
54
|
+
L,
|
|
55
|
+
{
|
|
56
|
+
comments: d,
|
|
57
|
+
isLoading: !1,
|
|
58
|
+
maxDepth: f,
|
|
59
|
+
onReply: y
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
] });
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
E as DiscussionsClient
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=Discussions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Discussions.js","sources":["../../src/components/Discussions.tsx"],"sourcesContent":["'use client';\n\nimport { useConfig } from '@payloadcms/ui';\nimport type { EntityID } from '@repo/common';\nimport { useCallback, useState } from 'react';\nimport { ENDPOINTS } from '@/procedures';\nimport type { PopulatedComment } from '../types';\nimport { CommentForm } from './CommentForm';\nimport { CommentList } from './CommentList';\nimport styles from './Discussions.module.css';\n\ninterface DiscussionsClientProps {\n initialComments: PopulatedComment[];\n documentId: number | string;\n documentCollectionSlug: string;\n maxDepth: number;\n}\n\nexport function DiscussionsClient({\n initialComments,\n documentId,\n documentCollectionSlug,\n maxDepth,\n}: DiscussionsClientProps) {\n const {\n config: {\n routes: { api: apiRoute },\n },\n } = useConfig();\n const [comments, setComments] = useState(initialComments);\n\n const handleCreateComment = async (content: string) => {\n const populated = await ENDPOINTS.createComment.call(apiRoute, {\n documentCollectionSlug,\n documentId,\n content,\n });\n setComments((prev) => [populated, ...prev]);\n };\n\n const handleReply = useCallback(\n async (parentId: EntityID, content: string) => {\n const populated = await ENDPOINTS.createReply.call(apiRoute, {\n parentId,\n content,\n });\n\n const insertReply = (items: PopulatedComment[]): PopulatedComment[] =>\n items.map((item) =>\n item.id === parentId\n ? {\n ...item,\n replies: [...(item.replies || []), populated],\n }\n : {\n ...item,\n replies: item.replies ? insertReply(item.replies) : null,\n },\n );\n\n setComments((prev) => insertReply(prev));\n },\n [apiRoute],\n );\n\n return (\n <div className={styles.root}>\n <CommentForm\n onSubmit={handleCreateComment}\n placeholder=\"Add a comment...\"\n submitLabel=\"Comment\"\n />\n\n <CommentList\n comments={comments}\n isLoading={false}\n maxDepth={maxDepth}\n onReply={handleReply}\n />\n </div>\n );\n}\n"],"names":["DiscussionsClient","initialComments","documentId","documentCollectionSlug","maxDepth","apiRoute","useConfig","comments","setComments","useState","handleCreateComment","content","populated","ENDPOINTS","prev","handleReply","useCallback","parentId","insertReply","items","item","jsxs","styles","jsx","CommentForm","CommentList"],"mappings":";;;;;;;;AAkBO,SAASA,EAAkB;AAAA,EAChC,iBAAAC;AAAA,EACA,YAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,UAAAC;AACF,GAA2B;AACzB,QAAM;AAAA,IACJ,QAAQ;AAAA,MACN,QAAQ,EAAE,KAAKC,EAAA;AAAA,IAAS;AAAA,EAC1B,IACEC,EAAA,GACE,CAACC,GAAUC,CAAW,IAAIC,EAASR,CAAe,GAElDS,IAAsB,OAAOC,MAAoB;AACrD,UAAMC,IAAY,MAAMC,EAAU,cAAc,KAAKR,GAAU;AAAA,MAC7D,wBAAAF;AAAA,MACA,YAAAD;AAAA,MACA,SAAAS;AAAA,IAAA,CACD;AACD,IAAAH,EAAY,CAACM,MAAS,CAACF,GAAW,GAAGE,CAAI,CAAC;AAAA,EAC5C,GAEMC,IAAcC;AAAA,IAClB,OAAOC,GAAoBN,MAAoB;AAC7C,YAAMC,IAAY,MAAMC,EAAU,YAAY,KAAKR,GAAU;AAAA,QAC3D,UAAAY;AAAA,QACA,SAAAN;AAAA,MAAA,CACD,GAEKO,IAAc,CAACC,MACnBA,EAAM;AAAA,QAAI,CAACC,MACTA,EAAK,OAAOH,IACR;AAAA,UACE,GAAGG;AAAA,UACH,SAAS,CAAC,GAAIA,EAAK,WAAW,CAAA,GAAKR,CAAS;AAAA,QAAA,IAE9C;AAAA,UACE,GAAGQ;AAAA,UACH,SAASA,EAAK,UAAUF,EAAYE,EAAK,OAAO,IAAI;AAAA,QAAA;AAAA,MACtD;AAGR,MAAAZ,EAAY,CAACM,MAASI,EAAYJ,CAAI,CAAC;AAAA,IACzC;AAAA,IACA,CAACT,CAAQ;AAAA,EAAA;AAGX,SACE,gBAAAgB,EAAC,OAAA,EAAI,WAAWC,EAAO,MACrB,UAAA;AAAA,IAAA,gBAAAC;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,UAAUd;AAAA,QACV,aAAY;AAAA,QACZ,aAAY;AAAA,MAAA;AAAA,IAAA;AAAA,IAGd,gBAAAa;AAAA,MAACE;AAAA,MAAA;AAAA,QACC,UAAAlB;AAAA,QACA,WAAW;AAAA,QACX,UAAAH;AAAA,QACA,SAASW;AAAA,MAAA;AAAA,IAAA;AAAA,EACX,GACF;AAEJ;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Discussions.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscussionsCell.d.ts","sourceRoot":"","sources":["../../src/components/DiscussionsCell.tsx"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;CACvC,2CAGA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscussionsCell.js","sources":["../../src/components/DiscussionsCell.tsx"],"sourcesContent":["export function DiscussionsCell({\n cellData,\n}: {\n cellData: number[] | null | undefined;\n}) {\n const count = cellData?.length ?? 0;\n return <span>{count}</span>;\n}\n"],"names":["DiscussionsCell","cellData","count","jsx"],"mappings":";AAAO,SAASA,EAAgB;AAAA,EAC9B,UAAAC;AACF,GAEG;AACD,QAAMC,IAAQD,GAAU,UAAU;AAClC,SAAO,gBAAAE,EAAC,UAAM,UAAAD,EAAA,CAAM;AACtB;"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ServerComponentProps } from 'payload';
|
|
2
|
+
import { FieldConfig } from '../types';
|
|
3
|
+
export declare const DiscussionsField: ({ payload, data, id, collectionSlug, commentsCollectionSlug, maxDepth, }: ServerComponentProps & FieldConfig) => Promise<import("react/jsx-runtime").JSX.Element>;
|
|
4
|
+
//# sourceMappingURL=DiscussionsField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscussionsField.d.ts","sourceRoot":"","sources":["../../src/components/DiscussionsField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEpE,OAAO,KAAK,EAAE,WAAW,EAAoB,MAAM,UAAU,CAAC;AAG9D,eAAO,MAAM,gBAAgB,6EAO1B,oBAAoB,GAAG,WAAW,qDA8BpC,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx as d } from "react/jsx-runtime";
|
|
2
|
+
import { populateComment as l } from "../utitls/populate-comment.js";
|
|
3
|
+
import { DiscussionsClient as f } from "./Discussions.js";
|
|
4
|
+
const h = async ({
|
|
5
|
+
payload: s,
|
|
6
|
+
data: t,
|
|
7
|
+
id: o,
|
|
8
|
+
collectionSlug: e,
|
|
9
|
+
commentsCollectionSlug: c,
|
|
10
|
+
maxDepth: i
|
|
11
|
+
}) => {
|
|
12
|
+
if (o === void 0)
|
|
13
|
+
throw new Error("Discussions field can only be used on existing documents");
|
|
14
|
+
const n = t?.discussions || [];
|
|
15
|
+
s.collections.users.config.admin.useAsTitle;
|
|
16
|
+
const r = n.length > 0 ? await s.find({
|
|
17
|
+
collection: c,
|
|
18
|
+
where: { id: { in: n } },
|
|
19
|
+
sort: "-createdAt",
|
|
20
|
+
depth: i
|
|
21
|
+
}).then(
|
|
22
|
+
({ docs: m }) => m.map((u) => l(u, s))
|
|
23
|
+
) : [];
|
|
24
|
+
return /* @__PURE__ */ d(
|
|
25
|
+
f,
|
|
26
|
+
{
|
|
27
|
+
documentCollectionSlug: e,
|
|
28
|
+
documentId: o,
|
|
29
|
+
initialComments: r,
|
|
30
|
+
maxDepth: i
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
export {
|
|
35
|
+
h as DiscussionsField
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=DiscussionsField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscussionsField.js","sources":["../../src/components/DiscussionsField.tsx"],"sourcesContent":["import type { CollectionSlug, ServerComponentProps } from 'payload';\nimport { populateComment } from '@/utitls/populate-comment';\nimport type { FieldConfig, PopulatedComment } from '../types';\nimport { DiscussionsClient } from './Discussions';\n\nexport const DiscussionsField = async ({\n payload,\n data,\n id,\n collectionSlug,\n commentsCollectionSlug,\n maxDepth,\n}: ServerComponentProps & FieldConfig) => {\n if (id === undefined)\n throw new Error('Discussions field can only be used on existing documents');\n\n const discussionIds: number[] = (data?.discussions as number[]) || [];\n\n payload.collections.users.config.admin.useAsTitle;\n\n const comments: PopulatedComment[] =\n discussionIds.length > 0\n ? await payload\n .find({\n collection: commentsCollectionSlug as 'comments',\n where: { id: { in: discussionIds } },\n sort: '-createdAt',\n depth: maxDepth,\n })\n .then(({ docs }) =>\n docs.map((comment) => populateComment(comment, payload)),\n )\n : [];\n\n return (\n <DiscussionsClient\n documentCollectionSlug={collectionSlug}\n documentId={id}\n initialComments={comments}\n maxDepth={maxDepth}\n />\n );\n};\n"],"names":["DiscussionsField","payload","data","id","collectionSlug","commentsCollectionSlug","maxDepth","discussionIds","comments","docs","comment","populateComment","jsx","DiscussionsClient"],"mappings":";;;AAKO,MAAMA,IAAmB,OAAO;AAAA,EACrC,SAAAC;AAAA,EACA,MAAAC;AAAA,EACA,IAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,UAAAC;AACF,MAA0C;AACxC,MAAIH,MAAO;AACT,UAAM,IAAI,MAAM,0DAA0D;AAE5E,QAAMI,IAA2BL,GAAM,eAA4B,CAAA;AAEnE,EAAAD,EAAQ,YAAY,MAAM,OAAO,MAAM;AAEvC,QAAMO,IACJD,EAAc,SAAS,IACnB,MAAMN,EACH,KAAK;AAAA,IACJ,YAAYI;AAAA,IACZ,OAAO,EAAE,IAAI,EAAE,IAAIE,IAAc;AAAA,IACjC,MAAM;AAAA,IACN,OAAOD;AAAA,EAAA,CACR,EACA;AAAA,IAAK,CAAC,EAAE,MAAAG,EAAA,MACPA,EAAK,IAAI,CAACC,MAAYC,EAAgBD,GAAST,CAAO,CAAC;AAAA,EAAA,IAE3D,CAAA;AAEN,SACE,gBAAAW;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,wBAAwBT;AAAA,MACxB,YAAYD;AAAA,MACZ,iBAAiBK;AAAA,MACjB,UAAAF;AAAA,IAAA;AAAA,EAAA;AAGN;"}
|
package/dist/const.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"const.d.ts","sourceRoot":"","sources":["../src/const.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-comment.d.ts","sourceRoot":"","sources":["../../src/endpoints/create-comment.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAkB,QAAQ,EAAE,MAAM,SAAS,CAAC;AAMxD,eAAO,MAAM,qBAAqB,wBAE/B;IACD,cAAc,EAAE,MAAM,CAAC;CACxB,KAAG,QA0CD,CAAC"}
|