payload-nested-docs-page-tree 1.1.0

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 (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +132 -0
  3. package/dist/components/PageTreeContext.d.ts +15 -0
  4. package/dist/components/PageTreeContext.js +26 -0
  5. package/dist/components/PageTreeContext.js.map +1 -0
  6. package/dist/components/PageTreeListView.client.d.ts +17 -0
  7. package/dist/components/PageTreeListView.client.js +960 -0
  8. package/dist/components/PageTreeListView.client.js.map +1 -0
  9. package/dist/components/PageTreeListView.module.css +358 -0
  10. package/dist/components/PageTreeListView.server.d.ts +3 -0
  11. package/dist/components/PageTreeListView.server.js +390 -0
  12. package/dist/components/PageTreeListView.server.js.map +1 -0
  13. package/dist/components/PageTreeTitleCell.d.ts +6 -0
  14. package/dist/components/PageTreeTitleCell.js +80 -0
  15. package/dist/components/PageTreeTitleCell.js.map +1 -0
  16. package/dist/endpoints/createMovePageEndpoint.d.ts +5 -0
  17. package/dist/endpoints/createMovePageEndpoint.js +265 -0
  18. package/dist/endpoints/createMovePageEndpoint.js.map +1 -0
  19. package/dist/exports/client.d.ts +1 -0
  20. package/dist/exports/client.js +3 -0
  21. package/dist/exports/client.js.map +1 -0
  22. package/dist/exports/rsc.d.ts +1 -0
  23. package/dist/exports/rsc.js +3 -0
  24. package/dist/exports/rsc.js.map +1 -0
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.js +142 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/types.d.ts +35 -0
  29. package/dist/types.js +8 -0
  30. package/dist/types.js.map +1 -0
  31. package/dist/utilities/badgeConfig.d.ts +2 -0
  32. package/dist/utilities/badgeConfig.js +30 -0
  33. package/dist/utilities/badgeConfig.js.map +1 -0
  34. package/dist/utilities/dropTargets.d.ts +31 -0
  35. package/dist/utilities/dropTargets.js +73 -0
  36. package/dist/utilities/dropTargets.js.map +1 -0
  37. package/dist/utilities/moveValidation.d.ts +11 -0
  38. package/dist/utilities/moveValidation.js +44 -0
  39. package/dist/utilities/moveValidation.js.map +1 -0
  40. package/dist/utilities/pageTree.d.ts +37 -0
  41. package/dist/utilities/pageTree.js +300 -0
  42. package/dist/utilities/pageTree.js.map +1 -0
  43. package/dist/utilities/pageTreeCollision.d.ts +16 -0
  44. package/dist/utilities/pageTreeCollision.js +70 -0
  45. package/dist/utilities/pageTreeCollision.js.map +1 -0
  46. package/dist/utilities/pageTreeConfig.d.ts +3 -0
  47. package/dist/utilities/pageTreeConfig.js +21 -0
  48. package/dist/utilities/pageTreeConfig.js.map +1 -0
  49. package/dist/utilities/status.d.ts +17 -0
  50. package/dist/utilities/status.js +72 -0
  51. package/dist/utilities/status.js.map +1 -0
  52. package/package.json +115 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 WLF Studios
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # Payload Nested Docs Page Tree
2
+
3
+ Companion admin plugin for [`@payloadcms/plugin-nested-docs`](https://payloadcms.com/docs/plugins/nested-docs).
4
+
5
+ <p align="center">
6
+ <img alt="Page tree demo" src="assets/page-tree.gif" width="100%" />
7
+ </p>
8
+
9
+ Adds a nested tree list view for nested docs collections in Payload admin, with drag-and-drop parent changes and status badges for published / changed / draft documents.
10
+
11
+ It works alongside `@payloadcms/plugin-nested-docs`. It does not replace nested docs persistence, breadcrumbs generation, or routing.
12
+
13
+ Tested with Payload `3.84.1` and Next.js `16.2`.
14
+
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ pnpm add payload-nested-docs-page-tree
20
+ ```
21
+
22
+ ## Quick Setup
23
+
24
+ `@payloadcms/plugin-nested-docs` should already be installed, and each target collection should already have:
25
+
26
+ - a nested docs parent field
27
+ - a nested docs breadcrumbs field
28
+ - a top-level `admin.useAsTitle` field
29
+
30
+ Add `nestedDocsPageTreePlugin(...)` right after `nestedDocsPlugin(...)`:
31
+
32
+ ```ts
33
+ import { nestedDocsPlugin } from '@payloadcms/plugin-nested-docs'
34
+ import { nestedDocsPageTreePlugin } from 'payload-nested-docs-page-tree'
35
+
36
+ export const plugins = [
37
+ nestedDocsPlugin({
38
+ // your existing nested docs config
39
+ }),
40
+ nestedDocsPageTreePlugin({
41
+ collections: ['pages'],
42
+ }),
43
+ ]
44
+ ```
45
+
46
+ If needed, refresh the admin import map:
47
+
48
+ ```bash
49
+ payload generate:importmap
50
+ ```
51
+
52
+ ## What It Adds
53
+
54
+ - replaces the collection list view with a nested tree table
55
+ - preserves sorting, filters, pagination, bulk selection, and row actions
56
+ - adds `POST /:id/move` for drag-and-drop parent changes
57
+ - hides the read-only breadcrumbs field by default
58
+
59
+ ## Status Badges
60
+
61
+ The tree view supports three document states:
62
+
63
+ - `published`: live and up to date
64
+ - `changed`: live, but has unpublished changes
65
+ - `draft`: not published
66
+
67
+ To override badge labels or colors, pass a `badges` object:
68
+
69
+ ```ts
70
+ nestedDocsPageTreePlugin({
71
+ collections: ['pages'],
72
+ badges: {
73
+ labels: {
74
+ published: 'Live',
75
+ changed: 'Has Changes',
76
+ draft: 'Draft Only',
77
+ },
78
+ colors: {
79
+ published: '#1e90ff',
80
+ changed: '#9333ea',
81
+ draft: '#dc2626',
82
+ },
83
+ },
84
+ }),
85
+ ```
86
+
87
+ `labels` and `colors` are optional partial overrides. Missing entries fall back to the built-in defaults.
88
+
89
+ ## Configuration
90
+
91
+ - `collections`: target collection slugs
92
+ - `parentFieldSlug`: defaults to `'parent'`
93
+ - `breadcrumbsFieldSlug`: defaults to `'breadcrumbs'`
94
+ - `defaultLimit`: defaults to `100`
95
+ - `hideBreadcrumbs`: defaults to `true`
96
+ - `disabled`: defaults to `false`
97
+ - `badges`: optional label and color overrides for `published`, `changed`, and `draft`
98
+
99
+ ## Development
100
+
101
+ For local plugin development, use the internal `dev/` app:
102
+
103
+ ```bash
104
+ pnpm install
105
+ pnpm dev
106
+ pnpm generate:types
107
+ pnpm generate:importmap
108
+ ```
109
+
110
+ Plugin source is in `src/`. The internal test app is in `dev/`.
111
+
112
+ For checks:
113
+
114
+ ```bash
115
+ pnpm test:int
116
+ pnpm exec tsc --noEmit
117
+ ```
118
+
119
+ ## Test in Another Project
120
+
121
+ For release validation, test the packed artifact instead of a live source-folder dependency:
122
+
123
+ ```bash
124
+ pnpm build
125
+ pnpm pack
126
+ ```
127
+
128
+ Then in the external consumer app:
129
+
130
+ ```bash
131
+ pnpm add /path/payload-nested-docs-page-tree-*.tgz
132
+ ```
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ type PageTreeContextValue = {
3
+ activeDragRowID: null | string;
4
+ canMoveDocs: boolean;
5
+ collapsedIDs: ReadonlySet<string>;
6
+ disableMoveDrag?: boolean;
7
+ pendingMoveRowID: null | string;
8
+ toggleRow: (rowID: string) => void;
9
+ };
10
+ export declare function PageTreeProvider({ children, value, }: {
11
+ children: React.ReactNode;
12
+ value: PageTreeContextValue;
13
+ }): import("react/jsx-runtime").JSX.Element;
14
+ export declare function usePageTree(): PageTreeContextValue;
15
+ export {};
@@ -0,0 +1,26 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import React from 'react';
4
+ const PageTreeContext = /*#__PURE__*/ React.createContext(null);
5
+ export function PageTreeProvider({ children, value }) {
6
+ return /*#__PURE__*/ _jsx(PageTreeContext.Provider, {
7
+ value: value,
8
+ children: children
9
+ });
10
+ }
11
+ export function usePageTree() {
12
+ const context = React.useContext(PageTreeContext);
13
+ if (!context) {
14
+ return {
15
+ activeDragRowID: null,
16
+ canMoveDocs: false,
17
+ collapsedIDs: new Set(),
18
+ disableMoveDrag: false,
19
+ pendingMoveRowID: null,
20
+ toggleRow: ()=>{}
21
+ };
22
+ }
23
+ return context;
24
+ }
25
+
26
+ //# sourceMappingURL=PageTreeContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/PageTreeContext.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\n\ntype PageTreeContextValue = {\n activeDragRowID: null | string\n canMoveDocs: boolean\n collapsedIDs: ReadonlySet<string>\n disableMoveDrag?: boolean\n pendingMoveRowID: null | string\n toggleRow: (rowID: string) => void\n}\n\nconst PageTreeContext = React.createContext<null | PageTreeContextValue>(null)\n\nexport function PageTreeProvider({\n children,\n value,\n}: {\n children: React.ReactNode\n value: PageTreeContextValue\n}) {\n return <PageTreeContext.Provider value={value}>{children}</PageTreeContext.Provider>\n}\n\nexport function usePageTree(): PageTreeContextValue {\n const context = React.useContext(PageTreeContext)\n\n if (!context) {\n return {\n activeDragRowID: null,\n canMoveDocs: false,\n collapsedIDs: new Set<string>(),\n disableMoveDrag: false,\n pendingMoveRowID: null,\n toggleRow: () => {},\n }\n }\n\n return context\n}\n"],"names":["React","PageTreeContext","createContext","PageTreeProvider","children","value","Provider","usePageTree","context","useContext","activeDragRowID","canMoveDocs","collapsedIDs","Set","disableMoveDrag","pendingMoveRowID","toggleRow"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AAWzB,MAAMC,gCAAkBD,MAAME,aAAa,CAA8B;AAEzE,OAAO,SAASC,iBAAiB,EAC/BC,QAAQ,EACRC,KAAK,EAIN;IACC,qBAAO,KAACJ,gBAAgBK,QAAQ;QAACD,OAAOA;kBAAQD;;AAClD;AAEA,OAAO,SAASG;IACd,MAAMC,UAAUR,MAAMS,UAAU,CAACR;IAEjC,IAAI,CAACO,SAAS;QACZ,OAAO;YACLE,iBAAiB;YACjBC,aAAa;YACbC,cAAc,IAAIC;YAClBC,iBAAiB;YACjBC,kBAAkB;YAClBC,WAAW,KAAO;QACpB;IACF;IAEA,OAAOR;AACT"}
@@ -0,0 +1,17 @@
1
+ import type { Column, ListQuery, ListViewClientProps } from 'payload';
2
+ import type { NestedDocsPageTreePluginResolvedBadgeConfig, PageTreeSourceDoc } from '../types.js';
3
+ import { type PageTreeDoc } from '../utilities/pageTree.js';
4
+ type PageTreeListViewClientOwnProps = {
5
+ allDocs: PageTreeDoc[];
6
+ badgeConfig: NestedDocsPageTreePluginResolvedBadgeConfig;
7
+ canMoveDocs: boolean;
8
+ columnState: Column[];
9
+ orderableFieldName?: string;
10
+ parentFieldSlug: string;
11
+ query: ListQuery;
12
+ sourceDocs: PageTreeSourceDoc[];
13
+ useAsTitle: string;
14
+ };
15
+ type PageTreeListViewClientProps = Omit<ListViewClientProps, 'columnState' | 'Table'> & PageTreeListViewClientOwnProps;
16
+ export default function PageTreeListViewClient({ allDocs, badgeConfig, canMoveDocs, columnState, orderableFieldName, parentFieldSlug, query, sourceDocs, useAsTitle, ...props }: PageTreeListViewClientProps): import("react/jsx-runtime").JSX.Element;
17
+ export {};