blocks-dusted 0.1.10 → 0.1.12

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 (249) hide show
  1. package/README.md +35 -0
  2. package/package.json +5 -2
  3. package/src/cli.js +39 -3
  4. package/src/commands/shop.js +59 -0
  5. package/src/commands/warehouse.js +73 -0
  6. package/src/utils/paths.js +13 -13
  7. package/templates/blocks/DD-Accordion/Component.tsx +229 -0
  8. package/templates/blocks/DD-Accordion/README.md +3 -0
  9. package/templates/blocks/DD-Accordion/config.ts +73 -0
  10. package/templates/blocks/DD-Accordion/manifest.json +75 -0
  11. package/templates/blocks/DD-AnimText/Component.tsx +788 -0
  12. package/templates/blocks/DD-AnimText/README.md +3 -0
  13. package/templates/blocks/DD-AnimText/config.ts +295 -0
  14. package/templates/blocks/DD-AnimText/manifest.json +85 -0
  15. package/templates/blocks/DD-AsideNav/Component.tsx +321 -0
  16. package/templates/blocks/DD-AsideNav/config.ts +204 -0
  17. package/templates/blocks/DD-AsideNav/manifest.json +80 -0
  18. package/templates/blocks/DD-Banner/Component.tsx +51 -0
  19. package/templates/blocks/DD-Banner/config.ts +57 -0
  20. package/templates/blocks/DD-Banner/manifest.json +72 -0
  21. package/templates/blocks/DD-BgLightning/Component.tsx +44 -0
  22. package/templates/blocks/DD-BgLightning/README.md +3 -0
  23. package/templates/blocks/DD-BgLightning/config.ts +97 -0
  24. package/templates/blocks/DD-BgLightning/manifest.json +79 -0
  25. package/templates/blocks/DD-BookCall/Component.tsx +535 -535
  26. package/templates/blocks/DD-BookCall/config.ts +238 -238
  27. package/templates/blocks/DD-ButtonPop/Component.tsx +117 -0
  28. package/templates/blocks/DD-ButtonPop/config.ts +105 -0
  29. package/templates/blocks/DD-ButtonPop/manifest.json +88 -0
  30. package/templates/blocks/DD-ButtonPop/svg-icons/Dust2.tsx +167 -0
  31. package/templates/blocks/DD-Card/Component.tsx +251 -0
  32. package/templates/blocks/DD-Card/README.md +4 -0
  33. package/templates/blocks/DD-Card/config.ts +154 -0
  34. package/templates/blocks/DD-Card/manifest.json +82 -0
  35. package/templates/blocks/DD-CardTemplate01/Component.tsx +140 -140
  36. package/templates/blocks/DD-CardTemplate01/config.ts +106 -106
  37. package/templates/blocks/DD-Carousel-A/Component.tsx +249 -249
  38. package/templates/blocks/DD-Carousel-B/Component.tsx +403 -403
  39. package/templates/blocks/DD-Chip/Component.tsx +250 -0
  40. package/templates/blocks/DD-Chip/EXAMPLES.md +313 -0
  41. package/templates/blocks/DD-Chip/README.md +202 -0
  42. package/templates/blocks/DD-Chip/config.ts +369 -0
  43. package/templates/blocks/DD-Chip/manifest.json +74 -0
  44. package/templates/blocks/DD-ComparisonTable/Component.tsx +256 -256
  45. package/templates/blocks/DD-Contact/Component.tsx +435 -434
  46. package/templates/blocks/DD-Contact/config.ts +22 -22
  47. package/templates/blocks/DD-Counter/Component.tsx +190 -0
  48. package/templates/blocks/DD-Counter/README.md +4 -0
  49. package/templates/blocks/DD-Counter/config.ts +291 -0
  50. package/templates/blocks/DD-Counter/manifest.json +74 -0
  51. package/templates/blocks/DD-CustomCSS/Component.tsx +8 -0
  52. package/templates/blocks/DD-CustomCSS/README.md +4 -0
  53. package/templates/blocks/DD-CustomCSS/addToLayout.md +5 -0
  54. package/templates/blocks/DD-CustomCSS/config.ts +22 -0
  55. package/templates/blocks/DD-CustomCSS/manifest.json +72 -0
  56. package/templates/blocks/DD-CustomCSS/renderCustomCSS.md +7 -0
  57. package/templates/blocks/DD-FeatCat/Component.tsx +302 -302
  58. package/templates/blocks/DD-FeatCat/config.ts +201 -201
  59. package/templates/blocks/DD-FeatStrip/Component.tsx +585 -585
  60. package/templates/blocks/DD-FeatStrip/config.ts +134 -134
  61. package/templates/blocks/DD-FluidBtn/ButtonsEyeCatching.tsx +628 -0
  62. package/templates/blocks/DD-FluidBtn/Component.tsx +43 -0
  63. package/templates/blocks/DD-FluidBtn/README.md +6 -0
  64. package/templates/blocks/DD-FluidBtn/config.ts +102 -0
  65. package/templates/blocks/DD-FluidBtn/manifest.json +86 -0
  66. package/templates/blocks/DD-GooeyInfo/Component.tsx +149 -0
  67. package/templates/blocks/DD-GooeyInfo/config.ts +135 -0
  68. package/templates/blocks/DD-GooeyInfo/manifest.json +72 -0
  69. package/templates/blocks/DD-Hero/Component.tsx +297 -297
  70. package/templates/blocks/DD-Hero/config.ts +267 -267
  71. package/templates/blocks/DD-HorizontalScroll/Component.tsx +936 -936
  72. package/templates/blocks/DD-HorizontalScroll/config.ts +231 -231
  73. package/templates/blocks/DD-Icon/Component.tsx +287 -0
  74. package/templates/blocks/DD-Icon/README.md +4 -0
  75. package/templates/blocks/DD-Icon/config.ts +258 -0
  76. package/templates/blocks/DD-Icon/hooks/revalidateBlockIds.ts +66 -0
  77. package/templates/blocks/DD-Icon/manifest.json +82 -0
  78. package/templates/blocks/DD-IconButton/Component.tsx +455 -0
  79. package/templates/blocks/DD-IconButton/README.md +326 -0
  80. package/templates/blocks/DD-IconButton/config.ts +239 -0
  81. package/templates/blocks/DD-IconButton/manifest.json +85 -0
  82. package/templates/blocks/DD-IdTag/Component.tsx +21 -0
  83. package/templates/blocks/DD-IdTag/README.md +4 -0
  84. package/templates/blocks/DD-IdTag/config.ts +41 -0
  85. package/templates/blocks/DD-IdTag/manifest.json +72 -0
  86. package/templates/blocks/DD-Iframe/Component.tsx +45 -0
  87. package/templates/blocks/DD-Iframe/README.md +4 -0
  88. package/templates/blocks/DD-Iframe/config.ts +47 -0
  89. package/templates/blocks/DD-Iframe/manifest.json +72 -0
  90. package/templates/blocks/DD-IframeMedia/Component.tsx +133 -0
  91. package/templates/blocks/DD-IframeMedia/README.md +4 -0
  92. package/templates/blocks/DD-IframeMedia/config.ts +79 -0
  93. package/templates/blocks/DD-IframeMedia/manifest.json +72 -0
  94. package/templates/blocks/DD-LineAnim/Component.tsx +36 -0
  95. package/templates/blocks/DD-LineAnim/README.md +4 -0
  96. package/templates/blocks/DD-LineAnim/config.ts +90 -0
  97. package/templates/blocks/DD-LineAnim/manifest.json +80 -0
  98. package/templates/blocks/DD-LinkGrid/Component.tsx +119 -0
  99. package/templates/blocks/DD-LinkGrid/README.md +4 -0
  100. package/templates/blocks/DD-LinkGrid/config.ts +51 -0
  101. package/templates/blocks/DD-LinkGrid/manifest.json +74 -0
  102. package/templates/blocks/DD-LogoMarq/Component.tsx +132 -0
  103. package/templates/blocks/DD-LogoMarq/README.md +4 -0
  104. package/templates/blocks/DD-LogoMarq/config.ts +264 -0
  105. package/templates/blocks/DD-LogoMarq/manifest.json +82 -0
  106. package/templates/blocks/DD-Lottie/Component.tsx +459 -0
  107. package/templates/blocks/DD-Lottie/README.md +4 -0
  108. package/templates/blocks/DD-Lottie/config.ts +379 -0
  109. package/templates/blocks/DD-Lottie/index.tsx +28 -0
  110. package/templates/blocks/DD-Lottie/manifest.json +83 -0
  111. package/templates/blocks/DD-MagicBento/Component.tsx +777 -0
  112. package/templates/blocks/DD-MagicBento/README.md +4 -0
  113. package/templates/blocks/DD-MagicBento/config.ts +264 -0
  114. package/templates/blocks/DD-MagicBento/manifest.json +74 -0
  115. package/templates/blocks/DD-MasonaryMedia/Component.tsx +545 -545
  116. package/templates/blocks/DD-MasonaryMedia/config.ts +2 -2
  117. package/templates/blocks/DD-MasonaryMedia/vendor.d.ts +2 -2
  118. package/templates/blocks/DD-Masonry/Component.tsx +645 -0
  119. package/templates/blocks/DD-Masonry/README.md +4 -0
  120. package/templates/blocks/DD-Masonry/config.ts +475 -0
  121. package/templates/blocks/DD-Masonry/manifest.json +82 -0
  122. package/templates/blocks/DD-Pricing/Component.tsx +2 -5
  123. package/templates/blocks/DD-Process/Component.tsx +2 -4
  124. package/templates/blocks/DD-Process/config.ts +150 -150
  125. package/templates/blocks/DD-Progress/Component.tsx +156 -0
  126. package/templates/blocks/DD-Progress/README.md +4 -0
  127. package/templates/blocks/DD-Progress/config.ts +175 -0
  128. package/templates/blocks/DD-Progress/manifest.json +74 -0
  129. package/templates/blocks/DD-ProjHeader/Component.tsx +91 -0
  130. package/templates/blocks/DD-ProjHeader/README.md +4 -0
  131. package/templates/blocks/DD-ProjHeader/config.ts +96 -0
  132. package/templates/blocks/DD-ProjHeader/manifest.json +72 -0
  133. package/templates/blocks/DD-ProjSlider/Component.tsx +123 -0
  134. package/templates/blocks/DD-ProjSlider/README.md +4 -0
  135. package/templates/blocks/DD-ProjSlider/config.ts +64 -0
  136. package/templates/blocks/DD-ProjSlider/manifest.json +72 -0
  137. package/templates/blocks/DD-ScrollText/Component.tsx +114 -0
  138. package/templates/blocks/DD-ScrollText/README.md +4 -0
  139. package/templates/blocks/DD-ScrollText/config.ts +58 -0
  140. package/templates/blocks/DD-ScrollText/manifest.json +72 -0
  141. package/templates/blocks/DD-Section/Component.tsx +266 -266
  142. package/templates/blocks/DD-Separator/Component.tsx +66 -0
  143. package/templates/blocks/DD-Separator/README.md +4 -0
  144. package/templates/blocks/DD-Separator/config.ts +58 -0
  145. package/templates/blocks/DD-Separator/manifest.json +72 -0
  146. package/templates/blocks/DD-Services/Component.tsx +176 -176
  147. package/templates/blocks/DD-Services/config.ts +149 -149
  148. package/templates/blocks/DD-ShowcaseGrid/Component.tsx +307 -307
  149. package/templates/blocks/DD-Slider-A/Component.tsx +1 -1
  150. package/templates/blocks/DD-StackCards/Component.tsx +1 -1
  151. package/templates/blocks/DD-StackCards/config.ts +399 -399
  152. package/templates/blocks/DD-Team/Component.tsx +247 -247
  153. package/templates/blocks/DD-Team/config.ts +173 -173
  154. package/templates/blocks/DD-TeamCards/Component.tsx +251 -0
  155. package/templates/blocks/DD-TeamCards/README.md +4 -0
  156. package/templates/blocks/DD-TeamCards/config.ts +302 -0
  157. package/templates/blocks/DD-TeamCards/manifest.json +74 -0
  158. package/templates/blocks/DD-TechStack/Component.tsx +174 -174
  159. package/templates/blocks/DD-TechStack/config.ts +153 -153
  160. package/templates/blocks/DD-TestMarq/Component.tsx +132 -0
  161. package/templates/blocks/DD-TestMarq/README.md +4 -0
  162. package/templates/blocks/DD-TestMarq/RowLabel.tsx +9 -0
  163. package/templates/blocks/DD-TestMarq/config.ts +88 -0
  164. package/templates/blocks/DD-TestMarq/manifest.json +72 -0
  165. package/templates/blocks/DD-Testim/Component.tsx +247 -0
  166. package/templates/blocks/DD-Testim/README.md +4 -0
  167. package/templates/blocks/DD-Testim/config.ts +101 -0
  168. package/templates/blocks/DD-Testim/manifest.json +75 -0
  169. package/templates/blocks/DD-Testim2/Component.tsx +256 -0
  170. package/templates/blocks/DD-Testim2/README.md +4 -0
  171. package/templates/blocks/DD-Testim2/config.ts +100 -0
  172. package/templates/blocks/DD-Testim2/manifest.json +74 -0
  173. package/templates/blocks/DD-Testimonials/Component.tsx +139 -147
  174. package/templates/blocks/DD-Testimonials/config.ts +120 -120
  175. package/templates/blocks/DD-TextMarq/Component.tsx +157 -0
  176. package/templates/blocks/DD-TextMarq/README.md +4 -0
  177. package/templates/blocks/DD-TextMarq/config.ts +237 -0
  178. package/templates/blocks/DD-TextMarq/manifest.json +82 -0
  179. package/templates/blocks/DD-Thanks/Component.tsx +501 -0
  180. package/templates/blocks/DD-Thanks/README.md +4 -0
  181. package/templates/blocks/DD-Thanks/config.ts +224 -0
  182. package/templates/blocks/DD-Thanks/manifest.json +72 -0
  183. package/templates/blocks/DD-VertMarq/Component.tsx +154 -0
  184. package/templates/blocks/DD-VertMarq/README.md +4 -0
  185. package/templates/blocks/DD-VertMarq/config.ts +236 -0
  186. package/templates/blocks/DD-VertMarq/dist/index.css +6 -0
  187. package/templates/blocks/DD-VertMarq/dist/index.min.css +1 -0
  188. package/templates/blocks/DD-VertMarq/manifest.json +74 -0
  189. package/templates/blocks/DD-Work/Component.tsx +318 -315
  190. package/templates/blocks/DD-Work/config.ts +165 -165
  191. package/templates/blocks/DD-Work-B/Component.tsx +294 -294
  192. package/templates/blocks/DDHG-CTASection2/Component.tsx +185 -0
  193. package/templates/blocks/DDHG-CTASection2/config.ts +140 -0
  194. package/templates/blocks/DDHG-CTASection2/manifest.json +45 -0
  195. package/templates/blocks/DDHG-HighlightArc/Component.tsx +243 -0
  196. package/templates/blocks/DDHG-HighlightArc/config.ts +85 -0
  197. package/templates/blocks/DDHG-HighlightArc/manifest.json +46 -0
  198. package/templates/blocks/DDHG-LogoMarquee/Component.tsx +143 -0
  199. package/templates/blocks/DDHG-LogoMarquee/config.ts +154 -0
  200. package/templates/blocks/DDHG-LogoMarquee/manifest.json +39 -0
  201. package/templates/blocks/DDHG-NavCodeGrid/Component.tsx +227 -0
  202. package/templates/blocks/DDHG-NavCodeGrid/config.ts +64 -0
  203. package/templates/blocks/DDHG-NavCodeGrid/manifest.json +45 -0
  204. package/templates/blocks/DDHG-ProcessSec/Component.tsx +574 -0
  205. package/templates/blocks/DDHG-ProcessSec/config.ts +170 -0
  206. package/templates/blocks/DDHG-ProcessSec/manifest.json +56 -0
  207. package/templates/blocks/DDHG-ServiceDetails/Component.tsx +164 -0
  208. package/templates/blocks/DDHG-ServiceDetails/ServiceDetailCard.tsx +390 -0
  209. package/templates/blocks/DDHG-ServiceDetails/config.ts +77 -0
  210. package/templates/blocks/DDHG-ServiceDetails/manifest.json +50 -0
  211. package/templates/blocks/DDHG-ServiceHero/Component.tsx +234 -0
  212. package/templates/blocks/DDHG-ServiceHero/config.ts +49 -0
  213. package/templates/blocks/DDHG-ServiceHero/manifest.json +26 -0
  214. package/templates/blocks/DDHG-ServiceOverview/Component.tsx +277 -0
  215. package/templates/blocks/DDHG-ServiceOverview/config.ts +64 -0
  216. package/templates/blocks/DDHG-ServiceOverview/manifest.json +44 -0
  217. package/templates/blocks/DDHG-StatsFAQ/Component.tsx +389 -0
  218. package/templates/blocks/DDHG-StatsFAQ/config.ts +204 -0
  219. package/templates/blocks/DDHG-StatsFAQ/manifest.json +45 -0
  220. package/templates/blocks/DDHG-TeamCards/Component.tsx +169 -0
  221. package/templates/blocks/DDHG-TeamCards/config.ts +48 -0
  222. package/templates/blocks/DDHG-TeamCards/manifest.json +29 -0
  223. package/templates/shared/src/components/BgLightning/index.tsx +242 -0
  224. package/templates/shared/src/components/ui/ShareButton/index.tsx +80 -0
  225. package/templates/shared/src/components/ui/anims/FadeOnScroll.tsx +48 -0
  226. package/templates/shared/src/components/ui/anims/FadeUpOnInView.tsx +63 -0
  227. package/templates/shared/src/components/ui/anims/GlareHover.tsx +111 -0
  228. package/templates/shared/src/components/ui/anims/LineAnims.tsx +81 -0
  229. package/templates/shared/src/components/ui/anims/TitleAnims01.tsx +54 -0
  230. package/templates/shared/src/components/ui/anims/animation-container.tsx +29 -0
  231. package/templates/shared/src/components/ui/anims/blur-in.tsx +26 -0
  232. package/templates/shared/src/components/ui/anims/counter.tsx +53 -0
  233. package/templates/shared/src/components/ui/anims/fade.tsx +83 -0
  234. package/templates/shared/src/components/ui/anims/gradual-spacing.tsx +39 -0
  235. package/templates/shared/src/components/ui/anims/pull-up.tsx +93 -0
  236. package/templates/shared/src/components/ui/anims/reveal-text.tsx +76 -0
  237. package/templates/shared/src/components/ui/anims/rotate-words.tsx +43 -0
  238. package/templates/shared/src/components/ui/anims/shiny-text.tsx +58 -0
  239. package/templates/shared/src/components/ui/anims/shuffle-text.tsx +85 -0
  240. package/templates/shared/src/components/ui/anims/split-text.tsx +211 -0
  241. package/templates/shared/src/components/ui/anims/staggered-fade.tsx +133 -0
  242. package/templates/shared/src/components/ui/anims/text-scroll.tsx +111 -0
  243. package/templates/shared/src/components/ui/anims/typing-effect.tsx +112 -0
  244. package/templates/shared/src/components/ui/button-dusted-fluid/index.tsx +1521 -0
  245. package/templates/shared/src/components/ui/separator.tsx +85 -0
  246. package/templates/shared/src/hooks/useBodyScrollLock.ts +97 -0
  247. package/templates/shared/src/hooks/useClickOutside.ts +28 -0
  248. package/templates/shared/src/utilities/renderCustomCSS.ts +5 -0
  249. package/templates/shared/src/utilities/smoothScroll.ts +65 -0
package/README.md CHANGED
@@ -1045,3 +1045,38 @@ The RichText standard is correctly implemented when:
1045
1045
  - CLI executable: `blocks-dusted`
1046
1046
 
1047
1047
  The repository can remain private while the npm package is published separately.
1048
+
1049
+ <!-- DESIGNSDUSTEDV4_SANDBOX_SYNC:START -->
1050
+ ## DesignsDustedv4 Sandbox Sync
1051
+
1052
+ Last updated: 2026-08-22.
1053
+
1054
+ The current local CLI version in `package.json` is `0.1.10`.
1055
+
1056
+ `blocks-dusted/templates/blocks` is the installable template source for productized DD/DDHG blocks. DesignsDustedv4 keeps matching sandbox runtime copies for its product catalogue previews.
1057
+
1058
+ Matching runtime source:
1059
+
1060
+ ```text
1061
+ D:\CodeDusted\DesignsDustedv4\src\sandbox\products\DDBlockProductSandboxes\blocks
1062
+ ```
1063
+
1064
+ Installable template source:
1065
+
1066
+ ```text
1067
+ D:\CodeDusted\Dusted-Payload-Blocks\blocks-dusted\templates\blocks
1068
+ ```
1069
+
1070
+ Current synced state:
1071
+
1072
+ - DesignsDustedv4 sandbox product block folders: 68
1073
+ - blocks-dusted template block folders: 68
1074
+ - shared sandbox/template files compared: 179
1075
+ - shared file mismatches after sync: 0
1076
+ - expected extra template files: 68 `config.ts` files
1077
+ - extra files outside `config.ts`: 0
1078
+
1079
+ `config.ts` is installer/admin schema metadata and intentionally exists only in `blocks-dusted`. Do not copy those files into the DesignsDustedv4 sandbox unless the app runtime explicitly needs them. Do not delete them from `blocks-dusted`.
1080
+
1081
+ When changing a productized block, update both the DesignsDustedv4 sandbox runtime file and the matching `blocks-dusted/templates/blocks` runtime file. Keep fixture/demo copy in DesignsDustedv4 public-safe: no local paths, repository names, private data, registry wiring copy, iframe copy, or sandbox-render implementation copy.
1082
+ <!-- DESIGNSDUSTEDV4_SANDBOX_SYNC:END -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blocks-dusted",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Manifest-driven CLI for installing reusable Payload CMS blocks.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -23,7 +23,10 @@
23
23
  "test:add": "node ./bin/index.js add DD-Hero --dry-run",
24
24
  "test:list": "node ./bin/index.js list",
25
25
  "test:doctor": "node ./bin/index.js doctor",
26
- "convert:studio": "node ./scripts/convertStudioBlock.mjs"
26
+ "convert:studio": "node ./scripts/convertStudioBlock.mjs",
27
+ "warehouse:sync-lab": "node ./bin/index.js warehouse sync-lab",
28
+ "warehouse:sync-lab:dry-run": "node ./bin/index.js warehouse sync-lab --dry-run",
29
+ "shop:pull-sandbox:dry-run": "node ./bin/index.js shop pull-sandbox --dry-run"
27
30
  },
28
31
  "engines": {
29
32
  "node": ">=20"
package/src/cli.js CHANGED
@@ -1,9 +1,11 @@
1
- import { readFile } from 'node:fs/promises'
1
+ import { readFile } from 'node:fs/promises'
2
2
  import { resolve } from 'node:path'
3
3
  import { addTemplate } from './commands/add.js'
4
4
  import { doctor } from './commands/doctor.js'
5
5
  import { addHeader } from './commands/header.js'
6
- import { list } from './commands/list.js'
6
+ import { list } from './commands/list.js'
7
+ import { pullSandboxFromWarehouse } from './commands/shop.js'
8
+ import { syncLabToWarehouse } from './commands/warehouse.js'
7
9
  import { error, info } from './utils/logger.js'
8
10
  import { packageRoot } from './utils/paths.js'
9
11
 
@@ -14,7 +16,9 @@ function printHelp() {
14
16
  info(' blocks-dusted list')
15
17
  info(' blocks-dusted doctor [--cwd <path>]')
16
18
  info(' blocks-dusted add <TemplateName> [--dry-run] [--no-register] [--cwd <path>]')
17
- info(' blocks-dusted header add <HeaderName> [--dry-run] [--cwd <path>]')
19
+ info(' blocks-dusted header add <HeaderName> [--dry-run] [--cwd <path>]')
20
+ info(' blocks-dusted warehouse sync-lab [--dry-run] [--lab <path>]')
21
+ info(' blocks-dusted shop pull-sandbox [--dry-run] [--warehouse <path>] [--cwd <shop path>]')
18
22
  info(' blocks-dusted --version')
19
23
  }
20
24
 
@@ -57,11 +61,42 @@ export async function runCli(args, options = {}) {
57
61
  })
58
62
  }
59
63
 
64
+ if (command === 'warehouse') {
65
+ const [subcommand] = rest
66
+ if (subcommand !== 'sync-lab') throw new Error('Usage: blocks-dusted warehouse sync-lab [--dry-run] [--lab <path>]')
67
+ return syncLabToWarehouse({
68
+ labRoot: optionValue(rest, '--lab'),
69
+ dryRun: rest.includes('--dry-run'),
70
+ })
71
+ }
72
+
73
+ if (command === 'shop') {
74
+ const [subcommand] = rest
75
+ if (subcommand !== 'pull-sandbox') throw new Error('Usage: blocks-dusted shop pull-sandbox [--dry-run] [--warehouse <path>] [--cwd <shop path>]')
76
+ return pullSandboxFromWarehouse({
77
+ targetDirectory,
78
+ warehouseRoot: optionValue(rest, '--warehouse'),
79
+ dryRun: rest.includes('--dry-run'),
80
+ })
81
+ }
82
+
60
83
  error(`Unknown command: ${command}`)
61
84
  printHelp()
62
85
  process.exitCode = 1
63
86
  }
64
87
 
88
+ function optionValue(args, name) {
89
+ for (let index = 0; index < args.length; index += 1) {
90
+ const argument = args[index]
91
+ if (argument === name) {
92
+ const value = args[index + 1]
93
+ if (!value) throw new Error(`${name} requires a path`)
94
+ return value
95
+ }
96
+ if (argument.startsWith(`${name}=`)) return argument.slice(name.length + 1)
97
+ }
98
+ return undefined
99
+ }
65
100
  function parseGlobalOptions(args, originalDirectory) {
66
101
  const commandArgs = []
67
102
  let targetDirectory = originalDirectory
@@ -90,3 +125,4 @@ async function packageVersion() {
90
125
  return packageJson.version
91
126
  }
92
127
 
128
+
@@ -0,0 +1,59 @@
1
+ import { mkdir, readdir, readFile, stat, copyFile } from 'node:fs/promises'
2
+ import { dirname, join, relative, resolve } from 'node:path'
3
+ import { packageRoot } from '../utils/paths.js'
4
+
5
+ const defaultSandboxBlocks = join('src', 'sandbox', 'products', 'DDBlockProductSandboxes', 'blocks')
6
+ const excludedTemplateFiles = new Set(['config.ts', 'manifest.json', 'README.md'])
7
+
8
+ export async function pullSandboxFromWarehouse({ targetDirectory = process.cwd(), warehouseRoot = packageRoot, dryRun = false } = {}) {
9
+ const sourceRoot = join(resolve(warehouseRoot), 'templates', 'blocks')
10
+ const targetRoot = join(resolve(targetDirectory), defaultSandboxBlocks)
11
+ const blockEntries = await readdir(sourceRoot, { withFileTypes: true })
12
+ const results = []
13
+ const errors = []
14
+
15
+ for (const entry of blockEntries.sort((a, b) => a.name.localeCompare(b.name))) {
16
+ if (!entry.isDirectory()) continue
17
+ const blockName = entry.name
18
+ const manifestPath = join(sourceRoot, blockName, 'manifest.json')
19
+ let manifest
20
+ try {
21
+ manifest = JSON.parse(await readFile(manifestPath, 'utf8'))
22
+ } catch (error) {
23
+ errors.push(`${blockName}: unable to read manifest: ${error.message}`)
24
+ continue
25
+ }
26
+
27
+ for (const file of manifest.files ?? []) {
28
+ const from = String(file.from ?? '')
29
+ if (!from || excludedTemplateFiles.has(from.replace(/\\/g, '/'))) continue
30
+ const source = join(sourceRoot, blockName, from)
31
+ const target = join(targetRoot, blockName, from)
32
+ try {
33
+ const sourceStat = await stat(source)
34
+ if (!sourceStat.isFile()) {
35
+ errors.push(`${blockName}: source is not a file: ${relative(resolve(warehouseRoot), source)}`)
36
+ continue
37
+ }
38
+ results.push({ blockName, from: relative(resolve(warehouseRoot), source), to: relative(resolve(targetDirectory), target) })
39
+ if (!dryRun) {
40
+ await mkdir(dirname(target), { recursive: true })
41
+ await copyFile(source, target)
42
+ }
43
+ } catch (error) {
44
+ errors.push(`${blockName}: missing warehouse runtime file ${from}: ${error.message}`)
45
+ }
46
+ }
47
+ }
48
+
49
+ console.log(`Warehouse to Shop sandbox pull${dryRun ? ' dry run' : ''}`)
50
+ console.log(`Target: ${targetRoot}`)
51
+ console.log(`Files ${dryRun ? 'planned' : 'copied'}: ${results.length}`)
52
+ for (const row of results) console.log(`- ${row.blockName}: ${row.from} -> ${row.to}`)
53
+ if (errors.length > 0) {
54
+ console.error('Errors:')
55
+ for (const error of errors) console.error(`- ${error}`)
56
+ throw new Error(`Warehouse to Shop pull failed with ${errors.length} error(s).`)
57
+ }
58
+ return { results, errors }
59
+ }
@@ -0,0 +1,73 @@
1
+ import { mkdir, readdir, readFile, stat, copyFile } from 'node:fs/promises'
2
+ import { dirname, join, relative, resolve } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+
5
+ const packageRoot = resolve(fileURLToPath(new URL('../..', import.meta.url)))
6
+ const defaultLabRoot = resolve(packageRoot, '..', 'CLI-TestGround', 'cli-testground')
7
+ const blockTemplateRoot = join(packageRoot, 'templates', 'blocks')
8
+
9
+ export async function syncLabToWarehouse({ labRoot = defaultLabRoot, dryRun = false } = {}) {
10
+ const labBlocksRoot = join(resolve(labRoot), 'src', 'blocks')
11
+ const manifests = await readBlockManifests(blockTemplateRoot)
12
+ const results = []
13
+ const errors = []
14
+
15
+ for (const { blockName, manifest, manifestDir } of manifests) {
16
+ for (const file of manifest.files ?? []) {
17
+ const from = String(file.from ?? '')
18
+ if (!from) continue
19
+ const source = join(labBlocksRoot, blockName, from)
20
+ const target = join(manifestDir, from)
21
+ try {
22
+ const sourceStat = await stat(source)
23
+ if (!sourceStat.isFile()) {
24
+ errors.push(`${blockName}: source is not a file: ${relative(resolve(labRoot), source)}`)
25
+ continue
26
+ }
27
+ results.push({ blockName, from: relative(resolve(labRoot), source), to: relative(packageRoot, target) })
28
+ if (!dryRun) {
29
+ await mkdir(dirname(target), { recursive: true })
30
+ await copyFile(source, target)
31
+ }
32
+ } catch (error) {
33
+ errors.push(`${blockName}: missing lab file for manifest entry ${from}: ${error.message}`)
34
+ }
35
+ }
36
+ }
37
+
38
+ printSyncResults({ title: 'Lab to Warehouse sync', dryRun, results, errors })
39
+ if (errors.length > 0) {
40
+ const error = new Error(`Lab to Warehouse sync failed with ${errors.length} error(s).`)
41
+ error.results = { results, errors }
42
+ throw error
43
+ }
44
+ return { results, errors }
45
+ }
46
+
47
+ async function readBlockManifests(root) {
48
+ const entries = await readdir(root, { withFileTypes: true })
49
+ const manifests = []
50
+ for (const entry of entries) {
51
+ if (!entry.isDirectory()) continue
52
+ const manifestDir = join(root, entry.name)
53
+ const manifestPath = join(manifestDir, 'manifest.json')
54
+ try {
55
+ const manifest = JSON.parse(await readFile(manifestPath, 'utf8'))
56
+ manifests.push({ blockName: entry.name, manifest, manifestDir })
57
+ } catch (error) {
58
+ throw new Error(`Unable to read ${relative(packageRoot, manifestPath)}: ${error.message}`)
59
+ }
60
+ }
61
+ manifests.sort((a, b) => a.blockName.localeCompare(b.blockName))
62
+ return manifests
63
+ }
64
+
65
+ function printSyncResults({ title, dryRun, results, errors }) {
66
+ console.log(`${title}${dryRun ? ' dry run' : ''}`)
67
+ console.log(`Files ${dryRun ? 'planned' : 'copied'}: ${results.length}`)
68
+ for (const row of results) console.log(`- ${row.blockName}: ${row.from} -> ${row.to}`)
69
+ if (errors.length > 0) {
70
+ console.error('Errors:')
71
+ for (const error of errors) console.error(`- ${error}`)
72
+ }
73
+ }
@@ -1,14 +1,14 @@
1
- import { dirname, resolve } from 'node:path'
2
- import { fileURLToPath } from 'node:url'
3
-
4
- const currentDirectory = dirname(fileURLToPath(import.meta.url))
5
- export const packageRoot = resolve(currentDirectory, '..', '..')
6
- export const templatesDirectory = resolve(packageRoot, 'templates')
7
- export const blocksDirectory = resolve(templatesDirectory, 'blocks')
8
- export const componentsDirectory = resolve(templatesDirectory, 'components')
9
- export const collectionsDirectory = resolve(templatesDirectory, 'collections')
10
- export const templateDirectories = [
11
- { type: 'block', path: blocksDirectory },
12
- { type: 'component', path: componentsDirectory },
13
- { type: 'collection', path: collectionsDirectory },
1
+ import { dirname, resolve } from 'node:path'
2
+ import { fileURLToPath } from 'node:url'
3
+
4
+ const currentDirectory = dirname(fileURLToPath(import.meta.url))
5
+ export const packageRoot = resolve(currentDirectory, '..', '..')
6
+ export const templatesDirectory = resolve(packageRoot, 'templates')
7
+ export const blocksDirectory = resolve(templatesDirectory, 'blocks')
8
+ export const componentsDirectory = resolve(templatesDirectory, 'components')
9
+ export const collectionsDirectory = resolve(templatesDirectory, 'collections')
10
+ export const templateDirectories = [
11
+ { type: 'block', path: blocksDirectory },
12
+ { type: 'component', path: componentsDirectory },
13
+ { type: 'collection', path: collectionsDirectory },
14
14
  ]
@@ -0,0 +1,229 @@
1
+ 'use client'
2
+
3
+ import React, { useEffect, useRef, useState } from 'react'
4
+ import { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical'
5
+ import { ChevronDown, ChevronUp } from 'lucide-react'
6
+ import { type VariantProps, cva } from 'class-variance-authority'
7
+
8
+ import RichText from '@/components/RichText'
9
+ import { cn } from '@/utilities/ui'
10
+
11
+ type AccordionButtonVariant = 'default' | 'destructive' | 'v1' | 'v2' | 'v3' | 'v5' | 'v7'
12
+
13
+ const rippleCSS = `
14
+ .accordion-ripple-container { position: relative; overflow: hidden; }
15
+ .accordion-ripple-effect { position: absolute; border-radius: 50%; transform: scale(0); animation: accordion-ripple-animation 600ms linear; pointer-events: none; z-index: 10; }
16
+ @keyframes accordion-ripple-animation { to { transform: scale(4); opacity: 0; } }
17
+ `
18
+
19
+ const buttonAccordVariants = cva(
20
+ 'accordion-ripple-container inline-flex items-start justify-between whitespace-normal text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
21
+ {
22
+ defaultVariants: { variant: 'default' },
23
+ variants: {
24
+ variant: {
25
+ default:
26
+ 'ripple-default bg-primary text-stone-200 dark:text-stone-900 hover:shadow-md hover:color-accent will-change-transform',
27
+ destructive:
28
+ 'ripple-destructive bg-red-950/50 border border-red-500/50 text-stone-200 shadow-[inset_0_0_0_1px_rgba(239,68,68,0.6),inset_0_0_12px_rgba(239,68,68,0.8)] dark:text-stone-200 text-destructive-foreground hover:bg-destructive/90 will-change-transform',
29
+ v1: 'ripple-v1 border-[0.5px] text-stone-200 dark:text-stone-200 rounded-sm bg-transparent duration-200 hover:bg-primary shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] active:shadow-none border-stone-800 hover:text-zinc-200 dark:border-stone-600 dark:shadow-[3px_3px_0px_0px_var(--border-color)] active:dark:shadow-none dark:bg-zinc-950',
30
+ v2: 'ripple-v2 text-stone-200 dark:text-stone-900 group relative rounded-none overflow-hidden ease-in-out hover:scale-100 hover:shadow-lg bg-gradient-to-tr from-zinc-900 to-zinc-700 hover:shadow-zinc-500/30 dark:bg-gradient-to-tr dark:from-neutral-950 dark:to-neutral-900 dark:hover:shadow-zinc-700/30',
31
+ v3: 'ripple-v3 text-stone-200 dark:text-stone-900 relative overflow-hidden group ease-out bg-zinc-900 hover:bg-gradient-to-r hover:from-zinc-800 hover:to-zinc-700 dark:bg-zinc-50 dark:hover:from-zinc-50 dark:hover:to-zinc-100',
32
+ v5: 'ripple-v5 text-stone-200 dark:text-stone-200 relative overflow-hidden border shadow group invert-[1] border-stone-300 bg-zinc-50 dark:border-stone-700 dark:bg-zinc-950',
33
+ v7: "ripple-v7 text-stone-200 dark:text-stone-200 relative hover:no-underline px-[1px] pb-0 ease-in after:absolute after:bottom-[-2px] after:left-0 after:h-0.5 after:w-full after:translate-y-[3px] after:rounded-full after:dark:bg-zinc-50 after:bg-zinc-800 after:opacity-0 after:duration-300 after:content-[''] hover:after:-translate-y-1 hover:after:opacity-100"
34
+ }
35
+ }
36
+ }
37
+ )
38
+
39
+ interface ButtonAccordProps
40
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
41
+ VariantProps<typeof buttonAccordVariants> {}
42
+
43
+ const ButtonAccord = React.forwardRef<HTMLButtonElement, ButtonAccordProps>(function ButtonAccord(
44
+ { className, variant, onClick, children, ...props },
45
+ ref
46
+ ) {
47
+ useEffect(() => {
48
+ const style = document.createElement('style')
49
+ style.innerHTML = rippleCSS
50
+ document.head.appendChild(style)
51
+ return () => style.remove()
52
+ }, [])
53
+
54
+ const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
55
+ const button = event.currentTarget
56
+ const ripple = document.createElement('span')
57
+ const rect = button.getBoundingClientRect()
58
+
59
+ ripple.className = 'accordion-ripple-effect'
60
+ ripple.style.left = `${event.clientX - rect.left}px`
61
+ ripple.style.top = `${event.clientY - rect.top}px`
62
+ ripple.style.width = ripple.style.height = `${Math.max(rect.width, rect.height)}px`
63
+ ripple.style.backgroundColor = variant === 'destructive' ? 'rgba(255, 0, 0, 0.3)' : 'rgba(139, 92, 246, 0.45)'
64
+
65
+ button.appendChild(ripple)
66
+ ripple.addEventListener('animationend', () => ripple.remove())
67
+ onClick?.(event)
68
+ }
69
+
70
+ const content =
71
+ variant === 'v5' ? (
72
+ <>
73
+ <span className="absolute inset-0 !border-none rounded-none flex items-center justify-center size-full duration-700 -translate-x-full group-hover:translate-x-0 bg-zinc-800 dark:bg-zinc-100 text-zinc-100 dark:text-zinc-100" />
74
+ <span className="absolute flex items-center justify-center w-full h-full transition-all duration-500 ease-out transform group-hover:translate-x-full">
75
+ {children}
76
+ </span>
77
+ <span className="relative invisible">{children}</span>
78
+ </>
79
+ ) : variant === 'v2' || variant === 'v3' ? (
80
+ <>
81
+ <span className="relative flex w-full items-start justify-between">{children}</span>
82
+ <span
83
+ className="absolute inset-0 flex size-full justify-center [transform:skew(-14deg)_translateX(-100%)] group-hover:duration-1000 group-hover:[transform:skew(-14deg)_translateX(100%)]"
84
+ style={{ width: '200% !important' }}
85
+ aria-hidden="true"
86
+ >
87
+ <span className="relative h-full w-64 scale-200 bg-indigo-500/50 dark:bg-lime-500/50" />
88
+ </span>
89
+ </>
90
+ ) : (
91
+ <span className="relative flex w-full items-start justify-between">{children}</span>
92
+ )
93
+
94
+ return (
95
+ <button
96
+ ref={ref}
97
+ onClick={handleClick}
98
+ className={cn(buttonAccordVariants({ variant }), className)}
99
+ {...props}
100
+ >
101
+ {content}
102
+ </button>
103
+ )
104
+ })
105
+
106
+ const AccordionSeparator = ({ className }: { className?: string }) => (
107
+ <div className={cn('h-px w-full shrink-0 bg-border', className)} />
108
+ )
109
+
110
+ // Heading reset: all h1-h6 inside the title RichText inherit colour, stay at base (16px)
111
+ // size, break words, and get the content-block font-weight/margin treatment.
112
+ // Paragraph reset: remove prose-injected vertical margins.
113
+ const TITLE_CLS =
114
+ 'm-0 p-0 !mx-0 list-none text-left ' +
115
+ '[&_h1]:text-inherit [&_h2]:text-inherit [&_h3]:text-inherit ' +
116
+ '[&_h4]:text-inherit [&_h5]:text-inherit [&_h6]:text-inherit ' +
117
+ '[&_h1]:!text-base [&_h2]:!text-base [&_h3]:!text-base ' +
118
+ '[&_h4]:!text-base [&_h5]:!text-base [&_h6]:!text-base ' +
119
+ '[&_h1]:break-words [&_h2]:break-words [&_h3]:break-words ' +
120
+ '[&_h4]:break-words [&_h5]:break-words [&_h6]:break-words ' +
121
+ '[&_.content-block_h1]:font-[inherit] [&_.content-block_h2]:font-[inherit] ' +
122
+ '[&_.content-block_h3]:font-[inherit] [&_.content-block_h4]:font-[inherit] ' +
123
+ '[&_.content-block_h5]:font-[inherit] [&_.content-block_h6]:font-[inherit] ' +
124
+ '[&_.content-block_h1]:mt-[inherit] [&_.content-block_h2]:mt-[inherit] ' +
125
+ '[&_.content-block_h3]:mt-[inherit] [&_.content-block_h4]:mt-[inherit] ' +
126
+ '[&_.content-block_h5]:mt-[inherit] [&_.content-block_h6]:mt-[inherit] ' +
127
+ '[&_.content-block_h1]:mb-4 [&_.content-block_h2]:mb-4 [&_.content-block_h3]:mb-4 ' +
128
+ '[&_.content-block_h4]:mb-4 [&_.content-block_h5]:mb-4 [&_.content-block_h6]:mb-4 ' +
129
+ '[&_p]:!mt-0 [&_p]:!mb-0'
130
+
131
+ export interface AccordionItemData {
132
+ title: SerializedEditorState
133
+ content: SerializedEditorState
134
+ accordionId?: string
135
+ }
136
+
137
+ export interface AccordionBlockProps {
138
+ items: AccordionItemData[]
139
+ accordionId?: string
140
+ accordionButtonVariant?: AccordionButtonVariant
141
+ }
142
+
143
+ export const AccordionItem: React.FC<AccordionItemData & { buttonVariant?: AccordionButtonVariant }> = ({
144
+ title,
145
+ content,
146
+ accordionId,
147
+ buttonVariant = 'v2'
148
+ }) => {
149
+ const [isOpen, setIsOpen] = useState(false)
150
+ const [height, setHeight] = useState('0px')
151
+ const contentRef = useRef<HTMLDivElement>(null)
152
+
153
+ useEffect(() => {
154
+ if (contentRef.current) {
155
+ setHeight(isOpen ? `${contentRef.current.scrollHeight}px` : '0px')
156
+ }
157
+ }, [isOpen])
158
+
159
+ return (
160
+ <div
161
+ data-container-type="accordionItem"
162
+ className={`accordion-item max-w-full ${isOpen ? 'mb-4 shadow-2xl' : 'mb-0 shadow-md'}`}
163
+ id={accordionId}
164
+ >
165
+ <div className="accordion-title-button shadow-lg backdrop-blur-lg">
166
+ <ButtonAccord
167
+ suppressHydrationWarning
168
+ suppressContentEditableWarning
169
+ variant={buttonVariant}
170
+ className="flex w-full items-start justify-between p-4 backdrop-blur-[16px] brightness-100 duration-300 !whitespace-normal !break-words !h-auto hover:brightness-105 !outline-none !ring-0 !ring-offset-0"
171
+ onClick={() => setIsOpen(!isOpen)}
172
+ aria-expanded={isOpen}
173
+ aria-controls={`accordion-content-${accordionId}`}
174
+ type="button"
175
+ style={{ borderRadius: '0 !important' }}
176
+ >
177
+ <div className="accordion-title-inner flex-grow text-left break-words pr-8">
178
+ <RichText className={TITLE_CLS} data={title as any} enableGutter={false} />
179
+ </div>
180
+ {isOpen ? (
181
+ <ChevronUp
182
+ className="chevron-up-icon fixed right-2 top-1 mt-3 h-6 w-6 opacity-50 color-accent dark:text-[var(--color-alt)]"
183
+ style={{ color: 'var(--active)' }}
184
+ />
185
+ ) : (
186
+ <ChevronDown
187
+ className="chevron-down-icon fixed right-2 top-1 mt-3 h-6 w-6 opacity-50 color-accent dark:text-[var(--color-alt)]"
188
+ style={{ color: 'var(--active)' }}
189
+ />
190
+ )}
191
+ </ButtonAccord>
192
+ <AccordionSeparator className="accordion-separator dd-bg-50" />
193
+ <div
194
+ ref={contentRef}
195
+ id={`accordion-content-${accordionId}`}
196
+ style={{
197
+ height,
198
+ transition: 'height 0.3s ease'
199
+ }}
200
+ className="accordion-content-wrapper overflow-hidden"
201
+ >
202
+ <RichText
203
+ className="p-4 color-text bg-[rgba(159,159,159,0.18)]"
204
+ data={content as any}
205
+ enableGutter={false}
206
+ />
207
+ </div>
208
+ </div>
209
+ </div>
210
+ )
211
+ }
212
+
213
+ export const DDAccordion: React.FC<AccordionBlockProps> = ({ items, accordionButtonVariant = 'v2' }) => {
214
+ return (
215
+ <div className="accordion-container max-w-full">
216
+ {items.map((item, index) => (
217
+ <AccordionItem
218
+ key={item.accordionId || `accordion-item-${index}`}
219
+ title={item.title}
220
+ content={item.content}
221
+ accordionId={item.accordionId || `accordion-item-${index}`}
222
+ buttonVariant={accordionButtonVariant}
223
+ />
224
+ ))}
225
+ </div>
226
+ )
227
+ }
228
+
229
+ export default DDAccordion
@@ -0,0 +1,3 @@
1
+ # DD-Accordion
2
+
3
+ Portable first-pass conversion of AccordionBlock. The raw source referenced deferred ButtonMainDD and project UI primitives, so this template uses native details/summary markup.
@@ -0,0 +1,73 @@
1
+ import type { Block } from 'payload'
2
+
3
+ import { BlocksFeature } from '@payloadcms/richtext-lexical'
4
+
5
+ import { defaultLexical } from '@/fields/defaultLexical'
6
+
7
+ import { DDBanner } from '@/blocks/DD-Banner/config'
8
+ import { Code } from '@/blocks/Code/config'
9
+ import { MediaBlock } from '@/blocks/MediaBlock/config'
10
+ import { DDIconButton } from '../DD-IconButton/config'
11
+ import { DDAnimText } from '@/blocks/DD-AnimText/config'
12
+
13
+ export const DDAccordion: Block = {
14
+ slug: 'DD-Accordion',
15
+ interfaceName: 'DDAccordion',
16
+ labels: {
17
+ singular: 'Accordion Block',
18
+ plural: 'Accordion Blocks'
19
+ },
20
+ fields: [
21
+ {
22
+ name: 'accordionId',
23
+ type: 'text',
24
+ hidden: true,
25
+ label: 'Accordian ID',
26
+ required: false,
27
+ admin: {
28
+ description: 'Unique ID for the accordian block',
29
+ width: '50%'
30
+ }
31
+ },
32
+ {
33
+ name: 'accordionButtonVariant',
34
+ type: 'select',
35
+ label: 'Accordion Button Variant',
36
+ defaultValue: 'v2',
37
+ options: [
38
+ { label: 'Default', value: 'default' },
39
+ { label: 'Destructive', value: 'destructive' },
40
+ { label: 'Offset Shadow', value: 'v1' },
41
+ { label: 'Gradient Sheen', value: 'v2' },
42
+ { label: 'Contrast Sweep', value: 'v3' },
43
+ { label: 'Reveal Panel', value: 'v5' },
44
+ { label: 'Underline Accent', value: 'v7' }
45
+ ],
46
+ admin: {
47
+ description: 'Selects the local ButtonAccord visual treatment for every accordion title button.',
48
+ width: '50%'
49
+ }
50
+ }, {
51
+ name: 'items',
52
+ type: 'array',
53
+ label: 'Accordion Items',
54
+ required: true,
55
+ fields: [
56
+ {
57
+ name: 'title',
58
+ label: 'Accordian Title',
59
+ type: 'richText',
60
+ editor: defaultLexical,
61
+ required: false
62
+ },
63
+ {
64
+ name: 'content',
65
+ label: 'Accordian Content',
66
+ type: 'richText',
67
+ editor: defaultLexical,
68
+ required: false
69
+ }
70
+ ]
71
+ }
72
+ ]
73
+ }
@@ -0,0 +1,75 @@
1
+ {
2
+ "type": "block",
3
+ "name": "DD-Accordion",
4
+ "label": "Accordion",
5
+ "sourceName": "AccordionBlock",
6
+ "portableName": "DD-Accordion",
7
+ "slug": "DD-Accordion",
8
+ "version": "0.0.1",
9
+ "source": {
10
+ "repo": "Hadizainal/DesignsDustedv3",
11
+ "originalPath": "src/blocks/AccordionBlock",
12
+ "originalSlug": "accordion",
13
+ "originalConfigExport": "AccordionBlock",
14
+ "originalComponentExport": "AccordionBlock",
15
+ "originalInterfaceName": "DDAccordion"
16
+ },
17
+ "files": [
18
+ {
19
+ "from": "Component.tsx",
20
+ "to": "src/blocks/DD-Accordion/Component.tsx"
21
+ },
22
+ {
23
+ "from": "config.ts",
24
+ "to": "src/blocks/DD-Accordion/config.ts"
25
+ }
26
+ ],
27
+ "dependencies": [
28
+ "lucide-react",
29
+ "class-variance-authority"
30
+ ],
31
+ "sharedFiles": [],
32
+ "requiredProjectFiles": [],
33
+ "optionalProjectFiles": [],
34
+ "collectionRegistration": {
35
+ "enabled": true,
36
+ "collections": [
37
+ "Pages",
38
+ "Posts"
39
+ ]
40
+ },
41
+ "renderBlocksRegistration": {
42
+ "enabled": true
43
+ },
44
+ "renderBlocksBehavior": {
45
+ "wrapperless": false
46
+ },
47
+ "pageRouteIntegration": {
48
+ "required": false,
49
+ "manualSteps": []
50
+ },
51
+ "manual": [
52
+ "Register DDAccordion in Pages/Posts blocks arrays if automatic registration was skipped.",
53
+ "Register DD-Accordion in RenderBlocks if automatic registration was skipped.",
54
+ "Run payload generate:types after schema changes."
55
+ ],
56
+ "manualSteps": [
57
+ "Register DDAccordion in Pages/Posts blocks arrays if automatic registration was skipped.",
58
+ "Register DD-Accordion in RenderBlocks if automatic registration was skipped.",
59
+ "Run payload generate:types after schema changes."
60
+ ],
61
+ "patchTargets": {
62
+ "blockConfigRegistration": {
63
+ "description": "Installer can add import { DDAccordion } from '@/blocks/DD-Accordion/config' and add DDAccordion to clear Pages/Posts block arrays."
64
+ },
65
+ "renderBlocksRegistration": {
66
+ "description": "Installer can register DD-Accordion in RenderBlocks."
67
+ }
68
+ },
69
+ "notes": [
70
+ "Accordion uses inline ButtonAccord and AccordionSeparator so it does not install shared button or separator files.",
71
+ "Title RichText supports animated text and banner blocks only to avoid nested button hydration issues."
72
+ ],
73
+ "exportName": "DDAccordion",
74
+ "interfaceName": "DDAccordion"
75
+ }