payload-nested-docs-page-tree 1.4.0 → 1.4.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/LICENSE +21 -21
- package/README.md +278 -231
- package/dist/components/PageTreeContext.js.map +1 -1
- package/dist/components/PageTreeListView.client.js.map +1 -1
- package/dist/components/PageTreeListView.module.css +358 -358
- package/dist/components/PageTreeListView.server.js.map +1 -1
- package/dist/components/PageTreeTitleCell.js.map +1 -1
- package/dist/endpoints/createMovePageEndpoint.d.ts +1 -0
- package/dist/endpoints/createMovePageEndpoint.js +24 -6
- package/dist/endpoints/createMovePageEndpoint.js.map +1 -1
- package/dist/endpoints/createReorderPageEndpoint.js +4 -1
- package/dist/endpoints/createReorderPageEndpoint.js.map +1 -1
- package/dist/exports/client.js.map +1 -1
- package/dist/exports/rsc.js.map +1 -1
- package/dist/index.js +17 -15
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +38 -0
- package/dist/types.js +22 -1
- package/dist/types.js.map +1 -1
- package/dist/utilities/badgeConfig.js.map +1 -1
- package/dist/utilities/dropTargets.js.map +1 -1
- package/dist/utilities/fields.d.ts +11 -0
- package/dist/utilities/fields.js +61 -0
- package/dist/utilities/fields.js.map +1 -0
- package/dist/utilities/moveValidation.js.map +1 -1
- package/dist/utilities/pageTree.js.map +1 -1
- package/dist/utilities/pageTreeCollision.js.map +1 -1
- package/dist/utilities/pageTreeConfig.js.map +1 -1
- package/dist/utilities/status.js.map +1 -1
- package/package.json +42 -21
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rows, collapsibles, unnamed groups, and unnamed tabs are presentational
|
|
3
|
+
* only: Payload stores their children directly on the document, so a field
|
|
4
|
+
* nested inside one is still a top-level field as far as the data is
|
|
5
|
+
* concerned. Named groups and named tabs nest their children under their own
|
|
6
|
+
* key, so traversal stops at those.
|
|
7
|
+
*/ function getPresentationalChildFields(field) {
|
|
8
|
+
if (field.type === 'row' || field.type === 'collapsible') {
|
|
9
|
+
return field.fields;
|
|
10
|
+
}
|
|
11
|
+
if (field.type === 'group' && !('name' in field)) {
|
|
12
|
+
return field.fields;
|
|
13
|
+
}
|
|
14
|
+
if (field.type === 'tabs') {
|
|
15
|
+
return field.tabs.flatMap((tab)=>'name' in tab ? [] : tab.fields);
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Finds the field stored under `fieldName` at the top level of the document,
|
|
21
|
+
* looking through presentational containers such as tabs and rows.
|
|
22
|
+
*/ export function findTopLevelField(fields, fieldName) {
|
|
23
|
+
for (const field of fields){
|
|
24
|
+
if ('name' in field && field.name === fieldName) {
|
|
25
|
+
return field;
|
|
26
|
+
}
|
|
27
|
+
const childFields = getPresentationalChildFields(field);
|
|
28
|
+
if (childFields) {
|
|
29
|
+
const match = findTopLevelField(childFields, fieldName);
|
|
30
|
+
if (match) {
|
|
31
|
+
return match;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Maps `mapField` over every field stored at the top level of the document,
|
|
39
|
+
* rebuilding presentational containers so nested fields are patched in place.
|
|
40
|
+
*/ export function mapTopLevelFields(fields, mapField) {
|
|
41
|
+
return fields.map((field)=>{
|
|
42
|
+
if (field.type === 'row' || field.type === 'collapsible' || field.type === 'group' && !('name' in field)) {
|
|
43
|
+
return {
|
|
44
|
+
...field,
|
|
45
|
+
fields: mapTopLevelFields(field.fields, mapField)
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (field.type === 'tabs') {
|
|
49
|
+
return {
|
|
50
|
+
...field,
|
|
51
|
+
tabs: field.tabs.map((tab)=>'name' in tab ? tab : {
|
|
52
|
+
...tab,
|
|
53
|
+
fields: mapTopLevelFields(tab.fields, mapField)
|
|
54
|
+
})
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return mapField(field);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/fields.ts"],"sourcesContent":["import type { Field } from 'payload'\n\n/**\n * Rows, collapsibles, unnamed groups, and unnamed tabs are presentational\n * only: Payload stores their children directly on the document, so a field\n * nested inside one is still a top-level field as far as the data is\n * concerned. Named groups and named tabs nest their children under their own\n * key, so traversal stops at those.\n */\nfunction getPresentationalChildFields(field: Field): Field[] | null {\n if (field.type === 'row' || field.type === 'collapsible') {\n return field.fields\n }\n\n if (field.type === 'group' && !('name' in field)) {\n return field.fields\n }\n\n if (field.type === 'tabs') {\n return field.tabs.flatMap((tab) => ('name' in tab ? [] : tab.fields))\n }\n\n return null\n}\n\n/**\n * Finds the field stored under `fieldName` at the top level of the document,\n * looking through presentational containers such as tabs and rows.\n */\nexport function findTopLevelField(fields: Field[], fieldName: string): Field | undefined {\n for (const field of fields) {\n if ('name' in field && field.name === fieldName) {\n return field\n }\n\n const childFields = getPresentationalChildFields(field)\n\n if (childFields) {\n const match = findTopLevelField(childFields, fieldName)\n\n if (match) {\n return match\n }\n }\n }\n\n return undefined\n}\n\n/**\n * Maps `mapField` over every field stored at the top level of the document,\n * rebuilding presentational containers so nested fields are patched in place.\n */\nexport function mapTopLevelFields(\n fields: Field[],\n mapField: (field: Field) => Field,\n): Field[] {\n return fields.map((field) => {\n if (\n field.type === 'row' ||\n field.type === 'collapsible' ||\n (field.type === 'group' && !('name' in field))\n ) {\n return {\n ...field,\n fields: mapTopLevelFields(field.fields, mapField),\n } as Field\n }\n\n if (field.type === 'tabs') {\n return {\n ...field,\n tabs: field.tabs.map((tab) =>\n 'name' in tab\n ? tab\n : {\n ...tab,\n fields: mapTopLevelFields(tab.fields, mapField),\n },\n ),\n } as Field\n }\n\n return mapField(field)\n })\n}\n"],"names":["getPresentationalChildFields","field","type","fields","tabs","flatMap","tab","findTopLevelField","fieldName","name","childFields","match","undefined","mapTopLevelFields","mapField","map"],"mappings":"AAEA;;;;;;CAMC,GACD,SAASA,6BAA6BC,KAAY;IAChD,IAAIA,MAAMC,IAAI,KAAK,SAASD,MAAMC,IAAI,KAAK,eAAe;QACxD,OAAOD,MAAME,MAAM;IACrB;IAEA,IAAIF,MAAMC,IAAI,KAAK,WAAW,CAAE,CAAA,UAAUD,KAAI,GAAI;QAChD,OAAOA,MAAME,MAAM;IACrB;IAEA,IAAIF,MAAMC,IAAI,KAAK,QAAQ;QACzB,OAAOD,MAAMG,IAAI,CAACC,OAAO,CAAC,CAACC,MAAS,UAAUA,MAAM,EAAE,GAAGA,IAAIH,MAAM;IACrE;IAEA,OAAO;AACT;AAEA;;;CAGC,GACD,OAAO,SAASI,kBAAkBJ,MAAe,EAAEK,SAAiB;IAClE,KAAK,MAAMP,SAASE,OAAQ;QAC1B,IAAI,UAAUF,SAASA,MAAMQ,IAAI,KAAKD,WAAW;YAC/C,OAAOP;QACT;QAEA,MAAMS,cAAcV,6BAA6BC;QAEjD,IAAIS,aAAa;YACf,MAAMC,QAAQJ,kBAAkBG,aAAaF;YAE7C,IAAIG,OAAO;gBACT,OAAOA;YACT;QACF;IACF;IAEA,OAAOC;AACT;AAEA;;;CAGC,GACD,OAAO,SAASC,kBACdV,MAAe,EACfW,QAAiC;IAEjC,OAAOX,OAAOY,GAAG,CAAC,CAACd;QACjB,IACEA,MAAMC,IAAI,KAAK,SACfD,MAAMC,IAAI,KAAK,iBACdD,MAAMC,IAAI,KAAK,WAAW,CAAE,CAAA,UAAUD,KAAI,GAC3C;YACA,OAAO;gBACL,GAAGA,KAAK;gBACRE,QAAQU,kBAAkBZ,MAAME,MAAM,EAAEW;YAC1C;QACF;QAEA,IAAIb,MAAMC,IAAI,KAAK,QAAQ;YACzB,OAAO;gBACL,GAAGD,KAAK;gBACRG,MAAMH,MAAMG,IAAI,CAACW,GAAG,CAAC,CAACT,MACpB,UAAUA,MACNA,MACA;wBACE,GAAGA,GAAG;wBACNH,QAAQU,kBAAkBP,IAAIH,MAAM,EAAEW;oBACxC;YAER;QACF;QAEA,OAAOA,SAASb;IAClB;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/moveValidation.ts"],"sourcesContent":["import type { PageTreeDoc } from './pageTree.js'\
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/moveValidation.ts"],"sourcesContent":["import type { PageTreeDoc } from './pageTree.js'\n\nexport const CANCEL_DRAG_MESSAGE = 'Release to cancel drag.'\n\nexport type PageTreeDropValidation = {\n isValid: boolean\n message?: string\n parentID: null | string\n}\n\nexport function getDropValidation(args: {\n activeDoc: PageTreeDoc\n targetDoc?: PageTreeDoc\n}): PageTreeDropValidation {\n const { activeDoc, targetDoc } = args\n\n if (!targetDoc) {\n if (activeDoc.__pageTreeParentID === null) {\n return {\n isValid: false,\n message: 'Document is already at the root.',\n parentID: null,\n }\n }\n\n return {\n isValid: true,\n parentID: null,\n }\n }\n\n if (targetDoc.__pageTreeID === activeDoc.__pageTreeID) {\n return {\n isValid: false,\n message: CANCEL_DRAG_MESSAGE,\n parentID: targetDoc.__pageTreeID,\n }\n }\n\n if (targetDoc.__pageTreeAncestorIDs.includes(activeDoc.__pageTreeID)) {\n return {\n isValid: false,\n message: 'A document cannot be moved under one of its descendants.',\n parentID: targetDoc.__pageTreeID,\n }\n }\n\n if (activeDoc.__pageTreeParentID === targetDoc.__pageTreeID) {\n return {\n isValid: false,\n message: 'Document already has that parent.',\n parentID: targetDoc.__pageTreeID,\n }\n }\n\n return {\n isValid: true,\n parentID: targetDoc.__pageTreeID,\n }\n}\n"],"names":["CANCEL_DRAG_MESSAGE","getDropValidation","args","activeDoc","targetDoc","__pageTreeParentID","isValid","message","parentID","__pageTreeID","__pageTreeAncestorIDs","includes"],"mappings":"AAEA,OAAO,MAAMA,sBAAsB,0BAAyB;AAQ5D,OAAO,SAASC,kBAAkBC,IAGjC;IACC,MAAM,EAAEC,SAAS,EAAEC,SAAS,EAAE,GAAGF;IAEjC,IAAI,CAACE,WAAW;QACd,IAAID,UAAUE,kBAAkB,KAAK,MAAM;YACzC,OAAO;gBACLC,SAAS;gBACTC,SAAS;gBACTC,UAAU;YACZ;QACF;QAEA,OAAO;YACLF,SAAS;YACTE,UAAU;QACZ;IACF;IAEA,IAAIJ,UAAUK,YAAY,KAAKN,UAAUM,YAAY,EAAE;QACrD,OAAO;YACLH,SAAS;YACTC,SAASP;YACTQ,UAAUJ,UAAUK,YAAY;QAClC;IACF;IAEA,IAAIL,UAAUM,qBAAqB,CAACC,QAAQ,CAACR,UAAUM,YAAY,GAAG;QACpE,OAAO;YACLH,SAAS;YACTC,SAAS;YACTC,UAAUJ,UAAUK,YAAY;QAClC;IACF;IAEA,IAAIN,UAAUE,kBAAkB,KAAKD,UAAUK,YAAY,EAAE;QAC3D,OAAO;YACLH,SAAS;YACTC,SAAS;YACTC,UAAUJ,UAAUK,YAAY;QAClC;IACF;IAEA,OAAO;QACLH,SAAS;QACTE,UAAUJ,UAAUK,YAAY;IAClC;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/pageTree.ts"],"sourcesContent":["import type { PageTreeSourceDoc } from '../types.js'\r\nexport type { PageTreeSourceDoc } from '../types.js'\r\n\r\nexport type PageTreeMeta = {\r\n __pageTreeAncestorIDs: string[]\r\n __pageTreeDepth: number\r\n __pageTreeHasChildren: boolean\r\n __pageTreeID: string\r\n __pageTreeOrderIndex: number\r\n __pageTreeParentID: null | string\r\n __pageTreeShadeLevel: number\r\n}\r\n\r\nexport type PageTreeDoc = PageTreeMeta & PageTreeSourceDoc\r\n\r\ntype SortToken = {\r\n descending: boolean\r\n path: string[]\r\n}\r\n\r\ntype SortValue = null | number | string\r\n\r\ntype TreeNode = {\r\n doc: PageTreeSourceDoc\r\n id: string\r\n originalIndex: number\r\n parentID: null | string\r\n}\r\n\r\nconst dateLikePattern = /^\\d{4}-\\d{2}-\\d{2}(?:[T\\s].*)?$/\r\n\r\nexport type BuildPageTreeDocsOptions = {\r\n parentFieldSlug?: string\r\n sort?: string\r\n}\r\n\r\nexport function stringifyDocID(id: number | string | undefined): string {\r\n return String(id ?? '')\r\n}\r\n\r\nexport function getRelationshipID(value: unknown): null | string {\r\n if (typeof value === 'number' || typeof value === 'string') {\r\n return stringifyDocID(value)\r\n }\r\n\r\n if (value && typeof value === 'object' && 'id' in value) {\r\n const relationshipID = (value as { id?: number | string }).id\r\n\r\n if (typeof relationshipID === 'number' || typeof relationshipID === 'string') {\r\n return stringifyDocID(relationshipID)\r\n }\r\n }\r\n\r\n return null\r\n}\r\n\r\nexport function getDocParentID(\r\n doc: PageTreeSourceDoc,\r\n parentFieldSlug = 'parent',\r\n): null | string {\r\n return getRelationshipID(doc[parentFieldSlug])\r\n}\r\n\r\nexport function getDocDisplayLabel(doc: PageTreeDoc): string {\r\n const title = doc.title\r\n\r\n if (typeof title === 'string' && title.trim().length > 0) {\r\n return title\r\n }\r\n\r\n if (typeof doc.slug === 'string' && doc.slug.trim().length > 0) {\r\n return doc.slug\r\n }\r\n\r\n return doc.__pageTreeID\r\n}\r\n\r\nexport function getDocSlugSegment(doc: PageTreeDoc): string {\r\n if (typeof doc.slug === 'string' && doc.slug.trim().length > 0) {\r\n return doc.slug.trim().replace(/^\\/+|\\/+$/g, '')\r\n }\r\n\r\n return doc.__pageTreeID\r\n}\r\n\r\nexport function buildDocSlugPath(args: {\r\n doc: PageTreeDoc\r\n docsByID: Map<string, PageTreeDoc>\r\n}): string {\r\n const { doc, docsByID } = args\r\n const segments = doc.__pageTreeAncestorIDs\r\n .map((ancestorID) => docsByID.get(ancestorID))\r\n .filter((ancestorDoc): ancestorDoc is PageTreeDoc => Boolean(ancestorDoc))\r\n .map(getDocSlugSegment)\r\n\r\n segments.push(getDocSlugSegment(doc))\r\n\r\n return `/${segments.filter(Boolean).join('/')}`\r\n}\r\n\r\nexport function buildProspectiveDocSlugPath(args: {\r\n activeDoc: PageTreeDoc\r\n docsByID: Map<string, PageTreeDoc>\r\n targetDoc?: PageTreeDoc\r\n}): string {\r\n const { activeDoc, docsByID, targetDoc } = args\r\n\r\n if (!targetDoc) {\r\n return `/${getDocSlugSegment(activeDoc)}`\r\n }\r\n\r\n const segments = targetDoc.__pageTreeAncestorIDs\r\n .map((ancestorID) => docsByID.get(ancestorID))\r\n .filter((ancestorDoc): ancestorDoc is PageTreeDoc => Boolean(ancestorDoc))\r\n .map(getDocSlugSegment)\r\n\r\n segments.push(getDocSlugSegment(targetDoc), getDocSlugSegment(activeDoc))\r\n\r\n return `/${segments.filter(Boolean).join('/')}`\r\n}\r\n\r\nexport function buildChildrenByParentID(args: {\r\n docs: PageTreeSourceDoc[]\r\n parentFieldSlug?: string\r\n}): Map<null | string, string[]> {\r\n const { docs, parentFieldSlug = 'parent' } = args\r\n const childrenByParentID = new Map<null | string, string[]>()\r\n\r\n for (const doc of docs) {\r\n const docID = stringifyDocID(doc.id)\r\n const parentID = getDocParentID(doc, parentFieldSlug)\r\n const existingChildren = childrenByParentID.get(parentID) ?? []\r\n\r\n existingChildren.push(docID)\r\n childrenByParentID.set(parentID, existingChildren)\r\n }\r\n\r\n return childrenByParentID\r\n}\r\n\r\nexport function collectDescendantIDs(\r\n rootID: string,\r\n childrenByParentID: Map<null | string, string[]>,\r\n): string[] {\r\n const descendantIDs: string[] = []\r\n const stack = [...(childrenByParentID.get(rootID) ?? [])]\r\n\r\n while (stack.length > 0) {\r\n const currentID = stack.pop()\r\n\r\n if (!currentID) {\r\n continue\r\n }\r\n\r\n descendantIDs.push(currentID)\r\n stack.push(...(childrenByParentID.get(currentID) ?? []))\r\n }\r\n\r\n return descendantIDs\r\n}\r\n\r\nfunction getCycleNodeIDs(nodes: TreeNode[], nodesByID: Map<string, TreeNode>): Set<string> {\r\n const cycleNodeIDs = new Set<string>()\r\n const pathStack: string[] = []\r\n const visitState = new Map<string, 'done' | 'visiting'>()\r\n\r\n const walk = (node: TreeNode) => {\r\n const currentState = visitState.get(node.id)\r\n\r\n if (currentState === 'done') {\r\n return\r\n }\r\n\r\n if (currentState === 'visiting') {\r\n const cycleStartIndex = pathStack.lastIndexOf(node.id)\r\n const cycleIDs = cycleStartIndex >= 0 ? pathStack.slice(cycleStartIndex) : [node.id]\r\n\r\n for (const cycleID of cycleIDs) {\r\n cycleNodeIDs.add(cycleID)\r\n }\r\n\r\n return\r\n }\r\n\r\n visitState.set(node.id, 'visiting')\r\n pathStack.push(node.id)\r\n\r\n if (node.parentID !== null) {\r\n const parentNode = nodesByID.get(node.parentID)\r\n\r\n if (parentNode) {\r\n walk(parentNode)\r\n }\r\n }\r\n\r\n pathStack.pop()\r\n visitState.set(node.id, 'done')\r\n }\r\n\r\n for (const node of nodes) {\r\n walk(node)\r\n }\r\n\r\n return cycleNodeIDs\r\n}\r\n\r\nfunction parseSortTokens(sort?: string): SortToken[] {\r\n if (typeof sort !== 'string' || sort.trim().length === 0) {\r\n return []\r\n }\r\n\r\n return sort\r\n .split(',')\r\n .map((token) => token.trim())\r\n .filter((token) => token.length > 0)\r\n .map((token) => {\r\n const descending = token.startsWith('-')\r\n const normalizedToken = descending ? token.slice(1) : token\r\n\r\n return {\r\n descending,\r\n path: normalizedToken.split('.').filter(Boolean),\r\n }\r\n })\r\n .filter((token) => token.path.length > 0)\r\n}\r\n\r\nfunction resolveSortValue(source: unknown, path: string[]): SortValue | undefined {\r\n let currentValue = source\r\n\r\n for (const segment of path) {\r\n if (!currentValue || typeof currentValue !== 'object' || Array.isArray(currentValue)) {\r\n return undefined\r\n }\r\n\r\n if (!(segment in currentValue)) {\r\n return undefined\r\n }\r\n\r\n currentValue = (currentValue as Record<string, unknown>)[segment]\r\n }\r\n\r\n if (currentValue === null || currentValue === undefined) {\r\n return null\r\n }\r\n\r\n if (currentValue instanceof Date) {\r\n const timestamp = currentValue.getTime()\r\n\r\n return Number.isNaN(timestamp) ? undefined : timestamp\r\n }\r\n\r\n if (typeof currentValue === 'boolean') {\r\n return currentValue ? 1 : 0\r\n }\r\n\r\n if (typeof currentValue === 'number') {\r\n return Number.isFinite(currentValue) ? currentValue : undefined\r\n }\r\n\r\n if (typeof currentValue !== 'string') {\r\n return undefined\r\n }\r\n\r\n const normalizedValue = currentValue.trim()\r\n\r\n if (dateLikePattern.test(normalizedValue)) {\r\n const timestamp = Date.parse(normalizedValue)\r\n\r\n if (!Number.isNaN(timestamp)) {\r\n return timestamp\r\n }\r\n }\r\n\r\n return normalizedValue\r\n}\r\n\r\nfunction compareSortValues(leftValue: SortValue, rightValue: SortValue): number {\r\n if (leftValue === null && rightValue === null) {\r\n return 0\r\n }\r\n\r\n if (leftValue === null) {\r\n return -1\r\n }\r\n\r\n if (rightValue === null) {\r\n return 1\r\n }\r\n\r\n if (typeof leftValue === 'number' && typeof rightValue === 'number') {\r\n if (leftValue === rightValue) {\r\n return 0\r\n }\r\n\r\n return leftValue < rightValue ? -1 : 1\r\n }\r\n\r\n // Payload orderable keys use fractional indexing strings (for example `_order`\r\n // values like `a5`, `a53`, `a5i`). These must sort by raw lexicographic order\r\n // to match the database; numeric-aware locale comparison places `a53` after\r\n // `a5i`, which is wrong for these keys.\r\n const leftString = String(leftValue)\r\n const rightString = String(rightValue)\r\n\r\n if (leftString === rightString) {\r\n return 0\r\n }\r\n\r\n return leftString < rightString ? -1 : 1\r\n}\r\n\r\nfunction createTreeNodeComparator(sort?: string) {\r\n const sortTokens = parseSortTokens(sort)\r\n\r\n if (sortTokens.length === 0) {\r\n return null\r\n }\r\n\r\n return (leftNode: TreeNode, rightNode: TreeNode): number => {\r\n for (const sortToken of sortTokens) {\r\n const leftValue = resolveSortValue(leftNode.doc, sortToken.path)\r\n const rightValue = resolveSortValue(rightNode.doc, sortToken.path)\r\n\r\n if (leftValue === undefined || rightValue === undefined) {\r\n continue\r\n }\r\n\r\n const comparison = compareSortValues(leftValue, rightValue)\r\n\r\n if (comparison !== 0) {\r\n return sortToken.descending ? -comparison : comparison\r\n }\r\n }\r\n\r\n return leftNode.originalIndex - rightNode.originalIndex\r\n }\r\n}\r\n\r\nexport function buildPageTreeDocs(\r\n docs: PageTreeSourceDoc[],\r\n options: BuildPageTreeDocsOptions = {},\r\n): PageTreeDoc[] {\r\n const parentFieldSlug = options.parentFieldSlug ?? 'parent'\r\n const nodes: TreeNode[] = docs.map((doc, index) => ({\r\n doc,\r\n id: stringifyDocID(doc.id),\r\n originalIndex: index,\r\n parentID: getDocParentID(doc, parentFieldSlug),\r\n }))\r\n const nodesByID = new Map(nodes.map((node) => [node.id, node]))\r\n const cycleNodeIDs = getCycleNodeIDs(nodes, nodesByID)\r\n const effectiveParentIDByNodeID = new Map<string, null | string>()\r\n const childrenByParentID = new Map<null | string, TreeNode[]>()\r\n const compareTreeNodes = createTreeNodeComparator(options.sort)\r\n\r\n for (const node of nodes) {\r\n const parentExists = node.parentID !== null && nodesByID.has(node.parentID)\r\n const effectiveParentID =\r\n parentExists && !cycleNodeIDs.has(node.id) ? node.parentID : null\r\n\r\n effectiveParentIDByNodeID.set(node.id, effectiveParentID)\r\n\r\n const currentChildren = childrenByParentID.get(effectiveParentID) ?? []\r\n currentChildren.push(node)\r\n childrenByParentID.set(effectiveParentID, currentChildren)\r\n }\r\n\r\n if (compareTreeNodes) {\r\n for (const children of childrenByParentID.values()) {\r\n children.sort(compareTreeNodes)\r\n }\r\n }\r\n\r\n const orderedDocs: PageTreeDoc[] = []\r\n const subtreeDepthByID = new Map<string, number>()\r\n const visitedNodeIDs = new Set<string>()\r\n\r\n const getShadeLevel = (rootMaxDepth: number, depth: number): number => {\r\n if (rootMaxDepth === 0) {\r\n return 0\r\n }\r\n\r\n return Math.max(rootMaxDepth - depth + 1, 1)\r\n }\r\n\r\n const getSubtreeDepth = (node: TreeNode): number => {\r\n const cachedDepth = subtreeDepthByID.get(node.id)\r\n\r\n if (typeof cachedDepth === 'number') {\r\n return cachedDepth\r\n }\r\n\r\n const children = childrenByParentID.get(node.id) ?? []\r\n\r\n if (children.length === 0) {\r\n subtreeDepthByID.set(node.id, 0)\r\n return 0\r\n }\r\n\r\n const depth = Math.max(...children.map((child) => getSubtreeDepth(child) + 1))\r\n subtreeDepthByID.set(node.id, depth)\r\n return depth\r\n }\r\n\r\n const visit = (node: TreeNode, ancestorIDs: string[], rootMaxDepth: number) => {\r\n if (visitedNodeIDs.has(node.id)) {\r\n return\r\n }\r\n\r\n visitedNodeIDs.add(node.id)\r\n\r\n const children = childrenByParentID.get(node.id) ?? []\r\n const depth = ancestorIDs.length\r\n const shadeLevel = getShadeLevel(rootMaxDepth, depth)\r\n\r\n orderedDocs.push({\r\n ...(node.doc as PageTreeSourceDoc),\r\n __pageTreeAncestorIDs: ancestorIDs,\r\n __pageTreeDepth: depth,\r\n __pageTreeHasChildren: children.length > 0,\r\n __pageTreeID: node.id,\r\n __pageTreeOrderIndex: orderedDocs.length,\r\n __pageTreeParentID: effectiveParentIDByNodeID.get(node.id) ?? null,\r\n __pageTreeShadeLevel: shadeLevel,\r\n })\r\n\r\n for (const child of children) {\r\n visit(child, [...ancestorIDs, node.id], rootMaxDepth)\r\n }\r\n }\r\n\r\n const roots = [...(childrenByParentID.get(null) ?? [])]\r\n\r\n for (const root of roots) {\r\n visit(root, [], getSubtreeDepth(root))\r\n }\r\n\r\n const fallbackNodes = compareTreeNodes ? [...nodes].sort(compareTreeNodes) : nodes\r\n\r\n for (const node of fallbackNodes) {\r\n if (!visitedNodeIDs.has(node.id)) {\r\n visit(node, [], getSubtreeDepth(node))\r\n }\r\n }\r\n\r\n return orderedDocs\r\n}\r\n\r\nexport function getVisibleTreeDocs(\r\n docs: PageTreeDoc[],\r\n collapsedIDs: ReadonlySet<string>,\r\n): PageTreeDoc[] {\r\n return docs.filter((doc) =>\r\n doc.__pageTreeAncestorIDs.every((ancestorID) => !collapsedIDs.has(ancestorID)),\r\n )\r\n}\r\n"],"names":["dateLikePattern","stringifyDocID","id","String","getRelationshipID","value","relationshipID","getDocParentID","doc","parentFieldSlug","getDocDisplayLabel","title","trim","length","slug","__pageTreeID","getDocSlugSegment","replace","buildDocSlugPath","args","docsByID","segments","__pageTreeAncestorIDs","map","ancestorID","get","filter","ancestorDoc","Boolean","push","join","buildProspectiveDocSlugPath","activeDoc","targetDoc","buildChildrenByParentID","docs","childrenByParentID","Map","docID","parentID","existingChildren","set","collectDescendantIDs","rootID","descendantIDs","stack","currentID","pop","getCycleNodeIDs","nodes","nodesByID","cycleNodeIDs","Set","pathStack","visitState","walk","node","currentState","cycleStartIndex","lastIndexOf","cycleIDs","slice","cycleID","add","parentNode","parseSortTokens","sort","split","token","descending","startsWith","normalizedToken","path","resolveSortValue","source","currentValue","segment","Array","isArray","undefined","Date","timestamp","getTime","Number","isNaN","isFinite","normalizedValue","test","parse","compareSortValues","leftValue","rightValue","leftString","rightString","createTreeNodeComparator","sortTokens","leftNode","rightNode","sortToken","comparison","originalIndex","buildPageTreeDocs","options","index","effectiveParentIDByNodeID","compareTreeNodes","parentExists","has","effectiveParentID","currentChildren","children","values","orderedDocs","subtreeDepthByID","visitedNodeIDs","getShadeLevel","rootMaxDepth","depth","Math","max","getSubtreeDepth","cachedDepth","child","visit","ancestorIDs","shadeLevel","__pageTreeDepth","__pageTreeHasChildren","__pageTreeOrderIndex","__pageTreeParentID","__pageTreeShadeLevel","roots","root","fallbackNodes","getVisibleTreeDocs","collapsedIDs","every"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/pageTree.ts"],"sourcesContent":["import type { PageTreeSourceDoc } from '../types.js'\nexport type { PageTreeSourceDoc } from '../types.js'\n\nexport type PageTreeMeta = {\n __pageTreeAncestorIDs: string[]\n __pageTreeDepth: number\n __pageTreeHasChildren: boolean\n __pageTreeID: string\n __pageTreeOrderIndex: number\n __pageTreeParentID: null | string\n __pageTreeShadeLevel: number\n}\n\nexport type PageTreeDoc = PageTreeMeta & PageTreeSourceDoc\n\ntype SortToken = {\n descending: boolean\n path: string[]\n}\n\ntype SortValue = null | number | string\n\ntype TreeNode = {\n doc: PageTreeSourceDoc\n id: string\n originalIndex: number\n parentID: null | string\n}\n\nconst dateLikePattern = /^\\d{4}-\\d{2}-\\d{2}(?:[T\\s].*)?$/\n\nexport type BuildPageTreeDocsOptions = {\n parentFieldSlug?: string\n sort?: string\n}\n\nexport function stringifyDocID(id: number | string | undefined): string {\n return String(id ?? '')\n}\n\nexport function getRelationshipID(value: unknown): null | string {\n if (typeof value === 'number' || typeof value === 'string') {\n return stringifyDocID(value)\n }\n\n if (value && typeof value === 'object' && 'id' in value) {\n const relationshipID = (value as { id?: number | string }).id\n\n if (typeof relationshipID === 'number' || typeof relationshipID === 'string') {\n return stringifyDocID(relationshipID)\n }\n }\n\n return null\n}\n\nexport function getDocParentID(\n doc: PageTreeSourceDoc,\n parentFieldSlug = 'parent',\n): null | string {\n return getRelationshipID(doc[parentFieldSlug])\n}\n\nexport function getDocDisplayLabel(doc: PageTreeDoc): string {\n const title = doc.title\n\n if (typeof title === 'string' && title.trim().length > 0) {\n return title\n }\n\n if (typeof doc.slug === 'string' && doc.slug.trim().length > 0) {\n return doc.slug\n }\n\n return doc.__pageTreeID\n}\n\nexport function getDocSlugSegment(doc: PageTreeDoc): string {\n if (typeof doc.slug === 'string' && doc.slug.trim().length > 0) {\n return doc.slug.trim().replace(/^\\/+|\\/+$/g, '')\n }\n\n return doc.__pageTreeID\n}\n\nexport function buildDocSlugPath(args: {\n doc: PageTreeDoc\n docsByID: Map<string, PageTreeDoc>\n}): string {\n const { doc, docsByID } = args\n const segments = doc.__pageTreeAncestorIDs\n .map((ancestorID) => docsByID.get(ancestorID))\n .filter((ancestorDoc): ancestorDoc is PageTreeDoc => Boolean(ancestorDoc))\n .map(getDocSlugSegment)\n\n segments.push(getDocSlugSegment(doc))\n\n return `/${segments.filter(Boolean).join('/')}`\n}\n\nexport function buildProspectiveDocSlugPath(args: {\n activeDoc: PageTreeDoc\n docsByID: Map<string, PageTreeDoc>\n targetDoc?: PageTreeDoc\n}): string {\n const { activeDoc, docsByID, targetDoc } = args\n\n if (!targetDoc) {\n return `/${getDocSlugSegment(activeDoc)}`\n }\n\n const segments = targetDoc.__pageTreeAncestorIDs\n .map((ancestorID) => docsByID.get(ancestorID))\n .filter((ancestorDoc): ancestorDoc is PageTreeDoc => Boolean(ancestorDoc))\n .map(getDocSlugSegment)\n\n segments.push(getDocSlugSegment(targetDoc), getDocSlugSegment(activeDoc))\n\n return `/${segments.filter(Boolean).join('/')}`\n}\n\nexport function buildChildrenByParentID(args: {\n docs: PageTreeSourceDoc[]\n parentFieldSlug?: string\n}): Map<null | string, string[]> {\n const { docs, parentFieldSlug = 'parent' } = args\n const childrenByParentID = new Map<null | string, string[]>()\n\n for (const doc of docs) {\n const docID = stringifyDocID(doc.id)\n const parentID = getDocParentID(doc, parentFieldSlug)\n const existingChildren = childrenByParentID.get(parentID) ?? []\n\n existingChildren.push(docID)\n childrenByParentID.set(parentID, existingChildren)\n }\n\n return childrenByParentID\n}\n\nexport function collectDescendantIDs(\n rootID: string,\n childrenByParentID: Map<null | string, string[]>,\n): string[] {\n const descendantIDs: string[] = []\n const stack = [...(childrenByParentID.get(rootID) ?? [])]\n\n while (stack.length > 0) {\n const currentID = stack.pop()\n\n if (!currentID) {\n continue\n }\n\n descendantIDs.push(currentID)\n stack.push(...(childrenByParentID.get(currentID) ?? []))\n }\n\n return descendantIDs\n}\n\nfunction getCycleNodeIDs(nodes: TreeNode[], nodesByID: Map<string, TreeNode>): Set<string> {\n const cycleNodeIDs = new Set<string>()\n const pathStack: string[] = []\n const visitState = new Map<string, 'done' | 'visiting'>()\n\n const walk = (node: TreeNode) => {\n const currentState = visitState.get(node.id)\n\n if (currentState === 'done') {\n return\n }\n\n if (currentState === 'visiting') {\n const cycleStartIndex = pathStack.lastIndexOf(node.id)\n const cycleIDs = cycleStartIndex >= 0 ? pathStack.slice(cycleStartIndex) : [node.id]\n\n for (const cycleID of cycleIDs) {\n cycleNodeIDs.add(cycleID)\n }\n\n return\n }\n\n visitState.set(node.id, 'visiting')\n pathStack.push(node.id)\n\n if (node.parentID !== null) {\n const parentNode = nodesByID.get(node.parentID)\n\n if (parentNode) {\n walk(parentNode)\n }\n }\n\n pathStack.pop()\n visitState.set(node.id, 'done')\n }\n\n for (const node of nodes) {\n walk(node)\n }\n\n return cycleNodeIDs\n}\n\nfunction parseSortTokens(sort?: string): SortToken[] {\n if (typeof sort !== 'string' || sort.trim().length === 0) {\n return []\n }\n\n return sort\n .split(',')\n .map((token) => token.trim())\n .filter((token) => token.length > 0)\n .map((token) => {\n const descending = token.startsWith('-')\n const normalizedToken = descending ? token.slice(1) : token\n\n return {\n descending,\n path: normalizedToken.split('.').filter(Boolean),\n }\n })\n .filter((token) => token.path.length > 0)\n}\n\nfunction resolveSortValue(source: unknown, path: string[]): SortValue | undefined {\n let currentValue = source\n\n for (const segment of path) {\n if (!currentValue || typeof currentValue !== 'object' || Array.isArray(currentValue)) {\n return undefined\n }\n\n if (!(segment in currentValue)) {\n return undefined\n }\n\n currentValue = (currentValue as Record<string, unknown>)[segment]\n }\n\n if (currentValue === null || currentValue === undefined) {\n return null\n }\n\n if (currentValue instanceof Date) {\n const timestamp = currentValue.getTime()\n\n return Number.isNaN(timestamp) ? undefined : timestamp\n }\n\n if (typeof currentValue === 'boolean') {\n return currentValue ? 1 : 0\n }\n\n if (typeof currentValue === 'number') {\n return Number.isFinite(currentValue) ? currentValue : undefined\n }\n\n if (typeof currentValue !== 'string') {\n return undefined\n }\n\n const normalizedValue = currentValue.trim()\n\n if (dateLikePattern.test(normalizedValue)) {\n const timestamp = Date.parse(normalizedValue)\n\n if (!Number.isNaN(timestamp)) {\n return timestamp\n }\n }\n\n return normalizedValue\n}\n\nfunction compareSortValues(leftValue: SortValue, rightValue: SortValue): number {\n if (leftValue === null && rightValue === null) {\n return 0\n }\n\n if (leftValue === null) {\n return -1\n }\n\n if (rightValue === null) {\n return 1\n }\n\n if (typeof leftValue === 'number' && typeof rightValue === 'number') {\n if (leftValue === rightValue) {\n return 0\n }\n\n return leftValue < rightValue ? -1 : 1\n }\n\n // Payload orderable keys use fractional indexing strings (for example `_order`\n // values like `a5`, `a53`, `a5i`). These must sort by raw lexicographic order\n // to match the database; numeric-aware locale comparison places `a53` after\n // `a5i`, which is wrong for these keys.\n const leftString = String(leftValue)\n const rightString = String(rightValue)\n\n if (leftString === rightString) {\n return 0\n }\n\n return leftString < rightString ? -1 : 1\n}\n\nfunction createTreeNodeComparator(sort?: string) {\n const sortTokens = parseSortTokens(sort)\n\n if (sortTokens.length === 0) {\n return null\n }\n\n return (leftNode: TreeNode, rightNode: TreeNode): number => {\n for (const sortToken of sortTokens) {\n const leftValue = resolveSortValue(leftNode.doc, sortToken.path)\n const rightValue = resolveSortValue(rightNode.doc, sortToken.path)\n\n if (leftValue === undefined || rightValue === undefined) {\n continue\n }\n\n const comparison = compareSortValues(leftValue, rightValue)\n\n if (comparison !== 0) {\n return sortToken.descending ? -comparison : comparison\n }\n }\n\n return leftNode.originalIndex - rightNode.originalIndex\n }\n}\n\nexport function buildPageTreeDocs(\n docs: PageTreeSourceDoc[],\n options: BuildPageTreeDocsOptions = {},\n): PageTreeDoc[] {\n const parentFieldSlug = options.parentFieldSlug ?? 'parent'\n const nodes: TreeNode[] = docs.map((doc, index) => ({\n doc,\n id: stringifyDocID(doc.id),\n originalIndex: index,\n parentID: getDocParentID(doc, parentFieldSlug),\n }))\n const nodesByID = new Map(nodes.map((node) => [node.id, node]))\n const cycleNodeIDs = getCycleNodeIDs(nodes, nodesByID)\n const effectiveParentIDByNodeID = new Map<string, null | string>()\n const childrenByParentID = new Map<null | string, TreeNode[]>()\n const compareTreeNodes = createTreeNodeComparator(options.sort)\n\n for (const node of nodes) {\n const parentExists = node.parentID !== null && nodesByID.has(node.parentID)\n const effectiveParentID =\n parentExists && !cycleNodeIDs.has(node.id) ? node.parentID : null\n\n effectiveParentIDByNodeID.set(node.id, effectiveParentID)\n\n const currentChildren = childrenByParentID.get(effectiveParentID) ?? []\n currentChildren.push(node)\n childrenByParentID.set(effectiveParentID, currentChildren)\n }\n\n if (compareTreeNodes) {\n for (const children of childrenByParentID.values()) {\n children.sort(compareTreeNodes)\n }\n }\n\n const orderedDocs: PageTreeDoc[] = []\n const subtreeDepthByID = new Map<string, number>()\n const visitedNodeIDs = new Set<string>()\n\n const getShadeLevel = (rootMaxDepth: number, depth: number): number => {\n if (rootMaxDepth === 0) {\n return 0\n }\n\n return Math.max(rootMaxDepth - depth + 1, 1)\n }\n\n const getSubtreeDepth = (node: TreeNode): number => {\n const cachedDepth = subtreeDepthByID.get(node.id)\n\n if (typeof cachedDepth === 'number') {\n return cachedDepth\n }\n\n const children = childrenByParentID.get(node.id) ?? []\n\n if (children.length === 0) {\n subtreeDepthByID.set(node.id, 0)\n return 0\n }\n\n const depth = Math.max(...children.map((child) => getSubtreeDepth(child) + 1))\n subtreeDepthByID.set(node.id, depth)\n return depth\n }\n\n const visit = (node: TreeNode, ancestorIDs: string[], rootMaxDepth: number) => {\n if (visitedNodeIDs.has(node.id)) {\n return\n }\n\n visitedNodeIDs.add(node.id)\n\n const children = childrenByParentID.get(node.id) ?? []\n const depth = ancestorIDs.length\n const shadeLevel = getShadeLevel(rootMaxDepth, depth)\n\n orderedDocs.push({\n ...(node.doc as PageTreeSourceDoc),\n __pageTreeAncestorIDs: ancestorIDs,\n __pageTreeDepth: depth,\n __pageTreeHasChildren: children.length > 0,\n __pageTreeID: node.id,\n __pageTreeOrderIndex: orderedDocs.length,\n __pageTreeParentID: effectiveParentIDByNodeID.get(node.id) ?? null,\n __pageTreeShadeLevel: shadeLevel,\n })\n\n for (const child of children) {\n visit(child, [...ancestorIDs, node.id], rootMaxDepth)\n }\n }\n\n const roots = [...(childrenByParentID.get(null) ?? [])]\n\n for (const root of roots) {\n visit(root, [], getSubtreeDepth(root))\n }\n\n const fallbackNodes = compareTreeNodes ? [...nodes].sort(compareTreeNodes) : nodes\n\n for (const node of fallbackNodes) {\n if (!visitedNodeIDs.has(node.id)) {\n visit(node, [], getSubtreeDepth(node))\n }\n }\n\n return orderedDocs\n}\n\nexport function getVisibleTreeDocs(\n docs: PageTreeDoc[],\n collapsedIDs: ReadonlySet<string>,\n): PageTreeDoc[] {\n return docs.filter((doc) =>\n doc.__pageTreeAncestorIDs.every((ancestorID) => !collapsedIDs.has(ancestorID)),\n )\n}\n"],"names":["dateLikePattern","stringifyDocID","id","String","getRelationshipID","value","relationshipID","getDocParentID","doc","parentFieldSlug","getDocDisplayLabel","title","trim","length","slug","__pageTreeID","getDocSlugSegment","replace","buildDocSlugPath","args","docsByID","segments","__pageTreeAncestorIDs","map","ancestorID","get","filter","ancestorDoc","Boolean","push","join","buildProspectiveDocSlugPath","activeDoc","targetDoc","buildChildrenByParentID","docs","childrenByParentID","Map","docID","parentID","existingChildren","set","collectDescendantIDs","rootID","descendantIDs","stack","currentID","pop","getCycleNodeIDs","nodes","nodesByID","cycleNodeIDs","Set","pathStack","visitState","walk","node","currentState","cycleStartIndex","lastIndexOf","cycleIDs","slice","cycleID","add","parentNode","parseSortTokens","sort","split","token","descending","startsWith","normalizedToken","path","resolveSortValue","source","currentValue","segment","Array","isArray","undefined","Date","timestamp","getTime","Number","isNaN","isFinite","normalizedValue","test","parse","compareSortValues","leftValue","rightValue","leftString","rightString","createTreeNodeComparator","sortTokens","leftNode","rightNode","sortToken","comparison","originalIndex","buildPageTreeDocs","options","index","effectiveParentIDByNodeID","compareTreeNodes","parentExists","has","effectiveParentID","currentChildren","children","values","orderedDocs","subtreeDepthByID","visitedNodeIDs","getShadeLevel","rootMaxDepth","depth","Math","max","getSubtreeDepth","cachedDepth","child","visit","ancestorIDs","shadeLevel","__pageTreeDepth","__pageTreeHasChildren","__pageTreeOrderIndex","__pageTreeParentID","__pageTreeShadeLevel","roots","root","fallbackNodes","getVisibleTreeDocs","collapsedIDs","every"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/pageTreeCollision.ts"],"sourcesContent":["import {\
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/pageTreeCollision.ts"],"sourcesContent":["import {\n closestCenter,\n type Collision,\n type CollisionDetection,\n pointerWithin,\n} from '@dnd-kit/core'\n\nimport type { PageTreeDropTarget, PageTreeRowDropTarget } from './dropTargets.js'\n\nexport const PAGE_TREE_INSERT_EDGE_SIZE_PX = 6\ntype PageTreeDragType = 'move' | 'order'\ntype PageTreeDragData = {\n dragType?: PageTreeDragType\n parentID?: null | string\n}\n\nexport type PageTreePointerCollisionCandidate = {\n dragType?: PageTreeDragType\n dropTarget?: PageTreeDropTarget\n id: Collision['id']\n parentID?: null | string\n rect?: {\n bottom: number\n top: number\n }\n}\n\nfunction getResolvedCollision(args: {\n collisionID: Collision['id']\n droppableContainers: Parameters<CollisionDetection>[0]['droppableContainers']\n pointerCollisions: Collision[]\n}): Collision | null {\n const { collisionID, droppableContainers, pointerCollisions } = args\n const existingPointerCollision = pointerCollisions.find(\n (collision) => collision.id === collisionID,\n )\n\n if (existingPointerCollision) {\n return existingPointerCollision\n }\n\n const droppableContainer = droppableContainers.find((container) => container.id === collisionID)\n\n if (!droppableContainer) {\n return null\n }\n\n return {\n id: collisionID,\n data: {\n droppableContainer,\n value: 0,\n },\n }\n}\n\ntype PageTreeResolvedRowCollision = {\n dropTarget: PageTreeRowDropTarget\n rect: {\n bottom: number\n top: number\n }\n} & PageTreePointerCollisionCandidate\n\nfunction isRowCollision(\n collision: PageTreePointerCollisionCandidate,\n): collision is PageTreeResolvedRowCollision {\n return collision.dropTarget?.dropType === 'row' && Boolean(collision.rect)\n}\n\nfunction getDragData(value: unknown): PageTreeDragData {\n if (!value || typeof value !== 'object') {\n return {}\n }\n\n const data = value as { dragType?: unknown; parentID?: unknown }\n const dragType = data.dragType === 'move' || data.dragType === 'order' ? data.dragType : undefined\n const parentID =\n data.parentID === null || typeof data.parentID === 'string' ? data.parentID : undefined\n\n return {\n dragType,\n parentID,\n }\n}\n\nfunction getCollisionDropTarget(collision: Collision): PageTreeDropTarget | undefined {\n return collision.data?.droppableContainer.data.current as PageTreeDropTarget | undefined\n}\n\nfunction getCollisionDragData(collision: Collision): PageTreeDragData {\n return getDragData(collision.data?.droppableContainer.data.current)\n}\n\nfunction isSortableOrderCollision(collision: Collision, activeDragData: PageTreeDragData): boolean {\n const collisionDragData = getCollisionDragData(collision)\n\n return (\n collisionDragData.dragType === 'order' && collisionDragData.parentID === activeDragData.parentID\n )\n}\n\nexport function resolvePageTreePointerCollisionID(args: {\n activeParentID?: null | string\n collisions: PageTreePointerCollisionCandidate[]\n dragType?: PageTreeDragType\n pointerCoordinates: Parameters<CollisionDetection>[0]['pointerCoordinates']\n}): Collision['id'] | null {\n const { activeParentID, collisions, dragType, pointerCoordinates } = args\n\n if (!pointerCoordinates) {\n return null\n }\n\n if (dragType === 'order') {\n return (\n collisions.find(\n (collision) => collision.dragType === 'order' && collision.parentID === activeParentID,\n )?.id ?? null\n )\n }\n\n const directInsertCollision = collisions.find(\n (collision) => collision.dropTarget?.dropType === 'insert',\n )\n\n if (directInsertCollision) {\n return directInsertCollision.id\n }\n\n const rowCollision = collisions.find(isRowCollision)\n\n if (!rowCollision) {\n return null\n }\n\n if (\n rowCollision.dropTarget.insertBeforeDropID &&\n pointerCoordinates.y - rowCollision.rect.top <= PAGE_TREE_INSERT_EDGE_SIZE_PX\n ) {\n return rowCollision.dropTarget.insertBeforeDropID\n }\n\n if (\n rowCollision.dropTarget.insertAfterDropID &&\n rowCollision.rect.bottom - pointerCoordinates.y <= PAGE_TREE_INSERT_EDGE_SIZE_PX\n ) {\n return rowCollision.dropTarget.insertAfterDropID\n }\n\n return rowCollision.id\n}\n\nexport const pageTreeCollisionDetectionStrategy: CollisionDetection = (args) => {\n const activeDragData = getDragData(args.active.data.current)\n\n if (activeDragData.dragType === 'order') {\n const closestRowCollision = closestCenter(args).find((collision) =>\n isSortableOrderCollision(collision, activeDragData),\n )\n\n return closestRowCollision ? [closestRowCollision] : []\n }\n\n const pointerCollisions = pointerWithin(args)\n const resolvedCollisionID = resolvePageTreePointerCollisionID({\n activeParentID: activeDragData.parentID,\n collisions: pointerCollisions.map((collision) => ({\n id: collision.id,\n ...getCollisionDragData(collision),\n dropTarget: getCollisionDropTarget(collision),\n rect: args.droppableRects.get(collision.id) ?? undefined,\n })),\n dragType: activeDragData.dragType,\n pointerCoordinates: args.pointerCoordinates,\n })\n\n if (resolvedCollisionID !== null) {\n const resolvedCollision = getResolvedCollision({\n collisionID: resolvedCollisionID,\n droppableContainers: args.droppableContainers,\n pointerCollisions,\n })\n\n if (resolvedCollision) {\n return [resolvedCollision]\n }\n }\n\n return closestCenter(args)\n}\n"],"names":["closestCenter","pointerWithin","PAGE_TREE_INSERT_EDGE_SIZE_PX","getResolvedCollision","args","collisionID","droppableContainers","pointerCollisions","existingPointerCollision","find","collision","id","droppableContainer","container","data","value","isRowCollision","dropTarget","dropType","Boolean","rect","getDragData","dragType","undefined","parentID","getCollisionDropTarget","current","getCollisionDragData","isSortableOrderCollision","activeDragData","collisionDragData","resolvePageTreePointerCollisionID","activeParentID","collisions","pointerCoordinates","directInsertCollision","rowCollision","insertBeforeDropID","y","top","insertAfterDropID","bottom","pageTreeCollisionDetectionStrategy","active","closestRowCollision","resolvedCollisionID","map","droppableRects","get","resolvedCollision"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/pageTreeConfig.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/pageTreeConfig.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nimport type { NestedDocsPageTreePluginCollectionCustom } from '../types.js'\nimport { nestedDocsPageTreePluginCustomKey } from '../types.js'\nimport { normalizeNestedDocsPageTreePluginBadgeConfig } from './badgeConfig.js'\n\nexport function getCollectionPageTreeConfig(\n collection: Pick<CollectionConfig, 'custom'>,\n): null | NestedDocsPageTreePluginCollectionCustom {\n const value = collection.custom?.[nestedDocsPageTreePluginCustomKey]\n\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return null\n }\n\n const config = value as Partial<NestedDocsPageTreePluginCollectionCustom>\n\n if (\n typeof config.breadcrumbsFieldSlug !== 'string' ||\n typeof config.defaultLimit !== 'number' ||\n typeof config.hideBreadcrumbs !== 'boolean' ||\n !config.homeIndicator ||\n typeof config.homeIndicator !== 'object' ||\n Array.isArray(config.homeIndicator) ||\n typeof config.homeIndicator.enabled !== 'boolean' ||\n typeof config.parentFieldSlug !== 'string'\n ) {\n return null\n }\n\n return {\n badges: normalizeNestedDocsPageTreePluginBadgeConfig(config.badges),\n breadcrumbsFieldSlug: config.breadcrumbsFieldSlug,\n defaultLimit: config.defaultLimit,\n hideBreadcrumbs: config.hideBreadcrumbs,\n homeIndicator: {\n enabled: config.homeIndicator.enabled,\n },\n parentFieldSlug: config.parentFieldSlug,\n }\n}\n"],"names":["nestedDocsPageTreePluginCustomKey","normalizeNestedDocsPageTreePluginBadgeConfig","getCollectionPageTreeConfig","collection","value","custom","Array","isArray","config","breadcrumbsFieldSlug","defaultLimit","hideBreadcrumbs","homeIndicator","enabled","parentFieldSlug","badges"],"mappings":"AAGA,SAASA,iCAAiC,QAAQ,cAAa;AAC/D,SAASC,4CAA4C,QAAQ,mBAAkB;AAE/E,OAAO,SAASC,4BACdC,UAA4C;IAE5C,MAAMC,QAAQD,WAAWE,MAAM,EAAE,CAACL,kCAAkC;IAEpE,IAAI,CAACI,SAAS,OAAOA,UAAU,YAAYE,MAAMC,OAAO,CAACH,QAAQ;QAC/D,OAAO;IACT;IAEA,MAAMI,SAASJ;IAEf,IACE,OAAOI,OAAOC,oBAAoB,KAAK,YACvC,OAAOD,OAAOE,YAAY,KAAK,YAC/B,OAAOF,OAAOG,eAAe,KAAK,aAClC,CAACH,OAAOI,aAAa,IACrB,OAAOJ,OAAOI,aAAa,KAAK,YAChCN,MAAMC,OAAO,CAACC,OAAOI,aAAa,KAClC,OAAOJ,OAAOI,aAAa,CAACC,OAAO,KAAK,aACxC,OAAOL,OAAOM,eAAe,KAAK,UAClC;QACA,OAAO;IACT;IAEA,OAAO;QACLC,QAAQd,6CAA6CO,OAAOO,MAAM;QAClEN,sBAAsBD,OAAOC,oBAAoB;QACjDC,cAAcF,OAAOE,YAAY;QACjCC,iBAAiBH,OAAOG,eAAe;QACvCC,eAAe;YACbC,SAASL,OAAOI,aAAa,CAACC,OAAO;QACvC;QACAC,iBAAiBN,OAAOM,eAAe;IACzC;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/status.ts"],"sourcesContent":["import type {\
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/status.ts"],"sourcesContent":["import type {\n PageTreeSourceDoc,\n NestedDocsPageTreePluginBadgeMap,\n NestedDocsPageTreePluginBadgeStatus,\n} from '../types.js'\n\nexport type PageTreeDisplayStatus = 'changed' | 'draft' | 'published' | 'unknown'\n\nfunction isBadgeStatus(status: PageTreeDisplayStatus): status is NestedDocsPageTreePluginBadgeStatus {\n return status === 'changed' || status === 'draft' || status === 'published'\n}\n\nexport function getPageTreeDisplayStatus(\n doc: Pick<PageTreeSourceDoc, '_displayStatus' | '_status'>,\n): PageTreeDisplayStatus {\n if (doc._displayStatus === 'changed') {\n return 'changed'\n }\n\n if (doc._displayStatus === 'draft') {\n return 'draft'\n }\n\n if (doc._displayStatus === 'published') {\n return 'published'\n }\n\n if (doc._status === 'draft') {\n return 'draft'\n }\n\n if (doc._status === 'published') {\n return 'published'\n }\n\n return 'unknown'\n}\n\nexport function getPageTreeDisplayStatusLabelKey(status: PageTreeDisplayStatus):\n | 'version:draft'\n | 'version:changed'\n | 'version:published'\n | 'general:noValue' {\n if (status === 'changed') {\n return 'version:changed'\n }\n\n if (status === 'draft') {\n return 'version:draft'\n }\n\n if (status === 'published') {\n return 'version:published'\n }\n\n return 'general:noValue'\n}\n\nexport function getPageTreeBadgeColor(args: {\n badgeColors: NestedDocsPageTreePluginBadgeMap\n status: PageTreeDisplayStatus\n}): string | undefined {\n const { badgeColors, status } = args\n\n if (!isBadgeStatus(status)) {\n return undefined\n }\n\n const badgeColor = badgeColors[status]\n\n return typeof badgeColor === 'string' && badgeColor.trim().length > 0\n ? badgeColor.trim()\n : undefined\n}\n\nexport function getPageTreeBadgeLabel(args: {\n badgeLabels: NestedDocsPageTreePluginBadgeMap\n status: PageTreeDisplayStatus\n t: (key: ReturnType<typeof getPageTreeDisplayStatusLabelKey>) => string\n}): string {\n const { badgeLabels, status, t } = args\n\n if (isBadgeStatus(status)) {\n const badgeLabel = badgeLabels[status]\n\n if (typeof badgeLabel === 'string' && badgeLabel.trim().length > 0) {\n return badgeLabel.trim()\n }\n }\n\n return t(getPageTreeDisplayStatusLabelKey(status))\n}\n\nexport function withPageTreeDisplayStatuses(args: {\n currentDocs: Pick<PageTreeSourceDoc, '_status' | 'id'>[]\n draftDocs: PageTreeSourceDoc[]\n}): PageTreeSourceDoc[] {\n const { currentDocs, draftDocs } = args\n const currentStatusByID = new Map(\n currentDocs.map((doc) => [String(doc.id ?? ''), doc._status ?? null]),\n )\n\n return draftDocs.map((doc) => {\n const docID = String(doc.id ?? '')\n const currentStatus = currentStatusByID.get(docID)\n const displayStatus =\n doc._status === 'draft' && currentStatus === 'published'\n ? 'changed'\n : doc._status === 'draft' || doc._status === 'published'\n ? doc._status\n : undefined\n\n if (doc._displayStatus === displayStatus) {\n return doc\n }\n\n return {\n ...doc,\n _displayStatus: displayStatus,\n }\n })\n}\n"],"names":["isBadgeStatus","status","getPageTreeDisplayStatus","doc","_displayStatus","_status","getPageTreeDisplayStatusLabelKey","getPageTreeBadgeColor","args","badgeColors","undefined","badgeColor","trim","length","getPageTreeBadgeLabel","badgeLabels","t","badgeLabel","withPageTreeDisplayStatuses","currentDocs","draftDocs","currentStatusByID","Map","map","String","id","docID","currentStatus","get","displayStatus"],"mappings":"AAQA,SAASA,cAAcC,MAA6B;IAClD,OAAOA,WAAW,aAAaA,WAAW,WAAWA,WAAW;AAClE;AAEA,OAAO,SAASC,yBACdC,GAA0D;IAE1D,IAAIA,IAAIC,cAAc,KAAK,WAAW;QACpC,OAAO;IACT;IAEA,IAAID,IAAIC,cAAc,KAAK,SAAS;QAClC,OAAO;IACT;IAEA,IAAID,IAAIC,cAAc,KAAK,aAAa;QACtC,OAAO;IACT;IAEA,IAAID,IAAIE,OAAO,KAAK,SAAS;QAC3B,OAAO;IACT;IAEA,IAAIF,IAAIE,OAAO,KAAK,aAAa;QAC/B,OAAO;IACT;IAEA,OAAO;AACT;AAEA,OAAO,SAASC,iCAAiCL,MAA6B;IAK5E,IAAIA,WAAW,WAAW;QACxB,OAAO;IACT;IAEA,IAAIA,WAAW,SAAS;QACtB,OAAO;IACT;IAEA,IAAIA,WAAW,aAAa;QAC1B,OAAO;IACT;IAEA,OAAO;AACT;AAEA,OAAO,SAASM,sBAAsBC,IAGrC;IACC,MAAM,EAAEC,WAAW,EAAER,MAAM,EAAE,GAAGO;IAEhC,IAAI,CAACR,cAAcC,SAAS;QAC1B,OAAOS;IACT;IAEA,MAAMC,aAAaF,WAAW,CAACR,OAAO;IAEtC,OAAO,OAAOU,eAAe,YAAYA,WAAWC,IAAI,GAAGC,MAAM,GAAG,IAChEF,WAAWC,IAAI,KACfF;AACN;AAEA,OAAO,SAASI,sBAAsBN,IAIrC;IACC,MAAM,EAAEO,WAAW,EAAEd,MAAM,EAAEe,CAAC,EAAE,GAAGR;IAEnC,IAAIR,cAAcC,SAAS;QACzB,MAAMgB,aAAaF,WAAW,CAACd,OAAO;QAEtC,IAAI,OAAOgB,eAAe,YAAYA,WAAWL,IAAI,GAAGC,MAAM,GAAG,GAAG;YAClE,OAAOI,WAAWL,IAAI;QACxB;IACF;IAEA,OAAOI,EAAEV,iCAAiCL;AAC5C;AAEA,OAAO,SAASiB,4BAA4BV,IAG3C;IACC,MAAM,EAAEW,WAAW,EAAEC,SAAS,EAAE,GAAGZ;IACnC,MAAMa,oBAAoB,IAAIC,IAC5BH,YAAYI,GAAG,CAAC,CAACpB,MAAQ;YAACqB,OAAOrB,IAAIsB,EAAE,IAAI;YAAKtB,IAAIE,OAAO,IAAI;SAAK;IAGtE,OAAOe,UAAUG,GAAG,CAAC,CAACpB;QACpB,MAAMuB,QAAQF,OAAOrB,IAAIsB,EAAE,IAAI;QAC/B,MAAME,gBAAgBN,kBAAkBO,GAAG,CAACF;QAC5C,MAAMG,gBACJ1B,IAAIE,OAAO,KAAK,WAAWsB,kBAAkB,cACzC,YACAxB,IAAIE,OAAO,KAAK,WAAWF,IAAIE,OAAO,KAAK,cACzCF,IAAIE,OAAO,GACXK;QAER,IAAIP,IAAIC,cAAc,KAAKyB,eAAe;YACxC,OAAO1B;QACT;QAEA,OAAO;YACL,GAAGA,GAAG;YACNC,gBAAgByB;QAClB;IACF;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payload-nested-docs-page-tree",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"description": "Page tree plugin for Payload nested docs collections",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "WLF Studios",
|
|
@@ -45,6 +45,27 @@
|
|
|
45
45
|
"README.md",
|
|
46
46
|
"LICENSE"
|
|
47
47
|
],
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "pnpm clean && pnpm build:types && pnpm build:swc && pnpm copyfiles && pnpm build:strip-tests",
|
|
50
|
+
"build:strip-tests": "rimraf \"dist/**/*.spec.*\"",
|
|
51
|
+
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
|
|
52
|
+
"build:types": "tsc --project tsconfig.build.json",
|
|
53
|
+
"clean": "rimraf dist \"*.tsbuildinfo\"",
|
|
54
|
+
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
|
|
55
|
+
"dev": "next dev dev --webpack",
|
|
56
|
+
"dev:generate-importmap": "pnpm dev:payload generate:importmap",
|
|
57
|
+
"dev:generate-types": "pnpm dev:payload generate:types",
|
|
58
|
+
"dev:payload": "cross-env PAYLOAD_CONFIG_PATH=./dev/payload.config.ts payload",
|
|
59
|
+
"generate:importmap": "pnpm dev:generate-importmap",
|
|
60
|
+
"generate:types": "pnpm dev:generate-types",
|
|
61
|
+
"lint": "eslint",
|
|
62
|
+
"lint:fix": "eslint ./src --fix",
|
|
63
|
+
"prepare": "pnpm clean && pnpm build",
|
|
64
|
+
"prepublishOnly": "pnpm clean && pnpm build",
|
|
65
|
+
"test": "pnpm test:int && pnpm test:e2e",
|
|
66
|
+
"test:e2e": "playwright test",
|
|
67
|
+
"test:int": "vitest"
|
|
68
|
+
},
|
|
48
69
|
"devDependencies": {
|
|
49
70
|
"@eslint/eslintrc": "^3.2.0",
|
|
50
71
|
"@payloadcms/db-mongodb": "3.81.0",
|
|
@@ -88,29 +109,29 @@
|
|
|
88
109
|
"node": "^18.20.2 || >=20.9.0"
|
|
89
110
|
},
|
|
90
111
|
"publishConfig": {
|
|
112
|
+
"main": "./dist/index.js",
|
|
113
|
+
"types": "./dist/index.d.ts",
|
|
114
|
+
"exports": {
|
|
115
|
+
".": {
|
|
116
|
+
"import": "./dist/index.js",
|
|
117
|
+
"types": "./dist/index.d.ts",
|
|
118
|
+
"default": "./dist/index.js"
|
|
119
|
+
},
|
|
120
|
+
"./client": {
|
|
121
|
+
"import": "./dist/exports/client.js",
|
|
122
|
+
"types": "./dist/exports/client.d.ts",
|
|
123
|
+
"default": "./dist/exports/client.js"
|
|
124
|
+
},
|
|
125
|
+
"./rsc": {
|
|
126
|
+
"import": "./dist/exports/rsc.js",
|
|
127
|
+
"types": "./dist/exports/rsc.d.ts",
|
|
128
|
+
"default": "./dist/exports/rsc.js"
|
|
129
|
+
}
|
|
130
|
+
},
|
|
91
131
|
"registry": "https://registry.npmjs.org/"
|
|
92
132
|
},
|
|
93
133
|
"dependencies": {
|
|
94
134
|
"@dnd-kit/core": "^6.3.1",
|
|
95
135
|
"@dnd-kit/sortable": "10.0.0"
|
|
96
|
-
},
|
|
97
|
-
"scripts": {
|
|
98
|
-
"build": "pnpm clean && pnpm build:types && pnpm build:swc && pnpm copyfiles && pnpm build:strip-tests",
|
|
99
|
-
"build:strip-tests": "rimraf \"dist/**/*.spec.*\"",
|
|
100
|
-
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
|
|
101
|
-
"build:types": "tsc --project tsconfig.build.json",
|
|
102
|
-
"clean": "rimraf dist \"*.tsbuildinfo\"",
|
|
103
|
-
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
|
|
104
|
-
"dev": "next dev dev --webpack",
|
|
105
|
-
"dev:generate-importmap": "pnpm dev:payload generate:importmap",
|
|
106
|
-
"dev:generate-types": "pnpm dev:payload generate:types",
|
|
107
|
-
"dev:payload": "cross-env PAYLOAD_CONFIG_PATH=./dev/payload.config.ts payload",
|
|
108
|
-
"generate:importmap": "pnpm dev:generate-importmap",
|
|
109
|
-
"generate:types": "pnpm dev:generate-types",
|
|
110
|
-
"lint": "eslint",
|
|
111
|
-
"lint:fix": "eslint ./src --fix",
|
|
112
|
-
"test": "pnpm test:int && pnpm test:e2e",
|
|
113
|
-
"test:e2e": "playwright test",
|
|
114
|
-
"test:int": "vitest"
|
|
115
136
|
}
|
|
116
|
-
}
|
|
137
|
+
}
|