@pro-laico/create-atomic-payload 0.1.4

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 (423) hide show
  1. package/bin/cli.js +159 -0
  2. package/package.json +29 -0
  3. package/template/.env.example +35 -0
  4. package/template/.gitattributes +2 -0
  5. package/template/.prettierrc.json +6 -0
  6. package/template/.vscode/extensions.json +3 -0
  7. package/template/.vscode/launch.json +24 -0
  8. package/template/.vscode/settings.json +86 -0
  9. package/template/.yarnrc +1 -0
  10. package/template/LICENSE.md +22 -0
  11. package/template/README.md +128 -0
  12. package/template/eslint.config.mjs +32 -0
  13. package/template/next-env.d.ts +6 -0
  14. package/template/next.config.ts +36 -0
  15. package/template/package.json +75 -0
  16. package/template/public/adminFavicon.svg +1 -0
  17. package/template/public/ogImage.webp +0 -0
  18. package/template/src/access/anyone.ts +3 -0
  19. package/template/src/access/authenticated.ts +7 -0
  20. package/template/src/access/authenticatedOrPublished.ts +6 -0
  21. package/template/src/app/(frontend)/[...slug]/page.tsx +48 -0
  22. package/template/src/app/(frontend)/layout.tsx +49 -0
  23. package/template/src/app/(frontend)/next/exit-preview/route.ts +7 -0
  24. package/template/src/app/(frontend)/next/preview/route.ts +45 -0
  25. package/template/src/app/(frontend)/next/seed/route.ts +31 -0
  26. package/template/src/app/(frontend)/not-found.tsx +93 -0
  27. package/template/src/app/(frontend)/page.tsx +5 -0
  28. package/template/src/app/(frontend)/sitemap.ts +14 -0
  29. package/template/src/app/(payload)/admin/[[...segments]]/not-found.tsx +24 -0
  30. package/template/src/app/(payload)/admin/[[...segments]]/page.tsx +24 -0
  31. package/template/src/app/(payload)/admin/importMap.js +85 -0
  32. package/template/src/app/(payload)/api/[...slug]/route.ts +19 -0
  33. package/template/src/app/(payload)/custom.scss +29 -0
  34. package/template/src/app/(payload)/layout.tsx +31 -0
  35. package/template/src/blocks/actions/blocks.ts +27 -0
  36. package/template/src/blocks/actions/cookieConsent/set/block.ts +17 -0
  37. package/template/src/blocks/actions/cookieConsent/set/filter.ts +3 -0
  38. package/template/src/blocks/actions/cookieConsent/set/options.ts +35 -0
  39. package/template/src/blocks/actions/cookieConsent/toDA/block.ts +14 -0
  40. package/template/src/blocks/actions/cookieConsent/toDA/filter.ts +3 -0
  41. package/template/src/blocks/actions/cookieConsent/toDA/options.ts +19 -0
  42. package/template/src/blocks/actions/dynamicStore/boolean/set/block.ts +15 -0
  43. package/template/src/blocks/actions/dynamicStore/boolean/set/filter.ts +4 -0
  44. package/template/src/blocks/actions/dynamicStore/boolean/set/options.ts +18 -0
  45. package/template/src/blocks/actions/dynamicStore/boolean/toDA/block.ts +10 -0
  46. package/template/src/blocks/actions/dynamicStore/boolean/toDA/filter.ts +3 -0
  47. package/template/src/blocks/actions/dynamicStore/boolean/toDA/options.ts +12 -0
  48. package/template/src/blocks/actions/dynamicStore/text/cycle/block.ts +41 -0
  49. package/template/src/blocks/actions/dynamicStore/text/cycle/filter.ts +4 -0
  50. package/template/src/blocks/actions/dynamicStore/text/cycle/options.ts +23 -0
  51. package/template/src/blocks/actions/dynamicStore/text/toDA/block.ts +10 -0
  52. package/template/src/blocks/actions/dynamicStore/text/toDA/filter.ts +3 -0
  53. package/template/src/blocks/actions/dynamicStore/text/toDA/options.ts +12 -0
  54. package/template/src/blocks/actions/filters.ts +27 -0
  55. package/template/src/blocks/actions/form/errorToDA/block.ts +18 -0
  56. package/template/src/blocks/actions/form/errorToDA/filter.ts +3 -0
  57. package/template/src/blocks/actions/form/errorToDA/options.ts +15 -0
  58. package/template/src/blocks/actions/form/reset/block.ts +18 -0
  59. package/template/src/blocks/actions/form/reset/filter.ts +3 -0
  60. package/template/src/blocks/actions/form/reset/options.ts +30 -0
  61. package/template/src/blocks/actions/form/statusToDA/block.ts +12 -0
  62. package/template/src/blocks/actions/form/statusToDA/filter.ts +3 -0
  63. package/template/src/blocks/actions/form/statusToDA/options.ts +15 -0
  64. package/template/src/blocks/actions/form/submit/block.ts +18 -0
  65. package/template/src/blocks/actions/form/submit/filter.ts +3 -0
  66. package/template/src/blocks/actions/form/submit/options.ts +35 -0
  67. package/template/src/blocks/actions/portal/set/block.ts +25 -0
  68. package/template/src/blocks/actions/portal/set/filter.ts +3 -0
  69. package/template/src/blocks/actions/portal/set/options.ts +43 -0
  70. package/template/src/blocks/actions/processor.ts +263 -0
  71. package/template/src/blocks/actions/theme/set/block.ts +10 -0
  72. package/template/src/blocks/actions/theme/set/filter.ts +3 -0
  73. package/template/src/blocks/actions/theme/set/options.ts +9 -0
  74. package/template/src/blocks/actions/zap.ts +4 -0
  75. package/template/src/blocks/children/atomic/block.ts +123 -0
  76. package/template/src/blocks/children/atomic/controlBar.ts +43 -0
  77. package/template/src/blocks/children/atomic/variants/button/typeField.ts +16 -0
  78. package/template/src/blocks/children/atomic/variants/button/variants/link/component.client.tsx +21 -0
  79. package/template/src/blocks/children/atomic/variants/button/variants/link/component.tsx +13 -0
  80. package/template/src/blocks/children/atomic/variants/button/variants/link/controlBar.ts +73 -0
  81. package/template/src/blocks/children/atomic/variants/button/variants/link/settings.ts +26 -0
  82. package/template/src/blocks/children/atomic/variants/button/variants/portal/controlBar.ts +35 -0
  83. package/template/src/blocks/children/atomic/variants/button/variants/portal/dialog/component.tsx +36 -0
  84. package/template/src/blocks/children/atomic/variants/button/variants/portal/dialog/settings.ts +24 -0
  85. package/template/src/blocks/children/atomic/variants/button/variants/portal/popover/component.tsx +41 -0
  86. package/template/src/blocks/children/atomic/variants/button/variants/portal/popover/settings.ts +111 -0
  87. package/template/src/blocks/children/atomic/variants/button/variants/regular/component.client.tsx +19 -0
  88. package/template/src/blocks/children/atomic/variants/button/variants/regular/component.tsx +11 -0
  89. package/template/src/blocks/children/atomic/variants/form/component.tsx +18 -0
  90. package/template/src/blocks/children/atomic/variants/form/controlBar.ts +22 -0
  91. package/template/src/blocks/children/atomic/variants/form/settings.ts +20 -0
  92. package/template/src/blocks/children/atomic/variants/input/autoCompleteOptions.ts +51 -0
  93. package/template/src/blocks/children/atomic/variants/input/controlBar.ts +13 -0
  94. package/template/src/blocks/children/atomic/variants/input/settings.ts +35 -0
  95. package/template/src/blocks/children/atomic/variants/input/typeField.ts +23 -0
  96. package/template/src/blocks/children/atomic/variants/input/variants/checkBox/component.client.tsx +12 -0
  97. package/template/src/blocks/children/atomic/variants/input/variants/checkBox/component.tsx +6 -0
  98. package/template/src/blocks/children/atomic/variants/input/variants/checkBox/settings.ts +9 -0
  99. package/template/src/blocks/children/atomic/variants/input/variants/number/component.client.tsx +12 -0
  100. package/template/src/blocks/children/atomic/variants/input/variants/number/component.tsx +6 -0
  101. package/template/src/blocks/children/atomic/variants/input/variants/number/settings.ts +9 -0
  102. package/template/src/blocks/children/atomic/variants/input/variants/radio/component.client.tsx +12 -0
  103. package/template/src/blocks/children/atomic/variants/input/variants/radio/component.tsx +6 -0
  104. package/template/src/blocks/children/atomic/variants/input/variants/radio/settings.ts +9 -0
  105. package/template/src/blocks/children/atomic/variants/input/variants/text/component.client.tsx +12 -0
  106. package/template/src/blocks/children/atomic/variants/input/variants/text/component.tsx +7 -0
  107. package/template/src/blocks/children/atomic/variants/input/variants/text/settings.ts +12 -0
  108. package/template/src/blocks/children/atomic/variants/tag/component.client.tsx +17 -0
  109. package/template/src/blocks/children/atomic/variants/tag/component.tsx +13 -0
  110. package/template/src/blocks/children/atomic/variants/tag/controlBar.ts +6 -0
  111. package/template/src/blocks/children/atomic/variants/tag/settings.ts +9 -0
  112. package/template/src/blocks/children/blocks.ts +13 -0
  113. package/template/src/blocks/children/icon/block.ts +41 -0
  114. package/template/src/blocks/children/icon/component.tsx +17 -0
  115. package/template/src/blocks/children/image/block.ts +80 -0
  116. package/template/src/blocks/children/image/component.tsx +21 -0
  117. package/template/src/blocks/children/richText/block.ts +50 -0
  118. package/template/src/blocks/children/richText/component/converters/index.tsx +10 -0
  119. package/template/src/blocks/children/richText/component/converters/internalLink.tsx +8 -0
  120. package/template/src/blocks/children/richText/component/index.tsx +10 -0
  121. package/template/src/blocks/children/richText/component.tsx +7 -0
  122. package/template/src/blocks/children/richText/defaultLexical.ts +65 -0
  123. package/template/src/blocks/children/simpleText/block.ts +41 -0
  124. package/template/src/blocks/children/simpleText/component.client.tsx +18 -0
  125. package/template/src/blocks/children/simpleText/component.tsx +11 -0
  126. package/template/src/blocks/children/svg/block.ts +39 -0
  127. package/template/src/blocks/children/svg/component.tsx +6 -0
  128. package/template/src/blocks/children/video/block.ts +70 -0
  129. package/template/src/blocks/children/video/component.tsx +11 -0
  130. package/template/src/blocks/children/zap.ts +54 -0
  131. package/template/src/blocks/submitForm/form/rateLimiting/blocks.ts +5 -0
  132. package/template/src/blocks/submitForm/form/rateLimiting/functions.ts +1 -0
  133. package/template/src/blocks/submitForm/form/rateLimiting/simpleSlidingWindow/block.ts +23 -0
  134. package/template/src/blocks/submitForm/form/rateLimiting/simpleSlidingWindow/serverFunction.ts +46 -0
  135. package/template/src/blocks/submitForm/form/sanitation/blocks.ts +6 -0
  136. package/template/src/blocks/submitForm/form/sanitation/combineTwoFields/block.ts +19 -0
  137. package/template/src/blocks/submitForm/form/sanitation/combineTwoFields/serverFunction.ts +22 -0
  138. package/template/src/blocks/submitForm/form/sanitation/functions.ts +1 -0
  139. package/template/src/blocks/submitForm/form/validation/blocks.ts +6 -0
  140. package/template/src/blocks/submitForm/form/validation/functions.ts +1 -0
  141. package/template/src/blocks/submitForm/form/validation/isUnique/block.ts +19 -0
  142. package/template/src/blocks/submitForm/form/validation/isUnique/serverFunction.ts +40 -0
  143. package/template/src/blocks/submitForm/form/zap.ts +8 -0
  144. package/template/src/blocks/submitForm/formProcessor.ts +222 -0
  145. package/template/src/blocks/submitForm/input/sanitation/blocks.ts +5 -0
  146. package/template/src/blocks/submitForm/input/sanitation/functions.ts +1 -0
  147. package/template/src/blocks/submitForm/input/sanitation/trimText/block.ts +24 -0
  148. package/template/src/blocks/submitForm/input/sanitation/trimText/serverFunction.ts +63 -0
  149. package/template/src/blocks/submitForm/input/useOn.ts +8 -0
  150. package/template/src/blocks/submitForm/input/validation/blocks.ts +6 -0
  151. package/template/src/blocks/submitForm/input/validation/contains/block.ts +12 -0
  152. package/template/src/blocks/submitForm/input/validation/contains/serverFunction.ts +23 -0
  153. package/template/src/blocks/submitForm/input/validation/doesNotContain/block.ts +12 -0
  154. package/template/src/blocks/submitForm/input/validation/doesNotContain/serverFunction.ts +23 -0
  155. package/template/src/blocks/submitForm/input/validation/functions.ts +2 -0
  156. package/template/src/blocks/submitForm/input/zap.ts +6 -0
  157. package/template/src/blocks/submitForm/serverFunction.ts +42 -0
  158. package/template/src/collections/designSets/collection.ts +44 -0
  159. package/template/src/collections/designSets/defaults.ts +20 -0
  160. package/template/src/collections/designSets/tabs/animation.ts +71 -0
  161. package/template/src/collections/designSets/tabs/colors.ts +31 -0
  162. package/template/src/collections/designSets/tabs/fonts.ts +53 -0
  163. package/template/src/collections/designSets/tabs/miscellaneous.ts +22 -0
  164. package/template/src/collections/designSets/tabs/prose.ts +151 -0
  165. package/template/src/collections/designSets/tabs/settings.ts +52 -0
  166. package/template/src/collections/designSets/tabs/sizes.ts +30 -0
  167. package/template/src/collections/designSets/tabs/storage.ts +51 -0
  168. package/template/src/collections/designSets/tabs/variables.ts +28 -0
  169. package/template/src/collections/favicons.ts +11 -0
  170. package/template/src/collections/fonts/collection.ts +20 -0
  171. package/template/src/collections/fonts/script.ts +199 -0
  172. package/template/src/collections/footers/collection.ts +48 -0
  173. package/template/src/collections/footers/component.tsx +13 -0
  174. package/template/src/collections/headers/collection.ts +47 -0
  175. package/template/src/collections/headers/component.tsx +13 -0
  176. package/template/src/collections/iconSets/collection.ts +80 -0
  177. package/template/src/collections/iconSets/defaults.ts +81 -0
  178. package/template/src/collections/icons.ts +20 -0
  179. package/template/src/collections/images.ts +29 -0
  180. package/template/src/collections/index.ts +17 -0
  181. package/template/src/collections/muxVideos.ts +13 -0
  182. package/template/src/collections/pages/collection.ts +88 -0
  183. package/template/src/collections/pages/tabs/SEO.ts +70 -0
  184. package/template/src/collections/pages/tabs/settings.ts +17 -0
  185. package/template/src/collections/posthogProperty.ts +48 -0
  186. package/template/src/collections/shortcutSets/collection.ts +30 -0
  187. package/template/src/collections/shortcutSets/defaults.ts +1 -0
  188. package/template/src/collections/shortcutSets/protectedNames.ts +135 -0
  189. package/template/src/collections/shortcutSets/tabs/settings.ts +13 -0
  190. package/template/src/collections/shortcutSets/tabs/shortcuts.ts +70 -0
  191. package/template/src/collections/users.ts +11 -0
  192. package/template/src/collections/zap.ts +59 -0
  193. package/template/src/components/child/SSRProps.ts +381 -0
  194. package/template/src/components/child/renderChildren.tsx +148 -0
  195. package/template/src/components/livePreviewListener.tsx +10 -0
  196. package/template/src/components/providers/formProvider.tsx +11 -0
  197. package/template/src/components/providers/tracking/gtm.tsx +11 -0
  198. package/template/src/components/providers/tracking/index.tsx +46 -0
  199. package/template/src/components/providers/tracking/postHog.tsx +41 -0
  200. package/template/src/components/providers/tracking/vercel.tsx +10 -0
  201. package/template/src/components/toast/index.module.css +142 -0
  202. package/template/src/components/toast/index.tsx +55 -0
  203. package/template/src/endpoints/seed/backendForm.ts +48 -0
  204. package/template/src/endpoints/seed/designSet.ts +476 -0
  205. package/template/src/endpoints/seed/footer.ts +389 -0
  206. package/template/src/endpoints/seed/header.ts +3511 -0
  207. package/template/src/endpoints/seed/iconSet.ts +19 -0
  208. package/template/src/endpoints/seed/icons/assets/check.svg +4 -0
  209. package/template/src/endpoints/seed/icons/assets/close.svg +4 -0
  210. package/template/src/endpoints/seed/icons/assets/cookie.svg +7 -0
  211. package/template/src/endpoints/seed/icons/assets/github.svg +1 -0
  212. package/template/src/endpoints/seed/icons/assets/logo.svg +11 -0
  213. package/template/src/endpoints/seed/icons/assets/menu.svg +4 -0
  214. package/template/src/endpoints/seed/icons/assets/theme.svg +4 -0
  215. package/template/src/endpoints/seed/icons/check.ts +14 -0
  216. package/template/src/endpoints/seed/icons/close.ts +14 -0
  217. package/template/src/endpoints/seed/icons/cookie.ts +14 -0
  218. package/template/src/endpoints/seed/icons/github.ts +14 -0
  219. package/template/src/endpoints/seed/icons/index.ts +7 -0
  220. package/template/src/endpoints/seed/icons/logo.ts +14 -0
  221. package/template/src/endpoints/seed/icons/menu.ts +14 -0
  222. package/template/src/endpoints/seed/icons/theme.ts +14 -0
  223. package/template/src/endpoints/seed/index.ts +100 -0
  224. package/template/src/endpoints/seed/pages/home.ts +858 -0
  225. package/template/src/endpoints/seed/pages/index.ts +4 -0
  226. package/template/src/endpoints/seed/pages/notFoundPage.ts +287 -0
  227. package/template/src/endpoints/seed/pages/prose.ts +1436 -0
  228. package/template/src/endpoints/seed/pages/testing.ts +2181 -0
  229. package/template/src/endpoints/seed/shortcutSet.ts +187 -0
  230. package/template/src/endpoints/seed/siteMetaData.ts +10 -0
  231. package/template/src/fields/actions/changeKey.ts +12 -0
  232. package/template/src/fields/actions/index.ts +6 -0
  233. package/template/src/fields/actions/initialValueCheckbox.ts +14 -0
  234. package/template/src/fields/actions/keyText.ts +10 -0
  235. package/template/src/fields/actions/persisted.ts +14 -0
  236. package/template/src/fields/actions/setData.ts +20 -0
  237. package/template/src/fields/actions/strict/index.ts +3 -0
  238. package/template/src/fields/actions/strict/keySelect.ts +28 -0
  239. package/template/src/fields/actions/strict/listenSelect.ts +28 -0
  240. package/template/src/fields/actions/strict/performSelect.ts +30 -0
  241. package/template/src/fields/actions/strict/registry/cookieConsent.ts +14 -0
  242. package/template/src/fields/actions/strict/registry/index.ts +6 -0
  243. package/template/src/fields/actions/strict/registry/theme.ts +9 -0
  244. package/template/src/fields/active.ts +16 -0
  245. package/template/src/fields/apf/index.ts +69 -0
  246. package/template/src/fields/apf/storage.ts +38 -0
  247. package/template/src/fields/blocks/actions.ts +30 -0
  248. package/template/src/fields/blocks/backdropChildren.ts +11 -0
  249. package/template/src/fields/blocks/children.ts +15 -0
  250. package/template/src/fields/blocks/submitForm/form.ts +24 -0
  251. package/template/src/fields/blocks/submitForm/input.ts +25 -0
  252. package/template/src/fields/className.ts +26 -0
  253. package/template/src/fields/coloredEnd.ts +5 -0
  254. package/template/src/fields/defaultOpen.ts +14 -0
  255. package/template/src/fields/designSets/value.ts +80 -0
  256. package/template/src/fields/devMode.ts +11 -0
  257. package/template/src/fields/favicon.ts +18 -0
  258. package/template/src/fields/for.ts +11 -0
  259. package/template/src/fields/keepMounted.ts +11 -0
  260. package/template/src/fields/modal.ts +16 -0
  261. package/template/src/fields/slug.ts +35 -0
  262. package/template/src/fields/staticDataAttributes.ts +29 -0
  263. package/template/src/fields/tabs/block/children/actions.ts +49 -0
  264. package/template/src/fields/tabs/block/children/backdrop.ts +17 -0
  265. package/template/src/fields/tabs/block/children/settings.ts +45 -0
  266. package/template/src/fields/tabs/block/children/submitForm/form.ts +23 -0
  267. package/template/src/fields/tabs/block/children/submitForm/input.ts +14 -0
  268. package/template/src/fields/tabs/block/children/tracking.ts +25 -0
  269. package/template/src/fields/tabs/collection/storage.ts +55 -0
  270. package/template/src/fields/tagType.ts +32 -0
  271. package/template/src/fields/testPath.ts +3 -0
  272. package/template/src/fields/uniqueTitle.ts +8 -0
  273. package/template/src/fields/validationMessage.ts +13 -0
  274. package/template/src/globals/index.ts +8 -0
  275. package/template/src/globals/settings.ts +36 -0
  276. package/template/src/globals/siteMetaData.ts +29 -0
  277. package/template/src/globals/storage.ts +15 -0
  278. package/template/src/globals/tracking/global.ts +25 -0
  279. package/template/src/globals/tracking/tabs/gtm.ts +18 -0
  280. package/template/src/globals/tracking/tabs/postHog.ts +35 -0
  281. package/template/src/hooks/collection/atomicHook/atomicHook.ts +223 -0
  282. package/template/src/hooks/collection/atomicHook/processors/cssProcessor.ts +60 -0
  283. package/template/src/hooks/collection/atomicHook/processors/processDesignSet/generatePreflights.ts +36 -0
  284. package/template/src/hooks/collection/atomicHook/processors/processDesignSet/index.ts +176 -0
  285. package/template/src/hooks/collection/atomicHook/processors/unsetActive.ts +24 -0
  286. package/template/src/hooks/collection/formatSVG.ts +157 -0
  287. package/template/src/hooks/collection/revalidate.ts +53 -0
  288. package/template/src/hooks/collection/sanitizeCollection.ts +5 -0
  289. package/template/src/hooks/field/apf.ts +59 -0
  290. package/template/src/hooks/field/formatSlug.ts +23 -0
  291. package/template/src/hooks/field/href.ts +6 -0
  292. package/template/src/hooks/field/publishedAt.ts +5 -0
  293. package/template/src/hooks/frontEnd/atomicStore/create.ts +69 -0
  294. package/template/src/hooks/frontEnd/atomicStore/index.tsx +20 -0
  295. package/template/src/hooks/frontEnd/atomicStore/slices/base.ts +7 -0
  296. package/template/src/hooks/frontEnd/atomicStore/slices/consent.ts +76 -0
  297. package/template/src/hooks/frontEnd/atomicStore/slices/dynamic.ts +51 -0
  298. package/template/src/hooks/frontEnd/useActions/dispatch/attributer/boolToDA/function.ts +14 -0
  299. package/template/src/hooks/frontEnd/useActions/dispatch/attributer/boolToDA/zap.ts +12 -0
  300. package/template/src/hooks/frontEnd/useActions/dispatch/attributer/cCToDA/function.ts +34 -0
  301. package/template/src/hooks/frontEnd/useActions/dispatch/attributer/cCToDA/zap.ts +17 -0
  302. package/template/src/hooks/frontEnd/useActions/dispatch/attributer/errorToDA/function.ts +22 -0
  303. package/template/src/hooks/frontEnd/useActions/dispatch/attributer/errorToDA/zap.ts +10 -0
  304. package/template/src/hooks/frontEnd/useActions/dispatch/attributer/function.ts +20 -0
  305. package/template/src/hooks/frontEnd/useActions/dispatch/attributer/statusToDA/function.ts +24 -0
  306. package/template/src/hooks/frontEnd/useActions/dispatch/attributer/statusToDA/zap.ts +10 -0
  307. package/template/src/hooks/frontEnd/useActions/dispatch/attributer/textToDA/function.ts +21 -0
  308. package/template/src/hooks/frontEnd/useActions/dispatch/attributer/textToDA/zap.ts +12 -0
  309. package/template/src/hooks/frontEnd/useActions/dispatch/attributer/zap.ts +15 -0
  310. package/template/src/hooks/frontEnd/useActions/dispatch/index.ts +2 -0
  311. package/template/src/hooks/frontEnd/useActions/dispatch/runner/cycleText/function.ts +30 -0
  312. package/template/src/hooks/frontEnd/useActions/dispatch/runner/cycleText/zap.ts +12 -0
  313. package/template/src/hooks/frontEnd/useActions/dispatch/runner/function.ts +21 -0
  314. package/template/src/hooks/frontEnd/useActions/dispatch/runner/resetForm/function.ts +7 -0
  315. package/template/src/hooks/frontEnd/useActions/dispatch/runner/resetForm/zap.ts +9 -0
  316. package/template/src/hooks/frontEnd/useActions/dispatch/runner/setBool/function.ts +10 -0
  317. package/template/src/hooks/frontEnd/useActions/dispatch/runner/setBool/zap.ts +11 -0
  318. package/template/src/hooks/frontEnd/useActions/dispatch/runner/setCCs/function.ts +33 -0
  319. package/template/src/hooks/frontEnd/useActions/dispatch/runner/setCCs/zap.ts +14 -0
  320. package/template/src/hooks/frontEnd/useActions/dispatch/runner/setThemes/function.ts +11 -0
  321. package/template/src/hooks/frontEnd/useActions/dispatch/runner/setThemes/zap.ts +10 -0
  322. package/template/src/hooks/frontEnd/useActions/dispatch/runner/submitForm/function.ts +32 -0
  323. package/template/src/hooks/frontEnd/useActions/dispatch/runner/submitForm/zap.ts +9 -0
  324. package/template/src/hooks/frontEnd/useActions/dispatch/runner/zap.ts +16 -0
  325. package/template/src/hooks/frontEnd/useActions/dispatch/zap.ts +2 -0
  326. package/template/src/hooks/frontEnd/useActions/index.ts +6 -0
  327. package/template/src/hooks/frontEnd/useActions/useActionContext.ts +21 -0
  328. package/template/src/hooks/frontEnd/useActions/useButtonActions.ts +17 -0
  329. package/template/src/hooks/frontEnd/useActions/useDaToText.ts +34 -0
  330. package/template/src/hooks/frontEnd/useActions/useForm.ts +114 -0
  331. package/template/src/hooks/frontEnd/useActions/usePortal.ts +33 -0
  332. package/template/src/hooks/frontEnd/useActions/useToDa.ts +12 -0
  333. package/template/src/hooks/global/revalidate.ts +26 -0
  334. package/template/src/payload.config.ts +78 -0
  335. package/template/src/plugins/blurDataUrls.ts +8 -0
  336. package/template/src/plugins/formBuilder.ts +40 -0
  337. package/template/src/plugins/index.ts +17 -0
  338. package/template/src/plugins/muxVideo.ts +13 -0
  339. package/template/src/plugins/nestedDocs.ts +9 -0
  340. package/template/src/plugins/vercelBlobStorage.ts +8 -0
  341. package/template/src/ts/JSONSchema.ts +93 -0
  342. package/template/src/ts/declarations.ts +24 -0
  343. package/template/src/ts/types/actions.ts +175 -0
  344. package/template/src/ts/types/apf.ts +108 -0
  345. package/template/src/ts/types/cache.ts +166 -0
  346. package/template/src/ts/types/css.ts +14 -0
  347. package/template/src/ts/types/forms.ts +214 -0
  348. package/template/src/ts/types/frontEnd.ts +115 -0
  349. package/template/src/ts/types/index.ts +49 -0
  350. package/template/src/ts/types/payload-types.ts +3684 -0
  351. package/template/src/ts/zap/ap.ts +82 -0
  352. package/template/src/ts/zap/index.ts +4 -0
  353. package/template/src/ui/apf/controls.tsx +88 -0
  354. package/template/src/ui/apf/field.tsx +81 -0
  355. package/template/src/ui/apf/index.scss +59 -0
  356. package/template/src/ui/apf/label.tsx +23 -0
  357. package/template/src/ui/assets/Icon.tsx +21 -0
  358. package/template/src/ui/assets/Logo.tsx +21 -0
  359. package/template/src/ui/assets/atomicIcon.tsx +27 -0
  360. package/template/src/ui/assets/warningIcon.ts +6 -0
  361. package/template/src/ui/blocks/actionBlock.tsx +44 -0
  362. package/template/src/ui/blocks/inputBlock.tsx +24 -0
  363. package/template/src/ui/decorative/coloredEnd.tsx +16 -0
  364. package/template/src/ui/decorative/index.scss +46 -0
  365. package/template/src/ui/fields/iconSelect/index.tsx +19 -0
  366. package/template/src/ui/fields/slug/index.scss +12 -0
  367. package/template/src/ui/fields/slug/index.tsx +72 -0
  368. package/template/src/ui/index.ts +32 -0
  369. package/template/src/ui/root/beforeDashboard/index.scss +22 -0
  370. package/template/src/ui/root/beforeDashboard/index.tsx +39 -0
  371. package/template/src/ui/root/beforeDashboard/seedButton/index.scss +12 -0
  372. package/template/src/ui/root/beforeDashboard/seedButton/index.tsx +84 -0
  373. package/template/src/ui/root/siteTriggers/index.scss +22 -0
  374. package/template/src/ui/root/siteTriggers/index.tsx +94 -0
  375. package/template/src/ui/root/siteTriggers/triggerVercelDeploy.ts +37 -0
  376. package/template/src/ui/rowLabels/animation.tsx +27 -0
  377. package/template/src/ui/rowLabels/atomic/index.scss +62 -0
  378. package/template/src/ui/rowLabels/atomic/index.tsx +96 -0
  379. package/template/src/ui/rowLabels/color.tsx +33 -0
  380. package/template/src/ui/rowLabels/designToken.tsx +30 -0
  381. package/template/src/ui/rowLabels/icon.tsx +32 -0
  382. package/template/src/ui/rowLabels/shortcut/index.scss +21 -0
  383. package/template/src/ui/rowLabels/shortcut/index.tsx +30 -0
  384. package/template/src/ui/rowLabels/simpleText.tsx +41 -0
  385. package/template/src/utilities/deepMerge.ts +30 -0
  386. package/template/src/utilities/extractSVG.ts +9 -0
  387. package/template/src/utilities/format/toKebabCase.ts +79 -0
  388. package/template/src/utilities/format/toTitleCase.ts +47 -0
  389. package/template/src/utilities/formatDurationWithTokens.ts +56 -0
  390. package/template/src/utilities/generateMetaData.ts +45 -0
  391. package/template/src/utilities/generatePreviewPath.ts +43 -0
  392. package/template/src/utilities/get/cache/getAtomicActions.ts +48 -0
  393. package/template/src/utilities/get/cache/getAtomicClasses.ts +20 -0
  394. package/template/src/utilities/get/cache/getDesignSet.ts +15 -0
  395. package/template/src/utilities/get/cache/getFooter.ts +17 -0
  396. package/template/src/utilities/get/cache/getFormSubmissions.ts +17 -0
  397. package/template/src/utilities/get/cache/getForms.ts +43 -0
  398. package/template/src/utilities/get/cache/getHeader.ts +17 -0
  399. package/template/src/utilities/get/cache/getIcon.ts +51 -0
  400. package/template/src/utilities/get/cache/getImage.ts +20 -0
  401. package/template/src/utilities/get/cache/getPage.ts +35 -0
  402. package/template/src/utilities/get/cache/getPages.ts +24 -0
  403. package/template/src/utilities/get/cache/getShortcutSet.ts +17 -0
  404. package/template/src/utilities/get/cache/getSiteCSS.ts +17 -0
  405. package/template/src/utilities/get/cache/getSiteMetadata.ts +14 -0
  406. package/template/src/utilities/get/cache/getSitemap.ts +50 -0
  407. package/template/src/utilities/get/cache/getTracking.ts +14 -0
  408. package/template/src/utilities/get/cache/index.ts +129 -0
  409. package/template/src/utilities/get/cache/react.ts +5 -0
  410. package/template/src/utilities/get/getImageURL.ts +20 -0
  411. package/template/src/utilities/get/getMeUser.ts +22 -0
  412. package/template/src/utilities/get/getURL.ts +20 -0
  413. package/template/src/utilities/log/cache.ts +8 -0
  414. package/template/src/utilities/log/manual.ts +11 -0
  415. package/template/src/utilities/log/revalidation.ts +6 -0
  416. package/template/src/utilities/mergeTags.ts +7 -0
  417. package/template/src/utilities/propertyApplicatorUtility.ts +20 -0
  418. package/template/src/utilities/revalidateTag.ts +55 -0
  419. package/template/src/utilities/runAPF.ts +10 -0
  420. package/template/src/utilities/sanitizeData.ts +24 -0
  421. package/template/src/utilities/seedNestedRelationship.ts +5 -0
  422. package/template/tailwind.config.js +9 -0
  423. package/template/tsconfig.json +49 -0
@@ -0,0 +1,46 @@
1
+ 'use server'
2
+ import { FormFunction } from '@/ts/types'
3
+ import { FrlSimpleSlidingWindow as FrlSimpleSlidingWindowType } from '@/ts/types'
4
+
5
+ const lastCleanup: Record<string, number> = {}
6
+ const memoryStore: Record<string, Record<string, number[]>> = {}
7
+
8
+ export const FrlSimpleSlidingWindow: FormFunction<{ block: FrlSimpleSlidingWindowType }> = async (args) => {
9
+ const { context, response, block } = args
10
+ const { backendFormID, ip } = context
11
+ const { rateLimit, rateLimitPeriod, validationMessage } = block
12
+
13
+ // Ensure store for this formID exists. (The store unifies all front end forms rate limiting to the backend form.)
14
+ if (!memoryStore[backendFormID]) memoryStore[backendFormID] = {}
15
+ if (!lastCleanup[backendFormID]) lastCleanup[backendFormID] = 0
16
+
17
+ const now = Date.now()
18
+ const windowStart = now - rateLimitPeriod * 60000
19
+
20
+ const timestamps = memoryStore[backendFormID][ip] || []
21
+ const recentRequests = timestamps.filter((ts) => ts > windowStart)
22
+
23
+ // Add the current request to the store.
24
+ memoryStore[backendFormID][ip] = [...recentRequests, now]
25
+
26
+ // Only run cleanup for this formID if rateLimitPeriod has passed since last cleanup
27
+ if (now - lastCleanup[backendFormID] > rateLimitPeriod * 60000) {
28
+ Object.keys(memoryStore[backendFormID]).forEach((ipKey) => {
29
+ const filtered = memoryStore[backendFormID][ipKey].filter((ts) => ts > windowStart)
30
+ if (filtered.length === 0) delete memoryStore[backendFormID][ipKey]
31
+ else memoryStore[backendFormID][ipKey] = filtered
32
+ })
33
+ lastCleanup[backendFormID] = now
34
+ }
35
+
36
+ if (recentRequests.length >= rateLimit) {
37
+ const earliest = Math.min(...recentRequests)
38
+ const durationMs = earliest + rateLimitPeriod * 60000 - now
39
+ response.success = false
40
+ context.waitFor = durationMs
41
+ response.fm = validationMessage
42
+ return args
43
+ }
44
+
45
+ return args
46
+ }
@@ -0,0 +1,6 @@
1
+ import { FsCombineTwoFields } from './combineTwoFields/block'
2
+
3
+ export { FsCombineTwoFields }
4
+ const fsBlocks = [FsCombineTwoFields]
5
+
6
+ export default fsBlocks
@@ -0,0 +1,19 @@
1
+ import type { Block } from 'payload'
2
+ import { APField } from '@/fields/apf'
3
+
4
+ const d = {
5
+ addBetween: 'Adds a string between the two fields. Defaults to a space.',
6
+ }
7
+
8
+ export const FsCombineTwoFields: Block = {
9
+ slug: 'FsCombineTwoFields',
10
+ interfaceName: 'FsCombineTwoFields',
11
+ admin: { disableBlockName: true },
12
+ labels: { singular: 'Combine Two Fields', plural: 'Combine Two Fields' },
13
+ fields: [
14
+ APField({ type: 'text', apf: ['form'], name: 'firstFieldName', required: true }),
15
+ APField({ type: 'text', apf: ['form'], name: 'addBetween', admin: { description: d.addBetween } }),
16
+ APField({ type: 'text', apf: ['form'], name: 'secondFieldName', required: true }),
17
+ APField({ type: 'text', apf: ['form'], name: 'outputFieldName', required: true }),
18
+ ],
19
+ }
@@ -0,0 +1,22 @@
1
+ 'use server'
2
+ import { FormFunction } from '@/ts/types'
3
+ import { FsCombineTwoFields as FsCombineTwoFieldsType } from '@/ts/types'
4
+
5
+ export const FsCombineTwoFields: FormFunction<{ block: FsCombineTwoFieldsType }> = async (args) => {
6
+ const { formData, block } = args
7
+ const { firstFieldName, secondFieldName, outputFieldName } = block
8
+
9
+ if (!formData.get(firstFieldName) || !formData.get(secondFieldName)) {
10
+ args.response.success = false
11
+ args.response.fm = `Combine Two Fields Block Needs: ${firstFieldName} and ${secondFieldName}`
12
+ return args
13
+ }
14
+
15
+ const firstFieldValue = formData.get(firstFieldName)
16
+ const addBetween = block.addBetween || ' '
17
+ const secondFieldValue = formData.get(secondFieldName)
18
+
19
+ formData.set(outputFieldName, `${firstFieldValue}${addBetween}${secondFieldValue}`)
20
+
21
+ return args
22
+ }
@@ -0,0 +1 @@
1
+ export * from './combineTwoFields/serverFunction'
@@ -0,0 +1,6 @@
1
+ import { FvIsUnique } from './isUnique/block'
2
+
3
+ export { FvIsUnique }
4
+ const fvBlocks = [FvIsUnique]
5
+
6
+ export default fvBlocks
@@ -0,0 +1 @@
1
+ export * from './isUnique/serverFunction'
@@ -0,0 +1,19 @@
1
+ import type { Block } from 'payload'
2
+ import { APField } from '@/fields/apf'
3
+ import { ValidationMessageField } from '@/fields/validationMessage'
4
+
5
+ const d = {
6
+ limit: 'The number of times the field can be used. It defaults to 1.',
7
+ }
8
+
9
+ export const FvIsUnique: Block = {
10
+ slug: 'FvIsUnique',
11
+ interfaceName: 'FvIsUnique',
12
+ admin: { disableBlockName: true },
13
+ labels: { singular: 'Is Unique', plural: 'Is Unique' },
14
+ fields: [
15
+ APField({ type: 'text', apf: ['form'], name: 'fieldName', required: true }),
16
+ APField({ type: 'number', apf: ['form'], name: 'limit', required: true, admin: { description: d.limit } }),
17
+ ValidationMessageField,
18
+ ],
19
+ }
@@ -0,0 +1,40 @@
1
+ 'use server'
2
+ import getCached from '@/utilities/get/cache/react'
3
+ import { FvIsUnique as FvIsUniqueType } from '@/ts/types'
4
+ import { FilterSubmissionsByFieldAndValue, FormFunction } from '@/ts/types'
5
+
6
+ /** Filters form submissions based on field and value inputs. */
7
+ const filterSubmissionsByFieldAndValue: FilterSubmissionsByFieldAndValue = ({ submissions, fieldName, fieldValue }) => {
8
+ return submissions.filter((submission) => {
9
+ if (!submission.submissionData || !Array.isArray(submission.submissionData)) return false
10
+ return submission.submissionData.some((data) => data.field === fieldName && data.value === String(fieldValue))
11
+ })
12
+ }
13
+
14
+ export const FvIsUnique: FormFunction<{ block: FvIsUniqueType }> = async (args) => {
15
+ const { formData, storedForm, response, block } = args
16
+ const { fieldName, validationMessage } = block
17
+
18
+ if (!formData.get(fieldName)) {
19
+ response.success = false
20
+ response.fm = `This form is missing a field named: ${fieldName}`
21
+ return args
22
+ }
23
+
24
+ const cachedSubmissions = await getCached('form-submissions', storedForm.backendForm)
25
+ const submissions = filterSubmissionsByFieldAndValue({ submissions: cachedSubmissions, fieldName, fieldValue: formData.get(fieldName) })
26
+
27
+ if (submissions.length > 0) {
28
+ if (!formData.get(fieldName)) {
29
+ response.success = false
30
+ response.fm = `Field '${fieldName}' not found in form data.`
31
+ return args
32
+ }
33
+
34
+ response.success = false
35
+ response.fm = validationMessage
36
+ return args
37
+ }
38
+
39
+ return args
40
+ }
@@ -0,0 +1,8 @@
1
+ import { z } from '@/ts/zap'
2
+ import sanitationBlocks from './sanitation/blocks'
3
+ import validationBlocks from './validation/blocks'
4
+ import rateLimitBlocks from './rateLimiting/blocks'
5
+
6
+ export const FormRateLimitBlockType = z.ap.add(z.enum(rateLimitBlocks.map((block) => block.slug)), { id: 'FormRateLimitBlockType' })
7
+ export const FormSanitationBlockType = z.ap.add(z.enum(sanitationBlocks.map((block) => block.slug)), { id: 'FormSanitationBlockType' })
8
+ export const FormValidationBlockType = z.ap.add(z.enum(validationBlocks.map((block) => block.slug)), { id: 'FormValidationBlockType' })
@@ -0,0 +1,222 @@
1
+ 'use server'
2
+ //Function Imports
3
+ import { FvIsUnique } from '@/blocks/submitForm/form/validation/functions'
4
+ import { IsTrimText } from '@/blocks/submitForm/input/sanitation/functions'
5
+ import { FsCombineTwoFields } from '@/blocks/submitForm/form/sanitation/functions'
6
+ import { FrlSimpleSlidingWindow } from '@/blocks/submitForm/form/rateLimiting/functions'
7
+ import { IvContains, IvDoesNotContain } from '@/blocks/submitForm/input/validation/functions'
8
+
9
+ //Other Imports
10
+ import { CookiePreferences } from '@/ts/types/actions'
11
+ import {
12
+ AFPBase,
13
+ RunBlocksMethod,
14
+ FormFunction,
15
+ ProcessMethod,
16
+ FormFunctionsMap,
17
+ PreProcessMethod,
18
+ PostProcessMethod,
19
+ MessageProcessorMethod,
20
+ } from '@/ts/types/forms'
21
+ import type {
22
+ FormRateLimitBlocks,
23
+ FormSanitationBlocks,
24
+ FormValidationBlocks,
25
+ InputSanitationBlocks,
26
+ InputValidationBlocks,
27
+ StoredAtomicFormInput,
28
+ } from '@/ts/types'
29
+ import { formatDurationString } from '@/utilities/formatDurationWithTokens'
30
+
31
+ const formFunctions: FormFunctionsMap = {
32
+ FrlSimpleSlidingWindow,
33
+ FsCombineTwoFields,
34
+ FvIsUnique,
35
+ IsTrimText,
36
+ IvContains,
37
+ IvDoesNotContain,
38
+ }
39
+
40
+ class SubmitFormProcessor {
41
+ //Context
42
+ private success: boolean = true
43
+ private args: AFPBase | undefined
44
+ private CCPreferences: CookiePreferences | undefined
45
+
46
+ //Form Level Values
47
+ private formRateLimitBlocks: FormRateLimitBlocks | undefined
48
+ private formSanitationBlocks: FormSanitationBlocks | undefined
49
+ private formValidationBlocks: FormValidationBlocks | undefined
50
+ private formInputBlocks: StoredAtomicFormInput[] | undefined
51
+
52
+ //Input Level Values
53
+ private inputSanitationBlocks: InputSanitationBlocks | undefined
54
+ private inputValidationBlocks: InputValidationBlocks | undefined
55
+
56
+ private reset(target: 'context' | 'form' | 'input' | 'all') {
57
+ if (target === 'context') {
58
+ this.args = undefined
59
+ this.success = true
60
+ this.CCPreferences = undefined
61
+ }
62
+ if (target === 'form') {
63
+ this.formRateLimitBlocks = undefined
64
+ this.formSanitationBlocks = undefined
65
+ this.formValidationBlocks = undefined
66
+ this.formInputBlocks = undefined
67
+ }
68
+ if (target === 'input') {
69
+ this.inputSanitationBlocks = undefined
70
+ this.inputValidationBlocks = undefined
71
+ }
72
+ if (target === 'all') {
73
+ this.reset('context')
74
+ this.reset('form')
75
+ this.reset('input')
76
+ }
77
+ }
78
+
79
+ private preProcess: PreProcessMethod = (args) => {
80
+ const { submissionData, headers, storedForm } = args
81
+ const { formData, clientData, submissionID } = submissionData
82
+ this.formInputBlocks = storedForm.inputs
83
+ this.CCPreferences = clientData.preferences
84
+ this.formSanitationBlocks = storedForm.sanitation
85
+ this.formValidationBlocks = storedForm.validation
86
+ this.formRateLimitBlocks = storedForm.rateLimiting
87
+ this.args = {
88
+ formData,
89
+ storedForm,
90
+ response: { success: true, submissionID, formData: new FormData(), fm: '', im: {} },
91
+ context: {
92
+ headers,
93
+ clientData,
94
+ backendFormID: storedForm.id,
95
+ referer: headers.get('referer') || 'unknown',
96
+ ip: headers.get('x-forwarded-for') || headers.get('x-real-ip') || headers.get('cf-connecting-ip') || 'unknown',
97
+ },
98
+ }
99
+ }
100
+
101
+ process: ProcessMethod = async (args) => {
102
+ this.preProcess(args)
103
+
104
+ //DO NOT CHANGE ORDER.
105
+ await this.formRateLimitProcessor(true)
106
+ await this.inputProcessor()
107
+ await this.formSanitationProcessor()
108
+ await this.formValidationProcessor()
109
+ await this.formRateLimitProcessor(false)
110
+
111
+ return this.postProcess()
112
+ }
113
+
114
+ private async formRateLimitProcessor(start: boolean) {
115
+ if (!this.formRateLimitBlocks || !this.success) return
116
+ const rateLimitArray = this.formRateLimitBlocks.filter((rateLimit) => rateLimit.atStart === start)
117
+ for (const block of rateLimitArray) if (this.success) await this.runBlocks({ block, type: block.blockType })
118
+ }
119
+
120
+ private async formSanitationProcessor() {
121
+ if (!this.formSanitationBlocks || !this.success) return
122
+ for (const block of this.formSanitationBlocks) if (this.success) await this.runBlocks({ block, type: block.blockType })
123
+ }
124
+
125
+ private async formValidationProcessor() {
126
+ if (!this.formValidationBlocks || !this.success) return
127
+ for (const block of this.formValidationBlocks) if (this.success) await this.runBlocks({ block, type: block.blockType })
128
+ }
129
+
130
+ private async inputProcessor() {
131
+ if (!this.formInputBlocks || !this.success) return
132
+ for (const input of this.formInputBlocks) {
133
+ if ((!input.sanitationBlocks && !input.validationBlocks) || !input.inputName) continue
134
+ this.inputSanitationBlocks = input.sanitationBlocks
135
+ this.inputValidationBlocks = input.validationBlocks
136
+ await this.inputSanitationProcessor(input.inputName)
137
+ await this.inputValidationProcessor(input.inputName)
138
+ this.reset('input')
139
+ }
140
+ }
141
+
142
+ private async inputSanitationProcessor(inputName: string) {
143
+ if (!this.inputSanitationBlocks) return
144
+ for (const block of this.inputSanitationBlocks) await this.runBlocks({ block: { ...block, inputName }, type: block.blockType, persevere: true })
145
+ }
146
+
147
+ private async inputValidationProcessor(inputName: string) {
148
+ if (!this.inputValidationBlocks) return
149
+ for (const block of this.inputValidationBlocks) await this.runBlocks({ block: { ...block, inputName }, type: block.blockType, persevere: true })
150
+ }
151
+
152
+ private runBlocks: RunBlocksMethod = async ({ type, block, persevere }) => {
153
+ if (!this.args) throw new Error('Args is not defined in form processor.')
154
+ if (!this.args.response.success) if (!persevere) return
155
+ const augmentedArgs: Parameters<FormFunction>[0] = { ...this.args, block }
156
+
157
+ const fn = formFunctions[type]
158
+ if (!fn) throw new Error(`Unknown Server Function: ${type} in form processor runBlocksFunction`)
159
+
160
+ //TODO: Fix typing
161
+ this.args = await fn(augmentedArgs as any)
162
+ if (!this.args.response.success) this.success = false
163
+ }
164
+
165
+ private postProcess: PostProcessMethod = () => {
166
+ if (!this.args?.formData) throw new Error('Form data is not defined in form processor postProcess')
167
+ if (!this.CCPreferences) throw new Error('CCPreferences is not defined in form processor postProcess')
168
+ const { response, storedForm, context, formData } = this.args
169
+ const { clientData, referer, headers, ip, waitFor } = context
170
+ const submitToPayload = Array.from(this.args.formData.entries())
171
+ //Only accepts string values currently
172
+ .filter((entry): entry is [string, string] => typeof entry[1] === 'string')
173
+ .map(([key, value]) => ({ field: key, value }))
174
+
175
+ //Handle Data Collection
176
+ if (this.CCPreferences.userData) {
177
+ submitToPayload.push({ field: 'ip', value: ip })
178
+ submitToPayload.push({ field: 'timezone', value: clientData.timezone })
179
+ submitToPayload.push({ field: 'userAgent', value: headers.get('user-agent') || 'unknown' })
180
+ }
181
+ if (this.CCPreferences.analytics) {
182
+ submitToPayload.push({ field: 'referer', value: referer })
183
+ submitToPayload.push({ field: 'screenWidth', value: clientData.screenWidth })
184
+ submitToPayload.push({ field: 'screenHeight', value: clientData.screenHeight })
185
+ }
186
+
187
+ // Process Form & Input Messages
188
+ let fm
189
+ if (response.fm) fm = response.fm
190
+ else if (this.success) fm = storedForm.sm || 'Form submitted successfully!'
191
+ else fm = storedForm.em || 'Failed to submit form.'
192
+ fm = this.messageProcessor({ vm: fm, formData, waitFor })
193
+ if (Object.keys(response.im).length > 0) {
194
+ for (const [key, vm] of Object.entries(response.im)) response.im[key] = this.messageProcessor({ vm, formData, waitFor })
195
+ }
196
+
197
+ //Submit Form Processor Response
198
+ const fps = { response: { ...response, fm }, submitToPayload }
199
+ this.reset('all')
200
+ return fps
201
+ }
202
+
203
+ private messageProcessor: MessageProcessorMethod = ({ vm, formData, waitFor }) => {
204
+ if (vm?.includes('{{') && vm?.includes('}}')) {
205
+ if (waitFor) vm = formatDurationString(waitFor, vm)
206
+ vm = vm.replace(/\{\{([^}]+)\}\}/g, (match: string, fieldKey: string) => {
207
+ // Check if the field exists in formData
208
+ if (formData.get(fieldKey) !== undefined) return String(formData.get(fieldKey))
209
+ // If field doesn't exist, return the original placeholder
210
+ return match
211
+ })
212
+ }
213
+
214
+ return vm
215
+ }
216
+ }
217
+
218
+ const submitFormProcessor = new SubmitFormProcessor()
219
+
220
+ export async function getSubmitFormProcessor() {
221
+ return submitFormProcessor
222
+ }
@@ -0,0 +1,5 @@
1
+ import { IsTrimText } from './trimText/block'
2
+ export * from './trimText/block'
3
+
4
+ const isBlocks = [IsTrimText]
5
+ export default isBlocks
@@ -0,0 +1 @@
1
+ export * from './trimText/serverFunction'
@@ -0,0 +1,24 @@
1
+ import type { Block } from 'payload'
2
+ import { APField } from '@/fields/apf'
3
+
4
+ const d = {
5
+ trimCharacters: 'The characters to trim. Comma seperated list. Defaults to just removing spaces.',
6
+ }
7
+
8
+ const options = [
9
+ { label: 'Beginning', value: 'beginning' },
10
+ { label: 'End', value: 'end' },
11
+ { label: 'Both', value: 'both' },
12
+ ]
13
+
14
+ export const IsTrimText: Block = {
15
+ slug: 'IsTrimText',
16
+ interfaceName: 'IsTrimText',
17
+ admin: { disableBlockName: true },
18
+ labels: { singular: 'Trim Text', plural: 'Trim Text' },
19
+ custom: { usedOn: ['text', 'textarea', 'email'] },
20
+ fields: [
21
+ APField({ type: 'select', apf: ['form'], required: true, name: 'trimType', defaultValue: 'both', options }),
22
+ APField({ type: 'text', apf: ['form'], required: true, name: 'trimCharacters', admin: { description: d.trimCharacters } }),
23
+ ],
24
+ }
@@ -0,0 +1,63 @@
1
+ 'use server'
2
+ import { FormFunction } from '@/ts/types'
3
+ import { IsTrimText as IsTrimTextType } from '@/ts/types'
4
+
5
+ export const IsTrimText: FormFunction<{ block: IsTrimTextType & { inputName: string } }> = async (args) => {
6
+ const { formData, response, block } = args
7
+ const { trimCharacters, trimType, inputName } = block
8
+
9
+ //Get the input value
10
+ const inputValue = formData.get(inputName)
11
+ if (typeof inputValue !== 'string') {
12
+ response.success = false
13
+ response.fm = `Input Value is not a string: ${inputName}`
14
+ return args
15
+ }
16
+
17
+ //Get the characters we can trim
18
+ const trimCharactersArray = trimCharacters
19
+ ?.split(',')
20
+ .map((char: string) => char.trim())
21
+ .filter((char: string) => char.length > 0)
22
+ if (!trimCharactersArray) {
23
+ response.success = false
24
+ response.fm = `Trim Characters is required: ${inputName}`
25
+ return args
26
+ }
27
+
28
+ //Trim the input value based on the trim type
29
+ switch (trimType) {
30
+ case 'beginning':
31
+ for (const char of trimCharactersArray) {
32
+ if (char.length === 0) continue
33
+ const escapedChar = escapeRegex(char)
34
+ formData.set(inputName, inputValue.replace(new RegExp(`^${escapedChar}+`, 'g'), ''))
35
+ }
36
+ break
37
+ case 'end':
38
+ for (const char of trimCharactersArray) {
39
+ if (char.length === 0) continue
40
+ const escapedChar = escapeRegex(char)
41
+ formData.set(inputName, inputValue.replace(new RegExp(`${escapedChar}+$`, 'g'), ''))
42
+ }
43
+ break
44
+ case 'both':
45
+ for (const char of trimCharactersArray) {
46
+ if (char.length === 0) continue
47
+ const escapedChar = escapeRegex(char)
48
+ const regexPattern = `^${escapedChar}+|${escapedChar}+$`
49
+ formData.set(inputName, inputValue.replace(new RegExp(regexPattern, 'g'), ''))
50
+ }
51
+ break
52
+ default:
53
+ // If no valid trim type, return original value
54
+ break
55
+ }
56
+
57
+ return args
58
+ }
59
+
60
+ // Helper function to escape regex special characters (for the trim characters)
61
+ const escapeRegex = (str: string) => {
62
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
63
+ }
@@ -0,0 +1,8 @@
1
+ import sanitationBlocks from './sanitation/blocks'
2
+ import validationBlocks from './validation/blocks'
3
+
4
+ /**
5
+ * Pre-computed mapping of block slugs to their usedOn field types.
6
+ * This is calculated once at module load time to avoid runtime recalculation.
7
+ */
8
+ export const useOn = [...sanitationBlocks, ...validationBlocks].map((block) => ({ block: block.slug, usedOn: block.custom?.usedOn }))
@@ -0,0 +1,6 @@
1
+ import { IvContains } from './contains/block'
2
+ import { IvDoesNotContain } from './doesNotContain/block'
3
+ export { IvContains, IvDoesNotContain }
4
+
5
+ const ivBlocks = [IvContains, IvDoesNotContain]
6
+ export default ivBlocks
@@ -0,0 +1,12 @@
1
+ import type { Block } from 'payload'
2
+ import { APField } from '@/fields/apf'
3
+ import { ValidationMessageField } from '@/fields/validationMessage'
4
+
5
+ export const IvContains: Block = {
6
+ slug: 'IvContains',
7
+ interfaceName: 'IvContains',
8
+ admin: { disableBlockName: true },
9
+ labels: { singular: 'Contains Value', plural: 'Contains Value' },
10
+ custom: { usedOn: ['text', 'textarea', 'email'] },
11
+ fields: [APField({ type: 'text', apf: ['form'], name: 'containsValue', required: true }), ValidationMessageField],
12
+ }
@@ -0,0 +1,23 @@
1
+ 'use server'
2
+ import { FormFunction } from '@/ts/types'
3
+ import { IvContains as IvContainsType } from '@/ts/types'
4
+
5
+ export const IvContains: FormFunction<{ block: IvContainsType & { inputName: string } }> = async (args) => {
6
+ const { formData, response, block } = args
7
+ const { containsValue, validationMessage, inputName } = block
8
+
9
+ const inputValue = formData.get(inputName)
10
+ if (typeof inputValue !== 'string') {
11
+ response.success = false
12
+ response.fm = `Input Value is not a string: ${inputName}`
13
+ return args
14
+ }
15
+
16
+ if (!inputValue.includes(containsValue)) {
17
+ response.success = false
18
+ response.im[inputName] = validationMessage
19
+ return args
20
+ }
21
+
22
+ return args
23
+ }
@@ -0,0 +1,12 @@
1
+ import type { Block } from 'payload'
2
+ import { APField } from '@/fields/apf'
3
+ import { ValidationMessageField } from '@/fields/validationMessage'
4
+
5
+ export const IvDoesNotContain: Block = {
6
+ slug: 'IvDoesNotContain',
7
+ interfaceName: 'IvDoesNotContain',
8
+ admin: { disableBlockName: true },
9
+ labels: { singular: 'Does Not Contain', plural: 'Does Not Contain' },
10
+ custom: { usedOn: ['text', 'textarea', 'email'] },
11
+ fields: [APField({ type: 'text', apf: ['form'], name: 'doesNotContainValue' }), ValidationMessageField],
12
+ }
@@ -0,0 +1,23 @@
1
+ 'use server'
2
+ import { FormFunction } from '@/ts/types'
3
+ import { IvDoesNotContain as IvDoesNotContainType } from '@/ts/types'
4
+
5
+ export const IvDoesNotContain: FormFunction<{ block: IvDoesNotContainType & { inputName: string } }> = async (args) => {
6
+ const { formData, response, block } = args
7
+ const { doesNotContainValue, validationMessage, inputName } = block
8
+
9
+ const inputValue = formData.get(inputName)
10
+ if (typeof inputValue !== 'string') {
11
+ response.success = false
12
+ response.fm = `Input Value is not a string: ${inputName}`
13
+ return args
14
+ }
15
+
16
+ if (doesNotContainValue && inputValue.includes(doesNotContainValue)) {
17
+ response.success = false
18
+ response.im[inputName] = validationMessage
19
+ return args
20
+ }
21
+
22
+ return args
23
+ }
@@ -0,0 +1,2 @@
1
+ export * from './contains/serverFunction'
2
+ export * from './doesNotContain/serverFunction'
@@ -0,0 +1,6 @@
1
+ import { z } from '@/ts/zap'
2
+ import sanitationBlocks from './sanitation/blocks'
3
+ import validationBlocks from './validation/blocks'
4
+
5
+ export const InputSanitationBlockType = z.ap.add(z.enum(sanitationBlocks.map((block) => block.slug)), { id: 'InputSanitationBlockType' })
6
+ export const InputValidationBlockType = z.ap.add(z.enum(validationBlocks.map((block) => block.slug)), { id: 'InputValidationBlockType' })
@@ -0,0 +1,42 @@
1
+ 'use server'
2
+ import getCached from '@/utilities/get/cache/react'
3
+ import { SubmitFormFunction } from '@/ts/types'
4
+ import { getSubmitFormProcessor } from './formProcessor'
5
+ import { getServerSideURL } from '@/utilities/get/getURL'
6
+ import { draftMode, headers as nextHeaders } from 'next/headers'
7
+
8
+ const formProcessor = await getSubmitFormProcessor()
9
+
10
+ export const submitForm: SubmitFormFunction = async (submissionData) => {
11
+ const headers = await nextHeaders()
12
+ const { isEnabled: draft } = await draftMode()
13
+ const { blockID, submissionID, formData } = submissionData
14
+
15
+ try {
16
+ // Get the stored form
17
+ const backendForms = await getCached('backend-forms')
18
+ if (!backendForms) return { success: false, formData, submissionID, fm: 'No backend forms found.', im: {} }
19
+ const atomicForms = await getCached('atomic-forms', draft)
20
+ if (!atomicForms) return { success: false, formData, submissionID, fm: 'No stored atomic forms found.', im: {} }
21
+ const allForms = await getCached('all-forms', draft, atomicForms, backendForms)
22
+ if (!allForms) return { success: false, formData, submissionID, fm: 'No all forms found.', im: {} }
23
+ const storedForm = allForms.find((form) => form.id === blockID)
24
+ if (!storedForm || !storedForm.id) return { success: false, formData, submissionID, fm: 'No backend form found for this atomic form.', im: {} }
25
+
26
+ const { response, submitToPayload } = await formProcessor.process({ submissionData, headers, storedForm })
27
+
28
+ if (response.success) {
29
+ const req = await fetch(`${getServerSideURL()}/api/form-submissions`, {
30
+ body: JSON.stringify({ form: storedForm.backendFormID, submissionData: submitToPayload }),
31
+ headers: { 'Content-Type': 'application/json' },
32
+ method: 'POST',
33
+ })
34
+ if (!req.ok) return { success: false, formData, submissionID, fm: 'Failed to store form submission.', im: {} }
35
+ }
36
+
37
+ return response
38
+ } catch (err: unknown) {
39
+ console.error(err)
40
+ return { success: false, formData, submissionID, fm: 'Unknown Error. Please try again later.', im: {} }
41
+ }
42
+ }