@webiny/app-headless-cms 6.5.0-beta.0 → 6.5.0-beta.10

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/ContentEntriesModule.js +14 -2
  2. package/ContentEntriesModule.js.map +1 -1
  3. package/admin/components/ContentEntries/BulkActions/ActionDelete.d.ts +2 -2
  4. package/admin/components/ContentEntries/BulkActions/ActionDelete.js.map +1 -1
  5. package/admin/components/ContentEntries/BulkActions/ActionMove.d.ts +2 -2
  6. package/admin/components/ContentEntries/BulkActions/ActionMove.js.map +1 -1
  7. package/admin/components/ContentEntries/BulkActions/ActionPublish.d.ts +2 -2
  8. package/admin/components/ContentEntries/BulkActions/ActionPublish.js.map +1 -1
  9. package/admin/components/ContentEntries/BulkActions/ActionUnpublish.d.ts +2 -2
  10. package/admin/components/ContentEntries/BulkActions/ActionUnpublish.js.map +1 -1
  11. package/admin/components/ContentEntries/Filters/RefFieldRenderer.d.ts +2 -0
  12. package/admin/components/ContentEntries/Filters/RefFieldRenderer.js +84 -0
  13. package/admin/components/ContentEntries/Filters/RefFieldRenderer.js.map +1 -0
  14. package/admin/components/ContentEntries/Table/Actions/DuplicateEntry.d.ts +2 -0
  15. package/admin/components/ContentEntries/Table/Actions/DuplicateEntry.js +34 -0
  16. package/admin/components/ContentEntries/Table/Actions/DuplicateEntry.js.map +1 -0
  17. package/admin/components/ContentEntries/Table/Actions/index.d.ts +1 -0
  18. package/admin/components/ContentEntries/Table/Actions/index.js +1 -0
  19. package/admin/components/ContentModelEditor/ContentModelEditor.js +1 -1
  20. package/admin/components/ContentModelEditor/ContentModelEditor.js.map +1 -1
  21. package/admin/components/Dialogs/DuplicateEntryConfirmDialog.d.ts +2 -0
  22. package/admin/components/Dialogs/DuplicateEntryConfirmDialog.js +22 -0
  23. package/admin/components/Dialogs/DuplicateEntryConfirmDialog.js.map +1 -0
  24. package/admin/components/FieldEditor/EditFieldDialog.d.ts +2 -2
  25. package/admin/components/FieldEditor/Field.js +4 -4
  26. package/admin/components/FieldEditor/Field.js.map +1 -1
  27. package/features/contentEntry/CmsEntryError.d.ts +10 -0
  28. package/features/contentEntry/CmsEntryError.js +11 -0
  29. package/features/contentEntry/CmsEntryError.js.map +1 -0
  30. package/features/contentEntry/createEntry/CreateEntryGateway.d.ts +0 -1
  31. package/features/contentEntry/createEntry/CreateEntryGateway.js +3 -10
  32. package/features/contentEntry/createEntry/CreateEntryGateway.js.map +1 -1
  33. package/features/contentEntry/createRevisionFrom/CreateRevisionFromGateway.d.ts +3 -1
  34. package/features/contentEntry/createRevisionFrom/CreateRevisionFromGateway.js +8 -3
  35. package/features/contentEntry/createRevisionFrom/CreateRevisionFromGateway.js.map +1 -1
  36. package/features/contentEntry/duplicateEntry/DuplicateEntryGateway.d.ts +14 -0
  37. package/features/contentEntry/duplicateEntry/DuplicateEntryGateway.js +43 -0
  38. package/features/contentEntry/duplicateEntry/DuplicateEntryGateway.js.map +1 -0
  39. package/features/contentEntry/duplicateEntry/DuplicateEntryRepository.d.ts +15 -0
  40. package/features/contentEntry/duplicateEntry/DuplicateEntryRepository.js +34 -0
  41. package/features/contentEntry/duplicateEntry/DuplicateEntryRepository.js.map +1 -0
  42. package/features/contentEntry/duplicateEntry/DuplicateEntryUseCase.d.ts +11 -0
  43. package/features/contentEntry/duplicateEntry/DuplicateEntryUseCase.js +18 -0
  44. package/features/contentEntry/duplicateEntry/DuplicateEntryUseCase.js.map +1 -0
  45. package/features/contentEntry/duplicateEntry/abstractions.d.ts +26 -0
  46. package/features/contentEntry/duplicateEntry/abstractions.js +7 -0
  47. package/features/contentEntry/duplicateEntry/abstractions.js.map +1 -0
  48. package/features/contentEntry/duplicateEntry/feature.d.ts +3 -0
  49. package/features/contentEntry/duplicateEntry/feature.js +21 -0
  50. package/features/contentEntry/duplicateEntry/feature.js.map +1 -0
  51. package/features/contentEntry/entryValueGateways.test.d.ts +1 -0
  52. package/features/contentEntry/entryValueGateways.test.js +106 -0
  53. package/features/contentEntry/entryValueGateways.test.js.map +1 -0
  54. package/features/contentEntry/feature.js +2 -0
  55. package/features/contentEntry/feature.js.map +1 -1
  56. package/features/contentEntry/singletonEntry/UpdateSingletonEntryGateway.d.ts +0 -1
  57. package/features/contentEntry/singletonEntry/UpdateSingletonEntryGateway.js +3 -10
  58. package/features/contentEntry/singletonEntry/UpdateSingletonEntryGateway.js.map +1 -1
  59. package/features/contentEntry/updateEntry/UpdateEntryGateway.d.ts +0 -1
  60. package/features/contentEntry/updateEntry/UpdateEntryGateway.js +3 -10
  61. package/features/contentEntry/updateEntry/UpdateEntryGateway.js.map +1 -1
  62. package/features/contentEntry/valueTransformers/EntryDataPreparer.d.ts +9 -0
  63. package/features/contentEntry/valueTransformers/EntryDataPreparer.js +8 -0
  64. package/features/contentEntry/valueTransformers/EntryDataPreparer.js.map +1 -1
  65. package/features/contentEntry/valueTransformers/EntryDataPreparer.test.d.ts +1 -0
  66. package/features/contentEntry/valueTransformers/EntryDataPreparer.test.js +113 -0
  67. package/features/contentEntry/valueTransformers/EntryDataPreparer.test.js.map +1 -0
  68. package/features/contentEntry/valueTransformers/entryValueFixtures.d.ts +146 -0
  69. package/features/contentEntry/valueTransformers/entryValueFixtures.js +171 -0
  70. package/features/contentEntry/valueTransformers/entryValueFixtures.js.map +1 -0
  71. package/features/formModel/CmsFormModelBuilder.d.ts +9 -1
  72. package/features/formModel/CmsFormModelBuilder.js +26 -15
  73. package/features/formModel/CmsFormModelBuilder.js.map +1 -1
  74. package/features/formModel/CmsFormModelBuilder.test.d.ts +1 -0
  75. package/features/formModel/CmsFormModelBuilder.test.js +252 -0
  76. package/features/formModel/CmsFormModelBuilder.test.js.map +1 -0
  77. package/features/formModel/CmsLayoutMapper.d.ts +8 -1
  78. package/features/formModel/CmsLayoutMapper.js +23 -1
  79. package/features/formModel/CmsLayoutMapper.js.map +1 -1
  80. package/features/formModel/mappers/DynamicZoneFieldMapper.js +4 -0
  81. package/features/formModel/mappers/DynamicZoneFieldMapper.js.map +1 -1
  82. package/features/formModel/mappers/ObjectFieldMapper.js +11 -6
  83. package/features/formModel/mappers/ObjectFieldMapper.js.map +1 -1
  84. package/features/model/exportModels/ExportModelsGateway.d.ts +1 -1
  85. package/features/model/exportModels/ExportModelsGateway.js.map +1 -1
  86. package/features/model/exportModels/ExportModelsUseCase.js +7 -1
  87. package/features/model/exportModels/ExportModelsUseCase.js.map +1 -1
  88. package/features/model/exportModels/abstractions.d.ts +8 -2
  89. package/features/model/exportModels/abstractions.js.map +1 -1
  90. package/package.json +26 -26
  91. package/presentation/cloneContentModel/CloneContentModelPresenter.d.ts +1 -0
  92. package/presentation/cloneContentModel/CloneContentModelPresenter.js +8 -6
  93. package/presentation/cloneContentModel/CloneContentModelPresenter.js.map +1 -1
  94. package/presentation/contentEntries/form/ContentEntryFormPresenter.js +34 -29
  95. package/presentation/contentEntries/form/ContentEntryFormPresenter.js.map +1 -1
  96. package/presentation/contentEntries/form/ContentEntryFormPresenter.test.d.ts +1 -0
  97. package/presentation/contentEntries/form/ContentEntryFormPresenter.test.js +210 -0
  98. package/presentation/contentEntries/form/ContentEntryFormPresenter.test.js.map +1 -0
  99. package/presentation/contentEntries/form/toFormErrors.d.ts +7 -0
  100. package/presentation/contentEntries/form/toFormErrors.js +49 -0
  101. package/presentation/contentEntries/form/toFormErrors.js.map +1 -0
  102. package/presentation/contentEntries/form/toFormErrors.test.d.ts +1 -0
  103. package/presentation/contentEntries/form/toFormErrors.test.js +175 -0
  104. package/presentation/contentEntries/form/toFormErrors.test.js.map +1 -0
  105. package/presentation/contentEntries/list/ContentEntriesDataSource.d.ts +5 -0
  106. package/presentation/contentEntries/list/ContentEntriesDataSource.js +11 -2
  107. package/presentation/contentEntries/list/ContentEntriesDataSource.js.map +1 -1
  108. package/presentation/contentEntries/list/ContentEntriesPresenter.d.ts +6 -2
  109. package/presentation/contentEntries/list/ContentEntriesPresenter.js +27 -2
  110. package/presentation/contentEntries/list/ContentEntriesPresenter.js.map +1 -1
  111. package/presentation/contentEntries/list/ContentEntriesPresenter.test.js +130 -5
  112. package/presentation/contentEntries/list/ContentEntriesPresenter.test.js.map +1 -1
  113. package/presentation/contentEntries/list/abstractions.d.ts +12 -0
  114. package/presentation/contentEntries/list/abstractions.js.map +1 -1
  115. package/presentation/contentEntries/preview/LivePreviewPresenter.d.ts +12 -1
  116. package/presentation/contentEntries/preview/LivePreviewPresenter.js +48 -5
  117. package/presentation/contentEntries/preview/LivePreviewPresenter.js.map +1 -1
  118. package/presentation/contentEntries/preview/LivePreviewPresenter.test.d.ts +1 -0
  119. package/presentation/contentEntries/preview/LivePreviewPresenter.test.js +81 -0
  120. package/presentation/contentEntries/preview/LivePreviewPresenter.test.js.map +1 -0
  121. package/presentation/contentEntries/preview/ModelEditorComponentDiscovery.js +1 -1
  122. package/presentation/contentEntries/preview/ModelEditorComponentDiscovery.js.map +1 -1
  123. package/presentation/contentEntries/preview/PreviewDecorator.js +25 -6
  124. package/presentation/contentEntries/preview/PreviewDecorator.js.map +1 -1
  125. package/presentation/contentEntries/preview/PreviewDomainStatus.d.ts +10 -0
  126. package/presentation/contentEntries/preview/PreviewDomainStatus.js +19 -0
  127. package/presentation/contentEntries/preview/PreviewDomainStatus.js.map +1 -0
  128. package/presentation/contentEntries/preview/PreviewPane.d.ts +10 -1
  129. package/presentation/contentEntries/preview/PreviewPane.js +81 -45
  130. package/presentation/contentEntries/preview/PreviewPane.js.map +1 -1
  131. package/presentation/contentEntries/preview/abstractions.d.ts +8 -0
  132. package/presentation/contentEntries/preview/abstractions.js.map +1 -1
  133. package/presentation/contentEntries/preview/resolvePreviewUrl.d.ts +21 -0
  134. package/presentation/contentEntries/preview/resolvePreviewUrl.js +50 -1
  135. package/presentation/contentEntries/preview/resolvePreviewUrl.js.map +1 -1
  136. package/presentation/contentEntries/preview/resolvePreviewUrl.test.d.ts +1 -0
  137. package/presentation/contentEntries/preview/resolvePreviewUrl.test.js +127 -0
  138. package/presentation/contentEntries/preview/resolvePreviewUrl.test.js.map +1 -0
  139. package/presentation/contentEntries/singleEntry/SingleEntryPresenter.js +9 -4
  140. package/presentation/contentEntries/singleEntry/SingleEntryPresenter.js.map +1 -1
  141. package/presentation/contentEntries/singleEntry/SingleEntryPresenter.test.d.ts +1 -0
  142. package/presentation/contentEntries/singleEntry/SingleEntryPresenter.test.js +122 -0
  143. package/presentation/contentEntries/singleEntry/SingleEntryPresenter.test.js.map +1 -0
  144. package/presentation/contentEntries/trashBin/CmsTrashBin.d.ts +2 -2
  145. package/presentation/contentEntries/views/CmsAdvancedSearch.d.ts +2 -2
  146. package/presentation/contentEntries/views/ContentEntriesListLayout.d.ts +2 -2
  147. package/presentation/contentEntries/views/ContentEntryFormView.d.ts +2 -2
  148. package/presentation/contentEntries/views/OlderRevisionAlert.d.ts +2 -2
  149. package/presentation/contentEntries/views/RevisionDrawer.d.ts +2 -2
  150. package/presentation/contentEntries/views/RevisionsList.d.ts +2 -2
  151. package/presentation/contentEntries/views/SingleEntryLayout.d.ts +2 -2
  152. package/presentation/contentEntries/views/Table/Table.d.ts +2 -2
  153. package/presentation/contentEntries/views/actions/CreateNewRevisionButton.d.ts +2 -2
  154. package/presentation/contentEntries/views/actions/DeleteEntryMenuItem.d.ts +2 -2
  155. package/presentation/contentEntries/views/actions/PublishOnlyButton.d.ts +2 -2
  156. package/presentation/contentEntries/views/actions/RevisionSelector.d.ts +2 -2
  157. package/presentation/contentEntries/views/actions/SaveAndPublishButton.d.ts +2 -2
  158. package/presentation/contentEntries/views/actions/SaveContentButton.d.ts +2 -2
  159. package/presentation/contentEntries/views/actions/ShowRevisionListMenuItem.d.ts +2 -2
  160. package/presentation/contentEntries/views/layout/ContentEntryForm.d.ts +12 -12
  161. package/presentation/contentModels/ContentModelsPresenter.d.ts +5 -5
  162. package/presentation/contentModels/ContentModelsPresenter.js +1 -1
  163. package/presentation/contentModels/ContentModelsPresenter.js.map +1 -1
  164. package/presentation/contentModels/abstractions.d.ts +7 -2
  165. package/presentation/contentModels/abstractions.js.map +1 -1
  166. package/presentation/contentModels/components/CloneContentModelDialog.d.ts +2 -2
  167. package/presentation/contentModels/components/ContentModels.d.ts +2 -2
  168. package/presentation/contentModels/components/ContentModelsDataList.d.ts +2 -2
  169. package/presentation/contentModels/components/ContentModelsDataList.js +6 -5
  170. package/presentation/contentModels/components/ContentModelsDataList.js.map +1 -1
  171. package/presentation/contentModels/components/NewContentModelDialog.d.ts +2 -2
  172. package/presentation/contentModels/components/fullDelete/dialog/Content.js +2 -2
  173. package/presentation/contentModels/components/fullDelete/dialog/Content.js.map +1 -1
  174. package/presentation/contentModels/components/fullDelete/types.js.map +1 -1
  175. package/presentation/fieldRenderers/ref/autocomplete/RefAutocompletePresenters.test.d.ts +1 -0
  176. package/presentation/fieldRenderers/ref/autocomplete/RefAutocompletePresenters.test.js +133 -0
  177. package/presentation/fieldRenderers/ref/autocomplete/RefAutocompletePresenters.test.js.map +1 -0
  178. package/presentation/fieldRenderers/ref/autocomplete/multi/RefMultiAutocompletePresenter.js +1 -1
  179. package/presentation/fieldRenderers/ref/autocomplete/multi/RefMultiAutocompletePresenter.js.map +1 -1
  180. package/presentation/fieldRenderers/ref/autocomplete/single/RefSingleAutocompletePresenter.js +1 -1
  181. package/presentation/fieldRenderers/ref/autocomplete/single/RefSingleAutocompletePresenter.js.map +1 -1
  182. package/presentation/fieldRenderers/ref/components/RefFieldOptions.d.ts +2 -2
  183. package/presentation/fieldRenderers/ref/components/RefFieldOptions.js +3 -2
  184. package/presentation/fieldRenderers/ref/components/RefFieldOptions.js.map +1 -1
  185. package/presentation/importContentModels/ImportContentModelsDialog.d.ts +2 -2
  186. package/presentation/importContentModels/ImportContentModelsPresenter.js +1 -1
  187. package/presentation/importContentModels/ImportContentModelsPresenter.js.map +1 -1
  188. package/presentation/importContentModels/components/DataList.d.ts +2 -2
  189. package/presentation/importContentModels/components/FileUpload.d.ts +2 -2
  190. package/presentation/importContentModels/components/FileUpload.js +1 -1
  191. package/presentation/importContentModels/components/FileUpload.js.map +1 -1
  192. package/presentation/importContentModels/components/Model/DataListModelItem.js +3 -3
  193. package/presentation/importContentModels/components/Model/DataListModelItem.js.map +1 -1
  194. package/presentation/importContentModels/components/Model/DataListModelItemInfo.js +2 -2
  195. package/presentation/importContentModels/components/Model/DataListModelItemInfo.js.map +1 -1
  196. package/presentation/importContentModels/components/Model/DataListModels.d.ts +2 -2
  197. package/presentation/menus/ContentGroupsMenuItems.d.ts +2 -2
  198. package/presentation/modelGroup/ModelGroupPresenter.js +1 -2
  199. package/presentation/modelGroup/ModelGroupPresenter.js.map +1 -1
  200. package/presentation/modelGroup/components/ContentModelGroups.d.ts +2 -2
  201. package/presentation/modelGroup/components/ContentModelGroupsDataList.d.ts +6 -2
  202. package/presentation/modelGroup/components/ContentModelGroupsForm.d.ts +8 -2
  203. package/presentation/newContentModel/NewContentModelPresenter.d.ts +1 -0
  204. package/presentation/newContentModel/NewContentModelPresenter.js +8 -6
  205. package/presentation/newContentModel/NewContentModelPresenter.js.map +1 -1
  206. package/utils/normalizeIcon.d.ts +4 -0
  207. package/utils/normalizeIcon.js +9 -6
  208. package/utils/normalizeIcon.js.map +1 -1
@@ -0,0 +1,171 @@
1
+ const createField = (field)=>({
2
+ id: field.fieldId,
3
+ label: field.fieldId,
4
+ ...field
5
+ });
6
+ const heroTemplate = {
7
+ id: "heroBlock",
8
+ name: "Hero Block",
9
+ gqlTypeName: "PageHeroBlock",
10
+ description: "",
11
+ icon: "fas/star",
12
+ layout: [],
13
+ validation: [],
14
+ fields: [
15
+ createField({
16
+ fieldId: "title",
17
+ type: "text"
18
+ }),
19
+ createField({
20
+ fieldId: "customUrls",
21
+ type: "object",
22
+ list: true,
23
+ settings: {
24
+ fields: [
25
+ createField({
26
+ fieldId: "ctaUrl",
27
+ type: "text"
28
+ })
29
+ ]
30
+ }
31
+ })
32
+ ]
33
+ };
34
+ const galleryTemplate = {
35
+ id: "galleryBlock",
36
+ name: "Gallery Block",
37
+ gqlTypeName: "PageGalleryBlock",
38
+ description: "",
39
+ icon: "fas/image",
40
+ layout: [],
41
+ validation: [],
42
+ fields: [
43
+ createField({
44
+ fieldId: "header",
45
+ type: "text"
46
+ }),
47
+ createField({
48
+ fieldId: "gallery",
49
+ type: "object",
50
+ list: true,
51
+ settings: {
52
+ fields: [
53
+ createField({
54
+ fieldId: "image",
55
+ type: "file"
56
+ })
57
+ ]
58
+ }
59
+ })
60
+ ]
61
+ };
62
+ const blocksField = createField({
63
+ fieldId: "blocks",
64
+ type: "dynamicZone",
65
+ list: true,
66
+ settings: {
67
+ templates: [
68
+ heroTemplate,
69
+ galleryTemplate
70
+ ]
71
+ }
72
+ });
73
+ const singleBlockField = createField({
74
+ fieldId: "featuredBlock",
75
+ type: "dynamicZone",
76
+ list: false,
77
+ settings: {
78
+ templates: [
79
+ heroTemplate
80
+ ]
81
+ }
82
+ });
83
+ const metaTitleField = createField({
84
+ fieldId: "metaTitle",
85
+ type: "text"
86
+ });
87
+ const pageModel = {
88
+ modelId: "page",
89
+ name: "Page",
90
+ singularApiName: "Page",
91
+ pluralApiName: "Pages",
92
+ fields: [
93
+ metaTitleField,
94
+ blocksField,
95
+ singleBlockField
96
+ ],
97
+ layout: [],
98
+ tags: []
99
+ };
100
+ const formValues = {
101
+ metaTitle: "Home",
102
+ blocks: [
103
+ {
104
+ _templateId: "heroBlock",
105
+ _id: "hero-1",
106
+ title: "Sunnyvale",
107
+ customUrls: [
108
+ {
109
+ _id: "url-1",
110
+ ctaUrl: "/memberships-passes/"
111
+ }
112
+ ]
113
+ },
114
+ {
115
+ _templateId: "galleryBlock",
116
+ _id: "gallery-1",
117
+ header: "Gallery",
118
+ gallery: [
119
+ {
120
+ _id: "image-1",
121
+ image: "https://example.com/1.jpg"
122
+ }
123
+ ]
124
+ }
125
+ ],
126
+ featuredBlock: {
127
+ _templateId: "heroBlock",
128
+ _id: "featured-1",
129
+ title: "Featured",
130
+ customUrls: []
131
+ }
132
+ };
133
+ const graphQLInputValues = {
134
+ metaTitle: "Home",
135
+ blocks: [
136
+ {
137
+ PageHeroBlock: {
138
+ _id: "hero-1",
139
+ title: "Sunnyvale",
140
+ customUrls: [
141
+ {
142
+ _id: "url-1",
143
+ ctaUrl: "/memberships-passes/"
144
+ }
145
+ ]
146
+ }
147
+ },
148
+ {
149
+ PageGalleryBlock: {
150
+ _id: "gallery-1",
151
+ header: "Gallery",
152
+ gallery: [
153
+ {
154
+ _id: "image-1",
155
+ image: "https://example.com/1.jpg"
156
+ }
157
+ ]
158
+ }
159
+ }
160
+ ],
161
+ featuredBlock: {
162
+ PageHeroBlock: {
163
+ _id: "featured-1",
164
+ title: "Featured",
165
+ customUrls: []
166
+ }
167
+ }
168
+ };
169
+ export { blocksField, createField, formValues, galleryTemplate, graphQLInputValues, heroTemplate, metaTitleField, pageModel, singleBlockField };
170
+
171
+ //# sourceMappingURL=entryValueFixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/contentEntry/valueTransformers/entryValueFixtures.js","sources":["../../../../src/features/contentEntry/valueTransformers/entryValueFixtures.ts"],"sourcesContent":["import type { CmsDynamicZoneTemplate, CmsModel, CmsModelField } from \"~/types.js\";\n\n/**\n * Shared fixtures for value transformer and gateway tests.\n * The model mirrors a real \"page\" model: a list dynamic zone field with templates\n * that contain nested object fields.\n */\nexport const createField = (field: Partial<CmsModelField>): CmsModelField => {\n return {\n id: field.fieldId,\n label: field.fieldId,\n ...field\n } as CmsModelField;\n};\n\nexport const heroTemplate: CmsDynamicZoneTemplate = {\n id: \"heroBlock\",\n name: \"Hero Block\",\n gqlTypeName: \"PageHeroBlock\",\n description: \"\",\n icon: \"fas/star\",\n layout: [],\n validation: [],\n fields: [\n createField({ fieldId: \"title\", type: \"text\" }),\n createField({\n fieldId: \"customUrls\",\n type: \"object\",\n list: true,\n settings: {\n fields: [createField({ fieldId: \"ctaUrl\", type: \"text\" })]\n }\n })\n ]\n};\n\nexport const galleryTemplate: CmsDynamicZoneTemplate = {\n id: \"galleryBlock\",\n name: \"Gallery Block\",\n gqlTypeName: \"PageGalleryBlock\",\n description: \"\",\n icon: \"fas/image\",\n layout: [],\n validation: [],\n fields: [\n createField({ fieldId: \"header\", type: \"text\" }),\n createField({\n fieldId: \"gallery\",\n type: \"object\",\n list: true,\n settings: {\n fields: [createField({ fieldId: \"image\", type: \"file\" })]\n }\n })\n ]\n};\n\nexport const blocksField = createField({\n fieldId: \"blocks\",\n type: \"dynamicZone\",\n list: true,\n settings: {\n templates: [heroTemplate, galleryTemplate]\n }\n});\n\nexport const singleBlockField = createField({\n fieldId: \"featuredBlock\",\n type: \"dynamicZone\",\n list: false,\n settings: {\n templates: [heroTemplate]\n }\n});\n\nexport const metaTitleField = createField({ fieldId: \"metaTitle\", type: \"text\" });\n\nexport const pageModel = {\n modelId: \"page\",\n name: \"Page\",\n singularApiName: \"Page\",\n pluralApiName: \"Pages\",\n fields: [metaTitleField, blocksField, singleBlockField],\n layout: [],\n tags: []\n} as unknown as CmsModel;\n\n/**\n * Values in the shape the entry form holds them.\n */\nexport const formValues = {\n metaTitle: \"Home\",\n blocks: [\n {\n _templateId: \"heroBlock\",\n _id: \"hero-1\",\n title: \"Sunnyvale\",\n customUrls: [{ _id: \"url-1\", ctaUrl: \"/memberships-passes/\" }]\n },\n {\n _templateId: \"galleryBlock\",\n _id: \"gallery-1\",\n header: \"Gallery\",\n gallery: [{ _id: \"image-1\", image: \"https://example.com/1.jpg\" }]\n }\n ],\n featuredBlock: {\n _templateId: \"heroBlock\",\n _id: \"featured-1\",\n title: \"Featured\",\n customUrls: []\n }\n};\n\n/**\n * The same values in the shape the GraphQL `<Model>Input` type expects.\n */\nexport const graphQLInputValues = {\n metaTitle: \"Home\",\n blocks: [\n {\n PageHeroBlock: {\n _id: \"hero-1\",\n title: \"Sunnyvale\",\n customUrls: [{ _id: \"url-1\", ctaUrl: \"/memberships-passes/\" }]\n }\n },\n {\n PageGalleryBlock: {\n _id: \"gallery-1\",\n header: \"Gallery\",\n gallery: [{ _id: \"image-1\", image: \"https://example.com/1.jpg\" }]\n }\n }\n ],\n featuredBlock: {\n PageHeroBlock: {\n _id: \"featured-1\",\n title: \"Featured\",\n customUrls: []\n }\n }\n};\n"],"names":["createField","field","heroTemplate","galleryTemplate","blocksField","singleBlockField","metaTitleField","pageModel","formValues","graphQLInputValues"],"mappings":"AAOO,MAAMA,cAAc,CAACC,QACjB;QACH,IAAIA,MAAM,OAAO;QACjB,OAAOA,MAAM,OAAO;QACpB,GAAGA,KAAK;IACZ;AAGG,MAAMC,eAAuC;IAChD,IAAI;IACJ,MAAM;IACN,aAAa;IACb,aAAa;IACb,MAAM;IACN,QAAQ,EAAE;IACV,YAAY,EAAE;IACd,QAAQ;QACJF,YAAY;YAAE,SAAS;YAAS,MAAM;QAAO;QAC7CA,YAAY;YACR,SAAS;YACT,MAAM;YACN,MAAM;YACN,UAAU;gBACN,QAAQ;oBAACA,YAAY;wBAAE,SAAS;wBAAU,MAAM;oBAAO;iBAAG;YAC9D;QACJ;KACH;AACL;AAEO,MAAMG,kBAA0C;IACnD,IAAI;IACJ,MAAM;IACN,aAAa;IACb,aAAa;IACb,MAAM;IACN,QAAQ,EAAE;IACV,YAAY,EAAE;IACd,QAAQ;QACJH,YAAY;YAAE,SAAS;YAAU,MAAM;QAAO;QAC9CA,YAAY;YACR,SAAS;YACT,MAAM;YACN,MAAM;YACN,UAAU;gBACN,QAAQ;oBAACA,YAAY;wBAAE,SAAS;wBAAS,MAAM;oBAAO;iBAAG;YAC7D;QACJ;KACH;AACL;AAEO,MAAMI,cAAcJ,YAAY;IACnC,SAAS;IACT,MAAM;IACN,MAAM;IACN,UAAU;QACN,WAAW;YAACE;YAAcC;SAAgB;IAC9C;AACJ;AAEO,MAAME,mBAAmBL,YAAY;IACxC,SAAS;IACT,MAAM;IACN,MAAM;IACN,UAAU;QACN,WAAW;YAACE;SAAa;IAC7B;AACJ;AAEO,MAAMI,iBAAiBN,YAAY;IAAE,SAAS;IAAa,MAAM;AAAO;AAExE,MAAMO,YAAY;IACrB,SAAS;IACT,MAAM;IACN,iBAAiB;IACjB,eAAe;IACf,QAAQ;QAACD;QAAgBF;QAAaC;KAAiB;IACvD,QAAQ,EAAE;IACV,MAAM,EAAE;AACZ;AAKO,MAAMG,aAAa;IACtB,WAAW;IACX,QAAQ;QACJ;YACI,aAAa;YACb,KAAK;YACL,OAAO;YACP,YAAY;gBAAC;oBAAE,KAAK;oBAAS,QAAQ;gBAAuB;aAAE;QAClE;QACA;YACI,aAAa;YACb,KAAK;YACL,QAAQ;YACR,SAAS;gBAAC;oBAAE,KAAK;oBAAW,OAAO;gBAA4B;aAAE;QACrE;KACH;IACD,eAAe;QACX,aAAa;QACb,KAAK;QACL,OAAO;QACP,YAAY,EAAE;IAClB;AACJ;AAKO,MAAMC,qBAAqB;IAC9B,WAAW;IACX,QAAQ;QACJ;YACI,eAAe;gBACX,KAAK;gBACL,OAAO;gBACP,YAAY;oBAAC;wBAAE,KAAK;wBAAS,QAAQ;oBAAuB;iBAAE;YAClE;QACJ;QACA;YACI,kBAAkB;gBACd,KAAK;gBACL,QAAQ;gBACR,SAAS;oBAAC;wBAAE,KAAK;wBAAW,OAAO;oBAA4B;iBAAE;YACrE;QACJ;KACH;IACD,eAAe;QACX,eAAe;YACX,KAAK;YACL,OAAO;YACP,YAAY,EAAE;QAClB;IACJ;AACJ"}
@@ -1,13 +1,21 @@
1
1
  import type { IFormModelConfig } from "@webiny/app-admin/features/formModel/abstractions.js";
2
- import { type CmsModel } from "../../types.js";
2
+ import type { CmsModel } from "../../types.js";
3
3
  import type { ICmsFieldTypeMapper, ICmsFormModelBuilder } from "./abstractions.js";
4
4
  import type { ICmsFieldRenderer } from "../../presentation/fieldRenderers/abstractions.js";
5
5
  declare class CmsFormModelBuilderImpl implements ICmsFormModelBuilder {
6
6
  private mappers;
7
7
  private rendererMap;
8
+ private renderers;
8
9
  constructor(customMappers: ICmsFieldTypeMapper[] | undefined, fieldRenderers: ICmsFieldRenderer[] | undefined);
9
10
  build(model: CmsModel): IFormModelConfig;
10
11
  private mapField;
12
+ /**
13
+ * A list renderer can't render a single value: `dateTimeInputs` calls `.map()` on a
14
+ * stored date string and crashes the form. When a single-value field is configured with
15
+ * a renderer that only accepts list fields, drop it so the field type's default
16
+ * single-value renderer is used instead.
17
+ */
18
+ private withCompatibleRenderer;
11
19
  }
12
20
  export declare const CmsFormModelBuilder: typeof CmsFormModelBuilderImpl & {
13
21
  __abstraction: import("@webiny/di").Abstraction<ICmsFormModelBuilder>;
@@ -1,7 +1,6 @@
1
- import { isLayoutField } from "../../types.js";
2
1
  import { CmsFieldTypeMapper, CmsFormModelBuilder } from "./abstractions.js";
3
2
  import { CmsFieldRenderer } from "../../presentation/fieldRenderers/abstractions.js";
4
- import { mapCmsLayout } from "./CmsLayoutMapper.js";
3
+ import { collectFieldIds, mapCmsLayout } from "./CmsLayoutMapper.js";
5
4
  import { createBuiltInMappers } from "./mappers/index.js";
6
5
  import { applyFieldProps } from "./mappers/applyFieldProps.js";
7
6
  class CmsFormModelBuilderImpl {
@@ -10,7 +9,11 @@ class CmsFormModelBuilderImpl {
10
9
  for (const mapper of createBuiltInMappers())this.mappers.set(mapper.type, mapper);
11
10
  for (const mapper of customMappers || [])this.mappers.set(mapper.type, mapper);
12
11
  this.rendererMap = new Map();
13
- for (const renderer of fieldRenderers || [])this.rendererMap.set(renderer.rendererName, renderer.formRenderer);
12
+ this.renderers = new Map();
13
+ for (const renderer of fieldRenderers || []){
14
+ this.rendererMap.set(renderer.rendererName, renderer.formRenderer);
15
+ this.renderers.set(renderer.rendererName, renderer);
16
+ }
14
17
  }
15
18
  build(model) {
16
19
  const context = {
@@ -34,11 +37,30 @@ class CmsFormModelBuilderImpl {
34
37
  layout: model.layout ? (layout)=>mapCmsLayout(model.layout, layout, idToFieldId) : void 0
35
38
  };
36
39
  }
37
- mapField(field, registry, context) {
40
+ mapField(modelField, registry, context) {
41
+ const field = this.withCompatibleRenderer(modelField, context.model);
38
42
  const mapper = this.mappers.get(field.type);
39
43
  if (mapper) return mapper.map(field, registry, context);
40
44
  return applyFieldProps(registry.text(), field, context.rendererMap);
41
45
  }
46
+ withCompatibleRenderer(field, model) {
47
+ if (field.list || !field.renderer || "object" != typeof field.renderer) return field;
48
+ const renderer = this.renderers.get(field.renderer.name);
49
+ if (!renderer || renderer.canUse({
50
+ field,
51
+ model
52
+ })) return field;
53
+ if (!renderer.canUse({
54
+ field: {
55
+ ...field,
56
+ list: true
57
+ },
58
+ model
59
+ })) return field;
60
+ if ("development" === process.env.NODE_ENV) console.warn(`[CmsFormModelBuilder] Renderer "${field.renderer.name}" is for list fields; field "${field.fieldId}" is not a list and uses its default renderer instead.`);
61
+ const { renderer: _renderer, ...rest } = field;
62
+ return rest;
63
+ }
42
64
  }
43
65
  const CmsFormModelBuilder_CmsFormModelBuilder = CmsFormModelBuilder.createImplementation({
44
66
  implementation: CmsFormModelBuilderImpl,
@@ -59,17 +81,6 @@ const CmsFormModelBuilder_CmsFormModelBuilder = CmsFormModelBuilder.createImplem
59
81
  ]
60
82
  ]
61
83
  });
62
- function collectFieldIds(layout, idToFieldId) {
63
- const fieldIds = new Set();
64
- for (const row of layout)for (const cell of row)if ("string" == typeof cell) {
65
- const fieldId = idToFieldId.get(cell);
66
- if (fieldId) fieldIds.add(fieldId);
67
- } else if (isLayoutField(cell) && "tabs" === cell.type) {
68
- const tabsField = cell;
69
- for (const tab of tabsField.tabs)for (const id of collectFieldIds(tab.layout, idToFieldId))fieldIds.add(id);
70
- }
71
- return fieldIds;
72
- }
73
84
  export { CmsFormModelBuilder_CmsFormModelBuilder as CmsFormModelBuilder };
74
85
 
75
86
  //# sourceMappingURL=CmsFormModelBuilder.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"features/formModel/CmsFormModelBuilder.js","sources":["../../../src/features/formModel/CmsFormModelBuilder.ts"],"sourcesContent":["import type {\n IFieldBuilder,\n IFieldBuilderRegistry,\n IFormModelConfig\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport {\n isLayoutField,\n type CmsEditorFieldsLayout,\n type CmsModel,\n type CmsModelField\n} from \"~/types.js\";\nimport type {\n ICmsFieldTypeMapper,\n ICmsFieldMapperContext,\n ICmsFormModelBuilder\n} from \"./abstractions.js\";\nimport { CmsFormModelBuilder as BuilderAbstraction } from \"./abstractions.js\";\nimport { CmsFieldTypeMapper } from \"./abstractions.js\";\nimport { CmsFieldRenderer } from \"~/presentation/fieldRenderers/abstractions.js\";\nimport type { ICmsFieldRenderer } from \"~/presentation/fieldRenderers/abstractions.js\";\nimport { mapCmsLayout } from \"./CmsLayoutMapper.js\";\nimport { createBuiltInMappers } from \"./mappers/index.js\";\nimport { applyFieldProps } from \"./mappers/applyFieldProps.js\";\n\nclass CmsFormModelBuilderImpl implements ICmsFormModelBuilder {\n private mappers: Map<string, ICmsFieldTypeMapper>;\n private rendererMap: Map<string, string>;\n\n constructor(\n customMappers: ICmsFieldTypeMapper[] | undefined,\n fieldRenderers: ICmsFieldRenderer[] | undefined\n ) {\n this.mappers = new Map();\n for (const mapper of createBuiltInMappers()) {\n this.mappers.set(mapper.type, mapper);\n }\n for (const mapper of customMappers || []) {\n this.mappers.set(mapper.type, mapper);\n }\n\n this.rendererMap = new Map();\n for (const renderer of fieldRenderers || []) {\n this.rendererMap.set(renderer.rendererName, renderer.formRenderer);\n }\n }\n\n build(model: CmsModel): IFormModelConfig {\n const context: ICmsFieldMapperContext = {\n model,\n rendererMap: this.rendererMap,\n mapField: (field, registry) => this.mapField(field, registry, context)\n };\n\n const idToFieldId = new Map<string, string>();\n for (const field of model.fields) {\n idToFieldId.set(field.id, field.fieldId);\n }\n\n const fieldIdsInLayout = model.layout ? collectFieldIds(model.layout, idToFieldId) : null;\n\n return {\n fields: registry => {\n const result: Record<string, IFieldBuilder> = {};\n for (const field of model.fields) {\n const builder = this.mapField(field, registry, context);\n if (fieldIdsInLayout && !fieldIdsInLayout.has(field.fieldId)) {\n builder.hidden();\n }\n result[field.fieldId] = builder;\n }\n return result;\n },\n layout: model.layout\n ? layout => mapCmsLayout(model.layout!, layout, idToFieldId)\n : undefined\n };\n }\n\n private mapField(\n field: CmsModelField,\n registry: IFieldBuilderRegistry,\n context: ICmsFieldMapperContext\n ): IFieldBuilder {\n const mapper = this.mappers.get(field.type);\n if (mapper) {\n return mapper.map(field, registry, context);\n }\n\n return applyFieldProps(registry.text(), field, context.rendererMap);\n }\n}\n\nexport const CmsFormModelBuilder = BuilderAbstraction.createImplementation({\n implementation: CmsFormModelBuilderImpl,\n dependencies: [\n [CmsFieldTypeMapper, { multiple: true, optional: true }],\n [CmsFieldRenderer, { multiple: true, optional: true }]\n ]\n});\n\nfunction collectFieldIds(\n layout: CmsEditorFieldsLayout,\n idToFieldId: Map<string, string>\n): Set<string> {\n const fieldIds = new Set<string>();\n\n for (const row of layout) {\n for (const cell of row) {\n if (typeof cell === \"string\") {\n const fieldId = idToFieldId.get(cell);\n if (fieldId) {\n fieldIds.add(fieldId);\n }\n } else if (isLayoutField(cell) && cell.type === \"tabs\") {\n const tabsField = cell as { tabs: Array<{ layout: CmsEditorFieldsLayout }> };\n for (const tab of tabsField.tabs) {\n for (const id of collectFieldIds(tab.layout, idToFieldId)) {\n fieldIds.add(id);\n }\n }\n }\n }\n }\n\n return fieldIds;\n}\n"],"names":["CmsFormModelBuilderImpl","customMappers","fieldRenderers","Map","mapper","createBuiltInMappers","renderer","model","context","field","registry","idToFieldId","fieldIdsInLayout","collectFieldIds","result","builder","layout","mapCmsLayout","undefined","applyFieldProps","CmsFormModelBuilder","BuilderAbstraction","CmsFieldTypeMapper","CmsFieldRenderer","fieldIds","Set","row","cell","fieldId","isLayoutField","tabsField","tab","id"],"mappings":";;;;;;AAwBA,MAAMA;IAIF,YACIC,aAAgD,EAChDC,cAA+C,CACjD;QACE,IAAI,CAAC,OAAO,GAAG,IAAIC;QACnB,KAAK,MAAMC,UAAUC,uBACjB,IAAI,CAAC,OAAO,CAAC,GAAG,CAACD,OAAO,IAAI,EAAEA;QAElC,KAAK,MAAMA,UAAUH,iBAAiB,EAAE,CACpC,IAAI,CAAC,OAAO,CAAC,GAAG,CAACG,OAAO,IAAI,EAAEA;QAGlC,IAAI,CAAC,WAAW,GAAG,IAAID;QACvB,KAAK,MAAMG,YAAYJ,kBAAkB,EAAE,CACvC,IAAI,CAAC,WAAW,CAAC,GAAG,CAACI,SAAS,YAAY,EAAEA,SAAS,YAAY;IAEzE;IAEA,MAAMC,KAAe,EAAoB;QACrC,MAAMC,UAAkC;YACpCD;YACA,aAAa,IAAI,CAAC,WAAW;YAC7B,UAAU,CAACE,OAAOC,WAAa,IAAI,CAAC,QAAQ,CAACD,OAAOC,UAAUF;QAClE;QAEA,MAAMG,cAAc,IAAIR;QACxB,KAAK,MAAMM,SAASF,MAAM,MAAM,CAC5BI,YAAY,GAAG,CAACF,MAAM,EAAE,EAAEA,MAAM,OAAO;QAG3C,MAAMG,mBAAmBL,MAAM,MAAM,GAAGM,gBAAgBN,MAAM,MAAM,EAAEI,eAAe;QAErF,OAAO;YACH,QAAQD,CAAAA;gBACJ,MAAMI,SAAwC,CAAC;gBAC/C,KAAK,MAAML,SAASF,MAAM,MAAM,CAAE;oBAC9B,MAAMQ,UAAU,IAAI,CAAC,QAAQ,CAACN,OAAOC,UAAUF;oBAC/C,IAAII,oBAAoB,CAACA,iBAAiB,GAAG,CAACH,MAAM,OAAO,GACvDM,QAAQ,MAAM;oBAElBD,MAAM,CAACL,MAAM,OAAO,CAAC,GAAGM;gBAC5B;gBACA,OAAOD;YACX;YACA,QAAQP,MAAM,MAAM,GACdS,CAAAA,SAAUC,aAAaV,MAAM,MAAM,EAAGS,QAAQL,eAC9CO;QACV;IACJ;IAEQ,SACJT,KAAoB,EACpBC,QAA+B,EAC/BF,OAA+B,EAClB;QACb,MAAMJ,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,CAACK,MAAM,IAAI;QAC1C,IAAIL,QACA,OAAOA,OAAO,GAAG,CAACK,OAAOC,UAAUF;QAGvC,OAAOW,gBAAgBT,SAAS,IAAI,IAAID,OAAOD,QAAQ,WAAW;IACtE;AACJ;AAEO,MAAMY,0CAAsBC,oBAAAA,oBAAuC,CAAC;IACvE,gBAAgBrB;IAChB,cAAc;QACV;YAACsB;YAAoB;gBAAE,UAAU;gBAAM,UAAU;YAAK;SAAE;QACxD;YAACC;YAAkB;gBAAE,UAAU;gBAAM,UAAU;YAAK;SAAE;KACzD;AACL;AAEA,SAASV,gBACLG,MAA6B,EAC7BL,WAAgC;IAEhC,MAAMa,WAAW,IAAIC;IAErB,KAAK,MAAMC,OAAOV,OACd,KAAK,MAAMW,QAAQD,IACf,IAAI,AAAgB,YAAhB,OAAOC,MAAmB;QAC1B,MAAMC,UAAUjB,YAAY,GAAG,CAACgB;QAChC,IAAIC,SACAJ,SAAS,GAAG,CAACI;IAErB,OAAO,IAAIC,cAAcF,SAASA,AAAc,WAAdA,KAAK,IAAI,EAAa;QACpD,MAAMG,YAAYH;QAClB,KAAK,MAAMI,OAAOD,UAAU,IAAI,CAC5B,KAAK,MAAME,MAAMnB,gBAAgBkB,IAAI,MAAM,EAAEpB,aACzCa,SAAS,GAAG,CAACQ;IAGzB;IAIR,OAAOR;AACX"}
1
+ {"version":3,"file":"features/formModel/CmsFormModelBuilder.js","sources":["../../../src/features/formModel/CmsFormModelBuilder.ts"],"sourcesContent":["import type {\n IFieldBuilder,\n IFieldBuilderRegistry,\n IFormModelConfig\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsModel, CmsModelField } from \"~/types.js\";\nimport type {\n ICmsFieldTypeMapper,\n ICmsFieldMapperContext,\n ICmsFormModelBuilder\n} from \"./abstractions.js\";\nimport { CmsFormModelBuilder as BuilderAbstraction } from \"./abstractions.js\";\nimport { CmsFieldTypeMapper } from \"./abstractions.js\";\nimport { CmsFieldRenderer } from \"~/presentation/fieldRenderers/abstractions.js\";\nimport type { ICmsFieldRenderer } from \"~/presentation/fieldRenderers/abstractions.js\";\nimport { collectFieldIds, mapCmsLayout } from \"./CmsLayoutMapper.js\";\nimport { createBuiltInMappers } from \"./mappers/index.js\";\nimport { applyFieldProps } from \"./mappers/applyFieldProps.js\";\n\nclass CmsFormModelBuilderImpl implements ICmsFormModelBuilder {\n private mappers: Map<string, ICmsFieldTypeMapper>;\n private rendererMap: Map<string, string>;\n private renderers: Map<string, ICmsFieldRenderer>;\n\n constructor(\n customMappers: ICmsFieldTypeMapper[] | undefined,\n fieldRenderers: ICmsFieldRenderer[] | undefined\n ) {\n this.mappers = new Map();\n for (const mapper of createBuiltInMappers()) {\n this.mappers.set(mapper.type, mapper);\n }\n for (const mapper of customMappers || []) {\n this.mappers.set(mapper.type, mapper);\n }\n\n this.rendererMap = new Map();\n this.renderers = new Map();\n for (const renderer of fieldRenderers || []) {\n this.rendererMap.set(renderer.rendererName, renderer.formRenderer);\n this.renderers.set(renderer.rendererName, renderer);\n }\n }\n\n build(model: CmsModel): IFormModelConfig {\n const context: ICmsFieldMapperContext = {\n model,\n rendererMap: this.rendererMap,\n mapField: (field, registry) => this.mapField(field, registry, context)\n };\n\n const idToFieldId = new Map<string, string>();\n for (const field of model.fields) {\n idToFieldId.set(field.id, field.fieldId);\n }\n\n const fieldIdsInLayout = model.layout ? collectFieldIds(model.layout, idToFieldId) : null;\n\n return {\n fields: registry => {\n const result: Record<string, IFieldBuilder> = {};\n for (const field of model.fields) {\n const builder = this.mapField(field, registry, context);\n if (fieldIdsInLayout && !fieldIdsInLayout.has(field.fieldId)) {\n builder.hidden();\n }\n result[field.fieldId] = builder;\n }\n return result;\n },\n layout: model.layout\n ? layout => mapCmsLayout(model.layout!, layout, idToFieldId)\n : undefined\n };\n }\n\n private mapField(\n modelField: CmsModelField,\n registry: IFieldBuilderRegistry,\n context: ICmsFieldMapperContext\n ): IFieldBuilder {\n const field = this.withCompatibleRenderer(modelField, context.model);\n const mapper = this.mappers.get(field.type);\n if (mapper) {\n return mapper.map(field, registry, context);\n }\n\n return applyFieldProps(registry.text(), field, context.rendererMap);\n }\n\n /**\n * A list renderer can't render a single value: `dateTimeInputs` calls `.map()` on a\n * stored date string and crashes the form. When a single-value field is configured with\n * a renderer that only accepts list fields, drop it so the field type's default\n * single-value renderer is used instead.\n */\n private withCompatibleRenderer(field: CmsModelField, model: CmsModel): CmsModelField {\n if (field.list || !field.renderer || typeof field.renderer !== \"object\") {\n return field;\n }\n const renderer = this.renderers.get(field.renderer.name);\n if (!renderer || renderer.canUse({ field, model })) {\n return field;\n }\n if (!renderer.canUse({ field: { ...field, list: true }, model })) {\n return field;\n }\n if (process.env.NODE_ENV === \"development\") {\n console.warn(\n `[CmsFormModelBuilder] Renderer \"${field.renderer.name}\" is for list fields; ` +\n `field \"${field.fieldId}\" is not a list and uses its default renderer instead.`\n );\n }\n // Mappers treat a missing renderer as \"use the field type's default\".\n const { renderer: _renderer, ...rest } = field;\n return rest as CmsModelField;\n }\n}\n\nexport const CmsFormModelBuilder = BuilderAbstraction.createImplementation({\n implementation: CmsFormModelBuilderImpl,\n dependencies: [\n [CmsFieldTypeMapper, { multiple: true, optional: true }],\n [CmsFieldRenderer, { multiple: true, optional: true }]\n ]\n});\n"],"names":["CmsFormModelBuilderImpl","customMappers","fieldRenderers","Map","mapper","createBuiltInMappers","renderer","model","context","field","registry","idToFieldId","fieldIdsInLayout","collectFieldIds","result","builder","layout","mapCmsLayout","undefined","modelField","applyFieldProps","process","console","_renderer","rest","CmsFormModelBuilder","BuilderAbstraction","CmsFieldTypeMapper","CmsFieldRenderer"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,252 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { Container } from "@webiny/di";
3
+ import { FormModelFeature } from "@webiny/app-admin/features/formModel/feature.js";
4
+ import { IdentityContextFeature } from "@webiny/app-admin/features/security/IdentityContext/feature.js";
5
+ import { FormModelFactory } from "@webiny/app-admin/features/formModel/abstractions.js";
6
+ import { CmsFormModelBuilder } from "./abstractions.js";
7
+ import { CmsFormModelFeature } from "./feature.js";
8
+ import { DateTimeInputRenderer } from "../../presentation/fieldTypes/renderers/dateTime/DateTimeInputRenderer.js";
9
+ import { DateTimeInputsRenderer } from "../../presentation/fieldTypes/renderers/dateTime/DateTimeInputsRenderer.js";
10
+ import { TextInputRenderer } from "../../presentation/fieldTypes/renderers/text/TextInputRenderer.js";
11
+ import { TextInputsRenderer } from "../../presentation/fieldTypes/renderers/text/TextInputsRenderer.js";
12
+ const field = (fieldId, type, list, renderer, extra = {})=>({
13
+ id: fieldId,
14
+ fieldId,
15
+ type,
16
+ label: fieldId,
17
+ tags: [],
18
+ list,
19
+ renderer: {
20
+ name: renderer,
21
+ settings: {}
22
+ },
23
+ validation: [],
24
+ listValidation: [],
25
+ settings: {},
26
+ predefinedValues: {
27
+ enabled: false,
28
+ values: []
29
+ },
30
+ ...extra
31
+ });
32
+ function createCmsForm(fields) {
33
+ const container = new Container();
34
+ IdentityContextFeature.register(container);
35
+ FormModelFeature.register(container);
36
+ CmsFormModelFeature.register(container);
37
+ container.register(DateTimeInputRenderer);
38
+ container.register(DateTimeInputsRenderer);
39
+ container.register(TextInputRenderer);
40
+ container.register(TextInputsRenderer);
41
+ const model = {
42
+ modelId: "test",
43
+ fields,
44
+ layout: fields.map((f)=>[
45
+ f.fieldId
46
+ ])
47
+ };
48
+ const config = container.resolve(CmsFormModelBuilder).build(model);
49
+ return container.resolve(FormModelFactory).create(config);
50
+ }
51
+ describe("CmsFormModelBuilder renderer cardinality", ()=>{
52
+ it("keeps renderers that match the field's cardinality", ()=>{
53
+ const form = createCmsForm([
54
+ field("single", "datetime", false, "date-time-input"),
55
+ field("many", "datetime", true, "date-time-inputs")
56
+ ]);
57
+ expect(form.field("single").vm.renderer).toBe("dateTimeInput");
58
+ expect(form.field("many").vm.renderer).toBe("dateTimeInputs");
59
+ });
60
+ it("falls back to the single-value renderer when a list renderer is set on a non-list field", ()=>{
61
+ const form = createCmsForm([
62
+ field("openTime", "datetime", false, "date-time-inputs"),
63
+ field("name", "text", false, "text-inputs")
64
+ ]);
65
+ expect(form.field("openTime").vm.renderer).toBe("dateTimeInput");
66
+ expect(form.field("name").vm.renderer).toBe("textInput");
67
+ });
68
+ it("keeps the list renderer for list datetime fields with a subtype", ()=>{
69
+ const form = createCmsForm([
70
+ "date",
71
+ "time",
72
+ "dateTimeWithTimezone",
73
+ "dateTimeWithoutTimezone"
74
+ ].map((type)=>field(type, "datetime", true, "date-time-inputs", {
75
+ settings: {
76
+ type
77
+ }
78
+ })));
79
+ expect(form.field("date").vm.renderer).toBe("dateTimeInputs");
80
+ expect(form.field("time").vm.renderer).toBe("dateTimeInputs");
81
+ expect(form.field("dateTimeWithTimezone").vm.renderer).toBe("dateTimeInputs");
82
+ expect(form.field("dateTimeWithoutTimezone").vm.renderer).toBe("dateTimeInputs");
83
+ });
84
+ it("applies the fallback to fields nested in object lists", ()=>{
85
+ const form = createCmsForm([
86
+ field("holidayHours", "object", true, "objects-accordion", {
87
+ settings: {
88
+ fields: [
89
+ field("openTime", "datetime", false, "date-time-inputs")
90
+ ],
91
+ layout: [
92
+ [
93
+ "openTime"
94
+ ]
95
+ ]
96
+ }
97
+ })
98
+ ]);
99
+ form.setData({
100
+ holidayHours: [
101
+ {
102
+ openTime: "2026-12-24T09:00:00.000Z"
103
+ }
104
+ ]
105
+ });
106
+ const item = form.field("holidayHours").items[0];
107
+ expect(item.children.get("openTime").vm.renderer).toBe("dateTimeInput");
108
+ });
109
+ });
110
+ const rowNames = (layout)=>layout.map((row)=>row.fields.map((f)=>f.name));
111
+ describe("CmsFormModelBuilder nested layouts", ()=>{
112
+ it("lays out a single object with the layout stored on the field", ()=>{
113
+ const form = createCmsForm([
114
+ field("address", "object", false, "object-accordion", {
115
+ settings: {
116
+ fields: [
117
+ field("street", "text", false, "text-input"),
118
+ field("city", "text", false, "text-input", {
119
+ id: "c1ty"
120
+ }),
121
+ field("zipCode", "text", false, "text-input")
122
+ ],
123
+ layout: [
124
+ [
125
+ "street"
126
+ ],
127
+ [
128
+ "c1ty",
129
+ "zipCode"
130
+ ]
131
+ ]
132
+ }
133
+ })
134
+ ]);
135
+ expect(rowNames(form.field("address").vm.layout)).toEqual([
136
+ [
137
+ "street"
138
+ ],
139
+ [
140
+ "city",
141
+ "zipCode"
142
+ ]
143
+ ]);
144
+ });
145
+ it("lays out every item of an object list", ()=>{
146
+ const form = createCmsForm([
147
+ field("facilityStats", "object", true, "objects-accordion", {
148
+ settings: {
149
+ fields: [
150
+ field("statValue", "text", false, "text-input"),
151
+ field("statLabel", "text", false, "text-input")
152
+ ],
153
+ layout: [
154
+ [
155
+ "statValue",
156
+ "statLabel"
157
+ ]
158
+ ]
159
+ }
160
+ })
161
+ ]);
162
+ form.setData({
163
+ facilityStats: [
164
+ {
165
+ statValue: "1",
166
+ statLabel: "a"
167
+ }
168
+ ]
169
+ });
170
+ const vm = form.field("facilityStats").vm;
171
+ expect(rowNames(vm.items[0].layout)).toEqual([
172
+ [
173
+ "statValue",
174
+ "statLabel"
175
+ ]
176
+ ]);
177
+ });
178
+ it("gives children missing from the stored layout a row of their own", ()=>{
179
+ const form = createCmsForm([
180
+ field("address", "object", false, "object-accordion", {
181
+ settings: {
182
+ fields: [
183
+ field("street", "text", false, "text-input"),
184
+ field("city", "text", false, "text-input"),
185
+ field("state", "text", false, "text-input")
186
+ ],
187
+ layout: [
188
+ [
189
+ "street",
190
+ "city"
191
+ ]
192
+ ]
193
+ }
194
+ })
195
+ ]);
196
+ expect(rowNames(form.field("address").vm.layout)).toEqual([
197
+ [
198
+ "street",
199
+ "city"
200
+ ],
201
+ [
202
+ "state"
203
+ ]
204
+ ]);
205
+ });
206
+ it("lays out a dynamic zone template with the template's layout", ()=>{
207
+ const form = createCmsForm([
208
+ field("blocks", "dynamicZone", true, "dynamicZone", {
209
+ settings: {
210
+ templates: [
211
+ {
212
+ id: "hero",
213
+ name: "Hero",
214
+ gqlTypeName: "Hero",
215
+ description: "",
216
+ icon: null,
217
+ fields: [
218
+ field("title", "text", false, "text-input"),
219
+ field("subtitle", "text", false, "text-input")
220
+ ],
221
+ layout: [
222
+ [
223
+ "title",
224
+ "subtitle"
225
+ ]
226
+ ],
227
+ validation: []
228
+ }
229
+ ]
230
+ }
231
+ })
232
+ ]);
233
+ form.setData({
234
+ blocks: [
235
+ {
236
+ _templateId: "hero",
237
+ title: "T",
238
+ subtitle: "S"
239
+ }
240
+ ]
241
+ });
242
+ const vm = form.field("blocks").vm;
243
+ expect(rowNames(vm.items[0].layout)).toEqual([
244
+ [
245
+ "title",
246
+ "subtitle"
247
+ ]
248
+ ]);
249
+ });
250
+ });
251
+
252
+ //# sourceMappingURL=CmsFormModelBuilder.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/formModel/CmsFormModelBuilder.test.js","sources":["../../../src/features/formModel/CmsFormModelBuilder.test.ts"],"sourcesContent":["import { describe, it, expect } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { FormModelFeature } from \"@webiny/app-admin/features/formModel/feature.js\";\nimport { IdentityContextFeature } from \"@webiny/app-admin/features/security/IdentityContext/feature.js\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { CmsFormModelBuilder } from \"~/features/formModel/abstractions.js\";\nimport { CmsFormModelFeature } from \"~/features/formModel/feature.js\";\nimport { DateTimeInputRenderer } from \"~/presentation/fieldTypes/renderers/dateTime/DateTimeInputRenderer.js\";\nimport { DateTimeInputsRenderer } from \"~/presentation/fieldTypes/renderers/dateTime/DateTimeInputsRenderer.js\";\nimport { TextInputRenderer } from \"~/presentation/fieldTypes/renderers/text/TextInputRenderer.js\";\nimport { TextInputsRenderer } from \"~/presentation/fieldTypes/renderers/text/TextInputsRenderer.js\";\n\nconst field = (fieldId: string, type: string, list: boolean, renderer: string, extra = {}) => ({\n id: fieldId,\n fieldId,\n type,\n label: fieldId,\n tags: [],\n list,\n renderer: { name: renderer, settings: {} },\n validation: [],\n listValidation: [],\n settings: {},\n predefinedValues: { enabled: false, values: [] },\n ...extra\n});\n\nfunction createCmsForm(fields: any[]) {\n const container = new Container();\n IdentityContextFeature.register(container);\n FormModelFeature.register(container);\n CmsFormModelFeature.register(container);\n container.register(DateTimeInputRenderer);\n container.register(DateTimeInputsRenderer);\n container.register(TextInputRenderer);\n container.register(TextInputsRenderer);\n\n const model = {\n modelId: \"test\",\n fields,\n layout: fields.map(f => [f.fieldId])\n } as any;\n const config = container.resolve(CmsFormModelBuilder).build(model);\n return container.resolve(FormModelFactory).create(config);\n}\n\ndescribe(\"CmsFormModelBuilder renderer cardinality\", () => {\n it(\"keeps renderers that match the field's cardinality\", () => {\n const form = createCmsForm([\n field(\"single\", \"datetime\", false, \"date-time-input\"),\n field(\"many\", \"datetime\", true, \"date-time-inputs\")\n ]);\n\n expect(form.field(\"single\").vm.renderer).toBe(\"dateTimeInput\");\n expect(form.field(\"many\").vm.renderer).toBe(\"dateTimeInputs\");\n });\n\n it(\"falls back to the single-value renderer when a list renderer is set on a non-list field\", () => {\n const form = createCmsForm([\n field(\"openTime\", \"datetime\", false, \"date-time-inputs\"),\n field(\"name\", \"text\", false, \"text-inputs\")\n ]);\n\n expect(form.field(\"openTime\").vm.renderer).toBe(\"dateTimeInput\");\n expect(form.field(\"name\").vm.renderer).toBe(\"textInput\");\n });\n\n it(\"keeps the list renderer for list datetime fields with a subtype\", () => {\n const form = createCmsForm(\n [\"date\", \"time\", \"dateTimeWithTimezone\", \"dateTimeWithoutTimezone\"].map(type =>\n field(type, \"datetime\", true, \"date-time-inputs\", { settings: { type } })\n )\n );\n\n expect(form.field(\"date\").vm.renderer).toBe(\"dateTimeInputs\");\n expect(form.field(\"time\").vm.renderer).toBe(\"dateTimeInputs\");\n expect(form.field(\"dateTimeWithTimezone\").vm.renderer).toBe(\"dateTimeInputs\");\n expect(form.field(\"dateTimeWithoutTimezone\").vm.renderer).toBe(\"dateTimeInputs\");\n });\n\n it(\"applies the fallback to fields nested in object lists\", () => {\n const form = createCmsForm([\n field(\"holidayHours\", \"object\", true, \"objects-accordion\", {\n settings: {\n fields: [field(\"openTime\", \"datetime\", false, \"date-time-inputs\")],\n layout: [[\"openTime\"]]\n }\n })\n ]);\n\n form.setData({ holidayHours: [{ openTime: \"2026-12-24T09:00:00.000Z\" }] });\n const item = (form.field(\"holidayHours\") as any).items[0];\n\n expect(item.children.get(\"openTime\").vm.renderer).toBe(\"dateTimeInput\");\n });\n});\n\nconst rowNames = (layout: any[]) => layout.map(row => row.fields.map((f: any) => f.name));\n\ndescribe(\"CmsFormModelBuilder nested layouts\", () => {\n it(\"lays out a single object with the layout stored on the field\", () => {\n const form = createCmsForm([\n field(\"address\", \"object\", false, \"object-accordion\", {\n settings: {\n fields: [\n field(\"street\", \"text\", false, \"text-input\"),\n // Fields created in the model editor have an `id` that differs from `fieldId`.\n field(\"city\", \"text\", false, \"text-input\", { id: \"c1ty\" }),\n field(\"zipCode\", \"text\", false, \"text-input\")\n ],\n layout: [[\"street\"], [\"c1ty\", \"zipCode\"]]\n }\n })\n ]);\n\n expect(rowNames((form.field(\"address\").vm as any).layout)).toEqual([\n [\"street\"],\n [\"city\", \"zipCode\"]\n ]);\n });\n\n it(\"lays out every item of an object list\", () => {\n const form = createCmsForm([\n field(\"facilityStats\", \"object\", true, \"objects-accordion\", {\n settings: {\n fields: [\n field(\"statValue\", \"text\", false, \"text-input\"),\n field(\"statLabel\", \"text\", false, \"text-input\")\n ],\n layout: [[\"statValue\", \"statLabel\"]]\n }\n })\n ]);\n\n form.setData({ facilityStats: [{ statValue: \"1\", statLabel: \"a\" }] });\n const vm = form.field(\"facilityStats\").vm as any;\n\n expect(rowNames(vm.items[0].layout)).toEqual([[\"statValue\", \"statLabel\"]]);\n });\n\n it(\"gives children missing from the stored layout a row of their own\", () => {\n const form = createCmsForm([\n field(\"address\", \"object\", false, \"object-accordion\", {\n settings: {\n fields: [\n field(\"street\", \"text\", false, \"text-input\"),\n field(\"city\", \"text\", false, \"text-input\"),\n field(\"state\", \"text\", false, \"text-input\")\n ],\n layout: [[\"street\", \"city\"]]\n }\n })\n ]);\n\n expect(rowNames((form.field(\"address\").vm as any).layout)).toEqual([\n [\"street\", \"city\"],\n [\"state\"]\n ]);\n });\n\n it(\"lays out a dynamic zone template with the template's layout\", () => {\n const form = createCmsForm([\n field(\"blocks\", \"dynamicZone\", true, \"dynamicZone\", {\n settings: {\n templates: [\n {\n id: \"hero\",\n name: \"Hero\",\n gqlTypeName: \"Hero\",\n description: \"\",\n icon: null,\n fields: [\n field(\"title\", \"text\", false, \"text-input\"),\n field(\"subtitle\", \"text\", false, \"text-input\")\n ],\n layout: [[\"title\", \"subtitle\"]],\n validation: []\n }\n ]\n }\n })\n ]);\n\n form.setData({ blocks: [{ _templateId: \"hero\", title: \"T\", subtitle: \"S\" }] });\n const vm = form.field(\"blocks\").vm as any;\n\n expect(rowNames(vm.items[0].layout)).toEqual([[\"title\", \"subtitle\"]]);\n });\n});\n"],"names":["field","fieldId","type","list","renderer","extra","createCmsForm","fields","container","Container","IdentityContextFeature","FormModelFeature","CmsFormModelFeature","DateTimeInputRenderer","DateTimeInputsRenderer","TextInputRenderer","TextInputsRenderer","model","f","config","CmsFormModelBuilder","FormModelFactory","describe","it","form","expect","item","rowNames","layout","row","vm"],"mappings":"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"}
@@ -1,3 +1,10 @@
1
- import { type CmsEditorFieldsLayout } from "../../types.js";
1
+ import { type CmsEditorFieldsLayout, type CmsModelField } from "../../types.js";
2
2
  import type { ILayoutBuilder, ILayoutNodeBuilder } from "@webiny/app-admin/features/formModel/abstractions.js";
3
3
  export declare function mapCmsLayout(cmsLayout: CmsEditorFieldsLayout, layoutBuilder: ILayoutBuilder, idToFieldId: Map<string, string>): ILayoutNodeBuilder[];
4
+ export declare function collectFieldIds(layout: CmsEditorFieldsLayout, idToFieldId: Map<string, string>): Set<string>;
5
+ /**
6
+ * Maps the layout stored on an object field or a dynamic zone template. Returns `undefined`
7
+ * when there is no layout, so the form falls back to one row per child. Children missing
8
+ * from the layout get a row of their own at the end, so a stale layout can't hide them.
9
+ */
10
+ export declare function mapCmsNestedLayout(cmsLayout: CmsEditorFieldsLayout | undefined, fields: CmsModelField[]): ((layoutBuilder: ILayoutBuilder) => ILayoutNodeBuilder[]) | undefined;