blocks-dusted 0.1.11 → 0.1.13

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 (161) hide show
  1. package/package.json +5 -2
  2. package/src/cli.js +39 -3
  3. package/src/commands/shop.js +59 -0
  4. package/src/commands/warehouse.js +73 -0
  5. package/src/installers/patchRenderBlocks.js +1 -1
  6. package/src/registry/validateTemplateManifest.js +2 -1
  7. package/templates/blocks/BannerDD790432/Component.tsx +63 -0
  8. package/templates/blocks/BannerDD790432/config.ts +54 -0
  9. package/templates/blocks/BannerDD790432/manifest.json +80 -0
  10. package/templates/blocks/Button47/Component.tsx +124 -0
  11. package/templates/blocks/Button47/config.ts +75 -0
  12. package/templates/blocks/Button47/link.ts +22 -0
  13. package/templates/blocks/Button47/manifest.json +105 -0
  14. package/templates/blocks/Button47/styles.module.scss +75 -0
  15. package/templates/blocks/DD-Accordion/Component.tsx +55 -36
  16. package/templates/blocks/DD-Accordion/config.ts +71 -59
  17. package/templates/blocks/DD-AnimText/Component.tsx +50 -32
  18. package/templates/blocks/DD-AnimText/config.ts +296 -295
  19. package/templates/blocks/DD-AsideNav/Component.tsx +323 -319
  20. package/templates/blocks/DD-Banner/Component.tsx +54 -51
  21. package/templates/blocks/DD-BookCall/Component.tsx +10 -9
  22. package/templates/blocks/DD-ButtonPop/Component.tsx +118 -117
  23. package/templates/blocks/DD-Card/Component.tsx +4 -4
  24. package/templates/blocks/DD-CardTemplate01/Component.tsx +5 -5
  25. package/templates/blocks/DD-CardsWithVariantV3/Component.tsx +472 -0
  26. package/templates/blocks/DD-CardsWithVariantV3/ElectricBorder/index.tsx +203 -0
  27. package/templates/blocks/DD-CardsWithVariantV3/ElectricBorder/styles.ts +87 -0
  28. package/templates/blocks/DD-CardsWithVariantV3/ElectricBorder/useInjectStyle.ts +39 -0
  29. package/templates/blocks/DD-CardsWithVariantV3/config.ts +326 -0
  30. package/templates/blocks/DD-CardsWithVariantV3/manifest.json +110 -0
  31. package/templates/blocks/DD-Carousel-A/Component.tsx +251 -249
  32. package/templates/blocks/DD-Carousel-B/Component.tsx +405 -403
  33. package/templates/blocks/DD-Chip/Component.tsx +14 -14
  34. package/templates/blocks/DD-ComparisonTable/Component.tsx +255 -256
  35. package/templates/blocks/DD-Contact/Component.tsx +433 -434
  36. package/templates/blocks/DD-Counter/Component.tsx +18 -13
  37. package/templates/blocks/DD-DeliCard/Component.tsx +303 -0
  38. package/templates/blocks/DD-DeliCard/config.ts +186 -0
  39. package/templates/blocks/DD-DeliCard/manifest.json +94 -0
  40. package/templates/blocks/DD-FeatCat/Component.tsx +302 -302
  41. package/templates/blocks/DD-FeatProd/CircularGallery.tsx +1179 -0
  42. package/templates/blocks/DD-FeatProd/Component.tsx +484 -0
  43. package/templates/blocks/DD-FeatProd/config.ts +173 -0
  44. package/templates/blocks/DD-FeatProd/manifest.json +93 -0
  45. package/templates/blocks/DD-FeatServ/Component.tsx +607 -0
  46. package/templates/blocks/DD-FeatServ/config.ts +213 -0
  47. package/templates/blocks/DD-FeatServ/manifest.json +113 -0
  48. package/templates/blocks/DD-FeatStrip/Component.tsx +584 -585
  49. package/templates/blocks/DD-FluidBtn/ButtonsEyeCatching.tsx +627 -628
  50. package/templates/blocks/DD-FluidBtn/Component.tsx +46 -43
  51. package/templates/blocks/DD-GooeyInfo/Component.tsx +150 -149
  52. package/templates/blocks/DD-GooeyInfo/config.ts +136 -135
  53. package/templates/blocks/DD-Hero/Component.tsx +16 -40
  54. package/templates/blocks/DD-HeroPlas/Component.tsx +50 -0
  55. package/templates/blocks/DD-HeroPlas/ThreeScene.tsx +109 -0
  56. package/templates/blocks/DD-HeroPlas/config.ts +33 -0
  57. package/templates/blocks/DD-HeroPlas/manifest.json +88 -0
  58. package/templates/blocks/DD-HorizontalScroll/Component.tsx +4 -5
  59. package/templates/blocks/DD-Icon/Component.tsx +46 -81
  60. package/templates/blocks/DD-IconButton/Component.tsx +13 -20
  61. package/templates/blocks/DD-IdTag/Component.tsx +22 -21
  62. package/templates/blocks/DD-IframeMedia/Component.tsx +14 -10
  63. package/templates/blocks/DD-LineAnim/Component.tsx +42 -36
  64. package/templates/blocks/DD-LogoMarq/Component.tsx +38 -48
  65. package/templates/blocks/DD-Lottie/Component.tsx +11 -3
  66. package/templates/blocks/DD-MasonaryMedia/Component.tsx +544 -547
  67. package/templates/blocks/DD-MasonaryMedia/config.ts +389 -389
  68. package/templates/blocks/DD-Masonry/Component.tsx +654 -644
  69. package/templates/blocks/DD-Masonry/config.ts +475 -475
  70. package/templates/blocks/DD-MaterialSwatches/Component.tsx +85 -0
  71. package/templates/blocks/DD-MaterialSwatches/config.ts +232 -0
  72. package/templates/blocks/DD-MaterialSwatches/manifest.json +84 -0
  73. package/templates/blocks/DD-MaterialSwatches/material.ts +107 -0
  74. package/templates/blocks/DD-NineCanvas/Component.tsx +129 -0
  75. package/templates/blocks/DD-NineCanvas/RenderBlocks.tsx +244 -0
  76. package/templates/blocks/DD-NineCanvas/allowedCanvasBlocks.ts +6 -0
  77. package/templates/blocks/DD-NineCanvas/blockComponents.tsx +8 -0
  78. package/templates/blocks/DD-NineCanvas/canvas/CanvasGrid.tsx +316 -0
  79. package/templates/blocks/DD-NineCanvas/canvas/RadialNav.tsx +432 -0
  80. package/templates/blocks/DD-NineCanvas/canvas/canvas-panels.css +889 -0
  81. package/templates/blocks/DD-NineCanvas/canvas/icons/custom-icons.tsx +364 -0
  82. package/templates/blocks/DD-NineCanvas/config.ts +61 -0
  83. package/templates/blocks/DD-NineCanvas/manifest.json +165 -0
  84. package/templates/blocks/DD-NineCanvas/styles.scss +152 -0
  85. package/templates/blocks/DD-NineCanvas/tooltip/get-strict-context.tsx +26 -0
  86. package/templates/blocks/DD-NineCanvas/tooltip/primitives.tsx +178 -0
  87. package/templates/blocks/DD-NineCanvas/tooltip/tooltip.tsx +71 -0
  88. package/templates/blocks/DD-NineCanvas/tooltip/use-controlled-state.tsx +33 -0
  89. package/templates/blocks/DD-NineCanvas/utilities/FadeOnScroll.tsx +68 -0
  90. package/templates/blocks/DD-NineCanvas/utilities/ParallaxWrapper.tsx +157 -0
  91. package/templates/blocks/DD-NineCanvas/utilities/renderCustomCSS.ts +5 -0
  92. package/templates/blocks/DD-NineCanvas/utilities/webglCleanup.ts +27 -0
  93. package/templates/blocks/DD-PayloadAIAssistant/Component.tsx +78 -0
  94. package/templates/blocks/DD-PayloadAIAssistant/DustedBot.tsx +590 -0
  95. package/templates/blocks/DD-PayloadAIAssistant/config.ts +37 -0
  96. package/templates/blocks/DD-PayloadAIAssistant/demo.css +125 -0
  97. package/templates/blocks/DD-PayloadAIAssistant/manifest.json +93 -0
  98. package/templates/blocks/DD-PayloadAIAssistant/source-defaults.ts +17 -0
  99. package/templates/blocks/DD-PayloadAIAssistant/styles.ts +306 -0
  100. package/templates/blocks/DD-Pricing/Component.tsx +368 -372
  101. package/templates/blocks/DD-Pricing/config.ts +215 -215
  102. package/templates/blocks/DD-Process/Component.tsx +147 -149
  103. package/templates/blocks/DD-Progress/Component.tsx +156 -141
  104. package/templates/blocks/DD-ProjHeader/Component.tsx +93 -91
  105. package/templates/blocks/DD-ProjSlider/Component.tsx +1 -1
  106. package/templates/blocks/DD-ProjSlider/config.ts +2 -2
  107. package/templates/blocks/DD-Section/Component.tsx +265 -266
  108. package/templates/blocks/DD-Separator/Component.tsx +66 -66
  109. package/templates/blocks/DD-Services/Component.tsx +176 -176
  110. package/templates/blocks/DD-ShowcaseGrid/Component.tsx +306 -307
  111. package/templates/blocks/DD-Slider-A/Component.tsx +237 -237
  112. package/templates/blocks/DD-StackCards/Component.tsx +474 -473
  113. package/templates/blocks/DD-Team/Component.tsx +247 -247
  114. package/templates/blocks/DD-TeamCards/Component.tsx +251 -251
  115. package/templates/blocks/DD-TechStack/Component.tsx +161 -168
  116. package/templates/blocks/DD-TestMarq/Component.tsx +158 -132
  117. package/templates/blocks/DD-Testim/Component.tsx +247 -247
  118. package/templates/blocks/DD-Testim2/Component.tsx +265 -256
  119. package/templates/blocks/DD-Testimonials/Component.tsx +139 -147
  120. package/templates/blocks/DD-TextMarq/Component.tsx +157 -157
  121. package/templates/blocks/DD-Thanks/Component.tsx +501 -500
  122. package/templates/blocks/DD-Work/Component.tsx +315 -315
  123. package/templates/blocks/DD-Work-B/Component.tsx +294 -294
  124. package/templates/blocks/DDHG-CTASection2/Component.tsx +183 -184
  125. package/templates/blocks/DDHG-HighlightArc/Component.tsx +246 -243
  126. package/templates/blocks/DDHG-LogoMarquee/Component.tsx +180 -93
  127. package/templates/blocks/DDHG-LogoMarquee/config.ts +154 -66
  128. package/templates/blocks/DDHG-NavCodeGrid/Component.tsx +225 -213
  129. package/templates/blocks/DDHG-ProcessSec/Component.tsx +38 -39
  130. package/templates/blocks/DDHG-ServiceDetails/Component.tsx +11 -11
  131. package/templates/blocks/DDHG-ServiceDetails/ServiceDetailCard.tsx +30 -47
  132. package/templates/blocks/DDHG-ServiceHero/Component.tsx +10 -10
  133. package/templates/blocks/DDHG-ServiceOverview/Component.tsx +23 -23
  134. package/templates/blocks/DDHG-StatsFAQ/Component.tsx +40 -40
  135. package/templates/blocks/DDHG-TeamCards/Component.tsx +140 -131
  136. package/templates/blocks/Form/Checkbox/index.tsx +45 -0
  137. package/templates/blocks/Form/Component.tsx +163 -0
  138. package/templates/blocks/Form/Country/index.tsx +65 -0
  139. package/templates/blocks/Form/Country/options.ts +982 -0
  140. package/templates/blocks/Form/Email/index.tsx +38 -0
  141. package/templates/blocks/Form/Error/index.tsx +15 -0
  142. package/templates/blocks/Form/Message/index.tsx +13 -0
  143. package/templates/blocks/Form/Number/index.tsx +36 -0
  144. package/templates/blocks/Form/Select/index.tsx +63 -0
  145. package/templates/blocks/Form/State/index.tsx +64 -0
  146. package/templates/blocks/Form/State/options.ts +52 -0
  147. package/templates/blocks/Form/Text/index.tsx +32 -0
  148. package/templates/blocks/Form/Textarea/index.tsx +40 -0
  149. package/templates/blocks/Form/Width/index.tsx +13 -0
  150. package/templates/blocks/Form/config.ts +51 -0
  151. package/templates/blocks/Form/fields.tsx +21 -0
  152. package/templates/blocks/Form/manifest.json +168 -0
  153. package/templates/blocks/MediaBlock/Component.tsx +67 -0
  154. package/templates/blocks/MediaBlock/config.ts +14 -0
  155. package/templates/blocks/MediaBlock/manifest.json +92 -0
  156. package/templates/blocks/TransitionsDustedShowcase/Component.tsx +9 -0
  157. package/templates/blocks/TransitionsDustedShowcase/config.ts +13 -0
  158. package/templates/blocks/TransitionsDustedShowcase/manifest.json +80 -0
  159. package/templates/blocks/rawHtml/Component.tsx +25 -0
  160. package/templates/blocks/rawHtml/config.ts +56 -0
  161. package/templates/blocks/rawHtml/manifest.json +80 -0
@@ -1,475 +1,475 @@
1
- import type { Block } from 'payload'
2
-
3
- // Lexical integration
4
- export const MasonryMediaBlockFeature = {
5
- type: 'masonryMediaBlock',
6
- fields: [
7
- // MasonryMediaBlock fields will be used
8
- ]
9
- }
10
-
11
- export const DDMasonry: Block = {
12
- slug: 'DD-Masonry',
13
- interfaceName: 'DDMasonry',
14
- labels: {
15
- singular: 'Masonry Media Block',
16
- plural: 'Masonry Media Blocks'
17
- },
18
- fields: [
19
- {
20
- name: 'mediaFiles',
21
- type: 'upload',
22
- relationTo: 'media',
23
- hasMany: true,
24
- required: false,
25
- label: 'Bulk Add Media',
26
- admin: {
27
- description:
28
- 'Select many media files at once. On save, each selected file will be appended into the "items" list with default settings. Existing items are never removed.'
29
- },
30
- filterOptions: () => {
31
- return {} // Return all media, ignore folders
32
- },
33
- hooks: {
34
- beforeChange: [
35
- ({ value, siblingData }) => {
36
- const selected = Array.isArray(value) ? value : value ? [value] : []
37
-
38
- const currentItems = Array.isArray(siblingData?.items) ? siblingData.items : []
39
-
40
- const existingMediaIds = new Set(
41
- currentItems
42
- .map((item: any) => {
43
- const mediaValue = item?.media
44
-
45
- if (typeof mediaValue === 'number' || typeof mediaValue === 'string') {
46
- return mediaValue
47
- }
48
-
49
- if (mediaValue && typeof mediaValue === 'object' && 'id' in mediaValue) {
50
- return (mediaValue as any).id
51
- }
52
-
53
- return undefined
54
- })
55
- .filter((v: any) => v !== undefined)
56
- )
57
-
58
- const newItems = selected
59
- .filter((mediaId) => mediaId !== null && mediaId !== undefined)
60
- .filter((mediaId) => !existingMediaIds.has(mediaId as any))
61
- .map((mediaId) => {
62
- existingMediaIds.add(mediaId as any)
63
-
64
- return {
65
- // Leave `id` empty so the existing row-level hook auto-generates it
66
- media: mediaId as any,
67
- linkType: 'none',
68
- newTab: false,
69
- aspectRatio: '1/1',
70
- showTextOverlay: false
71
- }
72
- })
73
-
74
- if (newItems.length > 0) {
75
- siblingData.items = [...currentItems, ...newItems]
76
- }
77
-
78
- // Treat this field as a "bulk add" input — clear it after processing
79
- return []
80
- }
81
- ]
82
- }
83
- },
84
- {
85
- name: 'items',
86
- type: 'array',
87
- label: 'Media Items',
88
- minRows: 1,
89
- fields: [
90
- {
91
- name: 'media',
92
- type: 'upload',
93
- relationTo: 'media',
94
- required: true,
95
- filterOptions: () => {
96
- return {} // Return all media, ignore folders
97
- }
98
- },
99
- {
100
- type: 'row',
101
- fields: [
102
- {
103
- name: 'linkType',
104
- type: 'radio',
105
- admin: { layout: 'horizontal', width: '50%' },
106
- defaultValue: 'none',
107
- options: [
108
- { label: 'No Link', value: 'none' },
109
- { label: 'Internal link', value: 'reference' },
110
- { label: 'Custom URL', value: 'custom' }
111
- ]
112
- },
113
- {
114
- name: 'newTab',
115
- type: 'checkbox',
116
- admin: {
117
- style: { alignSelf: 'flex-end' },
118
- width: '50%',
119
- condition: (_, siblingData) => siblingData?.linkType !== 'none'
120
- },
121
- label: 'Open in new tab',
122
- defaultValue: false
123
- }
124
- ]
125
- },
126
- {
127
- name: 'reference',
128
- type: 'relationship',
129
- admin: {
130
- condition: (_, siblingData) => siblingData?.linkType === 'reference',
131
- width: '100%'
132
- },
133
- label: 'Document to link to',
134
- relationTo: ['pages', 'posts']
135
- },
136
- {
137
- name: 'url',
138
- type: 'text',
139
- admin: {
140
- condition: (_, siblingData) => siblingData?.linkType === 'custom',
141
- width: '100%'
142
- },
143
- label: 'Custom URL'
144
- },
145
- {
146
- name: 'aspectRatio',
147
- type: 'select',
148
- defaultValue: '1/1',
149
- admin: { width: '50%' },
150
- options: [
151
- { label: 'Square (1:1)', value: '1/1' },
152
- { label: 'Portrait (2:3)', value: '2/3' },
153
- { label: 'Landscape (3:2)', value: '3/2' },
154
- { label: 'Wide (16:9)', value: '16/9' }
155
- ]
156
- },
157
- {
158
- type: 'row',
159
- fields: [
160
- {
161
- name: 'showTextOverlay',
162
- type: 'checkbox',
163
- label: 'Show Text Overlay',
164
- defaultValue: false,
165
- admin: { width: '50%' }
166
- },
167
- {
168
- name: 'textOverlay',
169
- type: 'text',
170
- label: 'Overlay Text',
171
- admin: {
172
- width: '50%',
173
- condition: (data: any, siblingData: any) => siblingData?.showTextOverlay
174
- }
175
- }
176
- ]
177
- }
178
- ]
179
- },
180
- {
181
- admin: {
182
- initCollapsed: true,
183
- className: 'custom-css-class'
184
- },
185
- type: 'collapsible',
186
- label: 'Layout Settings',
187
- fields: [
188
- {
189
- type: 'group',
190
- name: 'layout',
191
- label: false,
192
- fields: [
193
- {
194
- name: 'columns',
195
- type: 'group',
196
- label: 'Column Configuration',
197
- fields: [
198
- {
199
- type: 'row',
200
- fields: [
201
- {
202
- name: 'desktop',
203
- type: 'number',
204
- label: 'Desktop (≥1500px)',
205
- defaultValue: 5,
206
- min: 1,
207
- max: 8,
208
- admin: { width: '25%' }
209
- },
210
- {
211
- name: 'laptop',
212
- type: 'number',
213
- label: 'Laptop (≥1000px)',
214
- defaultValue: 4,
215
- min: 1,
216
- max: 6,
217
- admin: { width: '25%' }
218
- },
219
- {
220
- name: 'tablet',
221
- type: 'number',
222
- label: 'Tablet (≥600px)',
223
- defaultValue: 3,
224
- min: 1,
225
- max: 4,
226
- admin: { width: '25%' }
227
- },
228
- {
229
- name: 'mobile',
230
- type: 'number',
231
- label: 'Mobile (≥400px)',
232
- defaultValue: 2,
233
- min: 1,
234
- max: 3,
235
- admin: { width: '25%' }
236
- }
237
- ]
238
- }
239
- ]
240
- },
241
- {
242
- name: 'gap',
243
- type: 'number',
244
- label: 'Gap between items (px)',
245
- defaultValue: 16
246
- }
247
- ]
248
- },
249
- {
250
- type: 'group',
251
- name: 'animation',
252
- label: 'Animation Settings',
253
- fields: [
254
- {
255
- name: 'enableAnimation',
256
- type: 'checkbox',
257
- label: 'Enable Animation',
258
- defaultValue: true,
259
- admin: {
260
- description:
261
- 'Toggle animations on/off. When disabled, items appear instantly without any entrance animation.'
262
- }
263
- },
264
- {
265
- type: 'row',
266
- fields: [
267
- {
268
- name: 'animateFrom',
269
- type: 'select',
270
- label: 'Animate From',
271
- defaultValue: 'bottom',
272
- admin: {
273
- width: '33%',
274
- condition: (_, siblingData) => siblingData?.enableAnimation !== false
275
- },
276
- options: [
277
- { label: 'Bottom', value: 'bottom' },
278
- { label: 'Top', value: 'top' },
279
- { label: 'Left', value: 'left' },
280
- { label: 'Right', value: 'right' },
281
- { label: 'Center', value: 'center' },
282
- { label: 'Random', value: 'random' }
283
- ],
284
- dbName: 'animation_from'
285
- },
286
- {
287
- name: 'ease',
288
- type: 'select',
289
- label: 'Easing',
290
- defaultValue: 'power3.out',
291
- admin: {
292
- width: '33%',
293
- condition: (_, siblingData) => siblingData?.enableAnimation !== false
294
- },
295
- options: [
296
- { label: 'Power3 Out', value: 'power3.out' },
297
- { label: 'Power2 Out', value: 'power2.out' },
298
- { label: 'Power4 Out', value: 'power4.out' },
299
- { label: 'Back Out', value: 'back.out' },
300
- { label: 'Elastic Out', value: 'elastic.out' },
301
- { label: 'Bounce Out', value: 'bounce.out' }
302
- ],
303
- dbName: 'animation_ease'
304
- },
305
- {
306
- name: 'repeatOnScroll',
307
- type: 'checkbox',
308
- label: 'Repeat on Scroll',
309
- defaultValue: false,
310
- admin: {
311
- width: '34%',
312
- style: { alignSelf: 'flex-end' },
313
- condition: (_, siblingData) => siblingData?.enableAnimation !== false
314
- }
315
- }
316
- ]
317
- },
318
- {
319
- type: 'row',
320
- fields: [
321
- {
322
- name: 'duration',
323
- type: 'number',
324
- label: 'Duration (seconds)',
325
- defaultValue: 0.6,
326
- min: 0.1,
327
- max: 2,
328
- admin: {
329
- width: '50%',
330
- condition: (_, siblingData) => siblingData?.enableAnimation !== false
331
- }
332
- },
333
- {
334
- name: 'stagger',
335
- type: 'number',
336
- label: 'Stagger Delay (seconds)',
337
- defaultValue: 0.05,
338
- min: 0,
339
- max: 0.5,
340
- admin: {
341
- width: '50%',
342
- condition: (_, siblingData) => siblingData?.enableAnimation !== false
343
- }
344
- }
345
- ]
346
- }
347
- ]
348
- },
349
- {
350
- type: 'group',
351
- name: 'interaction',
352
- label: 'Interaction Settings',
353
- fields: [
354
- {
355
- type: 'row',
356
- fields: [
357
- {
358
- name: 'scaleOnHover',
359
- type: 'checkbox',
360
- label: 'Scale on Hover',
361
- defaultValue: true,
362
- admin: { width: '33%' }
363
- },
364
- {
365
- name: 'blurToFocus',
366
- type: 'checkbox',
367
- label: 'Blur to Focus Effect',
368
- defaultValue: true,
369
- admin: { width: '33%' }
370
- },
371
- {
372
- name: 'colorShiftOnHover',
373
- type: 'checkbox',
374
- label: 'Color Shift on Hover',
375
- defaultValue: false,
376
- admin: { width: '34%' }
377
- }
378
- ]
379
- },
380
- {
381
- name: 'hoverScale',
382
- type: 'number',
383
- label: 'Hover Scale Amount',
384
- defaultValue: 0.95,
385
- min: 0.5,
386
- max: 1.5,
387
- admin: {
388
- width: '50%',
389
- condition: (data: any, siblingData: any) => siblingData?.scaleOnHover
390
- }
391
- },
392
- {
393
- name: 'customHoverColors',
394
- type: 'group',
395
- label: 'Custom Hover Colors',
396
- admin: {
397
- condition: (data: any, siblingData: any) => siblingData?.colorShiftOnHover
398
- },
399
- fields: [
400
- {
401
- type: 'row',
402
- fields: [
403
- {
404
- name: 'fromColor',
405
- type: 'text',
406
- label: 'From Color',
407
- defaultValue: 'rgba(236, 72, 153, 0.5)',
408
- admin: { width: '50%' }
409
- },
410
- {
411
- name: 'toColor',
412
- type: 'text',
413
- label: 'To Color',
414
- defaultValue: 'rgba(14, 165, 233, 0.5)',
415
- admin: { width: '50%' }
416
- }
417
- ]
418
- }
419
- ]
420
- }
421
- ]
422
- },
423
- {
424
- type: 'group',
425
- name: 'advanced',
426
- label: 'Advanced Settings',
427
- fields: [
428
- {
429
- type: 'row',
430
- fields: [
431
- {
432
- name: 'sectionId',
433
- type: 'text',
434
- label: 'Section ID',
435
- admin: { width: '50%' }
436
- },
437
- {
438
- name: 'customClassName',
439
- type: 'text',
440
- label: 'Custom Class Name',
441
- defaultValue: 'min-h-[50vh] mt-16',
442
- admin: { width: '50%' }
443
- }
444
- ]
445
- },
446
- {
447
- type: 'row',
448
- fields: [
449
- {
450
- name: 'enableParallax',
451
- type: 'checkbox',
452
- label: 'Enable Parallax',
453
- defaultValue: false,
454
- admin: { width: '50%' }
455
- },
456
- {
457
- name: 'parallaxSpeed',
458
- type: 'number',
459
- label: 'Parallax Speed',
460
- defaultValue: 0.5,
461
- min: -2,
462
- max: 2,
463
- admin: {
464
- width: '50%',
465
- condition: (data: any, siblingData: any) => siblingData?.enableParallax
466
- }
467
- }
468
- ]
469
- }
470
- ]
471
- }
472
- ]
473
- }
474
- ]
475
- }
1
+ import type { Block } from 'payload'
2
+
3
+ // Lexical integration
4
+ export const MasonryMediaBlockFeature = {
5
+ type: 'masonryMediaBlock',
6
+ fields: [
7
+ // MasonryMediaBlock fields will be used
8
+ ],
9
+ }
10
+
11
+ export const DDMasonry: Block = {
12
+ slug: 'DD-Masonry',
13
+ interfaceName: 'DDMasonry',
14
+ labels: {
15
+ singular: 'Masonry Media Block',
16
+ plural: 'Masonry Media Blocks',
17
+ },
18
+ fields: [
19
+ {
20
+ name: 'mediaFiles',
21
+ type: 'upload',
22
+ relationTo: 'media',
23
+ hasMany: true,
24
+ required: false,
25
+ label: 'Bulk Add Media',
26
+ admin: {
27
+ description:
28
+ 'Select many media files at once. On save, each selected file will be appended into the "items" list with default settings. Existing items are never removed.',
29
+ },
30
+ filterOptions: () => {
31
+ return {} // Return all media, ignore folders
32
+ },
33
+ hooks: {
34
+ beforeChange: [
35
+ ({ value, siblingData }) => {
36
+ const selected = Array.isArray(value) ? value : value ? [value] : []
37
+
38
+ const currentItems = Array.isArray(siblingData?.items) ? siblingData.items : []
39
+
40
+ const existingMediaIds = new Set(
41
+ currentItems
42
+ .map((item: any) => {
43
+ const mediaValue = item?.media
44
+
45
+ if (typeof mediaValue === 'number' || typeof mediaValue === 'string') {
46
+ return mediaValue
47
+ }
48
+
49
+ if (mediaValue && typeof mediaValue === 'object' && 'id' in mediaValue) {
50
+ return (mediaValue as any).id
51
+ }
52
+
53
+ return undefined
54
+ })
55
+ .filter((v: any) => v !== undefined),
56
+ )
57
+
58
+ const newItems = selected
59
+ .filter((mediaId) => mediaId !== null && mediaId !== undefined)
60
+ .filter((mediaId) => !existingMediaIds.has(mediaId as any))
61
+ .map((mediaId) => {
62
+ existingMediaIds.add(mediaId as any)
63
+
64
+ return {
65
+ // Leave `id` empty so the existing row-level hook auto-generates it
66
+ media: mediaId as any,
67
+ linkType: 'none',
68
+ newTab: false,
69
+ aspectRatio: '1/1',
70
+ showTextOverlay: false,
71
+ }
72
+ })
73
+
74
+ if (newItems.length > 0) {
75
+ siblingData.items = [...currentItems, ...newItems]
76
+ }
77
+
78
+ // Treat this field as a "bulk add" input — clear it after processing
79
+ return []
80
+ },
81
+ ],
82
+ },
83
+ },
84
+ {
85
+ name: 'items',
86
+ type: 'array',
87
+ label: 'Media Items',
88
+ minRows: 1,
89
+ fields: [
90
+ {
91
+ name: 'media',
92
+ type: 'upload',
93
+ relationTo: 'media',
94
+ required: true,
95
+ filterOptions: () => {
96
+ return {} // Return all media, ignore folders
97
+ },
98
+ },
99
+ {
100
+ type: 'row',
101
+ fields: [
102
+ {
103
+ name: 'linkType',
104
+ type: 'radio',
105
+ admin: { layout: 'horizontal', width: '50%' },
106
+ defaultValue: 'none',
107
+ options: [
108
+ { label: 'No Link', value: 'none' },
109
+ { label: 'Internal link', value: 'reference' },
110
+ { label: 'Custom URL', value: 'custom' },
111
+ ],
112
+ },
113
+ {
114
+ name: 'newTab',
115
+ type: 'checkbox',
116
+ admin: {
117
+ style: { alignSelf: 'flex-end' },
118
+ width: '50%',
119
+ condition: (_, siblingData) => siblingData?.linkType !== 'none',
120
+ },
121
+ label: 'Open in new tab',
122
+ defaultValue: false,
123
+ },
124
+ ],
125
+ },
126
+ {
127
+ name: 'reference',
128
+ type: 'relationship',
129
+ admin: {
130
+ condition: (_, siblingData) => siblingData?.linkType === 'reference',
131
+ width: '100%',
132
+ },
133
+ label: 'Document to link to',
134
+ relationTo: ['pages'],
135
+ },
136
+ {
137
+ name: 'url',
138
+ type: 'text',
139
+ admin: {
140
+ condition: (_, siblingData) => siblingData?.linkType === 'custom',
141
+ width: '100%',
142
+ },
143
+ label: 'Custom URL',
144
+ },
145
+ {
146
+ name: 'aspectRatio',
147
+ type: 'select',
148
+ defaultValue: '1/1',
149
+ admin: { width: '50%' },
150
+ options: [
151
+ { label: 'Square (1:1)', value: '1/1' },
152
+ { label: 'Portrait (2:3)', value: '2/3' },
153
+ { label: 'Landscape (3:2)', value: '3/2' },
154
+ { label: 'Wide (16:9)', value: '16/9' },
155
+ ],
156
+ },
157
+ {
158
+ type: 'row',
159
+ fields: [
160
+ {
161
+ name: 'showTextOverlay',
162
+ type: 'checkbox',
163
+ label: 'Show Text Overlay',
164
+ defaultValue: false,
165
+ admin: { width: '50%' },
166
+ },
167
+ {
168
+ name: 'textOverlay',
169
+ type: 'text',
170
+ label: 'Overlay Text',
171
+ admin: {
172
+ width: '50%',
173
+ condition: (data: any, siblingData: any) => siblingData?.showTextOverlay,
174
+ },
175
+ },
176
+ ],
177
+ },
178
+ ],
179
+ },
180
+ {
181
+ admin: {
182
+ initCollapsed: true,
183
+ className: 'custom-css-class',
184
+ },
185
+ type: 'collapsible',
186
+ label: 'Layout Settings',
187
+ fields: [
188
+ {
189
+ type: 'group',
190
+ name: 'layout',
191
+ label: false,
192
+ fields: [
193
+ {
194
+ name: 'columns',
195
+ type: 'group',
196
+ label: 'Column Configuration',
197
+ fields: [
198
+ {
199
+ type: 'row',
200
+ fields: [
201
+ {
202
+ name: 'desktop',
203
+ type: 'number',
204
+ label: 'Desktop (< 500px)',
205
+ defaultValue: 5,
206
+ min: 1,
207
+ max: 8,
208
+ admin: { width: '25%' },
209
+ },
210
+ {
211
+ name: 'laptop',
212
+ type: 'number',
213
+ label: 'Laptop (>1000px)',
214
+ defaultValue: 4,
215
+ min: 1,
216
+ max: 6,
217
+ admin: { width: '25%' },
218
+ },
219
+ {
220
+ name: 'tablet',
221
+ type: 'number',
222
+ label: 'Tablet (>600px)',
223
+ defaultValue: 3,
224
+ min: 1,
225
+ max: 4,
226
+ admin: { width: '25%' },
227
+ },
228
+ {
229
+ name: 'mobile',
230
+ type: 'number',
231
+ label: 'Mobile (>400px)',
232
+ defaultValue: 2,
233
+ min: 1,
234
+ max: 3,
235
+ admin: { width: '25%' },
236
+ },
237
+ ],
238
+ },
239
+ ],
240
+ },
241
+ {
242
+ name: 'gap',
243
+ type: 'number',
244
+ label: 'Gap between items (px)',
245
+ defaultValue: 16,
246
+ },
247
+ ],
248
+ },
249
+ {
250
+ type: 'group',
251
+ name: 'animation',
252
+ label: 'Animation Settings',
253
+ fields: [
254
+ {
255
+ name: 'enableAnimation',
256
+ type: 'checkbox',
257
+ label: 'Enable Animation',
258
+ defaultValue: true,
259
+ admin: {
260
+ description:
261
+ 'Toggle animations on/off. When disabled, items appear instantly without any entrance animation.',
262
+ },
263
+ },
264
+ {
265
+ type: 'row',
266
+ fields: [
267
+ {
268
+ name: 'animateFrom',
269
+ type: 'select',
270
+ label: 'Animate From',
271
+ defaultValue: 'bottom',
272
+ admin: {
273
+ width: '33%',
274
+ condition: (_, siblingData) => siblingData?.enableAnimation !== false,
275
+ },
276
+ options: [
277
+ { label: 'Bottom', value: 'bottom' },
278
+ { label: 'Top', value: 'top' },
279
+ { label: 'Left', value: 'left' },
280
+ { label: 'Right', value: 'right' },
281
+ { label: 'Center', value: 'center' },
282
+ { label: 'Random', value: 'random' },
283
+ ],
284
+ dbName: 'animation_from',
285
+ },
286
+ {
287
+ name: 'ease',
288
+ type: 'select',
289
+ label: 'Easing',
290
+ defaultValue: 'power3.out',
291
+ admin: {
292
+ width: '33%',
293
+ condition: (_, siblingData) => siblingData?.enableAnimation !== false,
294
+ },
295
+ options: [
296
+ { label: 'Power3 Out', value: 'power3.out' },
297
+ { label: 'Power2 Out', value: 'power2.out' },
298
+ { label: 'Power4 Out', value: 'power4.out' },
299
+ { label: 'Back Out', value: 'back.out' },
300
+ { label: 'Elastic Out', value: 'elastic.out' },
301
+ { label: 'Bounce Out', value: 'bounce.out' },
302
+ ],
303
+ dbName: 'animation_ease',
304
+ },
305
+ {
306
+ name: 'repeatOnScroll',
307
+ type: 'checkbox',
308
+ label: 'Repeat on Scroll',
309
+ defaultValue: false,
310
+ admin: {
311
+ width: '34%',
312
+ style: { alignSelf: 'flex-end' },
313
+ condition: (_, siblingData) => siblingData?.enableAnimation !== false,
314
+ },
315
+ },
316
+ ],
317
+ },
318
+ {
319
+ type: 'row',
320
+ fields: [
321
+ {
322
+ name: 'duration',
323
+ type: 'number',
324
+ label: 'Duration (seconds)',
325
+ defaultValue: 0.6,
326
+ min: 0.1,
327
+ max: 2,
328
+ admin: {
329
+ width: '50%',
330
+ condition: (_, siblingData) => siblingData?.enableAnimation !== false,
331
+ },
332
+ },
333
+ {
334
+ name: 'stagger',
335
+ type: 'number',
336
+ label: 'Stagger Delay (seconds)',
337
+ defaultValue: 0.05,
338
+ min: 0,
339
+ max: 0.5,
340
+ admin: {
341
+ width: '50%',
342
+ condition: (_, siblingData) => siblingData?.enableAnimation !== false,
343
+ },
344
+ },
345
+ ],
346
+ },
347
+ ],
348
+ },
349
+ {
350
+ type: 'group',
351
+ name: 'interaction',
352
+ label: 'Interaction Settings',
353
+ fields: [
354
+ {
355
+ type: 'row',
356
+ fields: [
357
+ {
358
+ name: 'scaleOnHover',
359
+ type: 'checkbox',
360
+ label: 'Scale on Hover',
361
+ defaultValue: true,
362
+ admin: { width: '33%' },
363
+ },
364
+ {
365
+ name: 'blurToFocus',
366
+ type: 'checkbox',
367
+ label: 'Blur to Focus Effect',
368
+ defaultValue: true,
369
+ admin: { width: '33%' },
370
+ },
371
+ {
372
+ name: 'colorShiftOnHover',
373
+ type: 'checkbox',
374
+ label: 'Color Shift on Hover',
375
+ defaultValue: false,
376
+ admin: { width: '34%' },
377
+ },
378
+ ],
379
+ },
380
+ {
381
+ name: 'hoverScale',
382
+ type: 'number',
383
+ label: 'Hover Scale Amount',
384
+ defaultValue: 0.95,
385
+ min: 0.5,
386
+ max: 1.5,
387
+ admin: {
388
+ width: '50%',
389
+ condition: (data: any, siblingData: any) => siblingData?.scaleOnHover,
390
+ },
391
+ },
392
+ {
393
+ name: 'customHoverColors',
394
+ type: 'group',
395
+ label: 'Custom Hover Colors',
396
+ admin: {
397
+ condition: (data: any, siblingData: any) => siblingData?.colorShiftOnHover,
398
+ },
399
+ fields: [
400
+ {
401
+ type: 'row',
402
+ fields: [
403
+ {
404
+ name: 'fromColor',
405
+ type: 'text',
406
+ label: 'From Color',
407
+ defaultValue: 'rgba(236, 72, 153, 0.5)',
408
+ admin: { width: '50%' },
409
+ },
410
+ {
411
+ name: 'toColor',
412
+ type: 'text',
413
+ label: 'To Color',
414
+ defaultValue: 'rgba(14, 165, 233, 0.5)',
415
+ admin: { width: '50%' },
416
+ },
417
+ ],
418
+ },
419
+ ],
420
+ },
421
+ ],
422
+ },
423
+ {
424
+ type: 'group',
425
+ name: 'advanced',
426
+ label: 'Advanced Settings',
427
+ fields: [
428
+ {
429
+ type: 'row',
430
+ fields: [
431
+ {
432
+ name: 'sectionId',
433
+ type: 'text',
434
+ label: 'Section ID',
435
+ admin: { width: '50%' },
436
+ },
437
+ {
438
+ name: 'customClassName',
439
+ type: 'text',
440
+ label: 'Custom Class Name',
441
+ defaultValue: 'min-h-[50vh] mt-16',
442
+ admin: { width: '50%' },
443
+ },
444
+ ],
445
+ },
446
+ {
447
+ type: 'row',
448
+ fields: [
449
+ {
450
+ name: 'enableParallax',
451
+ type: 'checkbox',
452
+ label: 'Enable Parallax',
453
+ defaultValue: false,
454
+ admin: { width: '50%' },
455
+ },
456
+ {
457
+ name: 'parallaxSpeed',
458
+ type: 'number',
459
+ label: 'Parallax Speed',
460
+ defaultValue: 0.5,
461
+ min: -2,
462
+ max: 2,
463
+ admin: {
464
+ width: '50%',
465
+ condition: (data: any, siblingData: any) => siblingData?.enableParallax,
466
+ },
467
+ },
468
+ ],
469
+ },
470
+ ],
471
+ },
472
+ ],
473
+ },
474
+ ],
475
+ }