@strapi/content-type-builder 5.54.0 → 5.55.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.
Files changed (208) hide show
  1. package/dist/admin/components/AIChat/hooks/useAIFetch.js +6 -2
  2. package/dist/admin/components/AIChat/hooks/useAIFetch.js.map +1 -1
  3. package/dist/admin/components/AIChat/hooks/useAIFetch.mjs +7 -3
  4. package/dist/admin/components/AIChat/hooks/useAIFetch.mjs.map +1 -1
  5. package/dist/admin/components/AIChat/hooks/usePrefetchAIToken.js +20 -0
  6. package/dist/admin/components/AIChat/hooks/usePrefetchAIToken.js.map +1 -0
  7. package/dist/admin/components/AIChat/hooks/usePrefetchAIToken.mjs +18 -0
  8. package/dist/admin/components/AIChat/hooks/usePrefetchAIToken.mjs.map +1 -0
  9. package/dist/admin/components/ContentTypeBuilderNav/ContentTypeBuilderNav.js +83 -59
  10. package/dist/admin/components/ContentTypeBuilderNav/ContentTypeBuilderNav.js.map +1 -1
  11. package/dist/admin/components/ContentTypeBuilderNav/ContentTypeBuilderNav.mjs +86 -62
  12. package/dist/admin/components/ContentTypeBuilderNav/ContentTypeBuilderNav.mjs.map +1 -1
  13. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/DeleteFolderDialog.js +112 -0
  14. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/DeleteFolderDialog.js.map +1 -0
  15. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/DeleteFolderDialog.mjs +110 -0
  16. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/DeleteFolderDialog.mjs.map +1 -0
  17. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/FolderNameField.js +159 -0
  18. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/FolderNameField.js.map +1 -0
  19. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/FolderNameField.mjs +157 -0
  20. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/FolderNameField.mjs.map +1 -0
  21. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/FolderNavSection.js +311 -0
  22. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/FolderNavSection.js.map +1 -0
  23. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/FolderNavSection.mjs +309 -0
  24. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/FolderNavSection.mjs.map +1 -0
  25. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/SortableTreeRow.js +379 -0
  26. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/SortableTreeRow.js.map +1 -0
  27. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/SortableTreeRow.mjs +376 -0
  28. package/dist/admin/components/ContentTypeBuilderNav/components/FolderNav/SortableTreeRow.mjs.map +1 -0
  29. package/dist/admin/components/ContentTypeBuilderNav/hooks/useContentTypeBuilderMenu.js +172 -0
  30. package/dist/admin/components/ContentTypeBuilderNav/hooks/useContentTypeBuilderMenu.js.map +1 -0
  31. package/dist/admin/components/ContentTypeBuilderNav/hooks/useContentTypeBuilderMenu.mjs +166 -0
  32. package/dist/admin/components/ContentTypeBuilderNav/hooks/useContentTypeBuilderMenu.mjs.map +1 -0
  33. package/dist/admin/components/ContentTypeBuilderNav/hooks/useFolderActions.js +62 -0
  34. package/dist/admin/components/ContentTypeBuilderNav/hooks/useFolderActions.js.map +1 -0
  35. package/dist/admin/components/ContentTypeBuilderNav/hooks/useFolderActions.mjs +60 -0
  36. package/dist/admin/components/ContentTypeBuilderNav/hooks/useFolderActions.mjs.map +1 -0
  37. package/dist/admin/components/ContentTypeBuilderNav/hooks/useSortableTree.js +145 -0
  38. package/dist/admin/components/ContentTypeBuilderNav/hooks/useSortableTree.js.map +1 -0
  39. package/dist/admin/components/ContentTypeBuilderNav/hooks/useSortableTree.mjs +143 -0
  40. package/dist/admin/components/ContentTypeBuilderNav/hooks/useSortableTree.mjs.map +1 -0
  41. package/dist/admin/components/ContentTypeBuilderNav/lib/buildFolderTree.js +176 -0
  42. package/dist/admin/components/ContentTypeBuilderNav/lib/buildFolderTree.js.map +1 -0
  43. package/dist/admin/components/ContentTypeBuilderNav/lib/buildFolderTree.mjs +169 -0
  44. package/dist/admin/components/ContentTypeBuilderNav/lib/buildFolderTree.mjs.map +1 -0
  45. package/dist/admin/components/ContentTypeBuilderNav/lib/dropProjection.js +277 -0
  46. package/dist/admin/components/ContentTypeBuilderNav/lib/dropProjection.js.map +1 -0
  47. package/dist/admin/components/ContentTypeBuilderNav/lib/dropProjection.mjs +273 -0
  48. package/dist/admin/components/ContentTypeBuilderNav/lib/dropProjection.mjs.map +1 -0
  49. package/dist/admin/components/ContentTypeBuilderNav/lib/flatModel.js +62 -0
  50. package/dist/admin/components/ContentTypeBuilderNav/lib/flatModel.js.map +1 -0
  51. package/dist/admin/components/ContentTypeBuilderNav/lib/flatModel.mjs +58 -0
  52. package/dist/admin/components/ContentTypeBuilderNav/lib/flatModel.mjs.map +1 -0
  53. package/dist/admin/components/DataManager/DataManagerContext.js.map +1 -1
  54. package/dist/admin/components/DataManager/DataManagerContext.mjs.map +1 -1
  55. package/dist/admin/components/DataManager/DataManagerProvider.js +70 -8
  56. package/dist/admin/components/DataManager/DataManagerProvider.js.map +1 -1
  57. package/dist/admin/components/DataManager/DataManagerProvider.mjs +70 -8
  58. package/dist/admin/components/DataManager/DataManagerProvider.mjs.map +1 -1
  59. package/dist/admin/components/DataManager/reducer.js +411 -33
  60. package/dist/admin/components/DataManager/reducer.js.map +1 -1
  61. package/dist/admin/components/DataManager/reducer.mjs +411 -33
  62. package/dist/admin/components/DataManager/reducer.mjs.map +1 -1
  63. package/dist/admin/components/DataManager/utils/cleanData.js +11 -2
  64. package/dist/admin/components/DataManager/utils/cleanData.js.map +1 -1
  65. package/dist/admin/components/DataManager/utils/cleanData.mjs +11 -2
  66. package/dist/admin/components/DataManager/utils/cleanData.mjs.map +1 -1
  67. package/dist/admin/components/DataManager/utils/contentStructure.js +150 -0
  68. package/dist/admin/components/DataManager/utils/contentStructure.js.map +1 -0
  69. package/dist/admin/components/DataManager/utils/contentStructure.mjs +133 -0
  70. package/dist/admin/components/DataManager/utils/contentStructure.mjs.map +1 -0
  71. package/dist/admin/components/FolderSelect.js +200 -0
  72. package/dist/admin/components/FolderSelect.js.map +1 -0
  73. package/dist/admin/components/FolderSelect.mjs +198 -0
  74. package/dist/admin/components/FolderSelect.mjs.map +1 -0
  75. package/dist/admin/components/FormModal/FormModal.js +23 -2
  76. package/dist/admin/components/FormModal/FormModal.js.map +1 -1
  77. package/dist/admin/components/FormModal/FormModal.mjs +23 -2
  78. package/dist/admin/components/FormModal/FormModal.mjs.map +1 -1
  79. package/dist/admin/components/FormModal/contentType/contentTypeForm.js +15 -18
  80. package/dist/admin/components/FormModal/contentType/contentTypeForm.js.map +1 -1
  81. package/dist/admin/components/FormModal/contentType/contentTypeForm.mjs +15 -18
  82. package/dist/admin/components/FormModal/contentType/contentTypeForm.mjs.map +1 -1
  83. package/dist/admin/components/FormModal/reducer.js +6 -0
  84. package/dist/admin/components/FormModal/reducer.js.map +1 -1
  85. package/dist/admin/components/FormModal/reducer.mjs +6 -0
  86. package/dist/admin/components/FormModal/reducer.mjs.map +1 -1
  87. package/dist/admin/pages/App/index.js +2 -5
  88. package/dist/admin/pages/App/index.js.map +1 -1
  89. package/dist/admin/pages/App/index.mjs +2 -5
  90. package/dist/admin/pages/App/index.mjs.map +1 -1
  91. package/dist/admin/src/components/AIChat/hooks/usePrefetchAIToken.d.ts +1 -0
  92. package/dist/admin/src/components/ContentTypeBuilderNav/components/FolderNav/DeleteFolderDialog.d.ts +16 -0
  93. package/dist/admin/src/components/ContentTypeBuilderNav/components/FolderNav/FolderNameField.d.ts +12 -0
  94. package/dist/admin/src/components/ContentTypeBuilderNav/components/FolderNav/FolderNavSection.d.ts +14 -0
  95. package/dist/admin/src/components/ContentTypeBuilderNav/components/FolderNav/SortableTreeRow.d.ts +38 -0
  96. package/dist/admin/src/components/ContentTypeBuilderNav/{useContentTypeBuilderMenu.d.ts → hooks/useContentTypeBuilderMenu.d.ts} +17 -7
  97. package/dist/admin/src/components/ContentTypeBuilderNav/hooks/useFolderActions.d.ts +42 -0
  98. package/dist/admin/src/components/ContentTypeBuilderNav/hooks/useSortableTree.d.ts +53 -0
  99. package/dist/admin/src/components/ContentTypeBuilderNav/lib/buildFolderTree.d.ts +42 -0
  100. package/dist/admin/src/components/ContentTypeBuilderNav/lib/dropProjection.d.ts +58 -0
  101. package/dist/admin/src/components/ContentTypeBuilderNav/lib/flatModel.d.ts +18 -0
  102. package/dist/admin/src/components/DataManager/DataManagerContext.d.ts +41 -0
  103. package/dist/admin/src/components/DataManager/reducer.d.ts +105 -1
  104. package/dist/admin/src/components/DataManager/utils/cleanData.d.ts +5 -1
  105. package/dist/admin/src/components/DataManager/utils/contentStructure.d.ts +68 -0
  106. package/dist/admin/src/components/FolderSelect.d.ts +18 -0
  107. package/dist/admin/src/components/FormModal/contentType/contentTypeForm.d.ts +0 -21
  108. package/dist/admin/src/components/FormModal/forms/forms.d.ts +0 -10
  109. package/dist/admin/src/components/FormModal/reducer.d.ts +7 -0
  110. package/dist/admin/src/utils/folderTelemetry.d.ts +5 -0
  111. package/dist/admin/translations/en.json.js +23 -0
  112. package/dist/admin/translations/en.json.js.map +1 -1
  113. package/dist/admin/translations/en.json.mjs +23 -0
  114. package/dist/admin/translations/en.json.mjs.map +1 -1
  115. package/dist/admin/utils/folderTelemetry.js +19 -0
  116. package/dist/admin/utils/folderTelemetry.js.map +1 -0
  117. package/dist/admin/utils/folderTelemetry.mjs +16 -0
  118. package/dist/admin/utils/folderTelemetry.mjs.map +1 -0
  119. package/dist/server/controllers/schema.js +1 -1
  120. package/dist/server/controllers/schema.js.map +1 -1
  121. package/dist/server/controllers/schema.mjs +1 -1
  122. package/dist/server/controllers/schema.mjs.map +1 -1
  123. package/dist/server/controllers/validation/common.js +3 -0
  124. package/dist/server/controllers/validation/common.js.map +1 -1
  125. package/dist/server/controllers/validation/common.mjs +3 -1
  126. package/dist/server/controllers/validation/common.mjs.map +1 -1
  127. package/dist/server/controllers/validation/content-structure.js +177 -0
  128. package/dist/server/controllers/validation/content-structure.js.map +1 -0
  129. package/dist/server/controllers/validation/content-structure.mjs +173 -0
  130. package/dist/server/controllers/validation/content-structure.mjs.map +1 -0
  131. package/dist/server/controllers/validation/schema.js +3 -1
  132. package/dist/server/controllers/validation/schema.js.map +1 -1
  133. package/dist/server/controllers/validation/schema.mjs +3 -1
  134. package/dist/server/controllers/validation/schema.mjs.map +1 -1
  135. package/dist/server/register.js +1 -1
  136. package/dist/server/register.js.map +1 -1
  137. package/dist/server/register.mjs +1 -1
  138. package/dist/server/register.mjs.map +1 -1
  139. package/dist/server/routes/content-api.js +4 -4
  140. package/dist/server/routes/content-api.js.map +1 -1
  141. package/dist/server/routes/content-api.mjs +4 -4
  142. package/dist/server/routes/content-api.mjs.map +1 -1
  143. package/dist/server/services/api-handler.js +37 -4
  144. package/dist/server/services/api-handler.js.map +1 -1
  145. package/dist/server/services/api-handler.mjs +36 -5
  146. package/dist/server/services/api-handler.mjs.map +1 -1
  147. package/dist/server/services/content-structure.js +174 -0
  148. package/dist/server/services/content-structure.js.map +1 -0
  149. package/dist/server/services/content-structure.mjs +172 -0
  150. package/dist/server/services/content-structure.mjs.map +1 -0
  151. package/dist/server/services/content-types.js +196 -44
  152. package/dist/server/services/content-types.js.map +1 -1
  153. package/dist/server/services/content-types.mjs +195 -45
  154. package/dist/server/services/content-types.mjs.map +1 -1
  155. package/dist/server/services/index.js +3 -1
  156. package/dist/server/services/index.js.map +1 -1
  157. package/dist/server/services/index.mjs +3 -1
  158. package/dist/server/services/index.mjs.map +1 -1
  159. package/dist/server/services/schema-builder/index.js +4 -2
  160. package/dist/server/services/schema-builder/index.js.map +1 -1
  161. package/dist/server/services/schema-builder/index.mjs +4 -2
  162. package/dist/server/services/schema-builder/index.mjs.map +1 -1
  163. package/dist/server/services/schema-builder/schema-handler.js +16 -16
  164. package/dist/server/services/schema-builder/schema-handler.js.map +1 -1
  165. package/dist/server/services/schema-builder/schema-handler.mjs +16 -16
  166. package/dist/server/services/schema-builder/schema-handler.mjs.map +1 -1
  167. package/dist/server/services/schema-mutation.js +46 -0
  168. package/dist/server/services/schema-mutation.js.map +1 -0
  169. package/dist/server/services/schema-mutation.mjs +43 -0
  170. package/dist/server/services/schema-mutation.mjs.map +1 -0
  171. package/dist/server/services/schema.js +134 -79
  172. package/dist/server/services/schema.js.map +1 -1
  173. package/dist/server/services/schema.mjs +135 -80
  174. package/dist/server/services/schema.mjs.map +1 -1
  175. package/dist/server/src/controllers/schema.d.ts.map +1 -1
  176. package/dist/server/src/controllers/validation/common.d.ts +1 -0
  177. package/dist/server/src/controllers/validation/common.d.ts.map +1 -1
  178. package/dist/server/src/controllers/validation/content-structure.d.ts +56 -0
  179. package/dist/server/src/controllers/validation/content-structure.d.ts.map +1 -0
  180. package/dist/server/src/controllers/validation/schema.d.ts +35 -0
  181. package/dist/server/src/controllers/validation/schema.d.ts.map +1 -1
  182. package/dist/server/src/index.d.ts +3 -0
  183. package/dist/server/src/index.d.ts.map +1 -1
  184. package/dist/server/src/routes/content-api.d.ts.map +1 -1
  185. package/dist/server/src/services/api-handler.d.ts +13 -1
  186. package/dist/server/src/services/api-handler.d.ts.map +1 -1
  187. package/dist/server/src/services/content-structure.d.ts +37 -0
  188. package/dist/server/src/services/content-structure.d.ts.map +1 -0
  189. package/dist/server/src/services/content-types.d.ts +4 -0
  190. package/dist/server/src/services/content-types.d.ts.map +1 -1
  191. package/dist/server/src/services/index.d.ts +4 -0
  192. package/dist/server/src/services/index.d.ts.map +1 -1
  193. package/dist/server/src/services/schema-builder/index.d.ts +3 -1
  194. package/dist/server/src/services/schema-builder/index.d.ts.map +1 -1
  195. package/dist/server/src/services/schema-builder/schema-handler.d.ts.map +1 -1
  196. package/dist/server/src/services/schema-mutation.d.ts +26 -0
  197. package/dist/server/src/services/schema-mutation.d.ts.map +1 -0
  198. package/dist/server/src/services/schema.d.ts +1 -0
  199. package/dist/server/src/services/schema.d.ts.map +1 -1
  200. package/dist/server/src/utils/index.d.ts +2 -0
  201. package/dist/server/src/utils/index.d.ts.map +1 -1
  202. package/dist/server/utils/index.js.map +1 -1
  203. package/dist/server/utils/index.mjs.map +1 -1
  204. package/package.json +6 -6
  205. package/dist/admin/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.js +0 -157
  206. package/dist/admin/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.js.map +0 -1
  207. package/dist/admin/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.mjs +0 -151
  208. package/dist/admin/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.mjs.map +0 -1
@@ -0,0 +1,277 @@
1
+ 'use strict';
2
+
3
+ var sortable = require('@dnd-kit/sortable');
4
+ var contentStructure = require('../../DataManager/utils/contentStructure.js');
5
+ var buildFolderTree = require('./buildFolderTree.js');
6
+
7
+ const INDENT_WIDTH = 24; // theme.spaces[6]
8
+ const clamp = (value, min, max)=>{
9
+ return Math.min(Math.max(value, min), max);
10
+ };
11
+ /**
12
+ * Locates the position for the line indicator given that root-level re-ordering is currently
13
+ * not possible. This is temporary measure until root-level re-ordering is implemented.
14
+ */ function getDropTargetSectionRoot(items, activeId) {
15
+ const rootItems = items.filter((item)=>item.depth === 0 && item.id !== activeId);
16
+ const lastRootLeaf = [
17
+ ...rootItems
18
+ ].reverse().find((item)=>item.node.type === 'contentType');
19
+ const firstRootFolder = rootItems.find((item)=>item.node.type === 'folder');
20
+ const line = (()=>{
21
+ if (firstRootFolder) {
22
+ return {
23
+ anchorId: firstRootFolder.id,
24
+ edge: 'top'
25
+ };
26
+ }
27
+ if (lastRootLeaf) {
28
+ return {
29
+ anchorId: lastRootLeaf.id,
30
+ edge: 'bottom'
31
+ };
32
+ }
33
+ return null;
34
+ })();
35
+ return {
36
+ parentId: null,
37
+ index: 0,
38
+ depth: 0,
39
+ line
40
+ };
41
+ }
42
+ function getDropTargetBetweenRows(items, activeId, overId, offsetX, side) {
43
+ const activeIndex = items.findIndex((item)=>item.id === activeId);
44
+ const overIndex = items.findIndex((item)=>item.id === overId);
45
+ if (overIndex === -1 || activeIndex === -1) {
46
+ return null;
47
+ }
48
+ const active = items[activeIndex];
49
+ const { rowsBeforeSlot, previous, next } = (()=>{
50
+ if (side) {
51
+ const withoutActive = items.filter((item)=>item.id !== activeId);
52
+ const overPos = withoutActive.findIndex((item)=>item.id === overId);
53
+ const insertPos = side === 'before' ? overPos : overPos + 1;
54
+ return {
55
+ rowsBeforeSlot: withoutActive.slice(0, insertPos),
56
+ previous: withoutActive[insertPos - 1],
57
+ next: withoutActive[insertPos]
58
+ };
59
+ }
60
+ const reordered = sortable.arrayMove(items, activeIndex, overIndex);
61
+ return {
62
+ rowsBeforeSlot: reordered.slice(0, overIndex),
63
+ previous: reordered[overIndex - 1],
64
+ next: reordered[overIndex + 1]
65
+ };
66
+ })();
67
+ const dragDepth = Math.round(offsetX / INDENT_WIDTH);
68
+ const projectedDepth = active.depth + dragDepth;
69
+ const minDepth = next ? next.depth : 0;
70
+ let maxDepth;
71
+ if (!previous) {
72
+ maxDepth = 0;
73
+ } else if (previous.node.type === 'folder' && !previous.collapsed) {
74
+ maxDepth = previous.depth + 1;
75
+ } else {
76
+ maxDepth = previous.depth;
77
+ }
78
+ if (active.node.type === 'folder') {
79
+ const folderCeiling = contentStructure.MAX_FOLDER_DEPTH - buildFolderTree.subtreeFolderHeight(active.node);
80
+ maxDepth = Math.min(maxDepth, folderCeiling);
81
+ }
82
+ if (maxDepth < minDepth) {
83
+ return null;
84
+ }
85
+ const depth = clamp(projectedDepth, minDepth, maxDepth);
86
+ const parentId = (()=>{
87
+ if (depth === 0 || !previous) {
88
+ return null;
89
+ }
90
+ if (depth === previous.depth) {
91
+ return previous.parentId;
92
+ }
93
+ if (depth > previous.depth) {
94
+ return previous.node.type === 'folder' ? previous.node.id : previous.parentId;
95
+ }
96
+ const ancestor = [
97
+ ...rowsBeforeSlot
98
+ ].reverse().find((item)=>item.depth === depth);
99
+ return ancestor ? ancestor.parentId : null;
100
+ })();
101
+ let index = 0;
102
+ for (const item of rowsBeforeSlot){
103
+ if (item.parentId !== parentId || item.depth !== depth) {
104
+ continue;
105
+ }
106
+ if (parentId === null && item.node.type !== 'folder') {
107
+ continue;
108
+ }
109
+ index += 1;
110
+ }
111
+ const line = (()=>{
112
+ if (next) {
113
+ return {
114
+ anchorId: next.id,
115
+ edge: 'top'
116
+ };
117
+ }
118
+ if (previous) {
119
+ return {
120
+ anchorId: previous.id,
121
+ edge: 'bottom'
122
+ };
123
+ }
124
+ return null;
125
+ })();
126
+ /** For the time being, root content types have no stored order, so trying to move something there is not a real re-order operation. */ const insertingAmongRootContentTypes = parentId === null && next !== undefined && next.node.type === 'contentType' && next.parentId === null;
127
+ if (insertingAmongRootContentTypes) {
128
+ return getDropTargetSectionRoot(items, activeId);
129
+ }
130
+ return {
131
+ parentId,
132
+ index,
133
+ depth,
134
+ line
135
+ };
136
+ }
137
+ function getDropTargetFolderSibling(items, activeId, folderId, side) {
138
+ const folderIndex = items.findIndex((item)=>item.id === folderId);
139
+ const active = items.find((item)=>item.id === activeId);
140
+ if (folderIndex === -1 || !active) {
141
+ return null;
142
+ }
143
+ const folder = items[folderIndex];
144
+ const { parentId, depth } = folder;
145
+ if (active.node.type === 'folder' && depth + buildFolderTree.subtreeFolderHeight(active.node) > contentStructure.MAX_FOLDER_DEPTH) {
146
+ return null;
147
+ }
148
+ const boundary = side === 'before' ? folderIndex : folderIndex + 1;
149
+ let index = 0;
150
+ for(let i = 0; i < boundary; i += 1){
151
+ const item = items[i];
152
+ if (item.id === activeId) {
153
+ continue;
154
+ }
155
+ if (item.parentId !== parentId || item.depth !== depth) {
156
+ continue;
157
+ }
158
+ if (parentId === null && item.node.type !== 'folder') {
159
+ continue;
160
+ }
161
+ index += 1;
162
+ }
163
+ const line = (()=>{
164
+ if (side === 'before') {
165
+ return {
166
+ anchorId: folder.id,
167
+ edge: 'top'
168
+ };
169
+ }
170
+ let lastIndex = folderIndex;
171
+ for(let i = folderIndex + 1; i < items.length; i += 1){
172
+ if (items[i].depth <= depth) {
173
+ break;
174
+ }
175
+ lastIndex = i;
176
+ }
177
+ return {
178
+ anchorId: items[lastIndex].id,
179
+ edge: 'bottom'
180
+ };
181
+ })();
182
+ return {
183
+ parentId,
184
+ index,
185
+ depth,
186
+ line
187
+ };
188
+ }
189
+ /**
190
+ * This resolved the destination for a drag-and-drop operation in the contentStructure tree. It takes into account the active item being dragged, the item it is being dropped over, the horizontal offset of the drag, and optionally which side of the target item the drop is intended for.
191
+ * It returns a DropTarget object that describes where the active item should be placed in relation to its siblings and parent in the tree structure.
192
+ *
193
+ * When the dragged row is over a non-folder row, the drop target is always a sibling of that row (and its destination is based on which half of the row the pointer is over).
194
+ *
195
+ * When the dragged row is over a folder row, the drop target can be either a sibling of that folder (if the pointer is over the top or bottom third of the row) or a child of that folder (if the pointer is over the middle third of the row).
196
+ * If the folder is collapsed, dropping into it will expand it and place the active row inside it.
197
+ *
198
+ * If the destination is nested such that the destination could be one of several depths, the depth is determined by the horizontal offset of the pointer.
199
+ *
200
+ * This allows for a user to position a row at the end of a folder, even if there are several expanded folders above the destination. Otherwise, this would be a multi-step operation.
201
+ *
202
+ */ function resolveDropTarget(items, dragState) {
203
+ const { activeId, overId, offsetX, pointer, overRect } = dragState;
204
+ if (overId === activeId) {
205
+ return null;
206
+ }
207
+ const itemHoveredByCursor = items.find((item)=>item.id === overId);
208
+ // If item is valid FoldeRNode
209
+ if (itemHoveredByCursor && itemHoveredByCursor.node.type === 'folder' && pointer && overRect) {
210
+ const folderNode = itemHoveredByCursor.node;
211
+ const nextItem = items[items.indexOf(itemHoveredByCursor) + 1];
212
+ const hasVisibleChildren = nextItem != null && nextItem.depth > itemHoveredByCursor.depth;
213
+ // Determine which zone of the folder row the pointer is in (top, middle, bottom).
214
+ const zone = calculateFolderDropZone({
215
+ itemBoundingBox: overRect,
216
+ pointerY: pointer.y,
217
+ hasVisibleChildren
218
+ });
219
+ if (zone === 'nest') {
220
+ const activeNode = items.find(({ id })=>id === activeId)?.node;
221
+ const nestIsValid = activeNode == null || activeNode.type !== 'folder' || buildFolderTree.canNestFolderAt(activeNode, folderNode);
222
+ if (!nestIsValid) {
223
+ return null;
224
+ }
225
+ return {
226
+ kind: 'nest',
227
+ folderId: folderNode.id,
228
+ depth: itemHoveredByCursor.depth + 1
229
+ };
230
+ }
231
+ const sibling = getDropTargetFolderSibling(items, activeId, overId, zone);
232
+ if (sibling) {
233
+ return {
234
+ kind: 'insert',
235
+ ...sibling
236
+ };
237
+ }
238
+ }
239
+ const side = (()=>{
240
+ if (!pointer || !overRect) {
241
+ return undefined;
242
+ }
243
+ return pointer.y < overRect.top + overRect.height / 2 ? 'before' : 'after';
244
+ })();
245
+ const insert = getDropTargetBetweenRows(items, activeId, overId, offsetX, side);
246
+ return insert ? {
247
+ kind: 'insert',
248
+ ...insert
249
+ } : null;
250
+ }
251
+ /**
252
+ * Configuration for the folder drop zones.
253
+ *
254
+ * There are three zones and several possible behaviors:
255
+ * 1. The top zone of the folder row ("beore"). This drops the the dragged row above the folder row.
256
+ * 2. The bottom zone of the folder row ("after"). This drops the dragged row below the folder row.
257
+ * If the folder is expanded:
258
+ * 3. The middle zone of the folder row ("nest"). This drops the dragged row inside the folder row.
259
+ * If the folder is collapsed:
260
+ * 3A. The middle zone of the folder row ("nest"). This drops the dragged row inside the folder row.
261
+ * 3B. If the folder is held over the middle zone for a certain amount of time, the folder will expand and the dragged row can be dropped inside the folder row.
262
+ */ const NEST_ZONE_BOTTOM = 0.8;
263
+ const NEST_ZONE_TOP = 0.2;
264
+ function calculateFolderDropZone({ hasVisibleChildren, itemBoundingBox, pointerY }) {
265
+ if (pointerY < itemBoundingBox.top + itemBoundingBox.height * NEST_ZONE_TOP) {
266
+ return 'before';
267
+ }
268
+ if (!hasVisibleChildren && pointerY > itemBoundingBox.top + itemBoundingBox.height * NEST_ZONE_BOTTOM) {
269
+ return 'after';
270
+ }
271
+ return 'nest';
272
+ }
273
+
274
+ exports.INDENT_WIDTH = INDENT_WIDTH;
275
+ exports.calculateFolderDropZone = calculateFolderDropZone;
276
+ exports.resolveDropTarget = resolveDropTarget;
277
+ //# sourceMappingURL=dropProjection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dropProjection.js","sources":["../../../../../admin/src/components/ContentTypeBuilderNav/lib/dropProjection.ts"],"sourcesContent":["import { arrayMove } from '@dnd-kit/sortable';\n\nimport { MAX_FOLDER_DEPTH } from '../../DataManager/utils/contentStructure';\n\nimport { canNestFolderAt, subtreeFolderHeight } from './buildFolderTree';\n\nimport type { FlatItem } from './flatModel';\n\nexport const INDENT_WIDTH = 24; // theme.spaces[6]\n\n/**\n * Temporary flag to disable root content-type reordering.\n */\nconst ROOT_CONTENT_TYPE_REORDER = false;\n\nconst clamp = (value: number, min: number, max: number) => {\n return Math.min(Math.max(value, min), max);\n};\n\nexport type DropLine = {\n edge: 'top' | 'bottom';\n anchorId: string;\n};\n\nexport type InsertTarget = {\n parentId: string | null;\n line: DropLine | null;\n index: number;\n depth: number;\n};\n\nexport type DropTarget =\n | { kind: 'nest'; folderId: string; depth: number }\n | ({ kind: 'insert' } & InsertTarget);\n\n/**\n * Locates the position for the line indicator given that root-level re-ordering is currently\n * not possible. This is temporary measure until root-level re-ordering is implemented.\n */\nfunction getDropTargetSectionRoot(items: FlatItem[], activeId: string): InsertTarget {\n const rootItems = items.filter((item) => item.depth === 0 && item.id !== activeId);\n\n const lastRootLeaf = [...rootItems].reverse().find((item) => item.node.type === 'contentType');\n const firstRootFolder = rootItems.find((item) => item.node.type === 'folder');\n\n const line: DropLine | null = (() => {\n if (firstRootFolder) {\n return { anchorId: firstRootFolder.id, edge: 'top' };\n }\n\n if (lastRootLeaf) {\n return { anchorId: lastRootLeaf.id, edge: 'bottom' };\n }\n\n return null;\n })();\n\n return { parentId: null, index: 0, depth: 0, line };\n}\n\nfunction getDropTargetBetweenRows(\n items: FlatItem[],\n activeId: string,\n overId: string,\n offsetX: number,\n side?: 'before' | 'after'\n): InsertTarget | null {\n const activeIndex = items.findIndex((item) => item.id === activeId);\n const overIndex = items.findIndex((item) => item.id === overId);\n\n if (overIndex === -1 || activeIndex === -1) {\n return null;\n }\n\n const active = items[activeIndex];\n\n const { rowsBeforeSlot, previous, next } = (() => {\n if (side) {\n const withoutActive = items.filter((item) => item.id !== activeId);\n const overPos = withoutActive.findIndex((item) => item.id === overId);\n const insertPos = side === 'before' ? overPos : overPos + 1;\n\n return {\n rowsBeforeSlot: withoutActive.slice(0, insertPos),\n previous: withoutActive[insertPos - 1],\n next: withoutActive[insertPos],\n };\n }\n\n const reordered = arrayMove(items, activeIndex, overIndex);\n\n return {\n rowsBeforeSlot: reordered.slice(0, overIndex),\n previous: reordered[overIndex - 1],\n next: reordered[overIndex + 1],\n };\n })();\n\n const dragDepth = Math.round(offsetX / INDENT_WIDTH);\n const projectedDepth = active.depth + dragDepth;\n\n const minDepth = next ? next.depth : 0;\n\n let maxDepth: number;\n if (!previous) {\n maxDepth = 0;\n } else if (previous.node.type === 'folder' && !previous.collapsed) {\n maxDepth = previous.depth + 1;\n } else {\n maxDepth = previous.depth;\n }\n\n if (active.node.type === 'folder') {\n const folderCeiling = MAX_FOLDER_DEPTH - subtreeFolderHeight(active.node);\n maxDepth = Math.min(maxDepth, folderCeiling);\n }\n\n if (maxDepth < minDepth) {\n return null;\n }\n const depth = clamp(projectedDepth, minDepth, maxDepth);\n\n const parentId = ((): string | null => {\n if (depth === 0 || !previous) {\n return null;\n }\n\n if (depth === previous.depth) {\n return previous.parentId;\n }\n\n if (depth > previous.depth) {\n return previous.node.type === 'folder' ? previous.node.id : previous.parentId;\n }\n\n const ancestor = [...rowsBeforeSlot].reverse().find((item) => item.depth === depth);\n\n return ancestor ? ancestor.parentId : null;\n })();\n\n let index = 0;\n\n for (const item of rowsBeforeSlot) {\n if (item.parentId !== parentId || item.depth !== depth) {\n continue;\n }\n\n if (parentId === null && item.node.type !== 'folder') {\n continue;\n }\n\n index += 1;\n }\n\n const line: DropLine | null = (() => {\n if (next) {\n return { anchorId: next.id, edge: 'top' };\n }\n\n if (previous) {\n return { anchorId: previous.id, edge: 'bottom' };\n }\n\n return null;\n })();\n\n /** For the time being, root content types have no stored order, so trying to move something there is not a real re-order operation. */\n const insertingAmongRootContentTypes =\n parentId === null &&\n next !== undefined &&\n next.node.type === 'contentType' &&\n next.parentId === null;\n\n if (!ROOT_CONTENT_TYPE_REORDER && insertingAmongRootContentTypes) {\n return getDropTargetSectionRoot(items, activeId);\n }\n\n return { parentId, index, depth, line };\n}\n\nfunction getDropTargetFolderSibling(\n items: FlatItem[],\n activeId: string,\n folderId: string,\n side: 'before' | 'after'\n): InsertTarget | null {\n const folderIndex = items.findIndex((item) => item.id === folderId);\n const active = items.find((item) => item.id === activeId);\n\n if (folderIndex === -1 || !active) {\n return null;\n }\n\n const folder = items[folderIndex];\n const { parentId, depth } = folder;\n\n if (\n active.node.type === 'folder' &&\n depth + subtreeFolderHeight(active.node) > MAX_FOLDER_DEPTH\n ) {\n return null;\n }\n\n const boundary = side === 'before' ? folderIndex : folderIndex + 1;\n let index = 0;\n\n for (let i = 0; i < boundary; i += 1) {\n const item = items[i];\n\n if (item.id === activeId) {\n continue;\n }\n\n if (item.parentId !== parentId || item.depth !== depth) {\n continue;\n }\n\n if (parentId === null && item.node.type !== 'folder') {\n continue;\n }\n\n index += 1;\n }\n\n const line: DropLine = (() => {\n if (side === 'before') {\n return { anchorId: folder.id, edge: 'top' };\n }\n\n let lastIndex = folderIndex;\n\n for (let i = folderIndex + 1; i < items.length; i += 1) {\n if (items[i].depth <= depth) {\n break;\n }\n\n lastIndex = i;\n }\n\n return { anchorId: items[lastIndex].id, edge: 'bottom' };\n })();\n\n return { parentId, index, depth, line };\n}\n\ntype DragState = {\n activeId: string;\n overId: string;\n offsetX: number;\n pointer?: { x: number; y: number };\n overRect?: { top: number; height: number };\n};\n\n/**\n * This resolved the destination for a drag-and-drop operation in the contentStructure tree. It takes into account the active item being dragged, the item it is being dropped over, the horizontal offset of the drag, and optionally which side of the target item the drop is intended for.\n * It returns a DropTarget object that describes where the active item should be placed in relation to its siblings and parent in the tree structure.\n *\n * When the dragged row is over a non-folder row, the drop target is always a sibling of that row (and its destination is based on which half of the row the pointer is over).\n *\n * When the dragged row is over a folder row, the drop target can be either a sibling of that folder (if the pointer is over the top or bottom third of the row) or a child of that folder (if the pointer is over the middle third of the row).\n * If the folder is collapsed, dropping into it will expand it and place the active row inside it.\n *\n * If the destination is nested such that the destination could be one of several depths, the depth is determined by the horizontal offset of the pointer.\n *\n * This allows for a user to position a row at the end of a folder, even if there are several expanded folders above the destination. Otherwise, this would be a multi-step operation.\n *\n */\nexport function resolveDropTarget(items: FlatItem[], dragState: DragState): DropTarget | null {\n const { activeId, overId, offsetX, pointer, overRect } = dragState;\n\n if (overId === activeId) {\n return null;\n }\n\n const itemHoveredByCursor = items.find((item) => item.id === overId);\n\n // If item is valid FoldeRNode\n if (itemHoveredByCursor && itemHoveredByCursor.node.type === 'folder' && pointer && overRect) {\n const folderNode = itemHoveredByCursor.node;\n\n const nextItem = items[items.indexOf(itemHoveredByCursor) + 1];\n const hasVisibleChildren = nextItem != null && nextItem.depth > itemHoveredByCursor.depth;\n\n // Determine which zone of the folder row the pointer is in (top, middle, bottom).\n const zone = calculateFolderDropZone({\n itemBoundingBox: overRect,\n pointerY: pointer.y,\n hasVisibleChildren,\n });\n\n if (zone === 'nest') {\n const activeNode = items.find(({ id }) => id === activeId)?.node;\n const nestIsValid =\n activeNode == null ||\n activeNode.type !== 'folder' ||\n canNestFolderAt(activeNode, folderNode);\n\n if (!nestIsValid) {\n return null;\n }\n\n return { kind: 'nest', folderId: folderNode.id, depth: itemHoveredByCursor.depth + 1 };\n }\n\n const sibling = getDropTargetFolderSibling(items, activeId, overId, zone);\n if (sibling) {\n return { kind: 'insert', ...sibling };\n }\n }\n\n const side = (() => {\n if (!pointer || !overRect) {\n return undefined;\n }\n\n return pointer.y < overRect.top + overRect.height / 2 ? 'before' : 'after';\n })();\n\n const insert = getDropTargetBetweenRows(items, activeId, overId, offsetX, side);\n\n return insert ? { kind: 'insert', ...insert } : null;\n}\n\nexport type FolderDropZone = 'before' | 'nest' | 'after';\n\n/**\n * Configuration for the folder drop zones.\n *\n * There are three zones and several possible behaviors:\n * 1. The top zone of the folder row (\"beore\"). This drops the the dragged row above the folder row.\n * 2. The bottom zone of the folder row (\"after\"). This drops the dragged row below the folder row.\n * If the folder is expanded:\n * 3. The middle zone of the folder row (\"nest\"). This drops the dragged row inside the folder row.\n * If the folder is collapsed:\n * 3A. The middle zone of the folder row (\"nest\"). This drops the dragged row inside the folder row.\n * 3B. If the folder is held over the middle zone for a certain amount of time, the folder will expand and the dragged row can be dropped inside the folder row.\n */\n\nconst NEST_ZONE_BOTTOM = 0.8;\nconst NEST_ZONE_TOP = 0.2;\n\ntype CalculateFolderDropZoneProps = {\n itemBoundingBox: { top: number; height: number };\n hasVisibleChildren: boolean;\n pointerY: number;\n};\n\nexport function calculateFolderDropZone({\n hasVisibleChildren,\n itemBoundingBox,\n pointerY,\n}: CalculateFolderDropZoneProps): FolderDropZone {\n if (pointerY < itemBoundingBox.top + itemBoundingBox.height * NEST_ZONE_TOP) {\n return 'before';\n }\n\n if (\n !hasVisibleChildren &&\n pointerY > itemBoundingBox.top + itemBoundingBox.height * NEST_ZONE_BOTTOM\n ) {\n return 'after';\n }\n\n return 'nest';\n}\n"],"names":["INDENT_WIDTH","clamp","value","min","max","Math","getDropTargetSectionRoot","items","activeId","rootItems","filter","item","depth","id","lastRootLeaf","reverse","find","node","type","firstRootFolder","line","anchorId","edge","parentId","index","getDropTargetBetweenRows","overId","offsetX","side","activeIndex","findIndex","overIndex","active","rowsBeforeSlot","previous","next","withoutActive","overPos","insertPos","slice","reordered","arrayMove","dragDepth","round","projectedDepth","minDepth","maxDepth","collapsed","folderCeiling","MAX_FOLDER_DEPTH","subtreeFolderHeight","ancestor","insertingAmongRootContentTypes","undefined","getDropTargetFolderSibling","folderId","folderIndex","folder","boundary","i","lastIndex","length","resolveDropTarget","dragState","pointer","overRect","itemHoveredByCursor","folderNode","nextItem","indexOf","hasVisibleChildren","zone","calculateFolderDropZone","itemBoundingBox","pointerY","y","activeNode","nestIsValid","canNestFolderAt","kind","sibling","top","height","insert","NEST_ZONE_BOTTOM","NEST_ZONE_TOP"],"mappings":"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"}
@@ -0,0 +1,273 @@
1
+ import { arrayMove } from '@dnd-kit/sortable';
2
+ import { MAX_FOLDER_DEPTH } from '../../DataManager/utils/contentStructure.mjs';
3
+ import { canNestFolderAt, subtreeFolderHeight } from './buildFolderTree.mjs';
4
+
5
+ const INDENT_WIDTH = 24; // theme.spaces[6]
6
+ const clamp = (value, min, max)=>{
7
+ return Math.min(Math.max(value, min), max);
8
+ };
9
+ /**
10
+ * Locates the position for the line indicator given that root-level re-ordering is currently
11
+ * not possible. This is temporary measure until root-level re-ordering is implemented.
12
+ */ function getDropTargetSectionRoot(items, activeId) {
13
+ const rootItems = items.filter((item)=>item.depth === 0 && item.id !== activeId);
14
+ const lastRootLeaf = [
15
+ ...rootItems
16
+ ].reverse().find((item)=>item.node.type === 'contentType');
17
+ const firstRootFolder = rootItems.find((item)=>item.node.type === 'folder');
18
+ const line = (()=>{
19
+ if (firstRootFolder) {
20
+ return {
21
+ anchorId: firstRootFolder.id,
22
+ edge: 'top'
23
+ };
24
+ }
25
+ if (lastRootLeaf) {
26
+ return {
27
+ anchorId: lastRootLeaf.id,
28
+ edge: 'bottom'
29
+ };
30
+ }
31
+ return null;
32
+ })();
33
+ return {
34
+ parentId: null,
35
+ index: 0,
36
+ depth: 0,
37
+ line
38
+ };
39
+ }
40
+ function getDropTargetBetweenRows(items, activeId, overId, offsetX, side) {
41
+ const activeIndex = items.findIndex((item)=>item.id === activeId);
42
+ const overIndex = items.findIndex((item)=>item.id === overId);
43
+ if (overIndex === -1 || activeIndex === -1) {
44
+ return null;
45
+ }
46
+ const active = items[activeIndex];
47
+ const { rowsBeforeSlot, previous, next } = (()=>{
48
+ if (side) {
49
+ const withoutActive = items.filter((item)=>item.id !== activeId);
50
+ const overPos = withoutActive.findIndex((item)=>item.id === overId);
51
+ const insertPos = side === 'before' ? overPos : overPos + 1;
52
+ return {
53
+ rowsBeforeSlot: withoutActive.slice(0, insertPos),
54
+ previous: withoutActive[insertPos - 1],
55
+ next: withoutActive[insertPos]
56
+ };
57
+ }
58
+ const reordered = arrayMove(items, activeIndex, overIndex);
59
+ return {
60
+ rowsBeforeSlot: reordered.slice(0, overIndex),
61
+ previous: reordered[overIndex - 1],
62
+ next: reordered[overIndex + 1]
63
+ };
64
+ })();
65
+ const dragDepth = Math.round(offsetX / INDENT_WIDTH);
66
+ const projectedDepth = active.depth + dragDepth;
67
+ const minDepth = next ? next.depth : 0;
68
+ let maxDepth;
69
+ if (!previous) {
70
+ maxDepth = 0;
71
+ } else if (previous.node.type === 'folder' && !previous.collapsed) {
72
+ maxDepth = previous.depth + 1;
73
+ } else {
74
+ maxDepth = previous.depth;
75
+ }
76
+ if (active.node.type === 'folder') {
77
+ const folderCeiling = MAX_FOLDER_DEPTH - subtreeFolderHeight(active.node);
78
+ maxDepth = Math.min(maxDepth, folderCeiling);
79
+ }
80
+ if (maxDepth < minDepth) {
81
+ return null;
82
+ }
83
+ const depth = clamp(projectedDepth, minDepth, maxDepth);
84
+ const parentId = (()=>{
85
+ if (depth === 0 || !previous) {
86
+ return null;
87
+ }
88
+ if (depth === previous.depth) {
89
+ return previous.parentId;
90
+ }
91
+ if (depth > previous.depth) {
92
+ return previous.node.type === 'folder' ? previous.node.id : previous.parentId;
93
+ }
94
+ const ancestor = [
95
+ ...rowsBeforeSlot
96
+ ].reverse().find((item)=>item.depth === depth);
97
+ return ancestor ? ancestor.parentId : null;
98
+ })();
99
+ let index = 0;
100
+ for (const item of rowsBeforeSlot){
101
+ if (item.parentId !== parentId || item.depth !== depth) {
102
+ continue;
103
+ }
104
+ if (parentId === null && item.node.type !== 'folder') {
105
+ continue;
106
+ }
107
+ index += 1;
108
+ }
109
+ const line = (()=>{
110
+ if (next) {
111
+ return {
112
+ anchorId: next.id,
113
+ edge: 'top'
114
+ };
115
+ }
116
+ if (previous) {
117
+ return {
118
+ anchorId: previous.id,
119
+ edge: 'bottom'
120
+ };
121
+ }
122
+ return null;
123
+ })();
124
+ /** For the time being, root content types have no stored order, so trying to move something there is not a real re-order operation. */ const insertingAmongRootContentTypes = parentId === null && next !== undefined && next.node.type === 'contentType' && next.parentId === null;
125
+ if (insertingAmongRootContentTypes) {
126
+ return getDropTargetSectionRoot(items, activeId);
127
+ }
128
+ return {
129
+ parentId,
130
+ index,
131
+ depth,
132
+ line
133
+ };
134
+ }
135
+ function getDropTargetFolderSibling(items, activeId, folderId, side) {
136
+ const folderIndex = items.findIndex((item)=>item.id === folderId);
137
+ const active = items.find((item)=>item.id === activeId);
138
+ if (folderIndex === -1 || !active) {
139
+ return null;
140
+ }
141
+ const folder = items[folderIndex];
142
+ const { parentId, depth } = folder;
143
+ if (active.node.type === 'folder' && depth + subtreeFolderHeight(active.node) > MAX_FOLDER_DEPTH) {
144
+ return null;
145
+ }
146
+ const boundary = side === 'before' ? folderIndex : folderIndex + 1;
147
+ let index = 0;
148
+ for(let i = 0; i < boundary; i += 1){
149
+ const item = items[i];
150
+ if (item.id === activeId) {
151
+ continue;
152
+ }
153
+ if (item.parentId !== parentId || item.depth !== depth) {
154
+ continue;
155
+ }
156
+ if (parentId === null && item.node.type !== 'folder') {
157
+ continue;
158
+ }
159
+ index += 1;
160
+ }
161
+ const line = (()=>{
162
+ if (side === 'before') {
163
+ return {
164
+ anchorId: folder.id,
165
+ edge: 'top'
166
+ };
167
+ }
168
+ let lastIndex = folderIndex;
169
+ for(let i = folderIndex + 1; i < items.length; i += 1){
170
+ if (items[i].depth <= depth) {
171
+ break;
172
+ }
173
+ lastIndex = i;
174
+ }
175
+ return {
176
+ anchorId: items[lastIndex].id,
177
+ edge: 'bottom'
178
+ };
179
+ })();
180
+ return {
181
+ parentId,
182
+ index,
183
+ depth,
184
+ line
185
+ };
186
+ }
187
+ /**
188
+ * This resolved the destination for a drag-and-drop operation in the contentStructure tree. It takes into account the active item being dragged, the item it is being dropped over, the horizontal offset of the drag, and optionally which side of the target item the drop is intended for.
189
+ * It returns a DropTarget object that describes where the active item should be placed in relation to its siblings and parent in the tree structure.
190
+ *
191
+ * When the dragged row is over a non-folder row, the drop target is always a sibling of that row (and its destination is based on which half of the row the pointer is over).
192
+ *
193
+ * When the dragged row is over a folder row, the drop target can be either a sibling of that folder (if the pointer is over the top or bottom third of the row) or a child of that folder (if the pointer is over the middle third of the row).
194
+ * If the folder is collapsed, dropping into it will expand it and place the active row inside it.
195
+ *
196
+ * If the destination is nested such that the destination could be one of several depths, the depth is determined by the horizontal offset of the pointer.
197
+ *
198
+ * This allows for a user to position a row at the end of a folder, even if there are several expanded folders above the destination. Otherwise, this would be a multi-step operation.
199
+ *
200
+ */ function resolveDropTarget(items, dragState) {
201
+ const { activeId, overId, offsetX, pointer, overRect } = dragState;
202
+ if (overId === activeId) {
203
+ return null;
204
+ }
205
+ const itemHoveredByCursor = items.find((item)=>item.id === overId);
206
+ // If item is valid FoldeRNode
207
+ if (itemHoveredByCursor && itemHoveredByCursor.node.type === 'folder' && pointer && overRect) {
208
+ const folderNode = itemHoveredByCursor.node;
209
+ const nextItem = items[items.indexOf(itemHoveredByCursor) + 1];
210
+ const hasVisibleChildren = nextItem != null && nextItem.depth > itemHoveredByCursor.depth;
211
+ // Determine which zone of the folder row the pointer is in (top, middle, bottom).
212
+ const zone = calculateFolderDropZone({
213
+ itemBoundingBox: overRect,
214
+ pointerY: pointer.y,
215
+ hasVisibleChildren
216
+ });
217
+ if (zone === 'nest') {
218
+ const activeNode = items.find(({ id })=>id === activeId)?.node;
219
+ const nestIsValid = activeNode == null || activeNode.type !== 'folder' || canNestFolderAt(activeNode, folderNode);
220
+ if (!nestIsValid) {
221
+ return null;
222
+ }
223
+ return {
224
+ kind: 'nest',
225
+ folderId: folderNode.id,
226
+ depth: itemHoveredByCursor.depth + 1
227
+ };
228
+ }
229
+ const sibling = getDropTargetFolderSibling(items, activeId, overId, zone);
230
+ if (sibling) {
231
+ return {
232
+ kind: 'insert',
233
+ ...sibling
234
+ };
235
+ }
236
+ }
237
+ const side = (()=>{
238
+ if (!pointer || !overRect) {
239
+ return undefined;
240
+ }
241
+ return pointer.y < overRect.top + overRect.height / 2 ? 'before' : 'after';
242
+ })();
243
+ const insert = getDropTargetBetweenRows(items, activeId, overId, offsetX, side);
244
+ return insert ? {
245
+ kind: 'insert',
246
+ ...insert
247
+ } : null;
248
+ }
249
+ /**
250
+ * Configuration for the folder drop zones.
251
+ *
252
+ * There are three zones and several possible behaviors:
253
+ * 1. The top zone of the folder row ("beore"). This drops the the dragged row above the folder row.
254
+ * 2. The bottom zone of the folder row ("after"). This drops the dragged row below the folder row.
255
+ * If the folder is expanded:
256
+ * 3. The middle zone of the folder row ("nest"). This drops the dragged row inside the folder row.
257
+ * If the folder is collapsed:
258
+ * 3A. The middle zone of the folder row ("nest"). This drops the dragged row inside the folder row.
259
+ * 3B. If the folder is held over the middle zone for a certain amount of time, the folder will expand and the dragged row can be dropped inside the folder row.
260
+ */ const NEST_ZONE_BOTTOM = 0.8;
261
+ const NEST_ZONE_TOP = 0.2;
262
+ function calculateFolderDropZone({ hasVisibleChildren, itemBoundingBox, pointerY }) {
263
+ if (pointerY < itemBoundingBox.top + itemBoundingBox.height * NEST_ZONE_TOP) {
264
+ return 'before';
265
+ }
266
+ if (!hasVisibleChildren && pointerY > itemBoundingBox.top + itemBoundingBox.height * NEST_ZONE_BOTTOM) {
267
+ return 'after';
268
+ }
269
+ return 'nest';
270
+ }
271
+
272
+ export { INDENT_WIDTH, calculateFolderDropZone, resolveDropTarget };
273
+ //# sourceMappingURL=dropProjection.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dropProjection.mjs","sources":["../../../../../admin/src/components/ContentTypeBuilderNav/lib/dropProjection.ts"],"sourcesContent":["import { arrayMove } from '@dnd-kit/sortable';\n\nimport { MAX_FOLDER_DEPTH } from '../../DataManager/utils/contentStructure';\n\nimport { canNestFolderAt, subtreeFolderHeight } from './buildFolderTree';\n\nimport type { FlatItem } from './flatModel';\n\nexport const INDENT_WIDTH = 24; // theme.spaces[6]\n\n/**\n * Temporary flag to disable root content-type reordering.\n */\nconst ROOT_CONTENT_TYPE_REORDER = false;\n\nconst clamp = (value: number, min: number, max: number) => {\n return Math.min(Math.max(value, min), max);\n};\n\nexport type DropLine = {\n edge: 'top' | 'bottom';\n anchorId: string;\n};\n\nexport type InsertTarget = {\n parentId: string | null;\n line: DropLine | null;\n index: number;\n depth: number;\n};\n\nexport type DropTarget =\n | { kind: 'nest'; folderId: string; depth: number }\n | ({ kind: 'insert' } & InsertTarget);\n\n/**\n * Locates the position for the line indicator given that root-level re-ordering is currently\n * not possible. This is temporary measure until root-level re-ordering is implemented.\n */\nfunction getDropTargetSectionRoot(items: FlatItem[], activeId: string): InsertTarget {\n const rootItems = items.filter((item) => item.depth === 0 && item.id !== activeId);\n\n const lastRootLeaf = [...rootItems].reverse().find((item) => item.node.type === 'contentType');\n const firstRootFolder = rootItems.find((item) => item.node.type === 'folder');\n\n const line: DropLine | null = (() => {\n if (firstRootFolder) {\n return { anchorId: firstRootFolder.id, edge: 'top' };\n }\n\n if (lastRootLeaf) {\n return { anchorId: lastRootLeaf.id, edge: 'bottom' };\n }\n\n return null;\n })();\n\n return { parentId: null, index: 0, depth: 0, line };\n}\n\nfunction getDropTargetBetweenRows(\n items: FlatItem[],\n activeId: string,\n overId: string,\n offsetX: number,\n side?: 'before' | 'after'\n): InsertTarget | null {\n const activeIndex = items.findIndex((item) => item.id === activeId);\n const overIndex = items.findIndex((item) => item.id === overId);\n\n if (overIndex === -1 || activeIndex === -1) {\n return null;\n }\n\n const active = items[activeIndex];\n\n const { rowsBeforeSlot, previous, next } = (() => {\n if (side) {\n const withoutActive = items.filter((item) => item.id !== activeId);\n const overPos = withoutActive.findIndex((item) => item.id === overId);\n const insertPos = side === 'before' ? overPos : overPos + 1;\n\n return {\n rowsBeforeSlot: withoutActive.slice(0, insertPos),\n previous: withoutActive[insertPos - 1],\n next: withoutActive[insertPos],\n };\n }\n\n const reordered = arrayMove(items, activeIndex, overIndex);\n\n return {\n rowsBeforeSlot: reordered.slice(0, overIndex),\n previous: reordered[overIndex - 1],\n next: reordered[overIndex + 1],\n };\n })();\n\n const dragDepth = Math.round(offsetX / INDENT_WIDTH);\n const projectedDepth = active.depth + dragDepth;\n\n const minDepth = next ? next.depth : 0;\n\n let maxDepth: number;\n if (!previous) {\n maxDepth = 0;\n } else if (previous.node.type === 'folder' && !previous.collapsed) {\n maxDepth = previous.depth + 1;\n } else {\n maxDepth = previous.depth;\n }\n\n if (active.node.type === 'folder') {\n const folderCeiling = MAX_FOLDER_DEPTH - subtreeFolderHeight(active.node);\n maxDepth = Math.min(maxDepth, folderCeiling);\n }\n\n if (maxDepth < minDepth) {\n return null;\n }\n const depth = clamp(projectedDepth, minDepth, maxDepth);\n\n const parentId = ((): string | null => {\n if (depth === 0 || !previous) {\n return null;\n }\n\n if (depth === previous.depth) {\n return previous.parentId;\n }\n\n if (depth > previous.depth) {\n return previous.node.type === 'folder' ? previous.node.id : previous.parentId;\n }\n\n const ancestor = [...rowsBeforeSlot].reverse().find((item) => item.depth === depth);\n\n return ancestor ? ancestor.parentId : null;\n })();\n\n let index = 0;\n\n for (const item of rowsBeforeSlot) {\n if (item.parentId !== parentId || item.depth !== depth) {\n continue;\n }\n\n if (parentId === null && item.node.type !== 'folder') {\n continue;\n }\n\n index += 1;\n }\n\n const line: DropLine | null = (() => {\n if (next) {\n return { anchorId: next.id, edge: 'top' };\n }\n\n if (previous) {\n return { anchorId: previous.id, edge: 'bottom' };\n }\n\n return null;\n })();\n\n /** For the time being, root content types have no stored order, so trying to move something there is not a real re-order operation. */\n const insertingAmongRootContentTypes =\n parentId === null &&\n next !== undefined &&\n next.node.type === 'contentType' &&\n next.parentId === null;\n\n if (!ROOT_CONTENT_TYPE_REORDER && insertingAmongRootContentTypes) {\n return getDropTargetSectionRoot(items, activeId);\n }\n\n return { parentId, index, depth, line };\n}\n\nfunction getDropTargetFolderSibling(\n items: FlatItem[],\n activeId: string,\n folderId: string,\n side: 'before' | 'after'\n): InsertTarget | null {\n const folderIndex = items.findIndex((item) => item.id === folderId);\n const active = items.find((item) => item.id === activeId);\n\n if (folderIndex === -1 || !active) {\n return null;\n }\n\n const folder = items[folderIndex];\n const { parentId, depth } = folder;\n\n if (\n active.node.type === 'folder' &&\n depth + subtreeFolderHeight(active.node) > MAX_FOLDER_DEPTH\n ) {\n return null;\n }\n\n const boundary = side === 'before' ? folderIndex : folderIndex + 1;\n let index = 0;\n\n for (let i = 0; i < boundary; i += 1) {\n const item = items[i];\n\n if (item.id === activeId) {\n continue;\n }\n\n if (item.parentId !== parentId || item.depth !== depth) {\n continue;\n }\n\n if (parentId === null && item.node.type !== 'folder') {\n continue;\n }\n\n index += 1;\n }\n\n const line: DropLine = (() => {\n if (side === 'before') {\n return { anchorId: folder.id, edge: 'top' };\n }\n\n let lastIndex = folderIndex;\n\n for (let i = folderIndex + 1; i < items.length; i += 1) {\n if (items[i].depth <= depth) {\n break;\n }\n\n lastIndex = i;\n }\n\n return { anchorId: items[lastIndex].id, edge: 'bottom' };\n })();\n\n return { parentId, index, depth, line };\n}\n\ntype DragState = {\n activeId: string;\n overId: string;\n offsetX: number;\n pointer?: { x: number; y: number };\n overRect?: { top: number; height: number };\n};\n\n/**\n * This resolved the destination for a drag-and-drop operation in the contentStructure tree. It takes into account the active item being dragged, the item it is being dropped over, the horizontal offset of the drag, and optionally which side of the target item the drop is intended for.\n * It returns a DropTarget object that describes where the active item should be placed in relation to its siblings and parent in the tree structure.\n *\n * When the dragged row is over a non-folder row, the drop target is always a sibling of that row (and its destination is based on which half of the row the pointer is over).\n *\n * When the dragged row is over a folder row, the drop target can be either a sibling of that folder (if the pointer is over the top or bottom third of the row) or a child of that folder (if the pointer is over the middle third of the row).\n * If the folder is collapsed, dropping into it will expand it and place the active row inside it.\n *\n * If the destination is nested such that the destination could be one of several depths, the depth is determined by the horizontal offset of the pointer.\n *\n * This allows for a user to position a row at the end of a folder, even if there are several expanded folders above the destination. Otherwise, this would be a multi-step operation.\n *\n */\nexport function resolveDropTarget(items: FlatItem[], dragState: DragState): DropTarget | null {\n const { activeId, overId, offsetX, pointer, overRect } = dragState;\n\n if (overId === activeId) {\n return null;\n }\n\n const itemHoveredByCursor = items.find((item) => item.id === overId);\n\n // If item is valid FoldeRNode\n if (itemHoveredByCursor && itemHoveredByCursor.node.type === 'folder' && pointer && overRect) {\n const folderNode = itemHoveredByCursor.node;\n\n const nextItem = items[items.indexOf(itemHoveredByCursor) + 1];\n const hasVisibleChildren = nextItem != null && nextItem.depth > itemHoveredByCursor.depth;\n\n // Determine which zone of the folder row the pointer is in (top, middle, bottom).\n const zone = calculateFolderDropZone({\n itemBoundingBox: overRect,\n pointerY: pointer.y,\n hasVisibleChildren,\n });\n\n if (zone === 'nest') {\n const activeNode = items.find(({ id }) => id === activeId)?.node;\n const nestIsValid =\n activeNode == null ||\n activeNode.type !== 'folder' ||\n canNestFolderAt(activeNode, folderNode);\n\n if (!nestIsValid) {\n return null;\n }\n\n return { kind: 'nest', folderId: folderNode.id, depth: itemHoveredByCursor.depth + 1 };\n }\n\n const sibling = getDropTargetFolderSibling(items, activeId, overId, zone);\n if (sibling) {\n return { kind: 'insert', ...sibling };\n }\n }\n\n const side = (() => {\n if (!pointer || !overRect) {\n return undefined;\n }\n\n return pointer.y < overRect.top + overRect.height / 2 ? 'before' : 'after';\n })();\n\n const insert = getDropTargetBetweenRows(items, activeId, overId, offsetX, side);\n\n return insert ? { kind: 'insert', ...insert } : null;\n}\n\nexport type FolderDropZone = 'before' | 'nest' | 'after';\n\n/**\n * Configuration for the folder drop zones.\n *\n * There are three zones and several possible behaviors:\n * 1. The top zone of the folder row (\"beore\"). This drops the the dragged row above the folder row.\n * 2. The bottom zone of the folder row (\"after\"). This drops the dragged row below the folder row.\n * If the folder is expanded:\n * 3. The middle zone of the folder row (\"nest\"). This drops the dragged row inside the folder row.\n * If the folder is collapsed:\n * 3A. The middle zone of the folder row (\"nest\"). This drops the dragged row inside the folder row.\n * 3B. If the folder is held over the middle zone for a certain amount of time, the folder will expand and the dragged row can be dropped inside the folder row.\n */\n\nconst NEST_ZONE_BOTTOM = 0.8;\nconst NEST_ZONE_TOP = 0.2;\n\ntype CalculateFolderDropZoneProps = {\n itemBoundingBox: { top: number; height: number };\n hasVisibleChildren: boolean;\n pointerY: number;\n};\n\nexport function calculateFolderDropZone({\n hasVisibleChildren,\n itemBoundingBox,\n pointerY,\n}: CalculateFolderDropZoneProps): FolderDropZone {\n if (pointerY < itemBoundingBox.top + itemBoundingBox.height * NEST_ZONE_TOP) {\n return 'before';\n }\n\n if (\n !hasVisibleChildren &&\n pointerY > itemBoundingBox.top + itemBoundingBox.height * NEST_ZONE_BOTTOM\n ) {\n return 'after';\n }\n\n return 'nest';\n}\n"],"names":["INDENT_WIDTH","clamp","value","min","max","Math","getDropTargetSectionRoot","items","activeId","rootItems","filter","item","depth","id","lastRootLeaf","reverse","find","node","type","firstRootFolder","line","anchorId","edge","parentId","index","getDropTargetBetweenRows","overId","offsetX","side","activeIndex","findIndex","overIndex","active","rowsBeforeSlot","previous","next","withoutActive","overPos","insertPos","slice","reordered","arrayMove","dragDepth","round","projectedDepth","minDepth","maxDepth","collapsed","folderCeiling","MAX_FOLDER_DEPTH","subtreeFolderHeight","ancestor","insertingAmongRootContentTypes","undefined","getDropTargetFolderSibling","folderId","folderIndex","folder","boundary","i","lastIndex","length","resolveDropTarget","dragState","pointer","overRect","itemHoveredByCursor","folderNode","nextItem","indexOf","hasVisibleChildren","zone","calculateFolderDropZone","itemBoundingBox","pointerY","y","activeNode","nestIsValid","canNestFolderAt","kind","sibling","top","height","insert","NEST_ZONE_BOTTOM","NEST_ZONE_TOP"],"mappings":";;;;AAQO,MAAMA,YAAAA,GAAe,GAAG;AAO/B,MAAMC,KAAAA,GAAQ,CAACC,KAAAA,EAAeC,GAAAA,EAAaC,GAAAA,GAAAA;AACzC,IAAA,OAAOC,KAAKF,GAAG,CAACE,KAAKD,GAAG,CAACF,OAAOC,GAAAA,CAAAA,EAAMC,GAAAA,CAAAA;AACxC,CAAA;AAkBA;;;AAGC,IACD,SAASE,wBAAAA,CAAyBC,KAAiB,EAAEC,QAAgB,EAAA;AACnE,IAAA,MAAMC,SAAAA,GAAYF,KAAAA,CAAMG,MAAM,CAAC,CAACC,IAAAA,GAASA,IAAAA,CAAKC,KAAK,KAAK,CAAA,IAAKD,IAAAA,CAAKE,EAAE,KAAKL,QAAAA,CAAAA;AAEzE,IAAA,MAAMM,YAAAA,GAAe;AAAIL,QAAAA,GAAAA;KAAU,CAACM,OAAO,EAAA,CAAGC,IAAI,CAAC,CAACL,OAASA,IAAAA,CAAKM,IAAI,CAACC,IAAI,KAAK,aAAA,CAAA;IAChF,MAAMC,eAAAA,GAAkBV,SAAAA,CAAUO,IAAI,CAAC,CAACL,OAASA,IAAAA,CAAKM,IAAI,CAACC,IAAI,KAAK,QAAA,CAAA;IAEpE,MAAME,IAAAA,GAAwB,CAAC,IAAA;AAC7B,QAAA,IAAID,eAAAA,EAAiB;YACnB,OAAO;AAAEE,gBAAAA,QAAAA,EAAUF,gBAAgBN,EAAE;gBAAES,IAAAA,EAAM;AAAM,aAAA;AACrD,QAAA;AAEA,QAAA,IAAIR,YAAAA,EAAc;YAChB,OAAO;AAAEO,gBAAAA,QAAAA,EAAUP,aAAaD,EAAE;gBAAES,IAAAA,EAAM;AAAS,aAAA;AACrD,QAAA;QAEA,OAAO,IAAA;IACT,CAAA,GAAA;IAEA,OAAO;QAAEC,QAAAA,EAAU,IAAA;QAAMC,KAAAA,EAAO,CAAA;QAAGZ,KAAAA,EAAO,CAAA;AAAGQ,QAAAA;AAAK,KAAA;AACpD;AAEA,SAASK,wBAAAA,CACPlB,KAAiB,EACjBC,QAAgB,EAChBkB,MAAc,EACdC,OAAe,EACfC,IAAyB,EAAA;IAEzB,MAAMC,WAAAA,GAActB,MAAMuB,SAAS,CAAC,CAACnB,IAAAA,GAASA,IAAAA,CAAKE,EAAE,KAAKL,QAAAA,CAAAA;IAC1D,MAAMuB,SAAAA,GAAYxB,MAAMuB,SAAS,CAAC,CAACnB,IAAAA,GAASA,IAAAA,CAAKE,EAAE,KAAKa,MAAAA,CAAAA;AAExD,IAAA,IAAIK,SAAAA,KAAc,EAAC,IAAKF,WAAAA,KAAgB,EAAC,EAAG;QAC1C,OAAO,IAAA;AACT,IAAA;IAEA,MAAMG,MAAAA,GAASzB,KAAK,CAACsB,WAAAA,CAAY;IAEjC,MAAM,EAAEI,cAAc,EAAEC,QAAQ,EAAEC,IAAI,EAAE,GAAI,CAAA,IAAA;AAC1C,QAAA,IAAIP,IAAAA,EAAM;YACR,MAAMQ,aAAAA,GAAgB7B,MAAMG,MAAM,CAAC,CAACC,IAAAA,GAASA,IAAAA,CAAKE,EAAE,KAAKL,QAAAA,CAAAA;YACzD,MAAM6B,OAAAA,GAAUD,cAAcN,SAAS,CAAC,CAACnB,IAAAA,GAASA,IAAAA,CAAKE,EAAE,KAAKa,MAAAA,CAAAA;AAC9D,YAAA,MAAMY,SAAAA,GAAYV,IAAAA,KAAS,QAAA,GAAWS,OAAAA,GAAUA,OAAAA,GAAU,CAAA;YAE1D,OAAO;gBACLJ,cAAAA,EAAgBG,aAAAA,CAAcG,KAAK,CAAC,CAAA,EAAGD,SAAAA,CAAAA;gBACvCJ,QAAAA,EAAUE,aAAa,CAACE,SAAAA,GAAY,CAAA,CAAE;gBACtCH,IAAAA,EAAMC,aAAa,CAACE,SAAAA;AACtB,aAAA;AACF,QAAA;QAEA,MAAME,SAAAA,GAAYC,SAAAA,CAAUlC,KAAAA,EAAOsB,WAAAA,EAAaE,SAAAA,CAAAA;QAEhD,OAAO;YACLE,cAAAA,EAAgBO,SAAAA,CAAUD,KAAK,CAAC,CAAA,EAAGR,SAAAA,CAAAA;YACnCG,QAAAA,EAAUM,SAAS,CAACT,SAAAA,GAAY,CAAA,CAAE;YAClCI,IAAAA,EAAMK,SAAS,CAACT,SAAAA,GAAY,CAAA;AAC9B,SAAA;IACF,CAAA,GAAA;AAEA,IAAA,MAAMW,SAAAA,GAAYrC,IAAAA,CAAKsC,KAAK,CAAChB,OAAAA,GAAU3B,YAAAA,CAAAA;IACvC,MAAM4C,cAAAA,GAAiBZ,MAAAA,CAAOpB,KAAK,GAAG8B,SAAAA;AAEtC,IAAA,MAAMG,QAAAA,GAAWV,IAAAA,GAAOA,IAAAA,CAAKvB,KAAK,GAAG,CAAA;IAErC,IAAIkC,QAAAA;AACJ,IAAA,IAAI,CAACZ,QAAAA,EAAU;QACbY,QAAAA,GAAW,CAAA;IACb,CAAA,MAAO,IAAIZ,QAAAA,CAASjB,IAAI,CAACC,IAAI,KAAK,QAAA,IAAY,CAACgB,QAAAA,CAASa,SAAS,EAAE;QACjED,QAAAA,GAAWZ,QAAAA,CAAStB,KAAK,GAAG,CAAA;IAC9B,CAAA,MAAO;AACLkC,QAAAA,QAAAA,GAAWZ,SAAStB,KAAK;AAC3B,IAAA;AAEA,IAAA,IAAIoB,MAAAA,CAAOf,IAAI,CAACC,IAAI,KAAK,QAAA,EAAU;AACjC,QAAA,MAAM8B,aAAAA,GAAgBC,gBAAAA,GAAmBC,mBAAAA,CAAoBlB,MAAAA,CAAOf,IAAI,CAAA;QACxE6B,QAAAA,GAAWzC,IAAAA,CAAKF,GAAG,CAAC2C,QAAAA,EAAUE,aAAAA,CAAAA;AAChC,IAAA;AAEA,IAAA,IAAIF,WAAWD,QAAAA,EAAU;QACvB,OAAO,IAAA;AACT,IAAA;IACA,MAAMjC,KAAAA,GAAQX,KAAAA,CAAM2C,cAAAA,EAAgBC,QAAAA,EAAUC,QAAAA,CAAAA;IAE9C,MAAMvB,QAAAA,GAAW,CAAC,IAAA;QAChB,IAAIX,KAAAA,KAAU,CAAA,IAAK,CAACsB,QAAAA,EAAU;YAC5B,OAAO,IAAA;AACT,QAAA;QAEA,IAAItB,KAAAA,KAAUsB,QAAAA,CAAStB,KAAK,EAAE;AAC5B,YAAA,OAAOsB,SAASX,QAAQ;AAC1B,QAAA;QAEA,IAAIX,KAAAA,GAAQsB,QAAAA,CAAStB,KAAK,EAAE;AAC1B,YAAA,OAAOsB,QAAAA,CAASjB,IAAI,CAACC,IAAI,KAAK,QAAA,GAAWgB,QAAAA,CAASjB,IAAI,CAACJ,EAAE,GAAGqB,QAAAA,CAASX,QAAQ;AAC/E,QAAA;AAEA,QAAA,MAAM4B,QAAAA,GAAW;AAAIlB,YAAAA,GAAAA;SAAe,CAAClB,OAAO,GAAGC,IAAI,CAAC,CAACL,IAAAA,GAASA,IAAAA,CAAKC,KAAK,KAAKA,KAAAA,CAAAA;QAE7E,OAAOuC,QAAAA,GAAWA,QAAAA,CAAS5B,QAAQ,GAAG,IAAA;IACxC,CAAA,GAAA;AAEA,IAAA,IAAIC,KAAAA,GAAQ,CAAA;IAEZ,KAAK,MAAMb,QAAQsB,cAAAA,CAAgB;AACjC,QAAA,IAAItB,KAAKY,QAAQ,KAAKA,YAAYZ,IAAAA,CAAKC,KAAK,KAAKA,KAAAA,EAAO;AACtD,YAAA;AACF,QAAA;AAEA,QAAA,IAAIW,aAAa,IAAA,IAAQZ,IAAAA,CAAKM,IAAI,CAACC,IAAI,KAAK,QAAA,EAAU;AACpD,YAAA;AACF,QAAA;QAEAM,KAAAA,IAAS,CAAA;AACX,IAAA;IAEA,MAAMJ,IAAAA,GAAwB,CAAC,IAAA;AAC7B,QAAA,IAAIe,IAAAA,EAAM;YACR,OAAO;AAAEd,gBAAAA,QAAAA,EAAUc,KAAKtB,EAAE;gBAAES,IAAAA,EAAM;AAAM,aAAA;AAC1C,QAAA;AAEA,QAAA,IAAIY,QAAAA,EAAU;YACZ,OAAO;AAAEb,gBAAAA,QAAAA,EAAUa,SAASrB,EAAE;gBAAES,IAAAA,EAAM;AAAS,aAAA;AACjD,QAAA;QAEA,OAAO,IAAA;IACT,CAAA,GAAA;AAEA,4IACA,MAAM8B,8BAAAA,GACJ7B,QAAAA,KAAa,QACbY,IAAAA,KAASkB,SAAAA,IACTlB,IAAAA,CAAKlB,IAAI,CAACC,IAAI,KAAK,aAAA,IACnBiB,IAAAA,CAAKZ,QAAQ,KAAK,IAAA;IAEpB,IAAkC6B,8BAAAA,EAAgC;AAChE,QAAA,OAAO9C,yBAAyBC,KAAAA,EAAOC,QAAAA,CAAAA;AACzC,IAAA;IAEA,OAAO;AAAEe,QAAAA,QAAAA;AAAUC,QAAAA,KAAAA;AAAOZ,QAAAA,KAAAA;AAAOQ,QAAAA;AAAK,KAAA;AACxC;AAEA,SAASkC,2BACP/C,KAAiB,EACjBC,QAAgB,EAChB+C,QAAgB,EAChB3B,IAAwB,EAAA;IAExB,MAAM4B,WAAAA,GAAcjD,MAAMuB,SAAS,CAAC,CAACnB,IAAAA,GAASA,IAAAA,CAAKE,EAAE,KAAK0C,QAAAA,CAAAA;IAC1D,MAAMvB,MAAAA,GAASzB,MAAMS,IAAI,CAAC,CAACL,IAAAA,GAASA,IAAAA,CAAKE,EAAE,KAAKL,QAAAA,CAAAA;AAEhD,IAAA,IAAIgD,WAAAA,KAAgB,EAAC,IAAK,CAACxB,MAAAA,EAAQ;QACjC,OAAO,IAAA;AACT,IAAA;IAEA,MAAMyB,MAAAA,GAASlD,KAAK,CAACiD,WAAAA,CAAY;AACjC,IAAA,MAAM,EAAEjC,QAAQ,EAAEX,KAAK,EAAE,GAAG6C,MAAAA;IAE5B,IACEzB,MAAAA,CAAOf,IAAI,CAACC,IAAI,KAAK,QAAA,IACrBN,KAAAA,GAAQsC,mBAAAA,CAAoBlB,MAAAA,CAAOf,IAAI,CAAA,GAAIgC,gBAAAA,EAC3C;QACA,OAAO,IAAA;AACT,IAAA;AAEA,IAAA,MAAMS,QAAAA,GAAW9B,IAAAA,KAAS,QAAA,GAAW4B,WAAAA,GAAcA,WAAAA,GAAc,CAAA;AACjE,IAAA,IAAIhC,KAAAA,GAAQ,CAAA;AAEZ,IAAA,IAAK,IAAImC,CAAAA,GAAI,CAAA,EAAGA,CAAAA,GAAID,QAAAA,EAAUC,KAAK,CAAA,CAAG;QACpC,MAAMhD,IAAAA,GAAOJ,KAAK,CAACoD,CAAAA,CAAE;QAErB,IAAIhD,IAAAA,CAAKE,EAAE,KAAKL,QAAAA,EAAU;AACxB,YAAA;AACF,QAAA;AAEA,QAAA,IAAIG,KAAKY,QAAQ,KAAKA,YAAYZ,IAAAA,CAAKC,KAAK,KAAKA,KAAAA,EAAO;AACtD,YAAA;AACF,QAAA;AAEA,QAAA,IAAIW,aAAa,IAAA,IAAQZ,IAAAA,CAAKM,IAAI,CAACC,IAAI,KAAK,QAAA,EAAU;AACpD,YAAA;AACF,QAAA;QAEAM,KAAAA,IAAS,CAAA;AACX,IAAA;IAEA,MAAMJ,IAAAA,GAAiB,CAAC,IAAA;AACtB,QAAA,IAAIQ,SAAS,QAAA,EAAU;YACrB,OAAO;AAAEP,gBAAAA,QAAAA,EAAUoC,OAAO5C,EAAE;gBAAES,IAAAA,EAAM;AAAM,aAAA;AAC5C,QAAA;AAEA,QAAA,IAAIsC,SAAAA,GAAYJ,WAAAA;QAEhB,IAAK,IAAIG,IAAIH,WAAAA,GAAc,CAAA,EAAGG,IAAIpD,KAAAA,CAAMsD,MAAM,EAAEF,CAAAA,IAAK,CAAA,CAAG;AACtD,YAAA,IAAIpD,KAAK,CAACoD,CAAAA,CAAE,CAAC/C,KAAK,IAAIA,KAAAA,EAAO;AAC3B,gBAAA;AACF,YAAA;YAEAgD,SAAAA,GAAYD,CAAAA;AACd,QAAA;QAEA,OAAO;AAAEtC,YAAAA,QAAAA,EAAUd,KAAK,CAACqD,SAAAA,CAAU,CAAC/C,EAAE;YAAES,IAAAA,EAAM;AAAS,SAAA;IACzD,CAAA,GAAA;IAEA,OAAO;AAAEC,QAAAA,QAAAA;AAAUC,QAAAA,KAAAA;AAAOZ,QAAAA,KAAAA;AAAOQ,QAAAA;AAAK,KAAA;AACxC;AAUA;;;;;;;;;;;;;AAaC,IACM,SAAS0C,iBAAAA,CAAkBvD,KAAiB,EAAEwD,SAAoB,EAAA;IACvE,MAAM,EAAEvD,QAAQ,EAAEkB,MAAM,EAAEC,OAAO,EAAEqC,OAAO,EAAEC,QAAQ,EAAE,GAAGF,SAAAA;AAEzD,IAAA,IAAIrC,WAAWlB,QAAAA,EAAU;QACvB,OAAO,IAAA;AACT,IAAA;IAEA,MAAM0D,mBAAAA,GAAsB3D,MAAMS,IAAI,CAAC,CAACL,IAAAA,GAASA,IAAAA,CAAKE,EAAE,KAAKa,MAAAA,CAAAA;;IAG7D,IAAIwC,mBAAAA,IAAuBA,oBAAoBjD,IAAI,CAACC,IAAI,KAAK,QAAA,IAAY8C,WAAWC,QAAAA,EAAU;QAC5F,MAAME,UAAAA,GAAaD,oBAAoBjD,IAAI;AAE3C,QAAA,MAAMmD,WAAW7D,KAAK,CAACA,MAAM8D,OAAO,CAACH,uBAAuB,CAAA,CAAE;AAC9D,QAAA,MAAMI,qBAAqBF,QAAAA,IAAY,IAAA,IAAQA,SAASxD,KAAK,GAAGsD,oBAAoBtD,KAAK;;AAGzF,QAAA,MAAM2D,OAAOC,uBAAAA,CAAwB;YACnCC,eAAAA,EAAiBR,QAAAA;AACjBS,YAAAA,QAAAA,EAAUV,QAAQW,CAAC;AACnBL,YAAAA;AACF,SAAA,CAAA;AAEA,QAAA,IAAIC,SAAS,MAAA,EAAQ;YACnB,MAAMK,UAAAA,GAAarE,KAAAA,CAAMS,IAAI,CAAC,CAAC,EAAEH,EAAE,EAAE,GAAKA,EAAAA,KAAOL,QAAAA,CAAAA,EAAWS,IAAAA;YAC5D,MAAM4D,WAAAA,GACJD,cAAc,IAAA,IACdA,UAAAA,CAAW1D,IAAI,KAAK,QAAA,IACpB4D,gBAAgBF,UAAAA,EAAYT,UAAAA,CAAAA;AAE9B,YAAA,IAAI,CAACU,WAAAA,EAAa;gBAChB,OAAO,IAAA;AACT,YAAA;YAEA,OAAO;gBAAEE,IAAAA,EAAM,MAAA;AAAQxB,gBAAAA,QAAAA,EAAUY,WAAWtD,EAAE;gBAAED,KAAAA,EAAOsD,mBAAAA,CAAoBtD,KAAK,GAAG;AAAE,aAAA;AACvF,QAAA;AAEA,QAAA,MAAMoE,OAAAA,GAAU1B,0BAAAA,CAA2B/C,KAAAA,EAAOC,QAAAA,EAAUkB,MAAAA,EAAQ6C,IAAAA,CAAAA;AACpE,QAAA,IAAIS,OAAAA,EAAS;YACX,OAAO;gBAAED,IAAAA,EAAM,QAAA;AAAU,gBAAA,GAAGC;AAAQ,aAAA;AACtC,QAAA;AACF,IAAA;IAEA,MAAMpD,IAAAA,GAAO,CAAC,IAAA;QACZ,IAAI,CAACoC,OAAAA,IAAW,CAACC,QAAAA,EAAU;YACzB,OAAOZ,SAAAA;AACT,QAAA;QAEA,OAAOW,OAAAA,CAAQW,CAAC,GAAGV,QAAAA,CAASgB,GAAG,GAAGhB,QAAAA,CAASiB,MAAM,GAAG,CAAA,GAAI,QAAA,GAAW,OAAA;IACrE,CAAA,GAAA;AAEA,IAAA,MAAMC,MAAAA,GAAS1D,wBAAAA,CAAyBlB,KAAAA,EAAOC,QAAAA,EAAUkB,QAAQC,OAAAA,EAASC,IAAAA,CAAAA;AAE1E,IAAA,OAAOuD,MAAAA,GAAS;QAAEJ,IAAAA,EAAM,QAAA;AAAU,QAAA,GAAGI;KAAO,GAAI,IAAA;AAClD;AAIA;;;;;;;;;;;AAWC,IAED,MAAMC,gBAAAA,GAAmB,GAAA;AACzB,MAAMC,aAAAA,GAAgB,GAAA;AAQf,SAASb,wBAAwB,EACtCF,kBAAkB,EAClBG,eAAe,EACfC,QAAQ,EACqB,EAAA;AAC7B,IAAA,IAAIA,WAAWD,eAAAA,CAAgBQ,GAAG,GAAGR,eAAAA,CAAgBS,MAAM,GAAGG,aAAAA,EAAe;QAC3E,OAAO,QAAA;AACT,IAAA;IAEA,IACE,CAACf,sBACDI,QAAAA,GAAWD,eAAAA,CAAgBQ,GAAG,GAAGR,eAAAA,CAAgBS,MAAM,GAAGE,gBAAAA,EAC1D;QACA,OAAO,OAAA;AACT,IAAA;IAEA,OAAO,MAAA;AACT;;;;"}