{
  "version": 3,
  "sources": ["../src/index.ts"],
  "sourcesContent": ["import type { EntryContext } from '@remix-run/server-runtime';\nimport type { ComponentType } from 'react';\nimport { createElement, useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { RemixServer } from '@remix-run/react';\nimport { renderToString } from 'react-dom/server';\n\ntype HeadComponent = ComponentType<{\n  __remix_island_render_server?: boolean;\n}> & {\n  __remix_island_id?: string;\n};\n\nlet globalMounted = false;\nexport interface CreateHeadOpts {\n  id?: string;\n  cleanup?: boolean;\n}\nexport function createHead(\n  Comp: ComponentType,\n  { id = 'remix-island', cleanup = true }: CreateHeadOpts = {},\n): HeadComponent {\n  const Head: HeadComponent = (props) => {\n    const [mounted, setMounted] = useState(globalMounted);\n    useEffect(() => {\n      if (cleanup) {\n        removeOldHead(Head);\n      }\n      globalMounted = true;\n      setMounted(true);\n    }, []);\n\n    if (!mounted && props.__remix_island_render_server) {\n      return createElement(Comp);\n    }\n\n    if (mounted) {\n      return createPortal(createElement(Comp), document.head);\n    }\n\n    return null;\n  };\n\n  Head.displayName = 'RemixIslandHead';\n  Head.__remix_island_id = id;\n\n  return Head;\n}\n\nexport interface RenderHeadToStringOpts {\n  request: Request;\n  remixContext: EntryContext;\n  Head: HeadComponent;\n}\n\nexport function renderHeadToString({\n  request,\n  remixContext,\n  Head,\n}: RenderHeadToStringOpts) {\n  const head = renderToString(\n    createElement(RemixServer, {\n      context: switchRootComponent(remixContext, Head),\n      url: request.url,\n    }),\n  );\n  const id = Head.__remix_island_id;\n  return `<!--${id}-start-->${head}<!--${id}-end-->`;\n}\n\nexport function switchRootComponent(\n  remixContext: EntryContext,\n  Head: HeadComponent,\n): EntryContext {\n  let serverHandoffString = remixContext.serverHandoffString;\n  if (serverHandoffString) {\n    const serverHandoff = JSON.parse(serverHandoffString);\n    // remove errors from JSON string\n    delete serverHandoff?.state?.errors;\n    serverHandoffString = JSON.stringify(serverHandoff);\n  }\n\n  const { Layout, ...rootModuleWithoutLayout } =\n    remixContext.routeModules.root!;\n\n  return {\n    ...remixContext,\n    serverHandoffString,\n    staticHandlerContext: {\n      ...remixContext.staticHandlerContext,\n      errors: null, // remove errors from context\n    },\n    routeModules: {\n      ...remixContext.routeModules,\n      root: {\n        ...rootModuleWithoutLayout,\n        default: () =>\n          createElement(Head, { __remix_island_render_server: true }),\n      },\n    },\n  };\n}\n\nexport function removeOldHead(\n  Head: HeadComponent,\n  parent: HTMLElement = document.head,\n) {\n  let foundOldHeader = false;\n  const nodesToRemove: ChildNode[] = [];\n  const id = Head.__remix_island_id;\n  for (const node of parent.childNodes) {\n    if (!foundOldHeader && node.nodeName !== '#comment') {\n      continue;\n    }\n    if (\n      foundOldHeader &&\n      node.nodeName === '#comment' &&\n      node.nodeValue === `${id}-end`\n    ) {\n      nodesToRemove.push(node);\n      break;\n    }\n    if (\n      foundOldHeader ||\n      (node.nodeName === '#comment' && node.nodeValue === `${id}-start`)\n    ) {\n      foundOldHeader = true;\n      nodesToRemove.push(node);\n    }\n  }\n  for (const node of nodesToRemove) {\n    node.remove();\n  }\n}\n"],
  "mappings": "AAEA,OAAS,iBAAAA,EAAe,aAAAC,EAAW,YAAAC,MAAgB,QACnD,OAAS,gBAAAC,MAAoB,YAC7B,OAAS,eAAAC,MAAmB,mBAC5B,OAAS,kBAAAC,MAAsB,mBAQ/B,IAAIC,EAAgB,GAKb,SAASC,EACdC,EACA,CAAE,GAAAC,EAAK,eAAgB,QAAAC,EAAU,EAAK,EAAoB,CAAC,EAC5C,CACf,MAAMC,EAAuBC,GAAU,CACrC,KAAM,CAACC,EAASC,CAAU,EAAIZ,EAASI,CAAa,EASpD,OARAL,EAAU,IAAM,CACVS,GACFK,EAAcJ,CAAI,EAEpBL,EAAgB,GAChBQ,EAAW,EAAI,CACjB,EAAG,CAAC,CAAC,EAED,CAACD,GAAWD,EAAM,6BACbZ,EAAcQ,CAAI,EAGvBK,EACKV,EAAaH,EAAcQ,CAAI,EAAG,SAAS,IAAI,EAGjD,IACT,EAEA,OAAAG,EAAK,YAAc,kBACnBA,EAAK,kBAAoBF,EAElBE,CACT,CAQO,SAASK,EAAmB,CACjC,QAAAC,EACA,aAAAC,EACA,KAAAP,CACF,EAA2B,CACzB,MAAMQ,EAAOd,EACXL,EAAcI,EAAa,CACzB,QAASgB,EAAoBF,EAAcP,CAAI,EAC/C,IAAKM,EAAQ,GACf,CAAC,CACH,EACMR,EAAKE,EAAK,kBAChB,MAAO,OAAOF,CAAE,YAAYU,CAAI,OAAOV,CAAE,SAC3C,CAEO,SAASW,EACdF,EACAP,EACc,CACd,IAAIU,EAAsBH,EAAa,oBACvC,GAAIG,EAAqB,CACvB,MAAMC,EAAgB,KAAK,MAAMD,CAAmB,EAEpD,OAAOC,GAAe,OAAO,OAC7BD,EAAsB,KAAK,UAAUC,CAAa,CACpD,CAEA,KAAM,CAAE,OAAAC,EAAQ,GAAGC,CAAwB,EACzCN,EAAa,aAAa,KAE5B,MAAO,CACL,GAAGA,EACH,oBAAAG,EACA,qBAAsB,CACpB,GAAGH,EAAa,qBAChB,OAAQ,IACV,EACA,aAAc,CACZ,GAAGA,EAAa,aAChB,KAAM,CACJ,GAAGM,EACH,QAAS,IACPxB,EAAcW,EAAM,CAAE,6BAA8B,EAAK,CAAC,CAC9D,CACF,CACF,CACF,CAEO,SAASI,EACdJ,EACAc,EAAsB,SAAS,KAC/B,CACA,IAAIC,EAAiB,GACrB,MAAMC,EAA6B,CAAC,EAC9BlB,EAAKE,EAAK,kBAChB,UAAWiB,KAAQH,EAAO,WACxB,GAAI,GAACC,GAAkBE,EAAK,WAAa,YAGzC,IACEF,GACAE,EAAK,WAAa,YAClBA,EAAK,YAAc,GAAGnB,CAAE,OACxB,CACAkB,EAAc,KAAKC,CAAI,EACvB,KACF,EAEEF,GACCE,EAAK,WAAa,YAAcA,EAAK,YAAc,GAAGnB,CAAE,YAEzDiB,EAAiB,GACjBC,EAAc,KAAKC,CAAI,GAG3B,UAAWA,KAAQD,EACjBC,EAAK,OAAO,CAEhB",
  "names": ["createElement", "useEffect", "useState", "createPortal", "RemixServer", "renderToString", "globalMounted", "createHead", "Comp", "id", "cleanup", "Head", "props", "mounted", "setMounted", "removeOldHead", "renderHeadToString", "request", "remixContext", "head", "switchRootComponent", "serverHandoffString", "serverHandoff", "Layout", "rootModuleWithoutLayout", "parent", "foundOldHeader", "nodesToRemove", "node"]
}
