payload-plugin-marketing 0.9.3 → 0.9.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 (62) hide show
  1. package/README.md +68 -19
  2. package/dist/admin/client.cjs +3 -0
  3. package/dist/admin/client.cjs.map +1 -0
  4. package/dist/admin/client.d.ts +7 -0
  5. package/dist/admin/client.d.ts.map +1 -0
  6. package/dist/admin/client.js +3 -0
  7. package/dist/admin/client.js.map +1 -0
  8. package/dist/admin/components/audience-buttons.d.ts.map +1 -1
  9. package/dist/admin/components/broadcast-list.d.ts.map +1 -1
  10. package/dist/admin/components/broadcasts-table.d.ts.map +1 -1
  11. package/dist/admin/components/contacts-table.d.ts.map +1 -1
  12. package/dist/admin/components/create-broadcast-button.d.ts +9 -1
  13. package/dist/admin/components/create-broadcast-button.d.ts.map +1 -1
  14. package/dist/admin/components/marketing-components.d.ts +0 -6
  15. package/dist/admin/components/marketing-components.d.ts.map +1 -1
  16. package/dist/admin/components/marketing-view-shell.d.ts.map +1 -1
  17. package/dist/admin/components/payload-modal.d.ts +8 -8
  18. package/dist/admin/components/payload-modal.d.ts.map +1 -1
  19. package/dist/admin/constants.cjs +2 -0
  20. package/dist/admin/constants.cjs.map +1 -0
  21. package/dist/admin/constants.d.ts +2 -0
  22. package/dist/admin/constants.d.ts.map +1 -0
  23. package/dist/admin/constants.js +2 -0
  24. package/dist/admin/constants.js.map +1 -0
  25. package/dist/admin/index.cjs +1 -1
  26. package/dist/admin/index.cjs.map +1 -1
  27. package/dist/admin/index.d.ts +3 -3
  28. package/dist/admin/index.d.ts.map +1 -1
  29. package/dist/admin/index.js +1 -1
  30. package/dist/admin/index.js.map +1 -1
  31. package/dist/admin/locale-options.d.ts +7 -0
  32. package/dist/admin/locale-options.d.ts.map +1 -0
  33. package/dist/admin/server.cjs +2 -0
  34. package/dist/admin/server.cjs.map +1 -0
  35. package/dist/admin/server.d.ts +2 -0
  36. package/dist/admin/server.d.ts.map +1 -0
  37. package/dist/admin/server.js +2 -0
  38. package/dist/admin/server.js.map +1 -0
  39. package/dist/admin/use-marketing-api.d.ts.map +1 -1
  40. package/dist/{chunk-S2EABBIN.js → chunk-G6DIJ7B2.js} +1 -1
  41. package/dist/chunk-G6DIJ7B2.js.map +1 -0
  42. package/dist/email-broadcast-template.d.ts +15 -0
  43. package/dist/email-broadcast-template.d.ts.map +1 -0
  44. package/dist/endpoints/marketing-endpoints.d.ts.map +1 -1
  45. package/dist/form-builder/index.cjs.map +1 -1
  46. package/dist/form-builder/index.js +1 -1
  47. package/dist/form-builder/normalize-placeholder-rows.d.ts.map +1 -1
  48. package/dist/index.cjs +1 -1
  49. package/dist/index.cjs.map +1 -1
  50. package/dist/index.d.ts +1 -1
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +1 -1
  53. package/dist/index.js.map +1 -1
  54. package/dist/marketing-integration.d.ts +2 -1
  55. package/dist/marketing-integration.d.ts.map +1 -1
  56. package/dist/plugin.d.ts.map +1 -1
  57. package/dist/types.d.ts +31 -0
  58. package/dist/types.d.ts.map +1 -1
  59. package/package.json +10 -2
  60. package/dist/chunk-S2EABBIN.js.map +0 -1
  61. package/dist/chunk-SX3OTOU2.js +0 -2
  62. package/dist/chunk-SX3OTOU2.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/admin/components/audience-detail.tsx","../../src/admin/paths.ts","../../src/admin/use-marketing-api.ts","../../src/admin/components/broadcasts-table.tsx","../../src/admin/date-format.ts","../../src/admin/components/payload-modal.tsx","../../src/admin/components/audience-buttons.tsx","../../src/admin/components/contacts-table.tsx","../../src/admin/components/create-broadcast-button.tsx","../../src/marketing-integration.ts","../../src/admin/components/marketing-view-shell.tsx","../../src/admin/components/view-params.ts","../../src/admin/components/audience-list.tsx","../../src/admin/components/broadcast-list.tsx","../../src/admin/locale-options.ts"],"sourcesContent":["import { Gutter, Link } from \"@payloadcms/ui\"\nimport { notFound } from \"next/navigation\"\nimport { AudienceContactsTable, EditContactButton } from \"../client\"\nimport { Suspense } from \"react\"\n\nimport {\n getMarketingIntegration,\n resolveMarketingPermissions,\n tryGetMarketingIntegration,\n} from \"../../marketing-integration\"\nimport { MarketingViewShell } from \"./marketing-view-shell\"\nimport { marketingAudienceIdFromParams } from \"./view-params\"\n\nimport type { AdminViewServerProps } from \"payload\"\n\nexport type AudienceDetailViewProps = AdminViewServerProps & {\n basePath?: string\n}\n\nexport default function AudienceDetail({\n initPageResult,\n params,\n searchParams,\n}: AudienceDetailViewProps) {\n const audienceId = marketingAudienceIdFromParams(params)\n\n if (!audienceId) {\n throw new Error(\"No audience id in route params\")\n }\n\n return (\n <MarketingViewShell initPageResult={initPageResult} params={params} searchParams={searchParams}>\n <Gutter>\n <AudienceDetailBody audienceId={audienceId} initPageResult={initPageResult} />\n </Gutter>\n </MarketingViewShell>\n )\n}\n\nasync function AudienceDetailBody({\n audienceId,\n initPageResult,\n}: {\n audienceId: string\n initPageResult: AdminViewServerProps[\"initPageResult\"]\n}) {\n const integration = tryGetMarketingIntegration(initPageResult.req.payload)\n if (!integration) {\n return (\n <p role=\"alert\">Marketing plugin is not configured (missing adapter on Payload config).</p>\n )\n }\n\n const effective = resolveMarketingPermissions(integration.permissions)\n if (!effective.audiences.read) {\n return <p role=\"alert\">You do not have permission to view this audience.</p>\n }\n\n const { adapter } = getMarketingIntegration(initPageResult.req.payload)\n const audience = await adapter.audiences.get(audienceId)\n if (!audience) {\n notFound()\n }\n\n const audienceDashboardUrl = adapter.urls?.audience?.(audienceId)\n\n return (\n <>\n <header className=\"flex flex-col gap-4\">\n <h1>{audience.name}</h1>\n {audienceDashboardUrl ? (\n <Link href={audienceDashboardUrl} rel=\"noreferrer noopener\" target=\"_blank\">\n Open this audience in {adapter.label}\n </Link>\n ) : null}\n </header>\n\n <div className=\"mt-12 flex flex-col gap-6\">\n {effective.contacts.write ? (\n <div>\n <EditContactButton audienceId={audienceId} contact={null} />\n </div>\n ) : null}\n {effective.contacts.read ? (\n <Suspense fallback={<div aria-busy style={{ minHeight: \"12rem\" }} />}>\n <DetailContacts audienceId={audienceId} initPageResult={initPageResult} />\n </Suspense>\n ) : (\n <p role=\"alert\">You do not have permission to list contacts.</p>\n )}\n </div>\n </>\n )\n}\n\nasync function DetailContacts({\n audienceId,\n initPageResult,\n}: {\n audienceId: string\n initPageResult: AdminViewServerProps[\"initPageResult\"]\n}) {\n const { adapter } = getMarketingIntegration(initPageResult.req.payload)\n const contacts = await adapter.contacts.list({ audienceId })\n return <AudienceContactsTable audienceId={audienceId} contacts={contacts} />\n}\n","export function joinAdminSegments(adminRoute: string, ...segments: string[]): string {\n const trimmedAdmin = adminRoute.replace(/\\/+$/, \"\") || \"\"\n const body = segments\n .flatMap((s) => String(s).split(\"/\"))\n .map((segment) => segment.replace(/^\\/+|\\/+$/g, \"\"))\n .filter(Boolean)\n .join(\"/\")\n const combined = trimmedAdmin === \"\" ? `/${body}` : `${trimmedAdmin}/${body}`\n return combined.replace(/\\/{2,}/g, \"/\")\n}\n\n/** Absolute admin hrefs for marketing custom views (`/admin`, optional plugin `basePath`, then path segments). */\nexport function marketingAdminHref(basePath: string | undefined, ...segments: string[]): string {\n const normalized = basePath?.replace(/^\\/+|\\/+$/g, \"\") ?? \"\"\n const parts = [normalized, ...segments].filter(Boolean)\n return joinAdminSegments(\"/admin\", ...parts)\n}\n","\"use client\"\n\nimport { useConfig } from \"@payloadcms/ui\"\nimport { useCallback, useMemo } from \"react\"\n\nexport function useMarketingApi() {\n const context = useConfig() as unknown as {\n routes?: { api?: string }\n serverURL?: string\n }\n\n const base = useMemo(\n () => `${context.serverURL ?? \"\"}${context.routes?.api ?? \"/api\"}`,\n [context.routes?.api, context.serverURL],\n )\n\n const requestJson = useCallback(\n async (pathSegment: string, init?: RequestInit): Promise<unknown> => {\n const { headers: _headersIgnored, ...restInit } = init ?? {}\n const headers = new Headers(init?.headers)\n if (restInit.body !== undefined && restInit.body !== \"\" && restInit.body !== null) {\n if (!headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json\")\n }\n }\n\n const res = await fetch(`${base}${pathSegment}`, {\n ...restInit,\n credentials: \"include\",\n headers,\n })\n\n if (!res.ok) {\n let detail = `${res.status} ${res.statusText}`\n try {\n const parsed = (await res.json()) as { message?: string }\n if (typeof parsed.message === \"string\") detail = parsed.message\n } catch {\n //\n }\n throw new Error(detail)\n }\n\n if (res.status === 204) {\n return undefined\n }\n\n try {\n return await res.json()\n } catch {\n return undefined\n }\n },\n [base],\n )\n\n return { base, requestJson }\n}\n","\"use client\"\n\nimport {\n Button as PayloadButton,\n DateTimeField,\n Form,\n Pagination,\n Pill,\n Table,\n toast,\n useModal,\n useTranslation,\n} from \"@payloadcms/ui\"\nimport Link from \"next/link\"\nimport { useRouter } from \"next/navigation\"\nimport React from \"react\"\n\nimport { formatMarketingDate } from \"../date-format\"\nimport { useMarketingApi } from \"../use-marketing-api\"\nimport {\n PayloadModal,\n PayloadModalBody,\n PayloadModalClose,\n PayloadModalContent,\n PayloadModalFooter,\n PayloadModalTitle,\n} from \"./payload-modal\"\n\nimport type { MarketingBroadcast } from \"../../types\"\nimport type { Data, FormState } from \"payload\"\n\nexport interface MarketingBroadcastRow extends MarketingBroadcast {\n externalDashboardUrl?: string\n}\n\ninterface BroadcastsTableProps {\n broadcasts: MarketingBroadcastRow[]\n}\n\nexport function BroadcastsTable({ broadcasts }: BroadcastsTableProps) {\n const [page, setPage] = React.useState(1)\n const [limit] = React.useState(100)\n const currentPage = React.useMemo(\n () => broadcasts.slice((page - 1) * limit, page * limit),\n [broadcasts, limit, page],\n )\n\n return (\n <>\n <Table\n columns={[\n {\n Heading: \"Campaign name\",\n accessor: \"name\",\n active: true,\n field: { name: \"name\", type: \"text\" },\n renderedCells: currentPage.map((b) => <div key={b.id}>{b.name}</div>),\n },\n {\n Heading: \"Schedule date\",\n accessor: \"scheduledAt\",\n active: true,\n field: { name: \"scheduledAt\", type: \"text\" },\n renderedCells: currentPage.map((b) => (\n <div key={b.id}>{formatMarketingDate(b.scheduledAt)}</div>\n )),\n },\n {\n Heading: \"Sent date\",\n accessor: \"sentAt\",\n active: true,\n field: { name: \"sentAt\", type: \"text\" },\n renderedCells: currentPage.map((b) => (\n <div key={b.id}>{formatMarketingDate(b.sentAt)}</div>\n )),\n },\n {\n Heading: \"Status\",\n accessor: \"status\",\n active: true,\n field: { name: \"status\", type: \"text\" },\n renderedCells: currentPage.map((broadcast) => (\n <div key={broadcast.id}>\n <BroadcastStatusPill status={broadcast.status} />\n </div>\n )),\n },\n {\n Heading: \"\",\n accessor: \"\",\n active: true,\n field: { name: \"_\", type: \"text\" },\n renderedCells: currentPage.map((broadcast) => (\n <div key={broadcast.id} className=\"flex items-center gap-4 flex-wrap\">\n {broadcast.externalDashboardUrl ? (\n <Link\n href={broadcast.externalDashboardUrl}\n rel=\"noreferrer noopener\"\n target=\"_blank\"\n >\n <Pill>dashboard ↗</Pill>\n </Link>\n ) : null}\n {broadcast.status === \"draft\" || broadcast.status === \"save\" ? (\n <>\n <DeleteBroadcastButton\n broadcastId={broadcast.id}\n broadcastName={broadcast.name}\n />\n <SendBroadcastButton\n broadcastId={broadcast.id}\n broadcastName={broadcast.name}\n />\n </>\n ) : null}\n </div>\n )),\n },\n ]}\n data={currentPage as unknown as Record<string, unknown>[]}\n />\n <Pagination\n hasNextPage={page * limit < broadcasts.length}\n hasPrevPage={page > 1}\n limit={limit}\n onChange={(p) => setPage(p)}\n page={page}\n totalPages={Math.ceil(broadcasts.length / limit)}\n />\n </>\n )\n}\n\nfunction BroadcastStatusPill({ status }: { status: string }) {\n switch (status) {\n case \"draft\":\n case \"save\": {\n return <Pill pillStyle=\"light-gray\">Draft</Pill>\n }\n case \"queued\": {\n return <Pill pillStyle=\"white\">Queued</Pill>\n }\n case \"sent\": {\n return <Pill pillStyle=\"success\">Sent</Pill>\n }\n default: {\n return <Pill>{status}</Pill>\n }\n }\n}\n\nfunction DeleteBroadcastButton({\n broadcastId,\n broadcastName,\n}: {\n broadcastId: string\n broadcastName: string\n}) {\n const modal = useModal()\n const { t } = useTranslation()\n const router = useRouter()\n const { requestJson } = useMarketingApi()\n const modalSlug = `delete-broadcast_${broadcastId}`\n\n async function confirmDelete(): Promise<void> {\n await requestJson(`/marketing/broadcasts/${encodeURIComponent(broadcastId)}`, {\n method: \"DELETE\",\n })\n toast.success(t(\"general:deletedSuccessfully\"))\n modal.closeModal(modalSlug)\n router.refresh()\n }\n\n return (\n <>\n <PayloadModal slug={modalSlug}>\n <PayloadModalContent>\n <PayloadModalBody>\n <PayloadModalTitle>{t(\"general:confirmDeletion\")}</PayloadModalTitle>\n <p>{`Delete draft broadcast \"${broadcastName}\"?`}</p>\n </PayloadModalBody>\n <PayloadModalFooter style={{ display: \"flex\", gap: \"8px\", justifyContent: \"flex-end\" }}>\n <PayloadModalClose />\n <PayloadButton\n buttonStyle=\"error\"\n onClick={() => {\n void confirmDelete().catch((err: unknown) =>\n toast.error(err instanceof Error ? err.message : \"Delete failed\"),\n )\n }}\n >\n {t(\"general:confirm\")}\n </PayloadButton>\n </PayloadModalFooter>\n </PayloadModalContent>\n </PayloadModal>\n <button onClick={() => modal.openModal(modalSlug)} type=\"button\">\n {t(\"general:delete\")}\n </button>\n </>\n )\n}\n\nexport function SendBroadcastButton({\n broadcastId,\n broadcastName,\n}: {\n broadcastId: string\n broadcastName: string\n}) {\n const modal = useModal()\n const { t } = useTranslation()\n const router = useRouter()\n const { requestJson } = useMarketingApi()\n const modalSlug = `send-broadcast_${broadcastId}`\n\n const submit = (fields: FormState, data: Data) => {\n const row = data as Record<string, unknown>\n const scheduledRaw: unknown = row.scheduledAt\n let scheduledAt = \"\"\n if (typeof scheduledRaw === \"string\") {\n scheduledAt = scheduledRaw\n } else if (scheduledRaw instanceof Date) {\n scheduledAt = scheduledRaw.toISOString()\n }\n\n void (async () => {\n try {\n await requestJson(`/marketing/broadcasts/${encodeURIComponent(broadcastId)}/send`, {\n body: JSON.stringify({\n ...(scheduledAt && scheduledAt.trim() !== \"\"\n ? { scheduledAt: scheduledAt.trim() }\n : {}),\n }),\n method: \"POST\",\n })\n modal.closeModal(modalSlug)\n toast.success(t(\"general:success\"))\n router.refresh()\n } catch (err) {\n toast.error(err instanceof Error ? err.message : \"Send failed\")\n }\n })()\n }\n\n return (\n <>\n <PayloadModal slug={modalSlug}>\n <PayloadModalContent style={{ width: \"100%\", maxWidth: \"24rem\" }}>\n <PayloadModalBody>\n <PayloadModalTitle>{`Send “${broadcastName}”`}</PayloadModalTitle>\n <Form initialState={{}} onSubmit={submit} waitForAutocomplete>\n <DateTimeField\n field={{\n label: \"Schedule at (optional)\",\n name: \"scheduledAt\",\n required: false,\n }}\n path=\"scheduledAt\"\n />\n <PayloadModalFooter\n style={{ display: \"flex\", gap: \"8px\", justifyContent: \"flex-end\" }}\n >\n <PayloadModalClose />\n <PayloadButton size=\"large\" type=\"submit\">\n Send\n </PayloadButton>\n </PayloadModalFooter>\n </Form>\n </PayloadModalBody>\n </PayloadModalContent>\n </PayloadModal>\n <Pill pillStyle=\"dark\" onClick={() => modal.openModal(modalSlug)} size=\"small\">\n Send\n </Pill>\n </>\n )\n}\n","export function formatMarketingDate(iso?: string | null): string {\n if (!iso) return \"—\"\n const d = new Date(iso)\n return Number.isNaN(d.valueOf())\n ? String(iso)\n : new Intl.DateTimeFormat(undefined, { dateStyle: \"medium\" }).format(d)\n}\n","\"use client\"\n\nimport { Button, Modal, useModal, useTranslation } from \"@payloadcms/ui\"\nimport React from \"react\"\n\nfunction cn(...parts: Array<string | undefined | false | null>): string {\n return parts.filter(Boolean).join(\" \")\n}\n\nconst PayloadModalContext = React.createContext({\n modalSlug: \"\",\n})\n\ninterface PayloadModalProps extends React.ComponentProps<typeof Modal> {\n children: React.ReactNode\n}\n\nfunction PayloadModal({ children, className, slug: modalSlug, ...props }: PayloadModalProps) {\n const [loaded, setLoaded] = React.useState(false)\n\n React.useEffect(() => {\n setLoaded(true)\n }, [])\n\n return (\n <PayloadModalContext.Provider value={{ modalSlug }}>\n {/* Fix hydration error */}\n {loaded && (\n <Modal slug={modalSlug} className={cn(\"confirmation-modal\", className)} {...props}>\n {children}\n </Modal>\n )}\n </PayloadModalContext.Provider>\n )\n}\n\nfunction PayloadModalContent({ children, className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n className={cn(\"confirmation-modal__wrapper\", className)}\n data-slot=\"payload-modal-content\"\n {...props}\n >\n {children}\n </div>\n )\n}\n\nfunction PayloadModalBody({ children, className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n className={cn(\"confirmation-modal__content\", className)}\n data-slot=\"payload-modal-body\"\n {...props}\n >\n {children}\n </div>\n )\n}\n\nfunction PayloadModalTitle({ children, className, ...props }: React.ComponentProps<\"h1\">) {\n return (\n <h1 className={cn(\"\", className)} data-slot=\"payload-modal-title\" {...props}>\n {children}\n </h1>\n )\n}\n\nfunction PayloadModalFooter({ children, className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n className={cn(\"confirmation-modal__controls\", className)}\n data-slot=\"payload-modal-footer\"\n {...props}\n >\n {children}\n </div>\n )\n}\n\nfunction PayloadModalClose({ children, className, ...props }: React.ComponentProps<typeof Button>) {\n const { t } = useTranslation()\n const { modalSlug } = React.useContext(PayloadModalContext)\n const modal = useModal()\n\n return (\n <Button\n className={cn(\"\", className)}\n buttonStyle=\"secondary\"\n size=\"large\"\n data-slot=\"payload-modal-close\"\n {...props}\n onClick={() => modal.closeModal(modalSlug)}\n >\n {children ?? t(\"general:cancel\")}\n </Button>\n )\n}\n\nexport {\n PayloadModal,\n PayloadModalContent,\n PayloadModalBody,\n PayloadModalTitle,\n PayloadModalFooter,\n PayloadModalClose,\n}\n","\"use client\"\n\nimport {\n Button,\n Form,\n TextField,\n toast,\n useModal,\n useTranslation,\n Button as PayloadButton,\n} from \"@payloadcms/ui\"\nimport { useRouter } from \"next/navigation\"\nimport { useTransition } from \"react\"\n\nimport { useMarketingApi } from \"../use-marketing-api\"\nimport {\n PayloadModal,\n PayloadModalBody,\n PayloadModalClose,\n PayloadModalContent,\n PayloadModalFooter,\n PayloadModalTitle,\n} from \"./payload-modal\"\n\nimport type { Data, FormState } from \"payload\"\n\nconst createAudienceSlug = \"create-audience\"\n\nexport function CreateAudienceButton() {\n const modal = useModal()\n const { t } = useTranslation()\n\n return (\n <>\n <CreateAudienceModal />\n <Button onClick={() => modal.openModal(createAudienceSlug)} size=\"large\" type=\"button\">\n {t(\"general:createNew\")}\n </Button>\n </>\n )\n}\n\nfunction CreateAudienceModal() {\n const modal = useModal()\n const { t } = useTranslation()\n const router = useRouter()\n const { requestJson } = useMarketingApi()\n const [isPending, startTransition] = useTransition()\n\n const submit = (fields: FormState, data: Data) => {\n const row = data as Record<string, unknown>\n const nameRaw: unknown = row.audienceName\n const name = typeof nameRaw === \"string\" ? nameRaw.trim() : \"\"\n startTransition(() => {\n void (async () => {\n try {\n if (!name) {\n throw new Error(\"Name is required.\")\n }\n await requestJson(\"/marketing/audiences\", {\n body: JSON.stringify({ name }),\n method: \"POST\",\n })\n modal.closeModal(createAudienceSlug)\n toast.success(t(\"general:successfullyCreated\"))\n router.refresh()\n } catch (err) {\n toast.error(err instanceof Error ? err.message : \"Create failed\")\n }\n })()\n })\n }\n\n return (\n <PayloadModal closeOnBlur slug={createAudienceSlug}>\n <PayloadModalContent style={{ width: \"100%\", maxWidth: \"24rem\" }}>\n <Form initialState={{}} onSubmit={submit} waitForAutocomplete>\n <PayloadModalBody>\n <PayloadModalTitle>{t(\"general:createNew\")}</PayloadModalTitle>\n <TextField\n field={{\n name: \"audienceName\",\n required: true,\n type: \"text\",\n }}\n path=\"audienceName\"\n validate={(v) =>\n typeof v === \"string\" && v.trim().length > 0 ? true : \"Name is required\"\n }\n />\n <PayloadModalFooter style={{ display: \"flex\", gap: \"8px\", justifyContent: \"flex-end\" }}>\n <PayloadModalClose />\n <Button disabled={isPending} size=\"large\" type=\"submit\">\n {t(\"general:confirm\")}\n </Button>\n </PayloadModalFooter>\n </PayloadModalBody>\n </Form>\n </PayloadModalContent>\n </PayloadModal>\n )\n}\n\nexport function DeleteAudienceButton({\n audienceId,\n audienceName,\n}: {\n audienceId: string\n audienceName: string\n}) {\n const modal = useModal()\n const { t } = useTranslation()\n const router = useRouter()\n const { requestJson } = useMarketingApi()\n const modalSlug = `delete-audience_${audienceId}`\n\n async function confirmDelete(): Promise<void> {\n await requestJson(`/marketing/audiences/${encodeURIComponent(audienceId)}`, {\n method: \"DELETE\",\n })\n toast.success(t(\"general:deletedSuccessfully\"))\n modal.closeModal(modalSlug)\n router.refresh()\n }\n\n return (\n <>\n <PayloadModal slug={modalSlug}>\n <PayloadModalContent>\n <PayloadModalBody>\n <PayloadModalTitle>{t(\"general:confirmDeletion\")}</PayloadModalTitle>\n <p>{`Remove audience \"${audienceName}\"?`}</p>\n </PayloadModalBody>\n <PayloadModalFooter style={{ display: \"flex\", gap: \"8px\", justifyContent: \"flex-end\" }}>\n <PayloadModalClose />\n <PayloadButton\n buttonStyle=\"error\"\n onClick={() => {\n void confirmDelete().catch((err: unknown) =>\n toast.error(err instanceof Error ? err.message : \"Delete failed\"),\n )\n }}\n >\n {t(\"general:confirm\")}\n </PayloadButton>\n </PayloadModalFooter>\n </PayloadModalContent>\n </PayloadModal>\n <button onClick={() => modal.openModal(modalSlug)} type=\"button\">\n {t(\"general:delete\")}\n </button>\n </>\n )\n}\n","\"use client\"\n\nimport {\n CheckboxField,\n Form,\n Pagination,\n Table,\n TextField,\n toast,\n useModal,\n useTranslation,\n Button as PayloadButton,\n} from \"@payloadcms/ui\"\nimport { useRouter } from \"next/navigation\"\nimport React from \"react\"\nimport ReactRaw from \"react\"\nimport { useTransition } from \"react\"\n\nimport { formatMarketingDate } from \"../date-format\"\nimport { useMarketingApi } from \"../use-marketing-api\"\nimport {\n PayloadModal,\n PayloadModalBody,\n PayloadModalClose,\n PayloadModalContent,\n PayloadModalFooter,\n} from \"./payload-modal\"\n\nimport type { MarketingContact } from \"../../types\"\nimport type { Data, FormState } from \"payload\"\n\ninterface ContactsTableProps {\n audienceId: string\n contacts: MarketingContact[]\n}\n\nexport function ContactsTable({ audienceId, contacts }: ContactsTableProps) {\n const [page, setPage] = React.useState(1)\n const [limit] = React.useState(100)\n const currentPage = React.useMemo(\n () => contacts.slice((page - 1) * limit, page * limit),\n [contacts, limit, page],\n )\n\n return (\n <>\n <Table\n columns={[\n {\n Heading: \"First name\",\n accessor: \"firstName\",\n active: true,\n field: { name: \"firstName\", type: \"text\" },\n renderedCells: currentPage.map((contact) => (\n <div key={contact.id}>{contact.firstName ?? \"—\"}</div>\n )),\n },\n {\n Heading: \"Last name\",\n accessor: \"lastName\",\n active: true,\n field: { name: \"lastName\", type: \"text\" },\n renderedCells: currentPage.map((contact) => (\n <div key={contact.id}>{contact.lastName ?? \"—\"}</div>\n )),\n },\n {\n Heading: \"Email\",\n accessor: \"email\",\n active: true,\n field: { name: \"email\", type: \"text\" },\n renderedCells: currentPage.map((contact) => (\n <div key={contact.id}>{contact.email}</div>\n )),\n },\n {\n Heading: \"Created\",\n accessor: \"createdAt\",\n active: true,\n field: { name: \"createdAt\", type: \"text\" },\n renderedCells: currentPage.map((contact) => (\n <div key={contact.id}>{formatMarketingDate(contact.createdAt)}</div>\n )),\n },\n {\n Heading: \"Status\",\n accessor: \"subscribed\",\n active: true,\n field: { name: \"subscribed\", type: \"text\" },\n renderedCells: currentPage.map((contact) => (\n <div key={contact.id} className=\"flex items-center gap-4 flex-wrap\">\n <span>{contact.subscribed !== false ? \"✅ subscribed\" : \"❌ unsubscribed\"}</span>\n <EditContactButton audienceId={audienceId} contact={contact} />\n <DeleteContactButton\n audienceId={audienceId}\n contactEmail={contact.email}\n contactId={contact.id}\n />\n </div>\n )),\n },\n ]}\n data={currentPage as unknown as Record<string, unknown>[]}\n />\n <Pagination\n hasNextPage={page * limit < contacts.length}\n hasPrevPage={page > 1}\n limit={limit}\n onChange={(p) => {\n setPage(p)\n }}\n page={page}\n totalPages={Math.ceil(contacts.length / limit)}\n />\n </>\n )\n}\n\nfunction DeleteContactButton({\n audienceId,\n contactId,\n contactEmail,\n}: {\n audienceId: string\n contactEmail: string\n contactId: string\n}) {\n const modal = useModal()\n const { t } = useTranslation()\n const router = useRouter()\n const { requestJson } = useMarketingApi()\n const modalSlug = `delete-contact_${contactId}`\n\n async function confirmDelete(): Promise<void> {\n await requestJson(\n `/marketing/audiences/${encodeURIComponent(audienceId)}/contacts/${encodeURIComponent(contactId)}`,\n {\n method: \"DELETE\",\n },\n )\n toast.success(t(\"general:deletedSuccessfully\"))\n modal.closeModal(modalSlug)\n router.refresh()\n }\n\n return (\n <>\n <PayloadModal slug={modalSlug}>\n <PayloadModalContent>\n <PayloadModalBody>\n <h1>{t(\"general:confirmDeletion\")}</h1>\n <p>{`Remove contact ${contactEmail}?`}</p>\n </PayloadModalBody>\n <PayloadModalFooter style={{ display: \"flex\", gap: \"8px\", justifyContent: \"flex-end\" }}>\n <PayloadModalClose />\n <PayloadButton\n buttonStyle=\"error\"\n onClick={() => {\n void confirmDelete().catch((err: unknown) =>\n toast.error(err instanceof Error ? err.message : \"Delete failed\"),\n )\n }}\n >\n {t(\"general:confirm\")}\n </PayloadButton>\n </PayloadModalFooter>\n </PayloadModalContent>\n </PayloadModal>\n <button onClick={() => modal.openModal(modalSlug)} type=\"button\">\n {t(\"general:delete\")}\n </button>\n </>\n )\n}\n\nexport function EditContactButton({\n audienceId,\n contact,\n}: {\n audienceId: string\n contact: MarketingContact | null\n}) {\n const modal = useModal()\n const { t } = useTranslation()\n const id = ReactRaw.useId()\n const slug = contact ? `edit-contact_${contact.id}` : `create-contact_${audienceId}_${id}`\n\n const ButtonComp = contact ? \"button\" : PayloadButton\n\n return (\n <>\n <EditContactModalWrapper audienceId={audienceId} contact={contact} modalSlug={slug} />\n <ButtonComp\n {...(contact ? {} : { size: \"large\" })}\n onClick={() => modal.openModal(slug)}\n type=\"button\"\n >\n {contact ? t(\"general:edit\") : t(\"general:createNew\")}\n </ButtonComp>\n </>\n )\n}\n\nfunction EditContactModalWrapper({\n audienceId,\n contact,\n modalSlug,\n}: {\n audienceId: string\n contact: MarketingContact | null\n modalSlug: string\n}) {\n const modal = useModal()\n const { t } = useTranslation()\n const router = useRouter()\n const { requestJson } = useMarketingApi()\n const [, startTransition] = useTransition()\n\n const submit = (fields: FormState, data: Data) => {\n const email = data.email as string\n const firstName = String(data.firstName ?? \"\")\n const lastName = String(data.lastName ?? \"\")\n const subscribed = Boolean(data.subscribed)\n\n startTransition(() => {\n void (async () => {\n try {\n await requestJson(\"/marketing/contacts\", {\n body: JSON.stringify({\n audienceId,\n email,\n firstName,\n id: contact?.id,\n lastName,\n subscribed,\n }),\n method: \"POST\",\n })\n toast.success(contact ? \"Contact updated.\" : \"Contact created.\")\n modal.closeModal(modalSlug)\n router.refresh()\n } catch (err) {\n toast.error(err instanceof Error ? err.message : \"Save failed\")\n }\n })()\n })\n }\n\n return (\n <PayloadModal slug={modalSlug}>\n <PayloadModalContent style={{ width: \"100%\", maxWidth: \"32rem\" }}>\n <PayloadModalBody>\n <h1>{contact ? t(\"general:edit\") : t(\"general:createNew\")}</h1>\n <Form\n className=\"flex w-full flex-col gap-6\"\n initialState={{\n email: {\n value: contact?.email ?? \"\",\n },\n firstName: {\n value: contact?.firstName ?? \"\",\n },\n lastName: {\n value: contact?.lastName ?? \"\",\n },\n subscribed: {\n value: contact?.subscribed !== false,\n },\n }}\n onSubmit={submit}\n waitForAutocomplete\n >\n <TextField\n field={{\n label: t(\"general:email\"),\n name: \"email\",\n required: true,\n type: \"text\",\n }}\n path=\"email\"\n validate={(v) =>\n typeof v === \"string\" && v.includes(\"@\") ? true : \"Valid email required\"\n }\n />\n <TextField\n field={{\n label: \"First name\",\n name: \"firstName\",\n type: \"text\",\n }}\n path=\"firstName\"\n />\n <TextField\n field={{\n label: \"Last name\",\n name: \"lastName\",\n type: \"text\",\n }}\n path=\"lastName\"\n />\n <CheckboxField\n field={{\n label: \"Subscribed\",\n name: \"subscribed\",\n }}\n path=\"subscribed\"\n />\n <PayloadModalFooter style={{ display: \"flex\", gap: \"8px\", justifyContent: \"flex-end\" }}>\n <PayloadModalClose />\n <PayloadButton size=\"large\" type=\"submit\">\n {contact ? t(\"general:save\") : t(\"general:create\")}\n </PayloadButton>\n </PayloadModalFooter>\n </Form>\n </PayloadModalBody>\n </PayloadModalContent>\n </PayloadModal>\n )\n}\n","\"use client\"\n\nimport {\n Button,\n Drawer,\n Form,\n SelectField,\n TextareaField,\n TextField,\n toast,\n useFormFields,\n useModal,\n useTranslation,\n} from \"@payloadcms/ui\"\nimport { useRouter } from \"next/navigation\"\nimport React from \"react\"\n\nimport { useMarketingApi } from \"../use-marketing-api\"\n\nimport type { MarketingAudience } from \"../../types\"\nimport type { Data, FormState } from \"payload\"\n\nconst modalSlug = \"create-marketing-broadcast\"\n\nexport function CreateBroadcastButton({\n audiences,\n emailBroadcastTemplates,\n localeOptions,\n provider,\n}: {\n audiences: MarketingAudience[]\n emailBroadcastTemplates?: { id: string; name: string }[]\n localeOptions?: { label: string; value: string }[]\n provider: string\n}) {\n const modal = useModal()\n const { t } = useTranslation()\n\n return (\n <>\n <CreateBroadcastModal\n audiences={audiences}\n emailBroadcastTemplates={emailBroadcastTemplates}\n localeOptions={localeOptions ?? []}\n provider={provider}\n />\n <Button onClick={() => modal.openModal(modalSlug)} size=\"large\" type=\"button\">\n {t(\"general:createNew\")}\n </Button>\n </>\n )\n}\n\nfunction BroadcastContentFields({\n localeOptions,\n showReactEmailTemplates,\n showTemplateField,\n templateOptions,\n}: {\n localeOptions: { label: string; value: string }[]\n showReactEmailTemplates: boolean\n showTemplateField: boolean\n templateOptions: { id: string; name: string }[]\n}) {\n const broadcastFormat = useFormFields(([fields]) => {\n if (!showReactEmailTemplates) {\n return \"html\"\n }\n const v = fields?.broadcastFormat?.value\n return typeof v === \"string\" && v !== \"\" ? v : \"html\"\n })\n\n if (showReactEmailTemplates) {\n const isHtml = broadcastFormat === \"html\"\n return (\n <>\n <SelectField\n field={{\n label: \"Email content\",\n name: \"broadcastFormat\",\n options: [\n { label: \"<html>\", value: \"html\" },\n ...templateOptions.map((opt) => ({ label: opt.name, value: opt.id })),\n ],\n required: true,\n }}\n path=\"broadcastFormat\"\n />\n {!isHtml && localeOptions.length > 0 ? (\n <SelectField\n field={{\n label: \"Locale\",\n name: \"locale\",\n options: localeOptions,\n required: false,\n }}\n path=\"locale\"\n />\n ) : null}\n {isHtml ? (\n <TextareaField\n field={{\n admin: {\n description: \"Shown when Email content is <html>.\",\n },\n label: \"<html>\",\n name: \"htmlBody\",\n required: true,\n }}\n path=\"htmlBody\"\n />\n ) : null}\n </>\n )\n }\n\n return (\n <>\n {showTemplateField ? (\n <TextField\n field={{\n admin: {\n description:\n \"Optional Mailchimp saved-template id (numeric string). Leave <html> empty when using templates.\",\n },\n label: \"Template id\",\n name: \"templateId\",\n required: false,\n type: \"text\",\n }}\n path=\"templateId\"\n />\n ) : null}\n <TextareaField\n field={{\n admin: {\n description: showTemplateField\n ? \"Optional plain HTML alternative to a Mailchimp template.\"\n : \"HTML broadcast body.\",\n },\n label: showTemplateField ? \"<html> (optional with Mailchimp)\" : \"<html>\",\n name: \"htmlBody\",\n required: !showTemplateField,\n }}\n path=\"htmlBody\"\n />\n </>\n )\n}\n\nfunction CreateBroadcastModal({\n audiences,\n emailBroadcastTemplates,\n localeOptions,\n provider,\n}: {\n audiences: MarketingAudience[]\n emailBroadcastTemplates?: { id: string; name: string }[]\n localeOptions: { label: string; value: string }[]\n provider: string\n}) {\n const router = useRouter()\n const modal = useModal()\n const { t } = useTranslation()\n const { requestJson } = useMarketingApi()\n const [isPending, setIsPending] = React.useState(false)\n\n const showTemplateField = provider === \"mailchimp\"\n const templateOptions = emailBroadcastTemplates ?? []\n const showReactEmailTemplates = provider === \"resend\" && templateOptions.length > 0\n\n const submit = (fields: FormState, data: Data) => {\n const row = data as Record<string, unknown>\n const audienceIdRaw: unknown = row.audienceId\n const nameRaw: unknown = row.name\n const subjectRaw: unknown = row.subject\n const htmlRaw: unknown = row.htmlBody\n const templateIdRaw: unknown = row.templateId\n const replyToRaw: unknown = row.replyTo\n\n const broadcastFormatRaw: unknown = row.broadcastFormat\n const localeRaw: unknown = row.locale\n\n const audienceId = typeof audienceIdRaw === \"string\" ? audienceIdRaw : \"\"\n const name = typeof nameRaw === \"string\" ? nameRaw.trim() : \"\"\n const subject = typeof subjectRaw === \"string\" ? subjectRaw.trim() : \"\"\n const htmlBody = typeof htmlRaw === \"string\" ? htmlRaw.trim() : \"\"\n const templateId = typeof templateIdRaw === \"string\" ? templateIdRaw.trim() : \"\"\n const replyTo = typeof replyToRaw === \"string\" ? replyToRaw.trim() : \"\"\n const broadcastFormat =\n typeof broadcastFormatRaw === \"string\" ? broadcastFormatRaw.trim() : \"html\"\n const locale = typeof localeRaw === \"string\" ? localeRaw.trim() : \"\"\n\n setIsPending(true)\n void (async () => {\n try {\n if (!audienceId || !name || !subject) {\n throw new Error(\"Audience, name, and subject are required.\")\n }\n\n const mailchimpMode = showTemplateField\n const usingReactTemplate = showReactEmailTemplates && broadcastFormat !== \"html\"\n\n if (showReactEmailTemplates) {\n if (usingReactTemplate) {\n await requestJson(\"/marketing/broadcasts\", {\n body: JSON.stringify({\n audienceId,\n emailTemplateId: broadcastFormat,\n locale: locale || undefined,\n name,\n replyTo,\n subject,\n }),\n method: \"POST\",\n })\n } else if (!htmlBody) {\n throw new Error(\"<html> is required when using the <html> content option.\")\n } else {\n await requestJson(\"/marketing/broadcasts\", {\n body: JSON.stringify({\n audienceId,\n html: htmlBody,\n name,\n replyTo,\n subject,\n }),\n method: \"POST\",\n })\n }\n } else if (mailchimpMode) {\n if (!templateId && !htmlBody) {\n throw new Error(\"Provide <html> or a Mailchimp template id.\")\n }\n if (templateId && htmlBody) {\n throw new Error(\"Use either <html> or Mailchimp template id, not both.\")\n }\n await requestJson(\"/marketing/broadcasts\", {\n body: JSON.stringify({\n audienceId,\n html: htmlBody,\n name,\n replyTo,\n subject,\n templateId: templateId || undefined,\n }),\n method: \"POST\",\n })\n } else if (!htmlBody) {\n throw new Error(\"<html> is required for this provider.\")\n } else {\n await requestJson(\"/marketing/broadcasts\", {\n body: JSON.stringify({\n audienceId,\n html: htmlBody,\n name,\n replyTo,\n subject,\n }),\n method: \"POST\",\n })\n }\n\n modal.closeModal(modalSlug)\n toast.success(t(\"general:successfullyCreated\", { label: \"Broadcast\" }))\n router.refresh()\n } catch (err) {\n toast.error(err instanceof Error ? err.message : \"Create failed\")\n } finally {\n setIsPending(false)\n }\n })()\n }\n\n return (\n <Drawer slug={modalSlug} title={t(\"general:createNew\")}>\n <Form\n className=\"flex w-full flex-col gap-8\"\n initialState={showReactEmailTemplates ? { broadcastFormat: { value: \"html\" } } : {}}\n onSubmit={submit}\n waitForAutocomplete\n >\n <SelectField\n field={{\n label: \"Audience\",\n name: \"audienceId\",\n options: audiences.map((a) => ({ label: a.name, value: a.id })),\n required: true,\n }}\n path=\"audienceId\"\n />\n <TextField\n field={{\n label: \"Campaign name\",\n name: \"name\",\n required: true,\n type: \"text\",\n }}\n path=\"name\"\n />\n <TextField\n field={{\n label: \"Subject\",\n name: \"subject\",\n required: true,\n type: \"text\",\n }}\n path=\"subject\"\n />\n <TextField\n field={{\n label: \"Reply-to (optional)\",\n name: \"replyTo\",\n type: \"text\",\n }}\n path=\"replyTo\"\n />\n\n <BroadcastContentFields\n localeOptions={localeOptions}\n showReactEmailTemplates={showReactEmailTemplates}\n showTemplateField={showTemplateField}\n templateOptions={templateOptions}\n />\n\n <Button className=\"w-full\" disabled={isPending} type=\"submit\">\n {t(\"general:create\")}\n </Button>\n </Form>\n </Drawer>\n )\n}\n","import type {\n MarketingAdapter,\n MarketingEffectivePermissions,\n MarketingEmailBroadcastTemplate,\n MarketingPluginPermissions,\n} from \"./types\"\nimport type { Payload, PayloadRequest } from \"payload\"\n\nexport const MARKETING_CUSTOM_CONFIG_KEY = \"payloadPluginMarketing\"\n\nexport interface MarketingIntegrationState {\n adapter: MarketingAdapter\n adminBasePath: string\n emailBroadcastTemplates?: MarketingEmailBroadcastTemplate[]\n permissions?: MarketingPluginPermissions\n}\n\nfunction effectiveResource(slice: { read?: boolean; write?: boolean } | undefined): {\n read: boolean\n write: boolean\n} {\n return {\n read: slice?.read ?? true,\n write: slice?.write ?? true,\n }\n}\n\n/** Resolves endpoint access flags. If `permissions` is absent (plugin option omitted), all actions are allowed for authenticated users. */\nexport function resolveMarketingPermissions(\n permissions: MarketingPluginPermissions | undefined,\n): MarketingEffectivePermissions {\n if (!permissions) {\n return {\n audiences: { read: true, write: true },\n broadcasts: { read: true, write: true },\n contacts: { read: true, write: true },\n }\n }\n return {\n audiences: effectiveResource(permissions.audiences),\n contacts: effectiveResource(permissions.contacts),\n broadcasts: effectiveResource(permissions.broadcasts),\n }\n}\n\nexport function marketingMetaAllowed(effective: MarketingEffectivePermissions): boolean {\n return effective.audiences.read || effective.contacts.read || effective.broadcasts.read\n}\n\nfunction readIntegration(payload: Payload): MarketingIntegrationState | undefined {\n const custom = payload.config.custom as Record<string, unknown> | undefined\n if (!custom || typeof custom !== \"object\") {\n return undefined\n }\n const slice = custom[MARKETING_CUSTOM_CONFIG_KEY] as MarketingIntegrationState | undefined\n if (!slice?.adapter) {\n return undefined\n }\n return slice\n}\n\nexport function getMarketingIntegration(payload: Payload): MarketingIntegrationState {\n const state = readIntegration(payload)\n if (!state) {\n throw new Error(\n `${MARKETING_CUSTOM_CONFIG_KEY}: adapter missing on Payload config. Is marketingPlugin() registered?`,\n )\n }\n return state\n}\n\nexport function tryGetMarketingIntegration(\n payload: Payload,\n): MarketingIntegrationState | undefined {\n return readIntegration(payload)\n}\n\nexport function getMarketingIntegrationFromRequest(req: PayloadRequest): MarketingIntegrationState {\n return getMarketingIntegration(req.payload)\n}\n","import { DefaultTemplate } from \"@payloadcms/next/templates\"\n\nimport type { AdminViewServerProps } from \"payload\"\nimport type { ReactNode } from \"react\"\n\ntype ShellProps = Pick<AdminViewServerProps, \"initPageResult\" | \"params\" | \"searchParams\"> & {\n children: ReactNode\n}\n\nexport function MarketingViewShell({ children, initPageResult, params, searchParams }: ShellProps) {\n return (\n <DefaultTemplate\n i18n={initPageResult.req.i18n}\n locale={initPageResult.locale}\n params={params}\n payload={initPageResult.req.payload}\n permissions={initPageResult.permissions}\n searchParams={searchParams}\n user={initPageResult.req.user ?? undefined}\n visibleEntities={initPageResult.visibleEntities}\n >\n {children}\n </DefaultTemplate>\n )\n}\n","import type { AdminViewServerProps } from \"payload\"\n\nfunction firstString(value: string | string[] | undefined): string | undefined {\n if (typeof value === \"string\" && value.trim()) {\n return value.trim()\n }\n if (Array.isArray(value) && typeof value[0] === \"string\" && value[0].trim()) {\n return value[0].trim()\n }\n return undefined\n}\n\n/** Resolve audience id from custom admin view params (`:id` or URL segments). */\nexport function marketingAudienceIdFromParams(\n params: AdminViewServerProps[\"params\"] | undefined,\n): string | undefined {\n if (!params) {\n return undefined\n }\n\n const fromId = firstString(params.id)\n if (fromId) {\n return fromId\n }\n\n const segmentsRaw = params.segments\n const segmentList: string[] = Array.isArray(segmentsRaw)\n ? segmentsRaw.filter((s): s is string => typeof s === \"string\" && s.length > 0)\n : typeof segmentsRaw === \"string\"\n ? segmentsRaw.split(\"/\").filter(Boolean)\n : []\n\n if (segmentList.length === 0) {\n return undefined\n }\n\n const audienceIdx = segmentList.lastIndexOf(\"audience\")\n if (audienceIdx >= 0 && segmentList[audienceIdx + 1]) {\n return segmentList[audienceIdx + 1]\n }\n\n const last = segmentList[segmentList.length - 1]\n if (last === \"audience\") {\n return undefined\n }\n return last\n}\n","import { Gutter, Link, Table } from \"@payloadcms/ui\"\nimport { CreateAudienceButton, DeleteAudienceButton } from \"../client\"\nimport { Suspense } from \"react\"\n\nimport {\n getMarketingIntegration,\n resolveMarketingPermissions,\n tryGetMarketingIntegration,\n} from \"../../marketing-integration\"\nimport { marketingAdminHref } from \"../paths\"\nimport { MarketingViewShell } from \"./marketing-view-shell\"\n\nimport type { AdminViewServerProps } from \"payload\"\n\nexport type AudienceListViewProps = AdminViewServerProps & {\n basePath?: string\n}\n\nexport default function AudienceList({\n basePath = \"\",\n initPageResult,\n params,\n searchParams,\n}: AudienceListViewProps) {\n return (\n <MarketingViewShell initPageResult={initPageResult} params={params} searchParams={searchParams}>\n <Gutter>\n <AudienceListBody basePath={basePath} initPageResult={initPageResult} />\n </Gutter>\n </MarketingViewShell>\n )\n}\n\nfunction AudienceListBody({\n basePath,\n initPageResult,\n}: {\n basePath: string\n initPageResult: AdminViewServerProps[\"initPageResult\"]\n}) {\n const integration = tryGetMarketingIntegration(initPageResult.req.payload)\n if (!integration) {\n return (\n <p role=\"alert\">Marketing plugin is not configured (missing adapter on Payload config).</p>\n )\n }\n\n const effective = resolveMarketingPermissions(integration.permissions)\n if (!effective.audiences.read) {\n return <p role=\"alert\">You do not have permission to view audiences.</p>\n }\n\n const audiencesUrl = integration.adapter.urls?.audiences\n\n return (\n <>\n <header className=\"flex flex-col gap-4\">\n <h1>Audiences</h1>\n {audiencesUrl ? (\n <Link href={audiencesUrl} rel=\"noreferrer noopener\" target=\"_blank\">\n View audiences in {integration.adapter.label}\n </Link>\n ) : null}\n </header>\n\n <div className=\"mt-4 flex flex-col gap-8\">\n {effective.audiences.write ? (\n <div>\n <CreateAudienceButton />\n </div>\n ) : null}\n <Suspense fallback={<div aria-busy style={{ minHeight: \"4rem\" }} />}>\n <AudienceTableRows\n audiencesWrite={effective.audiences.write}\n basePath={basePath}\n initPageResult={initPageResult}\n />\n </Suspense>\n </div>\n </>\n )\n}\n\nasync function AudienceTableRows({\n audiencesWrite,\n basePath,\n initPageResult,\n}: {\n audiencesWrite: boolean\n basePath: string\n initPageResult: AdminViewServerProps[\"initPageResult\"]\n}) {\n const { adapter } = getMarketingIntegration(initPageResult.req.payload)\n const audiences = await adapter.audiences.list()\n\n const nameColumn = {\n Heading: \"Name\",\n accessor: \"name\",\n active: true,\n field: { name: \"name\", type: \"text\" as const },\n renderedCells: audiences.map((audience) => (\n <div key={audience.id}>\n <Link href={marketingAdminHref(basePath, \"audience\", audience.id)}>{audience.name}</Link>\n </div>\n )),\n }\n\n const deleteColumn = {\n Heading: \"\",\n accessor: \"\",\n active: true,\n field: { name: \"_delete\", type: \"text\" as const },\n renderedCells: audiences.map((audience) => (\n <div key={audience.id}>\n <DeleteAudienceButton audienceId={audience.id} audienceName={audience.name} />\n </div>\n )),\n }\n\n return (\n <Table\n columns={audiencesWrite ? [nameColumn, deleteColumn] : [nameColumn]}\n data={audiences as unknown as Record<string, unknown>[]}\n />\n )\n}\n","import { Gutter, Link } from \"@payloadcms/ui\"\nimport {\n BroadcastsTable,\n CreateBroadcastButton,\n type MarketingBroadcastRow,\n} from \"../client\"\nimport { Suspense } from \"react\"\n\nimport {\n getMarketingIntegration,\n resolveMarketingPermissions,\n tryGetMarketingIntegration,\n} from \"../../marketing-integration\"\nimport { getLocaleSelectOptionsFromConfig } from \"../locale-options\"\nimport { MarketingViewShell } from \"./marketing-view-shell\"\n\nimport type { AdminViewServerProps } from \"payload\"\n\nexport type BroadcastListViewProps = AdminViewServerProps & {\n basePath?: string\n}\n\nexport default function BroadcastList({\n initPageResult,\n params,\n searchParams,\n}: BroadcastListViewProps) {\n return (\n <MarketingViewShell initPageResult={initPageResult} params={params} searchParams={searchParams}>\n <Gutter>\n <BroadcastListBody initPageResult={initPageResult} />\n </Gutter>\n </MarketingViewShell>\n )\n}\n\nfunction BroadcastListBody({\n initPageResult,\n}: {\n initPageResult: AdminViewServerProps[\"initPageResult\"]\n}) {\n const integration = tryGetMarketingIntegration(initPageResult.req.payload)\n if (!integration) {\n return (\n <p role=\"alert\">Marketing plugin is not configured (missing adapter on Payload config).</p>\n )\n }\n\n const effective = resolveMarketingPermissions(integration.permissions)\n if (!effective.broadcasts.read) {\n return <p role=\"alert\">You do not have permission to view broadcasts.</p>\n }\n\n const { adapter } = getMarketingIntegration(initPageResult.req.payload)\n const broadcastsUrl = adapter.urls?.broadcasts\n\n return (\n <>\n <header className=\"flex flex-col gap-4\">\n <h1>Campaigns</h1>\n {broadcastsUrl ? (\n <Link href={broadcastsUrl} rel=\"noreferrer noopener\" target=\"_blank\">\n View campaigns in {adapter.label}\n </Link>\n ) : null}\n </header>\n\n <div className=\"mt-4 flex flex-col gap-8\">\n {effective.broadcasts.write ? (\n <div>\n <Suspense fallback={<div aria-busy style={{ minHeight: \"2.5rem\" }} />}>\n <CreateBroadcastRegion initPageResult={initPageResult} />\n </Suspense>\n </div>\n ) : null}\n <Suspense fallback={<div aria-busy style={{ minHeight: \"4rem\" }} />}>\n <BroadcastTableRegion initPageResult={initPageResult} />\n </Suspense>\n </div>\n </>\n )\n}\n\nasync function CreateBroadcastRegion({\n initPageResult,\n}: {\n initPageResult: AdminViewServerProps[\"initPageResult\"]\n}) {\n const integration = getMarketingIntegration(initPageResult.req.payload)\n const { adapter } = integration\n const audiences = await adapter.audiences.list()\n const emailBroadcastTemplates =\n integration.emailBroadcastTemplates?.map(({ id, name }) => ({ id, name })) ?? []\n const localeOptions = getLocaleSelectOptionsFromConfig(initPageResult.req.payload.config)\n return (\n <CreateBroadcastButton\n audiences={audiences}\n emailBroadcastTemplates={emailBroadcastTemplates}\n localeOptions={localeOptions}\n provider={adapter.provider}\n />\n )\n}\n\nasync function BroadcastTableRegion({\n initPageResult,\n}: {\n initPageResult: AdminViewServerProps[\"initPageResult\"]\n}) {\n const { adapter } = getMarketingIntegration(initPageResult.req.payload)\n const rows = await adapter.broadcasts.list()\n const broadcasts: MarketingBroadcastRow[] = rows.map((b) => ({\n ...b,\n externalDashboardUrl: adapter.urls?.broadcast?.(b.id),\n }))\n\n return <BroadcastsTable broadcasts={broadcasts} />\n}\n","import type { Locale, SanitizedConfig } from \"payload\"\n\nfunction labelForLocale(loc: Locale): string {\n const { label, code } = loc\n if (typeof label === \"string\") {\n return label\n }\n if (label && typeof label === \"object\") {\n for (const value of Object.values(label)) {\n if (typeof value === \"string\") {\n return value\n }\n }\n }\n return code\n}\n\n/** Options for admin selects; values are locale codes from `config.localization.locales`. */\nexport function getLocaleSelectOptionsFromConfig(\n config: SanitizedConfig,\n): { label: string; value: string }[] {\n const raw = config.localization\n if (raw === false || raw === undefined) {\n return []\n }\n const locales = raw.locales\n if (!locales?.length) {\n return []\n }\n return locales.map((locItem: Locale) => ({\n label: labelForLocale(locItem),\n value: locItem.code,\n }))\n}\n"],"mappings":"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","names":["Gutter","Link","notFound","joinAdminSegments","adminRoute","segments","trimmedAdmin","body","s","segment","marketingAdminHref","basePath","parts","useConfig","useCallback","useMemo","useMarketingApi","context","base","requestJson","pathSegment","init","_headersIgnored","restInit","headers","res","detail","parsed","PayloadButton","DateTimeField","Form","Pagination","Pill","Table","toast","useModal","useTranslation","Link","useRouter","React","formatMarketingDate","iso","d","Button","Modal","useModal","useTranslation","React","jsx","cn","parts","PayloadModalContext","PayloadModal","children","className","modalSlug","props","loaded","setLoaded","PayloadModalContent","PayloadModalBody","PayloadModalTitle","PayloadModalFooter","PayloadModalClose","t","modal","Fragment","jsx","jsxs","BroadcastsTable","broadcasts","page","setPage","React","limit","currentPage","Table","b","formatMarketingDate","broadcast","BroadcastStatusPill","Link","Pill","DeleteBroadcastButton","SendBroadcastButton","Pagination","p","status","broadcastId","broadcastName","modal","useModal","t","useTranslation","router","useRouter","requestJson","useMarketingApi","modalSlug","confirmDelete","toast","PayloadModal","PayloadModalContent","PayloadModalBody","PayloadModalTitle","PayloadModalFooter","PayloadModalClose","PayloadButton","err","submit","fields","data","scheduledRaw","scheduledAt","Form","DateTimeField","Button","Form","TextField","toast","useModal","useTranslation","PayloadButton","useRouter","useTransition","Fragment","jsx","jsxs","createAudienceSlug","CreateAudienceButton","modal","useModal","t","useTranslation","CreateAudienceModal","Button","router","useRouter","requestJson","useMarketingApi","isPending","startTransition","useTransition","PayloadModal","PayloadModalContent","Form","fields","data","nameRaw","name","toast","err","PayloadModalBody","PayloadModalTitle","TextField","v","PayloadModalFooter","PayloadModalClose","DeleteAudienceButton","audienceId","audienceName","modalSlug","confirmDelete","PayloadButton","CheckboxField","Form","Pagination","Table","TextField","toast","useModal","useTranslation","PayloadButton","useRouter","React","ReactRaw","useTransition","Fragment","jsx","jsxs","ContactsTable","audienceId","contacts","page","setPage","React","limit","currentPage","Table","contact","formatMarketingDate","EditContactButton","DeleteContactButton","Pagination","p","contactId","contactEmail","modal","useModal","t","useTranslation","router","useRouter","requestJson","useMarketingApi","modalSlug","confirmDelete","toast","PayloadModal","PayloadModalContent","PayloadModalBody","PayloadModalFooter","PayloadModalClose","PayloadButton","err","id","ReactRaw","slug","EditContactModalWrapper","startTransition","useTransition","submit","fields","data","email","firstName","lastName","subscribed","Form","TextField","v","CheckboxField","Button","Drawer","Form","SelectField","TextareaField","TextField","toast","useFormFields","useModal","useTranslation","useRouter","React","Fragment","jsx","jsxs","modalSlug","CreateBroadcastButton","audiences","emailBroadcastTemplates","localeOptions","provider","modal","useModal","t","useTranslation","CreateBroadcastModal","Button","BroadcastContentFields","showReactEmailTemplates","showTemplateField","templateOptions","broadcastFormat","useFormFields","fields","v","isHtml","SelectField","opt","TextareaField","TextField","router","useRouter","requestJson","useMarketingApi","isPending","setIsPending","React","submit","data","row","audienceIdRaw","nameRaw","subjectRaw","htmlRaw","templateIdRaw","replyToRaw","broadcastFormatRaw","localeRaw","audienceId","name","subject","htmlBody","templateId","replyTo","locale","mailchimpMode","usingReactTemplate","toast","err","Drawer","Form","a","Suspense","MARKETING_CUSTOM_CONFIG_KEY","effectiveResource","slice","resolveMarketingPermissions","permissions","readIntegration","payload","custom","slice","MARKETING_CUSTOM_CONFIG_KEY","getMarketingIntegration","state","tryGetMarketingIntegration","DefaultTemplate","jsx","MarketingViewShell","children","initPageResult","params","searchParams","firstString","value","marketingAudienceIdFromParams","params","fromId","segmentsRaw","segmentList","s","audienceIdx","last","Fragment","jsx","jsxs","AudienceDetail","initPageResult","params","searchParams","audienceId","marketingAudienceIdFromParams","MarketingViewShell","Gutter","AudienceDetailBody","integration","tryGetMarketingIntegration","effective","resolveMarketingPermissions","adapter","getMarketingIntegration","audience","notFound","audienceDashboardUrl","Link","EditContactButton","Suspense","DetailContacts","contacts","ContactsTable","Gutter","Link","Table","Suspense","Fragment","jsx","jsxs","AudienceList","basePath","initPageResult","params","searchParams","MarketingViewShell","Gutter","AudienceListBody","integration","tryGetMarketingIntegration","effective","resolveMarketingPermissions","audiencesUrl","Link","CreateAudienceButton","Suspense","AudienceTableRows","audiencesWrite","adapter","getMarketingIntegration","audiences","nameColumn","audience","marketingAdminHref","deleteColumn","DeleteAudienceButton","Table","Gutter","Link","Suspense","labelForLocale","loc","label","code","value","getLocaleSelectOptionsFromConfig","config","raw","locales","locItem","Fragment","jsx","jsxs","BroadcastList","initPageResult","params","searchParams","MarketingViewShell","Gutter","BroadcastListBody","integration","tryGetMarketingIntegration","effective","resolveMarketingPermissions","adapter","getMarketingIntegration","broadcastsUrl","Link","Suspense","CreateBroadcastRegion","BroadcastTableRegion","audiences","emailBroadcastTemplates","id","name","localeOptions","getLocaleSelectOptionsFromConfig","CreateBroadcastButton","broadcasts","b","BroadcastsTable"]}
@@ -1 +1 @@
1
- {"version":3,"file":"use-marketing-api.d.ts","sourceRoot":"","sources":["../../src/admin/use-marketing-api.ts"],"names":[],"mappings":"AAKA,wBAAgB,eAAe;;+BAYP,MAAM,SAAS,WAAW,KAAG,OAAO,CAAC,OAAO,CAAC;EA4CpE"}
1
+ {"version":3,"file":"use-marketing-api.d.ts","sourceRoot":"","sources":["../../src/admin/use-marketing-api.ts"],"names":[],"mappings":"AAKA,wBAAgB,eAAe;;+BAYP,MAAM,SAAS,WAAW,KAAG,OAAO,CAAC,OAAO,CAAC;EAwCpE"}
@@ -1,2 +1,2 @@
1
1
  function d(e,n){if(!n)return e;let{overrides:t,...i}=n;return{...e,...i,...t??{},admin:{..."admin"in e?e.admin:void 0,...i.admin??{},...t?.admin??{}}}}function y(e){return{type:"row",fields:e}}function I(e,n,t){let i=t?.fields??{};return{...{slug:e,labels:t?.labels??n,fields:[y([d({name:"name",type:"text",label:"Name (lowercase, no special characters)",required:!0,admin:{width:"50%"}},i.name),d({name:"label",type:"text",label:"Label",localized:!0,admin:{width:"50%"}},i.label)]),y([d({name:"width",type:"number",label:"Field Width (percentage)",admin:{width:"20%"}},i.width),d({name:"placeholder",type:"text",label:"Placeholder",localized:!0,admin:{width:"40%"}},i.placeholder),d({name:"defaultValue",type:"text",label:"Default Value",localized:!0,admin:{width:"40%"}},i.defaultValue)]),d({name:"required",type:"checkbox",label:"Required"},i.required)]},...t?.overrides??{}}}function R(e){let n=e?.fields??{};return{...{slug:"acceptance",labels:e?.labels??{singular:"Acceptance",plural:"Acceptances"},fields:[y([d({name:"name",type:"text",label:"Name (lowercase, no special characters)",required:!0,admin:{width:"50%"}},n.name),d({name:"label",type:"richText",label:"Label",localized:!0,admin:{width:"50%"}},n.label)]),y([d({name:"width",type:"number",label:"Field Width (percentage)",admin:{width:"50%"}},n.width),d({name:"required",type:"checkbox",label:"Required"},n.required)])]},...e?.overrides??{}}}function k(e={}){return{url:I("url",{singular:"URL",plural:"URLs"},e.url||void 0),phone:I("phone",{singular:"Phone",plural:"Phones"},e.phone||void 0),acceptance:R(e.acceptance||void 0)}}var h="__website",w="__startedAt",H=1500,T={acceptance:5,checkbox:5,country:200,date:100,email:320,message:5e3,number:64,payment:1e3,phone:50,select:200,state:200,text:200,textarea:5e3,upload:1e3,url:2048};function U(e){return e===h||e===w}function z(e){let n=e.find(i=>i.field===h)?.value,t=e.find(i=>i.field===w)?.value;return{honeypot:typeof n=="string"?n:"",startedAt:typeof t=="string"||typeof t=="number"?String(t):""}}function D(e){return typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e)?String(e):typeof e=="string"?e.trim():""}function j(e,n){if(!n)return!e.required;if(n.length>(T[e.blockType]??1e3))return!1;if(e.blockType==="email")return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(n);if(e.blockType==="url")try{return new URL(n),!0}catch{return!1}return e.blockType==="number"?Number.isFinite(Number(n)):e.blockType==="checkbox"||e.blockType==="acceptance"?n==="true"||n==="false":e.blockType==="select"&&e.options?.length?e.options.some(t=>t.value===n):!0}function $(e,n){return e.required?e.blockType==="acceptance"?n==="true":!!n:!0}function S(e){let n=z(e.submissionData??[]);if(n.honeypot.trim())return{ok:!1,error:"Invalid submission."};let t=Number(n.startedAt);if(!Number.isFinite(t))return{ok:!1,error:"Invalid submission."};if(e.now-t<1500)return{ok:!1,error:"Form submitted too quickly."};let i=e.formFields.flatMap(a=>a.name&&a.blockType in T?[{...a,name:a.name}]:[]),r=new Map(i.map(a=>[a.name,a])),s=[],l=new Set;for(let a of e.submissionData??[]){let o=a.field?.trim();if(!o||U(o))continue;if(l.has(o))return{ok:!1,error:`Field "${o}" was submitted more than once.`};l.add(o);let c=r.get(o);if(!c)return{ok:!1,error:`Unexpected field "${o}".`};let u=D(a.value);if(!j(c,u))return{ok:!1,error:`Field "${o}" is invalid.`};s.push({field:o,value:u})}for(let a of i){let o=s.find(c=>c.field===a.name)?.value;if(!$(a,o))return{ok:!1,error:`Field "${a.name}" is required.`}}return{ok:!0,data:s}}function B(e){return Object.fromEntries(e.flatMap(n=>n.field?[[n.field,D(n.value)]]:[]))}function N(e,n){return e.replace(/\{\{\s*([\w.-]+)\s*\}\}/g,(t,i)=>n[i]??"")}function M(e,n){return(e??"").split(",").map(t=>N(t,n).trim()).filter(Boolean)}function x(e,n){let t=e.submissionData?.find(i=>i.field===n)?.value;if(typeof t=="string")return t;if(t!=null&&(typeof t=="number"&&Number.isFinite(t)||typeof t=="boolean"))return String(t)}async function P(e,n,t="forms"){return typeof e.form=="string"?await n.payload.findByID({collection:t,depth:0,id:e.form,overrideAccess:!0}):e.form}function C(e={}){return async({data:n,operation:t,req:i})=>{if(t!=="create")return n;let r=await P(n,i,e.formsSlug),s=S({formFields:r?.fields??[],now:Date.now(),submissionData:n?.submissionData??[]});if(!s.ok)throw new Error(s.error);return n.submissionData=s.data,n}}function O(e,n={}){return async({data:t,operation:i,req:r})=>{if(i!=="create")return t;let l=await P(t,r,n.formsSlug);if(l?.event!=="lead"||!l.audienceId)return t;let a=t,o=x(a,"email");if(!o)return t;let c=B(a.submissionData??[]),u=M(l.tags,c);return await e.contacts.upsert({audienceId:l.audienceId,email:o,firstName:x(a,"firstName"),lastName:x(a,"lastName"),properties:u.length>0?{tags:u.join(",")}:void 0,subscribed:!0}),t}}var W=new Set(["acceptance","checkbox","message","payment","upload"]);function p(e){return{type:"row",fields:e}}function m(e){return typeof e=="object"&&e!==null&&"type"in e&&e.type==="row"&&"fields"in e&&Array.isArray(e.fields)}function G(e){let n=new Map;function t(i){for(let r of i)"name"in r&&typeof r.name=="string"&&n.set(r.name,r),m(r)&&t(r.fields)}return t(e),n}function _(e,n){let t="admin"in e&&e.admin&&typeof e.admin=="object"?e.admin:{};return{...e,admin:{...t,width:n}}}function g(e,n){let t={name:"width",type:"number",label:"Field Width (percentage)",admin:{width:"20%"}},i=n?d(t,n):t;return i=d(i,e?.fields?.width),_(i,"20%")}function F(e,n){let t=e.get("placeholder"),i={name:"placeholder",type:"text",label:"Placeholder",localized:!0,admin:{width:"40%"}},r=t?d(i,t):i;return r=d(r,n?.fields?.placeholder),_(r,"40%")}function b(e,n,t){let i={...t,admin:{..."admin"in t&&t.admin&&typeof t.admin=="object"?t.admin:{},width:"40%"}},r=n?d(i,n):i;return r=d(r,e?.fields?.defaultValue),_(r,"40%")}function v(e,n){let t=e.slug;if(!t||W.has(t))return e;let i=[...e.fields],r=G(i);if(t==="text"||t==="textarea"||t==="radio"){let s=i[1];if(!m(s))return e;let l=p([g(n,r.get("width")),F(r,n),b(n,r.get("defaultValue"),{name:"defaultValue",type:"text",label:"Default Value",localized:!0})]);return{...e,fields:[i[0],l,...i.slice(2)]}}if(t==="number"){let s=i[1];if(!m(s))return e;let l=p([g(n,r.get("width")),F(r,n),b(n,r.get("defaultValue"),{name:"defaultValue",type:"number",label:"Default Value"})]);return{...e,fields:[i[0],l,...i.slice(2)]}}if(t==="select"){let s=i[1],l=i[2];if(!m(s))return e;let a=m(l)&&l.fields.length===1&&"name"in l.fields[0]&&l.fields[0].name==="placeholder",o=p([g(n,r.get("width")),F(r,n),b(n,r.get("defaultValue"),{name:"defaultValue",type:"text",label:"Default Value",localized:!0})]),c=a?3:2;return{...e,fields:[i[0],o,...i.slice(c)]}}if(t==="email"||t==="state"||t==="country"){let s=i[0],l=i[1],a=i.slice(2);if(!m(s)||!l||!("name"in l)||l.name!=="width")return e;let o=p([g(n,r.get("width")),F(r,n),b(n,r.get("defaultValue"),{name:"defaultValue",type:"text",label:"Default Value",localized:!0})]);return{...e,fields:[s,o,...a]}}if(t==="date"){let s=i[0],l=i[1],a=i[2];if(!m(s)||!m(l)||!a||!("name"in a)||a.name!=="defaultValue")return e;let o=l.fields.find(u=>"name"in u&&u.name==="required");if(!o)return e;let c=p([g(n,r.get("width")),F(r,n),b(n,r.get("defaultValue"),{name:"defaultValue",type:"date",label:"Default Value"})]);return{...e,fields:[s,c,o]}}return e}function V(e,n){return"name"in e&&e.name===n}function E(e){return!!(e&&typeof e=="object"&&"slug"in e&&typeof e.slug=="string")}function L(e){return!!(e&&typeof e=="object")}function K(e,n){return!("name"in n)||!n.name?[...e,n]:e.some(t=>V(t,n.name))?e.map(t=>V(t,n.name)?n:t):[...e,n]}function Y(e){let n=e.admin?.components?.audienceSelect??{path:"payload-plugin-marketing/admin",exportName:"AudienceSelect"};return[{name:"event",type:"select",defaultValue:"submission",options:[{label:"Submission",value:"submission"},{label:"Lead",value:"lead"}]},{name:"audienceId",type:"text",label:"Audience ID",required:!1,admin:{condition:(t,i)=>i?.event==="lead",components:{Field:n}},validate:(t,{siblingData:i}={})=>i?.event==="lead"&&!t?"Audience is required for lead forms.":!0},{name:"tags",type:"textarea",label:"Tags",admin:{condition:(t,i)=>i?.event==="lead",description:"Optional comma-separated tags. Use {{fieldName}} to insert submitted values."}}]}function X(e,n){let t=[...e.fields],i=t.findIndex(u=>V(u,"fields")&&u.type==="blocks");if(i<0){if(n.formBuilder?.strict===!1)return e;throw new Error(`Could not find a blocks field named "fields" on form-builder forms collection "${e.slug}".`)}let r=t[i],s=Array.isArray(r.blocks)?r.blocks:[],l=n.formBuilder?.fields??{},a=s.map(u=>{if(!E(u)||!L(u))return u;let f=l[u.slug],q=f&&L(f)?{...u,...f.overrides??{},...f.labels?{labels:f.labels}:{}}:u;return v(q,f)}),o=new Set(a.flatMap(u=>E(u)?[u.slug]:[])),c=Object.values(k(n.formBuilder?.fields)).filter(u=>!o.has(u.slug));t[i]={...r,blocks:[...a,...c]};for(let u of Y(n))t.splice(0,t.length,...K(t,u));return{...e,fields:t}}function J(e,n){let t=e.hooks??{};return{...e,hooks:{...t,beforeChange:[...t.beforeChange??[],C({formsSlug:n.formBuilder?.formsSlug}),O(n.adapter,{formsSlug:n.formBuilder?.formsSlug})]}}}function A(e,n){let t=n.formBuilder?.formsSlug??"forms",i=n.formBuilder?.submissionsSlug??"form-submissions",r=n.formBuilder?.strict??!0,s=e??[],l=s.some(o=>o.slug===t),a=s.some(o=>o.slug===i);if(r&&!l)throw new Error(`Could not find form-builder forms collection "${t}".`);if(r&&!a)throw new Error(`Could not find form-builder submissions collection "${i}".`);return s.map(o=>o.slug===t?X(o,n):o.slug===i?J(o,n):o)}export{R as a,k as b,h as c,w as d,H as e,S as f,B as g,N as h,M as i,C as j,O as k,A as l};
2
- //# sourceMappingURL=chunk-S2EABBIN.js.map
2
+ //# sourceMappingURL=chunk-G6DIJ7B2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/form-builder/fields.ts","../src/form-builder/submission.ts","../src/form-builder/hooks.ts","../src/form-builder/normalize-placeholder-rows.ts","../src/form-builder/mutate-collections.ts"],"sourcesContent":["import type { FieldOverride, MarketingBlockOptions, MarketingFormFieldOverrides } from \"../types\"\nimport type { Block, Field } from \"payload\"\n\nexport const CUSTOM_MARKETING_FIELD_NAMES = [\"url\", \"phone\", \"acceptance\"] as const\n\nexport function mergeField(base: Field, override?: FieldOverride): Field {\n if (!override) {\n return base\n }\n\n const { overrides, ...direct } = override\n return {\n ...base,\n ...direct,\n ...(overrides ?? {}),\n admin: {\n ...(\"admin\" in base ? base.admin : undefined),\n ...(direct.admin ?? {}),\n ...(overrides?.admin ?? {}),\n },\n } as Field\n}\n\nfunction row(fields: Field[]): Field {\n return { type: \"row\", fields } as Field\n}\n\nfunction textLikeBlock(\n slug: \"phone\" | \"url\",\n labels: Required<Block>[\"labels\"],\n options?: MarketingBlockOptions,\n): Block {\n const fields = options?.fields ?? {}\n const block: Block = {\n slug,\n labels: options?.labels ?? labels,\n fields: [\n row([\n mergeField(\n {\n name: \"name\",\n type: \"text\",\n label: \"Name (lowercase, no special characters)\",\n required: true,\n admin: { width: \"50%\" },\n },\n fields.name,\n ),\n mergeField(\n {\n name: \"label\",\n type: \"text\",\n label: \"Label\",\n localized: true,\n admin: { width: \"50%\" },\n },\n fields.label,\n ),\n ]),\n row([\n mergeField(\n {\n name: \"width\",\n type: \"number\",\n label: \"Field Width (percentage)\",\n admin: { width: \"20%\" },\n },\n fields.width,\n ),\n mergeField(\n {\n name: \"placeholder\",\n type: \"text\",\n label: \"Placeholder\",\n localized: true,\n admin: { width: \"40%\" },\n },\n fields.placeholder,\n ),\n mergeField(\n {\n name: \"defaultValue\",\n type: \"text\",\n label: \"Default Value\",\n localized: true,\n admin: { width: \"40%\" },\n },\n fields.defaultValue,\n ),\n ]),\n mergeField({ name: \"required\", type: \"checkbox\", label: \"Required\" }, fields.required),\n ],\n }\n\n return { ...block, ...(options?.overrides ?? {}) }\n}\n\nexport function createAcceptanceBlock(options?: MarketingBlockOptions): Block {\n const fields = options?.fields ?? {}\n const block: Block = {\n slug: \"acceptance\",\n labels: options?.labels ?? { singular: \"Acceptance\", plural: \"Acceptances\" },\n fields: [\n row([\n mergeField(\n {\n name: \"name\",\n type: \"text\",\n label: \"Name (lowercase, no special characters)\",\n required: true,\n admin: { width: \"50%\" },\n },\n fields.name,\n ),\n mergeField(\n {\n name: \"label\",\n type: \"richText\",\n label: \"Label\",\n localized: true,\n admin: { width: \"50%\" },\n },\n fields.label,\n ),\n ]),\n row([\n mergeField(\n {\n name: \"width\",\n type: \"number\",\n label: \"Field Width (percentage)\",\n admin: { width: \"50%\" },\n },\n fields.width,\n ),\n mergeField({ name: \"required\", type: \"checkbox\", label: \"Required\" }, fields.required),\n ]),\n ],\n }\n\n return { ...block, ...(options?.overrides ?? {}) }\n}\n\nexport function createMarketingFormFields(\n overrides: MarketingFormFieldOverrides = {},\n): Record<(typeof CUSTOM_MARKETING_FIELD_NAMES)[number], Block> {\n return {\n url: textLikeBlock(\"url\", { singular: \"URL\", plural: \"URLs\" }, overrides.url || undefined),\n phone: textLikeBlock(\n \"phone\",\n { singular: \"Phone\", plural: \"Phones\" },\n overrides.phone || undefined,\n ),\n acceptance: createAcceptanceBlock(overrides.acceptance || undefined),\n }\n}\n\nexport function createMarketingBlocksForMutation(\n overrides: MarketingFormFieldOverrides = {},\n): Block[] {\n return Object.values(createMarketingFormFields(overrides))\n}\n","export const FORM_HONEYPOT_FIELD = \"__website\"\nexport const FORM_STARTED_AT_FIELD = \"__startedAt\"\nexport const MIN_SUBMISSION_TIME_MS = 1_500\n\nconst MAX_LENGTH_BY_BLOCK: Record<string, number> = {\n acceptance: 5,\n checkbox: 5,\n country: 200,\n date: 100,\n email: 320,\n message: 5_000,\n number: 64,\n payment: 1_000,\n phone: 50,\n select: 200,\n state: 200,\n text: 200,\n textarea: 5_000,\n upload: 1_000,\n url: 2_048,\n}\n\nexport interface ValidationFormField {\n blockType: string\n name?: string | null\n options?: Array<{ value: string }> | null\n required?: boolean | null\n}\n\nexport interface ValidationSubmissionField {\n field?: string | null\n value?: unknown\n}\n\nexport type SubmissionValidationResult =\n | { data: Array<{ field: string; value: string }>; ok: true }\n | { error: string; ok: false }\n\nfunction isControlField(fieldName: string): boolean {\n return fieldName === FORM_HONEYPOT_FIELD || fieldName === FORM_STARTED_AT_FIELD\n}\n\nfunction extractControlFields(submissionData: ValidationSubmissionField[]): {\n honeypot: string\n startedAt: string\n} {\n const honeypot = submissionData.find((entry) => entry.field === FORM_HONEYPOT_FIELD)?.value\n const startedAt = submissionData.find((entry) => entry.field === FORM_STARTED_AT_FIELD)?.value\n return {\n honeypot: typeof honeypot === \"string\" ? honeypot : \"\",\n startedAt:\n typeof startedAt === \"string\" || typeof startedAt === \"number\" ? String(startedAt) : \"\",\n }\n}\n\nfunction stringifySubmissionValue(value: unknown): string {\n if (typeof value === \"boolean\") {\n return String(value)\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value)\n }\n return typeof value === \"string\" ? value.trim() : \"\"\n}\n\nfunction isValidFieldValue(field: ValidationFormField, value: string): boolean {\n if (!value) {\n return !field.required\n }\n if (value.length > (MAX_LENGTH_BY_BLOCK[field.blockType] ?? 1_000)) {\n return false\n }\n if (field.blockType === \"email\") {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n }\n if (field.blockType === \"url\") {\n try {\n new URL(value)\n return true\n } catch {\n return false\n }\n }\n if (field.blockType === \"number\") {\n return Number.isFinite(Number(value))\n }\n if (field.blockType === \"checkbox\" || field.blockType === \"acceptance\") {\n return value === \"true\" || value === \"false\"\n }\n if (field.blockType === \"select\" && field.options?.length) {\n return field.options.some((option) => option.value === value)\n }\n return true\n}\n\nfunction requiredValueIsPresent(field: ValidationFormField, value: string | undefined): boolean {\n if (!field.required) {\n return true\n }\n if (field.blockType === \"acceptance\") {\n return value === \"true\"\n }\n return Boolean(value)\n}\n\nexport function validateSubmissionInput(input: {\n formFields: ValidationFormField[]\n now: number\n submissionData: ValidationSubmissionField[] | null | undefined\n}): SubmissionValidationResult {\n const controlFields = extractControlFields(input.submissionData ?? [])\n if (controlFields.honeypot.trim()) {\n return { ok: false, error: \"Invalid submission.\" }\n }\n const startedAt = Number(controlFields.startedAt)\n if (!Number.isFinite(startedAt)) {\n return { ok: false, error: \"Invalid submission.\" }\n }\n if (input.now - startedAt < MIN_SUBMISSION_TIME_MS) {\n return { ok: false, error: \"Form submitted too quickly.\" }\n }\n\n const supportedFields = input.formFields.flatMap((field) =>\n field.name && field.blockType in MAX_LENGTH_BY_BLOCK ? [{ ...field, name: field.name }] : [],\n )\n const formFieldMap = new Map(supportedFields.map((field) => [field.name, field]))\n const normalized: Array<{ field: string; value: string }> = []\n const seenFields = new Set<string>()\n\n for (const entry of input.submissionData ?? []) {\n const fieldName = entry.field?.trim()\n if (!fieldName || isControlField(fieldName)) {\n continue\n }\n if (seenFields.has(fieldName)) {\n return { ok: false, error: `Field \"${fieldName}\" was submitted more than once.` }\n }\n seenFields.add(fieldName)\n const formField = formFieldMap.get(fieldName)\n if (!formField) {\n return { ok: false, error: `Unexpected field \"${fieldName}\".` }\n }\n const value = stringifySubmissionValue(entry.value)\n if (!isValidFieldValue(formField, value)) {\n return { ok: false, error: `Field \"${fieldName}\" is invalid.` }\n }\n normalized.push({ field: fieldName, value })\n }\n\n for (const field of supportedFields) {\n const value = normalized.find((entry) => entry.field === field.name)?.value\n if (!requiredValueIsPresent(field, value)) {\n return { ok: false, error: `Field \"${field.name}\" is required.` }\n }\n }\n\n return { ok: true, data: normalized }\n}\n\nexport function submissionDataToPlainRecord(\n submissionData: ValidationSubmissionField[],\n): Record<string, string> {\n return Object.fromEntries(\n submissionData.flatMap((entry) =>\n entry.field ? [[entry.field, stringifySubmissionValue(entry.value)]] : [],\n ),\n )\n}\n\nexport function substituteSubmissionPlaceholders(\n template: string,\n values: Record<string, string>,\n): string {\n return template.replace(\n /\\{\\{\\s*([\\w.-]+)\\s*\\}\\}/g,\n (_, fieldName: string) => values[fieldName] ?? \"\",\n )\n}\n\nexport function resolveCommaSeparatedSubmissionTags(\n tags: string | null | undefined,\n values: Record<string, string>,\n): string[] {\n return (tags ?? \"\")\n .split(\",\")\n .map((tag) => substituteSubmissionPlaceholders(tag, values).trim())\n .filter(Boolean)\n}\n","import {\n resolveCommaSeparatedSubmissionTags,\n submissionDataToPlainRecord,\n validateSubmissionInput,\n} from \"./submission\"\n\nimport type { MarketingAdapter } from \"../types\"\nimport type { CollectionBeforeChangeHook, PayloadRequest } from \"payload\"\n\ninterface FormSubmissionData {\n form?: unknown\n submissionData?: Array<{ field?: string | null; value?: unknown }>\n}\n\nfunction getStringField(data: FormSubmissionData, field: string): string | undefined {\n const value = data.submissionData?.find((row) => row.field === field)?.value\n if (typeof value === \"string\") {\n return value\n }\n if (value == null) {\n return undefined\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value)\n }\n if (typeof value === \"boolean\") {\n return String(value)\n }\n return undefined\n}\n\ninterface HookOptions {\n formsSlug?: string\n minSubmitDurationMs?: number\n}\n\nasync function resolveMarketingForm(\n data: { form?: unknown },\n req: PayloadRequest,\n formsSlug = \"forms\",\n): Promise<unknown> {\n if (typeof data.form === \"string\") {\n return await req.payload.findByID({\n collection: formsSlug,\n depth: 0,\n id: data.form,\n overrideAccess: true,\n })\n }\n return data.form\n}\n\nexport function createValidateFormSubmissionHook(\n options: HookOptions = {},\n): CollectionBeforeChangeHook {\n return async ({ data, operation, req }) => {\n if (operation !== \"create\") {\n return data\n }\n const form = await resolveMarketingForm(data as { form?: unknown }, req, options.formsSlug)\n const result = validateSubmissionInput({\n formFields: ((form as { fields?: unknown[] } | undefined)?.fields ?? []) as never,\n now: Date.now(),\n submissionData: (data?.submissionData ?? []) as never,\n })\n if (!result.ok) {\n throw new Error(result.error)\n }\n data.submissionData = result.data\n return data\n }\n}\n\nexport function createCreateLeadHook(\n adapter: MarketingAdapter,\n options: HookOptions = {},\n): CollectionBeforeChangeHook {\n return async ({ data, operation, req }) => {\n if (operation !== \"create\") {\n return data\n }\n const form = await resolveMarketingForm(data as { form?: unknown }, req, options.formsSlug)\n const formRecord = form as\n | { audienceId?: string; event?: string; tags?: string | null }\n | undefined\n if (formRecord?.event !== \"lead\" || !formRecord.audienceId) {\n return data\n }\n\n const submission = data as FormSubmissionData\n const email = getStringField(submission, \"email\")\n if (!email) {\n return data\n }\n\n const fieldValues = submissionDataToPlainRecord(submission.submissionData ?? [])\n const tags = resolveCommaSeparatedSubmissionTags(formRecord.tags, fieldValues)\n await adapter.contacts.upsert({\n audienceId: formRecord.audienceId,\n email,\n firstName: getStringField(submission, \"firstName\"),\n lastName: getStringField(submission, \"lastName\"),\n properties: tags.length > 0 ? { tags: tags.join(\",\") } : undefined,\n subscribed: true,\n })\n return data\n }\n}\n","import { mergeField } from \"./fields\"\n\nimport type { FieldOverride, MarketingBlockOptions } from \"../types\"\nimport type { Block, Field } from \"payload\"\n\n/** Blocks that do not use a free-text style placeholder in the admin or render layer. */\nconst BLOCK_SLUGS_WITHOUT_PLACEHOLDER_ROW = new Set([\n \"acceptance\",\n \"checkbox\",\n \"message\",\n \"payment\",\n \"upload\",\n])\n\nfunction row(fields: Field[]): Field {\n return { type: \"row\", fields }\n}\n\nfunction isRowField(field: Field): field is Field & { type: \"row\"; fields: Field[] } {\n return (\n typeof field === \"object\" &&\n field !== null &&\n \"type\" in field &&\n field.type === \"row\" &&\n \"fields\" in field &&\n Array.isArray((field as { fields: unknown }).fields)\n )\n}\n\nfunction collectNamedFields(fields: Field[]): Map<string, Field> {\n const map = new Map<string, Field>()\n function walk(items: Field[]) {\n for (const item of items) {\n if (\"name\" in item && typeof item.name === \"string\") {\n map.set(item.name, item)\n }\n if (isRowField(item)) {\n walk(item.fields)\n }\n }\n }\n walk(fields)\n return map\n}\n\nfunction withAdminWidth(field: Field, width: string): Field {\n const prevAdmin =\n \"admin\" in field && field.admin && typeof field.admin === \"object\" ? field.admin : {}\n return { ...field, admin: { ...prevAdmin, width } } as Field\n}\n\nfunction widthColumn(override: MarketingBlockOptions | undefined, existing?: Field): Field {\n const base: Field = {\n name: \"width\",\n type: \"number\",\n label: \"Field Width (percentage)\",\n admin: { width: \"20%\" },\n }\n let field = existing ? mergeField(base, existing as FieldOverride) : base\n field = mergeField(field, override?.fields?.width)\n return withAdminWidth(field, \"20%\")\n}\n\nfunction placeholderColumn(\n named: Map<string, Field>,\n override: MarketingBlockOptions | undefined,\n): Field {\n const existing = named.get(\"placeholder\")\n const base: Field = {\n name: \"placeholder\",\n type: \"text\",\n label: \"Placeholder\",\n localized: true,\n admin: { width: \"40%\" },\n }\n let field = existing ? mergeField(base, existing as FieldOverride) : base\n field = mergeField(field, override?.fields?.placeholder)\n return withAdminWidth(field, \"40%\")\n}\n\nfunction defaultValueColumn(\n override: MarketingBlockOptions | undefined,\n existing: Field | undefined,\n fallback: Field,\n): Field {\n const base = {\n ...fallback,\n admin: {\n ...(\"admin\" in fallback && fallback.admin && typeof fallback.admin === \"object\"\n ? fallback.admin\n : {}),\n width: \"40%\",\n },\n } as Field\n let field = existing ? mergeField(base, existing as FieldOverride) : base\n field = mergeField(field, override?.fields?.defaultValue)\n return withAdminWidth(field, \"40%\")\n}\n\n/** Layout: row 2 is width (20%) | placeholder (40%) | defaultValue (40%). */\nexport function normalizeFormBuilderPlaceholderRow(\n block: Block,\n override?: MarketingBlockOptions,\n): Block {\n const slug = block.slug\n if (!slug || BLOCK_SLUGS_WITHOUT_PLACEHOLDER_ROW.has(slug)) {\n return block\n }\n\n const fields = [...block.fields]\n const named = collectNamedFields(fields)\n\n if (slug === \"text\" || slug === \"textarea\" || slug === \"radio\") {\n const row1 = fields[1]\n if (!isRowField(row1)) {\n return block\n }\n const newSecond = row([\n widthColumn(override, named.get(\"width\")),\n placeholderColumn(named, override),\n defaultValueColumn(override, named.get(\"defaultValue\"), {\n name: \"defaultValue\",\n type: \"text\",\n label: \"Default Value\",\n localized: true,\n } as Field),\n ])\n return { ...block, fields: [fields[0], newSecond, ...fields.slice(2)] }\n }\n\n if (slug === \"number\") {\n const row1 = fields[1]\n if (!isRowField(row1)) {\n return block\n }\n const newSecond = row([\n widthColumn(override, named.get(\"width\")),\n placeholderColumn(named, override),\n defaultValueColumn(override, named.get(\"defaultValue\"), {\n name: \"defaultValue\",\n type: \"number\",\n label: \"Default Value\",\n } as Field),\n ])\n return { ...block, fields: [fields[0], newSecond, ...fields.slice(2)] }\n }\n\n if (slug === \"select\") {\n const row1 = fields[1]\n const row2 = fields[2]\n if (!isRowField(row1)) {\n return block\n }\n const wasStandalonePlaceholderRow =\n isRowField(row2) &&\n row2.fields.length === 1 &&\n \"name\" in row2.fields[0] &&\n row2.fields[0].name === \"placeholder\"\n const newSecond = row([\n widthColumn(override, named.get(\"width\")),\n placeholderColumn(named, override),\n defaultValueColumn(override, named.get(\"defaultValue\"), {\n name: \"defaultValue\",\n type: \"text\",\n label: \"Default Value\",\n localized: true,\n } as Field),\n ])\n const tailStart = wasStandalonePlaceholderRow ? 3 : 2\n return { ...block, fields: [fields[0], newSecond, ...fields.slice(tailStart)] }\n }\n\n if (slug === \"email\" || slug === \"state\" || slug === \"country\") {\n const row0 = fields[0]\n const maybeWidth = fields[1]\n const rest = fields.slice(2)\n if (\n !isRowField(row0) ||\n !maybeWidth ||\n !(\"name\" in maybeWidth) ||\n maybeWidth.name !== \"width\"\n ) {\n return block\n }\n const newSecond = row([\n widthColumn(override, named.get(\"width\")),\n placeholderColumn(named, override),\n defaultValueColumn(override, named.get(\"defaultValue\"), {\n name: \"defaultValue\",\n type: \"text\",\n label: \"Default Value\",\n localized: true,\n } as Field),\n ])\n return { ...block, fields: [row0, newSecond, ...rest] }\n }\n\n if (slug === \"date\") {\n const row0 = fields[0]\n const row1 = fields[1]\n const defaultField = fields[2]\n if (\n !isRowField(row0) ||\n !isRowField(row1) ||\n !defaultField ||\n !(\"name\" in defaultField) ||\n defaultField.name !== \"defaultValue\"\n ) {\n return block\n }\n const requiredField = row1.fields.find((f) => \"name\" in f && f.name === \"required\")\n if (!requiredField) {\n return block\n }\n const newSecond = row([\n widthColumn(override, named.get(\"width\")),\n placeholderColumn(named, override),\n defaultValueColumn(override, named.get(\"defaultValue\"), {\n name: \"defaultValue\",\n type: \"date\",\n label: \"Default Value\",\n } as Field),\n ])\n return { ...block, fields: [row0, newSecond, requiredField] }\n }\n\n return block\n}\n","import { createMarketingFormFields } from \"./fields\"\nimport { createCreateLeadHook, createValidateFormSubmissionHook } from \"./hooks\"\nimport { normalizeFormBuilderPlaceholderRow } from \"./normalize-placeholder-rows\"\n\nimport type { PayloadPluginMarketingOptions } from \"../types\"\nimport type { Block, CollectionConfig, Field } from \"payload\"\n\nfunction isNamedField(field: Field, name: string): field is Field & { name: string } {\n return \"name\" in field && field.name === name\n}\n\nfunction hasSlug(item: unknown): item is { slug: string } {\n return Boolean(\n item && typeof item === \"object\" && \"slug\" in item && typeof item.slug === \"string\",\n )\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\")\n}\n\nfunction upsertField(fields: Field[], field: Field): Field[] {\n if (!(\"name\" in field) || !field.name) {\n return [...fields, field]\n }\n return fields.some((existing) => isNamedField(existing, field.name))\n ? fields.map((existing) => (isNamedField(existing, field.name) ? field : existing))\n : [...fields, field]\n}\n\nfunction createMarketingConfigFields(options: PayloadPluginMarketingOptions): Field[] {\n const audienceSelect = options.admin?.components?.audienceSelect ?? {\n path: \"payload-plugin-marketing/admin\",\n exportName: \"AudienceSelect\",\n }\n return [\n {\n name: \"event\",\n type: \"select\",\n defaultValue: \"submission\",\n options: [\n { label: \"Submission\", value: \"submission\" },\n { label: \"Lead\", value: \"lead\" },\n ],\n },\n {\n name: \"audienceId\",\n type: \"text\",\n label: \"Audience ID\",\n required: false,\n admin: {\n condition: (_data, siblingData) => siblingData?.event === \"lead\",\n components: { Field: audienceSelect },\n },\n validate: (value: unknown, { siblingData }: { siblingData?: { event?: string } } = {}) =>\n siblingData?.event === \"lead\" && !value ? \"Audience is required for lead forms.\" : true,\n },\n {\n name: \"tags\",\n type: \"textarea\",\n label: \"Tags\",\n admin: {\n condition: (_data, siblingData) => siblingData?.event === \"lead\",\n description: \"Optional comma-separated tags. Use {{fieldName}} to insert submitted values.\",\n },\n },\n ] as Field[]\n}\n\nfunction mutateFormsCollection(\n collection: CollectionConfig,\n options: PayloadPluginMarketingOptions,\n): CollectionConfig {\n const fields = [...collection.fields]\n const fieldsIndex = fields.findIndex(\n (field) => isNamedField(field, \"fields\") && field.type === \"blocks\",\n )\n if (fieldsIndex < 0) {\n if (options.formBuilder?.strict === false) {\n return collection\n }\n throw new Error(\n `Could not find a blocks field named \"fields\" on form-builder forms collection \"${collection.slug}\".`,\n )\n }\n\n const fieldsField = fields[fieldsIndex] as Field & { blocks: unknown[] }\n const existingBlocks = Array.isArray(fieldsField.blocks) ? fieldsField.blocks : []\n const blockOverrides = options.formBuilder?.fields ?? {}\n const overriddenExistingBlocks = existingBlocks.map((block) => {\n if (!hasSlug(block)) {\n return block\n }\n if (!isRecord(block)) {\n return block\n }\n const override = blockOverrides[block.slug as keyof typeof blockOverrides]\n const merged =\n override && isRecord(override)\n ? {\n ...block,\n ...(override.overrides ?? {}),\n ...(override.labels ? { labels: override.labels } : {}),\n }\n : block\n return normalizeFormBuilderPlaceholderRow(merged as Block, override)\n })\n const existingSlugs = new Set(\n overriddenExistingBlocks.flatMap((block) => (hasSlug(block) ? [block.slug] : [])),\n )\n const marketingBlocks = Object.values(\n createMarketingFormFields(options.formBuilder?.fields),\n ).filter((block) => !existingSlugs.has(block.slug))\n\n fields[fieldsIndex] = {\n ...fieldsField,\n blocks: [...overriddenExistingBlocks, ...marketingBlocks],\n } as Field\n\n for (const field of createMarketingConfigFields(options)) {\n fields.splice(0, fields.length, ...upsertField(fields, field))\n }\n\n return { ...collection, fields }\n}\n\nfunction mutateSubmissionsCollection(\n collection: CollectionConfig,\n options: PayloadPluginMarketingOptions,\n): CollectionConfig {\n const hooks = collection.hooks ?? {}\n return {\n ...collection,\n hooks: {\n ...hooks,\n beforeChange: [\n ...(hooks.beforeChange ?? []),\n createValidateFormSubmissionHook({ formsSlug: options.formBuilder?.formsSlug }),\n createCreateLeadHook(options.adapter, { formsSlug: options.formBuilder?.formsSlug }),\n ],\n },\n }\n}\n\nexport function mutateFormBuilderCollections(\n collections: CollectionConfig[] | undefined,\n options: PayloadPluginMarketingOptions,\n): CollectionConfig[] | undefined {\n const formsSlug = options.formBuilder?.formsSlug ?? \"forms\"\n const submissionsSlug = options.formBuilder?.submissionsSlug ?? \"form-submissions\"\n const strict = options.formBuilder?.strict ?? true\n const list = collections ?? []\n const hasForms = list.some((collection) => collection.slug === formsSlug)\n const hasSubmissions = list.some((collection) => collection.slug === submissionsSlug)\n\n if (strict && !hasForms) {\n throw new Error(`Could not find form-builder forms collection \"${formsSlug}\".`)\n }\n if (strict && !hasSubmissions) {\n throw new Error(`Could not find form-builder submissions collection \"${submissionsSlug}\".`)\n }\n\n return list.map((collection) => {\n if (collection.slug === formsSlug) {\n return mutateFormsCollection(collection, options)\n }\n if (collection.slug === submissionsSlug) {\n return mutateSubmissionsCollection(collection, options)\n }\n return collection\n })\n}\n"],"mappings":"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","names":["mergeField","base","override","overrides","direct","row","fields","textLikeBlock","slug","labels","options","createAcceptanceBlock","createMarketingFormFields","FORM_HONEYPOT_FIELD","FORM_STARTED_AT_FIELD","MIN_SUBMISSION_TIME_MS","MAX_LENGTH_BY_BLOCK","isControlField","fieldName","extractControlFields","submissionData","honeypot","entry","startedAt","stringifySubmissionValue","value","isValidFieldValue","field","option","requiredValueIsPresent","validateSubmissionInput","input","controlFields","supportedFields","formFieldMap","normalized","seenFields","formField","submissionDataToPlainRecord","substituteSubmissionPlaceholders","template","values","_","resolveCommaSeparatedSubmissionTags","tags","tag","getStringField","data","field","value","row","resolveMarketingForm","req","formsSlug","createValidateFormSubmissionHook","options","operation","form","result","validateSubmissionInput","createCreateLeadHook","adapter","formRecord","submission","email","fieldValues","submissionDataToPlainRecord","tags","resolveCommaSeparatedSubmissionTags","BLOCK_SLUGS_WITHOUT_PLACEHOLDER_ROW","row","fields","isRowField","field","collectNamedFields","map","walk","items","item","withAdminWidth","width","prevAdmin","widthColumn","override","existing","base","mergeField","placeholderColumn","named","defaultValueColumn","fallback","normalizeFormBuilderPlaceholderRow","block","slug","row1","newSecond","row2","wasStandalonePlaceholderRow","tailStart","row0","maybeWidth","rest","defaultField","requiredField","f","isNamedField","field","name","hasSlug","item","isRecord","value","upsertField","fields","existing","createMarketingConfigFields","options","audienceSelect","_data","siblingData","mutateFormsCollection","collection","fieldsIndex","fieldsField","existingBlocks","blockOverrides","overriddenExistingBlocks","block","override","merged","normalizeFormBuilderPlaceholderRow","existingSlugs","marketingBlocks","createMarketingFormFields","mutateSubmissionsCollection","hooks","createValidateFormSubmissionHook","createCreateLeadHook","mutateFormBuilderCollections","collections","formsSlug","submissionsSlug","strict","list","hasForms","hasSubmissions"]}
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ import type { MarketingEmailBroadcastTemplate, MarketingEmailTemplateProps } from "./types";
3
+ import type { ComponentType } from "react";
4
+ /**
5
+ * Splits `path` into a dynamic-import specifier and optional named export using a `#` suffix,
6
+ * e.g. `"@/emails/digest#DigestEmail"`.
7
+ */
8
+ export declare function parseEmailBroadcastTemplatePath(path: string): {
9
+ importPath: string;
10
+ namedExport?: string;
11
+ };
12
+ export declare function validateEmailBroadcastTemplates(templates: MarketingEmailBroadcastTemplate[]): void;
13
+ export declare function resolveEmailBroadcastTemplateComponent(definition: MarketingEmailBroadcastTemplate): Promise<ComponentType<MarketingEmailTemplateProps>>;
14
+ export declare function createEmailBroadcastReactElement(Component: ComponentType<MarketingEmailTemplateProps>, props: MarketingEmailTemplateProps): React.ReactElement;
15
+ //# sourceMappingURL=email-broadcast-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email-broadcast-template.d.ts","sourceRoot":"","sources":["../src/email-broadcast-template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,+BAA+B,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAA;AAC3F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAI1C;;;GAGG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,MAAM,GAAG;IAC7D,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAiBA;AAED,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,+BAA+B,EAAE,GAC3C,IAAI,CAiCN;AAED,wBAAsB,sCAAsC,CAC1D,UAAU,EAAE,+BAA+B,GAC1C,OAAO,CAAC,aAAa,CAAC,2BAA2B,CAAC,CAAC,CA+BrD;AAED,wBAAgB,gCAAgC,CAC9C,SAAS,EAAE,aAAa,CAAC,2BAA2B,CAAC,EACrD,KAAK,EAAE,2BAA2B,GACjC,KAAK,CAAC,YAAY,CAEpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"marketing-endpoints.d.ts","sourceRoot":"","sources":["../../src/endpoints/marketing-endpoints.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAA;AA8CvD,wBAAgB,wBAAwB,IAAI,QAAQ,EAAE,CA8SrD"}
1
+ {"version":3,"file":"marketing-endpoints.d.ts","sourceRoot":"","sources":["../../src/endpoints/marketing-endpoints.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAA;AA8CvD,wBAAgB,wBAAwB,IAAI,QAAQ,EAAE,CAuVrD"}