UNPKG

@prismicio/next

Version:

Helpers to integrate Prismic into Next.js apps

1 lines 5.93 kB
{"version":3,"file":"PrismicPreview.cjs","sources":["../../src/pages/PrismicPreview.tsx"],"sourcesContent":["import { type ReactNode, useEffect, FC } from \"react\";\nimport { useRouter } from \"next/router\";\nimport Script from \"next/script\";\nimport { getToolbarSrc, cookie as prismicCookie } from \"@prismicio/client\";\n\n/** Props for `<PrismicPreview>`. */\nexport type PrismicPreviewProps = {\n\t/**\n\t * The name of your Prismic repository. A Prismic Toolbar will be registered\n\t * using this repository.\n\t */\n\trepositoryName: string;\n\n\t/**\n\t * The URL of your app's Prismic preview endpoint (default: `/api/preview`).\n\t * This URL will be fetched on preview update events.\n\t */\n\tupdatePreviewURL?: string;\n\n\t/**\n\t * The URL of your app's exit preview endpoint (default: `/api/exit-preview`).\n\t * This URL will be fetched on preview exit events.\n\t */\n\texitPreviewURL?: string;\n\n\t/** Children to render adjacent to the Prismic Toolbar. */\n\tchildren?: ReactNode;\n};\n\n/**\n * React component that sets up Prismic Previews using the Prismic Toolbar. When\n * the Prismic Toolbar send events to the browser, such as on preview updates\n * and exiting, this component will automatically refresh the page with the\n * changes.\n *\n * This component can be wrapped around your app or added anywhere in your app's\n * tree. It must be rendered on every page.\n */\nexport const PrismicPreview: FC<PrismicPreviewProps> = (props) => {\n\tconst {\n\t\trepositoryName,\n\t\tupdatePreviewURL = \"/api/preview\",\n\t\texitPreviewURL = \"/api/exit-preview\",\n\t\tchildren,\n\t} = props;\n\n\tconst router = useRouter();\n\n\tconst toolbarSrc = getToolbarSrc(repositoryName);\n\n\tuseEffect(() => {\n\t\tconst controller = new AbortController();\n\n\t\twindow.addEventListener(\"prismicPreviewUpdate\", onUpdate, {\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\twindow.addEventListener(\"prismicPreviewEnd\", onEnd, {\n\t\t\tsignal: controller.signal,\n\t\t});\n\n\t\t// Start the preview for preview share links. Previews from\n\t\t// share links do not go to the `updatePreviewURL` like a normal\n\t\t// preview.\n\t\t//\n\t\t// We check that the current URL is a descendant of the base\n\t\t// path to prevent infinite refrehes.\n\t\tif (\n\t\t\twindow.location.href.startsWith(\n\t\t\t\twindow.location.origin + router.basePath,\n\t\t\t) &&\n\t\t\tgetPreviewCookieRepositoryName() === repositoryName &&\n\t\t\t!router.isPreview\n\t\t) {\n\t\t\tstart();\n\t\t}\n\n\t\tfunction onEnd(event: Event) {\n\t\t\tevent.preventDefault();\n\t\t\tfetch(router.basePath + exitPreviewURL, { signal: controller.signal })\n\t\t\t\t.then((res) => {\n\t\t\t\t\tif (!res.ok) {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t`[<PrismicPreview>] Failed to exit Preview Mode using the \"${exitPreviewURL}\" API endpoint. Does it exist?`,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\trefresh();\n\t\t\t\t})\n\t\t\t\t.catch(() => {});\n\t\t}\n\n\t\tfunction onUpdate(event: Event) {\n\t\t\tevent.preventDefault();\n\t\t\tstart();\n\t\t}\n\n\t\tfunction start() {\n\t\t\t// We check `opaqueredirect` because we don't care if\n\t\t\t// the redirect was successful or not. As long as it\n\t\t\t// redirects, we know the endpoint exists and at least\n\t\t\t// attempted to set preview data.\n\t\t\tfetch(router.basePath + updatePreviewURL, {\n\t\t\t\tredirect: \"manual\",\n\t\t\t\tsignal: controller.signal,\n\t\t\t})\n\t\t\t\t.then((res) => {\n\t\t\t\t\tif (res.type !== \"opaqueredirect\") {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t`[<PrismicPreview>] Failed to start or update the preview using \"${updatePreviewURL}\". Does it exist?`,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\trefresh();\n\t\t\t\t})\n\t\t\t\t.catch(() => {});\n\t\t}\n\n\t\tfunction refresh() {\n\t\t\trouter.replace(router.asPath, undefined, { scroll: false });\n\t\t}\n\n\t\treturn () => controller.abort();\n\t}, [exitPreviewURL, updatePreviewURL, repositoryName, router]);\n\n\treturn (\n\t\t<>\n\t\t\t{children}\n\t\t\t<Script src={toolbarSrc} strategy=\"lazyOnload\" />\n\t\t</>\n\t);\n};\n\nfunction getPreviewCookieRepositoryName() {\n\tconst cookie = window.document.cookie\n\t\t.split(\"; \")\n\t\t.find((row) => row.startsWith(`${prismicCookie.preview}=`))\n\t\t?.split(\"=\")[1];\n\n\treturn (decodeURIComponent(cookie ?? \"\").match(/\"([^\"]+)\\.prismic\\.io\"/) ||\n\t\t[])[1];\n}\n"],"names":["router","useRouter","getToolbarSrc","useEffect","_jsxs","_Fragment","_jsx","prismicCookie"],"mappings":";;;;;;;AAsCa,MAAA,iBAA0C,CAAC,UAAS;AAChE,QAAM,EACL,gBACA,mBAAmB,gBACnB,iBAAiB,qBACjB,aACG;AAEJ,QAAMA,WAASC,OAAAA,UAAS;AAElB,QAAA,aAAaC,qBAAc,cAAc;AAE/CC,QAAAA,UAAU,MAAK;AACR,UAAA,aAAa,IAAI;AAEhB,WAAA,iBAAiB,wBAAwB,UAAU;AAAA,MACzD,QAAQ,WAAW;AAAA,IAAA,CACnB;AACM,WAAA,iBAAiB,qBAAqB,OAAO;AAAA,MACnD,QAAQ,WAAW;AAAA,IAAA,CACnB;AAQD,QACC,OAAO,SAAS,KAAK,WACpB,OAAO,SAAS,SAASH,SAAO,QAAQ,KAEzC,+BAA8B,MAAO,kBACrC,CAACA,SAAO,WACP;;;AAIF,aAAS,MAAM,OAAY;AAC1B,YAAM,eAAc;AACd,YAAAA,SAAO,WAAW,gBAAgB,EAAE,QAAQ,WAAW,OAAQ,CAAA,EACnE,KAAK,CAAC,QAAO;AACT,YAAA,CAAC,IAAI,IAAI;AACJ,kBAAA,MACP,6DAA6D,cAAc,gCAAgC;AAG5G;AAAA,QAAA;;OAID,EACA,MAAM,MAAO;AAAA,MAAA,CAAC;AAAA,IAAA;AAGjB,aAAS,SAAS,OAAY;AAC7B,YAAM,eAAc;;;AAIrB,aAAS,QAAK;AAKP,YAAAA,SAAO,WAAW,kBAAkB;AAAA,QACzC,UAAU;AAAA,QACV,QAAQ,WAAW;AAAA,MAAA,CACnB,EACC,KAAK,CAAC,QAAO;AACT,YAAA,IAAI,SAAS,kBAAkB;AAC1B,kBAAA,MACP,mEAAmE,gBAAgB,mBAAmB;AAGvG;AAAA,QAAA;;OAID,EACA,MAAM,MAAO;AAAA,MAAA,CAAC;AAAA,IAAA;AAGjB,aAAS,UAAO;AACfA,eAAO,QAAQA,SAAO,QAAQ,QAAW,EAAE,QAAQ,OAAO;AAAA,IAAA;AAGpD,WAAA,MAAM,WAAW;KACtB,CAAC,gBAAgB,kBAAkB,gBAAgBA,QAAM,CAAC;AAE7D,SACCI,gBACEC,WAAA,UAAA,EAAA,UAAA,CAAA,UACDC,WAAC,IAAA,QAAO,EAAA,KAAK,YAAY,UAAS,aAAe,CAAA,CAAA,GAAA;AAGpD;AAEA,SAAS,iCAA8B;;AAChC,QAAA,UAAS,YAAO,SAAS,OAC7B,MAAM,IAAI,EACV,KAAK,CAAC,QAAQ,IAAI,WAAW,GAAGC,cAAc,OAAO,GAAG,CAAC,MAF5C,mBAGZ,MAAM,KAAK;AAEN,UAAA,mBAAmB,UAAU,EAAE,EAAE,MAAM,wBAAwB,KACtE,CAAA,GAAI,CAAC;AACP;;"}