@flamingo-stack/openframe-frontend-core 0.0.568 → 0.0.569

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 (176) hide show
  1. package/dist/{chunk-P7QGTNEW.cjs → chunk-2DSDGWWU.cjs} +101 -101
  2. package/dist/{chunk-P7QGTNEW.cjs.map → chunk-2DSDGWWU.cjs.map} +1 -1
  3. package/dist/{chunk-ZARYIFCI.js → chunk-3UPQAOES.js} +5 -3
  4. package/dist/{chunk-ZARYIFCI.js.map → chunk-3UPQAOES.js.map} +1 -1
  5. package/dist/{chunk-KL6ZDLDF.js → chunk-4NN7V443.js} +2 -2
  6. package/dist/{chunk-G2PAUMV6.js → chunk-6STF67EF.js} +4 -4
  7. package/dist/{chunk-6RSKK4E7.cjs → chunk-74DB5H5T.cjs} +1258 -1162
  8. package/dist/chunk-74DB5H5T.cjs.map +1 -0
  9. package/dist/{chunk-6TDWCBQM.js → chunk-A2T266F3.js} +7 -7
  10. package/dist/{chunk-HKG7BZON.cjs → chunk-AAROYQ4O.cjs} +14 -14
  11. package/dist/{chunk-HKG7BZON.cjs.map → chunk-AAROYQ4O.cjs.map} +1 -1
  12. package/dist/{chunk-CEAAOVCV.cjs → chunk-AJPGQCZ2.cjs} +1 -1
  13. package/dist/chunk-AJPGQCZ2.cjs.map +1 -0
  14. package/dist/{chunk-ZXASQL3E.js → chunk-C5GKBUT7.js} +4 -4
  15. package/dist/{chunk-RBYMJF2V.cjs → chunk-D6SBYELJ.cjs} +35 -35
  16. package/dist/{chunk-RBYMJF2V.cjs.map → chunk-D6SBYELJ.cjs.map} +1 -1
  17. package/dist/{chunk-LNUXUOPN.cjs → chunk-EBE22KOQ.cjs} +4 -4
  18. package/dist/{chunk-LNUXUOPN.cjs.map → chunk-EBE22KOQ.cjs.map} +1 -1
  19. package/dist/{chunk-EYXZF46V.js → chunk-FE5QR7PT.js} +995 -899
  20. package/dist/chunk-FE5QR7PT.js.map +1 -0
  21. package/dist/{chunk-6PWUUWCO.cjs → chunk-FMWIA5IH.cjs} +42 -42
  22. package/dist/{chunk-6PWUUWCO.cjs.map → chunk-FMWIA5IH.cjs.map} +1 -1
  23. package/dist/{chunk-DHTT77AG.cjs → chunk-GY22CIEF.cjs} +78 -78
  24. package/dist/{chunk-DHTT77AG.cjs.map → chunk-GY22CIEF.cjs.map} +1 -1
  25. package/dist/{chunk-O3JCKEVG.js → chunk-HOMYI5RR.js} +2 -2
  26. package/dist/{chunk-BZ7B255K.js → chunk-KCAGMTJ6.js} +9 -9
  27. package/dist/{chunk-DZ2Z7HRF.js → chunk-KO333Q2B.js} +3 -3
  28. package/dist/{chunk-MQQM4NCN.js → chunk-LJBNHO6B.js} +3 -3
  29. package/dist/{chunk-KZS2DFC2.cjs → chunk-ME346OJF.cjs} +42 -42
  30. package/dist/{chunk-KZS2DFC2.cjs.map → chunk-ME346OJF.cjs.map} +1 -1
  31. package/dist/{chunk-UWY722RH.js → chunk-MR6RRXSD.js} +1 -1
  32. package/dist/chunk-MR6RRXSD.js.map +1 -0
  33. package/dist/{chunk-ZIZJDXUI.js → chunk-MZG3QQUR.js} +2 -2
  34. package/dist/{chunk-HB3IG2MC.js → chunk-OS5RFMW5.js} +3 -3
  35. package/dist/{chunk-VEXTUGUA.js → chunk-OWCN3BM6.js} +7 -7
  36. package/dist/{chunk-QVQLNKFS.js → chunk-P7ZENKIA.js} +2 -2
  37. package/dist/{chunk-T7AE7CKV.cjs → chunk-PCL6WYYT.cjs} +7 -7
  38. package/dist/{chunk-T7AE7CKV.cjs.map → chunk-PCL6WYYT.cjs.map} +1 -1
  39. package/dist/{chunk-2LKVYI7H.js → chunk-PLJAOZYZ.js} +6 -6
  40. package/dist/{chunk-L22CSZZU.cjs → chunk-QY3VTOB6.cjs} +18 -18
  41. package/dist/{chunk-L22CSZZU.cjs.map → chunk-QY3VTOB6.cjs.map} +1 -1
  42. package/dist/{chunk-Y2BYHTEN.cjs → chunk-SMW5Z4NW.cjs} +23 -23
  43. package/dist/{chunk-Y2BYHTEN.cjs.map → chunk-SMW5Z4NW.cjs.map} +1 -1
  44. package/dist/{chunk-LXWQLUBR.cjs → chunk-SW3K3JSP.cjs} +9 -7
  45. package/dist/chunk-SW3K3JSP.cjs.map +1 -0
  46. package/dist/{chunk-NKEOD2AD.cjs → chunk-TDYTAED2.cjs} +3 -3
  47. package/dist/{chunk-NKEOD2AD.cjs.map → chunk-TDYTAED2.cjs.map} +1 -1
  48. package/dist/{chunk-ZNEVGXMU.js → chunk-TXEI4PES.js} +112 -4
  49. package/dist/chunk-TXEI4PES.js.map +1 -0
  50. package/dist/{chunk-KZ3PIUCH.cjs → chunk-VNE2EHCD.cjs} +14 -14
  51. package/dist/{chunk-KZ3PIUCH.cjs.map → chunk-VNE2EHCD.cjs.map} +1 -1
  52. package/dist/{chunk-6I76UK2Z.cjs → chunk-XMECOGLY.cjs} +3 -3
  53. package/dist/{chunk-6I76UK2Z.cjs.map → chunk-XMECOGLY.cjs.map} +1 -1
  54. package/dist/{chunk-NK3M6F5A.cjs → chunk-Z3SRMLMK.cjs} +121 -13
  55. package/dist/chunk-Z3SRMLMK.cjs.map +1 -0
  56. package/dist/components/case-studies/index.cjs +10 -10
  57. package/dist/components/case-studies/index.js +4 -4
  58. package/dist/components/chat/index.cjs +4 -17
  59. package/dist/components/chat/index.cjs.map +1 -1
  60. package/dist/components/chat/index.js +3 -16
  61. package/dist/components/chat/utils/index.d.ts +0 -2
  62. package/dist/components/chat/utils/index.d.ts.map +1 -1
  63. package/dist/components/contact/index.cjs +5 -5
  64. package/dist/components/contact/index.js +4 -4
  65. package/dist/components/docs/index.cjs +7 -7
  66. package/dist/components/docs/index.js +6 -6
  67. package/dist/components/embeds/claude-embed.d.ts +15 -8
  68. package/dist/components/embeds/claude-embed.d.ts.map +1 -1
  69. package/dist/components/embeds/embed-viewer-frame.d.ts +8 -1
  70. package/dist/components/embeds/embed-viewer-frame.d.ts.map +1 -1
  71. package/dist/components/embeds/index.cjs +5 -5
  72. package/dist/components/embeds/index.js +4 -4
  73. package/dist/components/faq/index.cjs +6 -6
  74. package/dist/components/faq/index.js +5 -5
  75. package/dist/components/features/index.cjs +4 -4
  76. package/dist/components/features/index.js +3 -3
  77. package/dist/components/help-center-pages/index.cjs +25 -25
  78. package/dist/components/help-center-pages/index.js +16 -16
  79. package/dist/components/index.cjs +142 -154
  80. package/dist/components/index.cjs.map +1 -1
  81. package/dist/components/index.js +14 -26
  82. package/dist/components/index.js.map +1 -1
  83. package/dist/components/meeting-scheduler/index.cjs +36 -36
  84. package/dist/components/meeting-scheduler/index.js +5 -5
  85. package/dist/components/navigation/index.cjs +4 -4
  86. package/dist/components/navigation/index.js +3 -3
  87. package/dist/components/onboarding-guides/index.cjs +8 -8
  88. package/dist/components/onboarding-guides/index.js +7 -7
  89. package/dist/components/related-content/index.cjs +6 -6
  90. package/dist/components/related-content/index.js +5 -5
  91. package/dist/components/tickets/index.cjs +8 -8
  92. package/dist/components/tickets/index.js +7 -7
  93. package/dist/components/ui/index.cjs +4 -16
  94. package/dist/components/ui/index.cjs.map +1 -1
  95. package/dist/components/ui/index.js +3 -15
  96. package/dist/components/ui/markdown/sanitize.d.ts.map +1 -1
  97. package/dist/components/ui/table/table.d.ts +1 -1
  98. package/dist/components/ui/table/table.d.ts.map +1 -1
  99. package/dist/components/ui/table/types.d.ts +9 -0
  100. package/dist/components/ui/table/types.d.ts.map +1 -1
  101. package/dist/contexts/endpoints-runtime-context.d.ts +6 -0
  102. package/dist/contexts/endpoints-runtime-context.d.ts.map +1 -1
  103. package/dist/contexts/index.cjs +2 -2
  104. package/dist/contexts/index.js +1 -1
  105. package/dist/hooks/index.cjs +5 -3
  106. package/dist/hooks/index.cjs.map +1 -1
  107. package/dist/hooks/index.d.ts +1 -0
  108. package/dist/hooks/index.d.ts.map +1 -1
  109. package/dist/hooks/index.js +4 -2
  110. package/dist/hooks/use-claude-mirror-src.d.ts +17 -0
  111. package/dist/hooks/use-claude-mirror-src.d.ts.map +1 -0
  112. package/dist/index.cjs +10 -8
  113. package/dist/index.cjs.map +1 -1
  114. package/dist/index.js +15 -13
  115. package/dist/utils/embed-proxy-auth-storage.d.ts.map +1 -1
  116. package/dist/utils/embed-url-converters.d.ts +20 -0
  117. package/dist/utils/embed-url-converters.d.ts.map +1 -1
  118. package/dist/utils/fullscreen-switch.d.ts +85 -0
  119. package/dist/utils/fullscreen-switch.d.ts.map +1 -0
  120. package/dist/utils/index.cjs +114 -0
  121. package/dist/utils/index.cjs.map +1 -1
  122. package/dist/utils/index.d.ts +1 -0
  123. package/dist/utils/index.d.ts.map +1 -1
  124. package/dist/utils/index.js +113 -1
  125. package/dist/utils/index.js.map +1 -1
  126. package/package.json +1 -1
  127. package/src/components/chat/hooks/use-chat-attachments.ts +3 -3
  128. package/src/components/chat/hooks/use-chat-history-hydration.ts +2 -2
  129. package/src/components/chat/hooks/use-chat-identity.ts +5 -5
  130. package/src/components/chat/hooks/use-sse-chat-adapter.ts +3 -3
  131. package/src/components/chat/utils/.index.md +1 -2
  132. package/src/components/chat/utils/chat-conversation-storage.ts +2 -2
  133. package/src/components/chat/utils/index.ts +3 -10
  134. package/src/components/embeds/claude-embed.tsx +41 -14
  135. package/src/components/embeds/embed-viewer-frame.tsx +77 -4
  136. package/src/components/ui/markdown/__tests__/sanitize-invariant.test.ts +30 -0
  137. package/src/components/ui/markdown/rich/__tests__/shortcodes.test.ts +8 -0
  138. package/src/components/ui/markdown/sanitize.ts +4 -0
  139. package/src/components/ui/table/table.tsx +7 -2
  140. package/src/components/ui/table/types.ts +9 -0
  141. package/src/contexts/endpoints-runtime-context.tsx +6 -0
  142. package/src/hooks/index.ts +4 -0
  143. package/src/hooks/use-claude-mirror-src.ts +43 -0
  144. package/src/utils/.embed-proxy-auth-storage.md +2 -2
  145. package/src/utils/embed-proxy-auth-storage.ts +19 -14
  146. package/src/utils/embed-url-converters.ts +45 -0
  147. package/src/utils/fullscreen-switch.ts +180 -0
  148. package/src/utils/index.ts +8 -6
  149. package/dist/chunk-6RSKK4E7.cjs.map +0 -1
  150. package/dist/chunk-CEAAOVCV.cjs.map +0 -1
  151. package/dist/chunk-EYXZF46V.js.map +0 -1
  152. package/dist/chunk-LXWQLUBR.cjs.map +0 -1
  153. package/dist/chunk-NK3M6F5A.cjs.map +0 -1
  154. package/dist/chunk-UWY722RH.js.map +0 -1
  155. package/dist/chunk-ZNEVGXMU.js.map +0 -1
  156. package/dist/components/chat/utils/chat-authed-fetch.d.ts +0 -15
  157. package/dist/components/chat/utils/chat-authed-fetch.d.ts.map +0 -1
  158. package/dist/components/chat/utils/chat-proxy-auth-storage.d.ts +0 -16
  159. package/dist/components/chat/utils/chat-proxy-auth-storage.d.ts.map +0 -1
  160. package/src/components/chat/utils/.chat-authed-fetch.md +0 -25
  161. package/src/components/chat/utils/.chat-proxy-auth-storage.md +0 -38
  162. package/src/components/chat/utils/chat-authed-fetch.ts +0 -17
  163. package/src/components/chat/utils/chat-proxy-auth-storage.ts +0 -25
  164. /package/dist/{chunk-KL6ZDLDF.js.map → chunk-4NN7V443.js.map} +0 -0
  165. /package/dist/{chunk-G2PAUMV6.js.map → chunk-6STF67EF.js.map} +0 -0
  166. /package/dist/{chunk-6TDWCBQM.js.map → chunk-A2T266F3.js.map} +0 -0
  167. /package/dist/{chunk-ZXASQL3E.js.map → chunk-C5GKBUT7.js.map} +0 -0
  168. /package/dist/{chunk-O3JCKEVG.js.map → chunk-HOMYI5RR.js.map} +0 -0
  169. /package/dist/{chunk-BZ7B255K.js.map → chunk-KCAGMTJ6.js.map} +0 -0
  170. /package/dist/{chunk-DZ2Z7HRF.js.map → chunk-KO333Q2B.js.map} +0 -0
  171. /package/dist/{chunk-MQQM4NCN.js.map → chunk-LJBNHO6B.js.map} +0 -0
  172. /package/dist/{chunk-ZIZJDXUI.js.map → chunk-MZG3QQUR.js.map} +0 -0
  173. /package/dist/{chunk-HB3IG2MC.js.map → chunk-OS5RFMW5.js.map} +0 -0
  174. /package/dist/{chunk-VEXTUGUA.js.map → chunk-OWCN3BM6.js.map} +0 -0
  175. /package/dist/{chunk-QVQLNKFS.js.map → chunk-P7ZENKIA.js.map} +0 -0
  176. /package/dist/{chunk-2LKVYI7H.js.map → chunk-PLJAOZYZ.js.map} +0 -0
@@ -40,4 +40,4 @@ export {
40
40
  useChatRuntime,
41
41
  useRequiredChatRuntime
42
42
  };
43
- //# sourceMappingURL=chunk-UWY722RH.js.map
43
+ //# sourceMappingURL=chunk-MR6RRXSD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/contexts/endpoints-runtime-context.tsx","../src/contexts/chat-runtime-context.tsx"],"sourcesContent":["'use client'\n\n/**\n * Endpoints runtime — sibling of ChatRuntime. Carries the API path\n * literals consumed by oss-lib components/hooks/utils so a host\n * application can override them (e.g. when running behind a reverse\n * proxy as `user1.openframe.ai` → `/api/mingo-guide/*`).\n *\n * The hub mounts `<HubRuntimeProvider>` at root with the\n * canonical hub paths; an embedded app mounts its own provider with\n * remapped paths. The pattern mirrors ChatRuntimeContext exactly:\n *\n * - `useEndpointsRuntime()` returns null when no provider is mounted.\n * For optional consumers that should gracefully no-op without one.\n * - `useRequiredEndpointsRuntime()` throws on missing provider — for\n * hooks/components that cannot function without endpoints.\n *\n * IMPORTANT for embedders: memoize the value passed to\n * `<EndpointsRuntimeContext.Provider value={...}>` (e.g. React.useMemo).\n * Reference changes invalidate downstream effect dependency arrays and\n * trigger unnecessary re-fetches.\n */\n\nimport { createContext, useContext } from 'react'\n\nexport interface EndpointsRuntime {\n /** GET active announcement (used by `<AnnouncementBar>` mount fetch + refocus revalidation). */\n announcementsUrl: string\n accessCode: {\n /** POST validate access code. */\n validateUrl: string\n /** POST consume / redeem access code after registration. */\n consumeUrl: string\n }\n /** POST contact-form submission. */\n contactUrl: string\n /** GET base of the host's private-storage view proxy\n * (`<base>/<bucket>/<object>`). `ClaudeEmbed` derives artifact mirror\n * urls under it (`<base>/design-briefs/<uuid>.html`). OPTIONAL: a host\n * without the proxy simply omits it and claude embeds fall back to\n * claude.ai — no probing happens. */\n storageViewBaseUrl?: string\n}\n\nexport const EndpointsRuntimeContext = createContext<EndpointsRuntime | null>(null)\n\n/**\n * Optional read — returns null when no provider is mounted. Use for\n * surfaces that should silently skip the fetch (e.g. announcement\n * polling on a page rendered outside the provider tree).\n */\nexport function useEndpointsRuntime(): EndpointsRuntime | null {\n return useContext(EndpointsRuntimeContext)\n}\n\n/**\n * Strict variant — throws on missing provider. Use for consumers that\n * cannot function without an endpoint (form submission, code\n * validation). In tests/Storybook, wrap with the hub's\n * `<HubRuntimeProvider>` or a stub\n * `<EndpointsRuntimeContext.Provider value={mockedEndpoints}>`.\n */\nexport function useRequiredEndpointsRuntime(): EndpointsRuntime {\n const v = useContext(EndpointsRuntimeContext)\n if (!v) {\n throw new Error(\n '[endpoints-runtime] hook called outside an <EndpointsRuntimeContext.Provider>. ' +\n 'Hub: mount <HubRuntimeProvider> in your providers tree. ' +\n 'Embedded app: mount your own provider with proxied URLs at the tree root. ' +\n 'Tests/Storybook: wrap render() in <EndpointsRuntimeContext.Provider value={mocked}>.',\n )\n }\n return v\n}\n","'use client'\n\n/**\n * Chat runtime context — single seam for embedding the chat panel in a\n * different host (e.g. user1.openframe.ai reverse-proxying API calls\n * under /api/mingo-guide/* to hub.openframe.ai/api/*).\n *\n * Three concerns, one context:\n * 1. API endpoints: chatStreamUrl / approvalToolUrl / commandsUrl /\n * buildListUrl + attachment endpoints + chat-identity. The chat\n * reads them from runtime; hub vs embedded app supply different\n * strings via different providers.\n * 2. Navigation mode + callbacks: 'host' or 'embed' mode. Host wires\n * its own router/docNav via the optional `navigate` callback\n * (plain function, NOT a hook); embed forces new-tab via\n * `defaultContentOrigin` + lib's `resolveExternalNavigation`.\n * 3. Identity context: only `source` (required for localStorage\n * namespacing). The display identity (greeting first-name etc.)\n * comes from the server via `useChatIdentity()` — never injected\n * client-side, so it always matches the server-resolved auth.\n *\n * Sibling of EndpointsRuntimeContext (announcement bar, contact form,\n * access codes). Each runtime stays an independent React context so\n * embedders can opt into either feature without forcing the other.\n *\n * IMPORTANT for embedders: memoize the value passed to\n * `<ChatRuntimeContext.Provider value={...}>` (e.g. via React.useMemo).\n * Every change to its reference identity invalidates downstream\n * `useMemo` consumers (the chat input's slash-commands binding,\n * useNavLink's embed-resolution memo, useDocChat's streamFn factory).\n * The hub's `<HubRuntimeProvider>` already memoizes correctly with\n * stable deps. Embedded apps that build the value inline on each render\n * will pay an avoidable re-render cost across the entire chat tree.\n */\n\nimport { createContext, useContext, type ReactNode } from 'react'\n\nimport type { ComposeContentUrl } from '../utils/content-href'\n\n/**\n * Runtime config consumed by the chat panel.\n */\nexport interface ChatRuntime {\n endpoints: {\n /** POST streaming chat. Hub: '/api/docs/chat'. */\n chatStreamUrl: string\n /** POST agent approve/reject. Hub: '/api/chat/agent/confirm-tool'. */\n approvalToolUrl: string\n /** Customer-ticket agent endpoints (Help Center). OPTIONAL — when unset,\n * the ticket hooks fall back to the bare hub paths\n * (`/api/chat/agent/{find-ticket,ticket-action,list-engagements}`).\n * Embedders behind a reverse proxy set these to their proxied paths\n * (e.g. `/content/api/chat/agent/...`) so tickets route through the SAME\n * endpoint config + proxy as every other endpoint. */\n findTicketUrl?: string\n ticketActionUrl?: string\n listEngagementsUrl?: string\n /** Ticket live-stream + read-receipt endpoints (Help Center\n * realtime). OPTIONAL — unset → bare hub paths under the DEDICATED\n * ticket surface (`/api/tickets/{stream,read}` — deliberately NOT\n * the chat agent's `/api/chat/agent/*` prefix). Reverse-proxy\n * embedders set their proxied paths. Consumed by\n * `TicketLiveProvider`. The unread summary has NO endpoint — it\n * arrives as `ticket-summary` frames on the stream and in\n * `ticket-read` responses. */\n ticketStreamUrl?: string\n ticketReadUrl?: string\n /** GET slash-command catalog. Hub: '/api/docs/commands'. */\n commandsUrl: string\n /** GET server-side conversation history (`?conversationId=<id>`) — the\n * chat panel's mount-time hydration read against the server transcript\n * store (localStorage keeps only the server-issued conversation id).\n * OPTIONAL — defaults to `<chatStreamUrl>/history`, which is correct for\n * same-origin hosts AND for reverse-proxy embedders (the proxied chat\n * prefix covers it). Set explicitly only when the history route lives\n * elsewhere. */\n chatHistoryUrl?: string\n /** GET RAG-search endpoint behind `<DocSearchBar>` (the in-source search\n * bar mounted by `<DocViewer>` / `<DocsHubPage>` when `showAIChat` is on).\n * Hub: '/api/docs/search'. OPTIONAL — falls back to the hub path so\n * same-origin Next.js hosts don't need to set it. Cross-origin embedders\n * set their proxied path so the search bar routes through the same\n * reverse proxy as everything else. Same pattern as `findTicketUrl`. */\n docsSearchUrl?: string\n /** POST internal-link resolver. The in-source markdown renderer (lib or\n * custom) calls `<DocViewer>`'s `handlers.onResolveLink(href, currentPath)`\n * for relative hrefs like `./getting-started/intro.md` — that callback\n * posts to this URL with `{ link, currentPath, source }` and expects a\n * `ResolveLinkResult` back. Hub: '/api/docs/resolve-link'. OPTIONAL — same\n * fall-back chain as `docsSearchUrl`: prop override → runtime → default. */\n docsResolveLinkUrl?: string\n /** GET per-platform empty-state config (admin-edited in\n * `/admin/chat-config`): `{ greeting, enabledRagTableIds, suggestedQueries }`.\n * Hub: '/api/docs/empty-state'. OPTIONAL — the in-app (host-mode) chat\n * injects these values as SSR props instead, so it leaves this unset.\n * Cross-origin EMBEDDERS (no server hop) set it to their proxied path\n * (e.g. '/content/api/docs/empty-state') so `<EmbeddableChat>` can fetch\n * the greeting / quick-action chips / RAG-source filter at runtime. When\n * unset, the chat falls back to the explicit `emptyStateGreeting` /\n * `suggestedQueries` / `enabledRagTableIds` props (or in-code defaults). */\n emptyStateUrl?: string\n /** Build the per-agent display-config URL for an OpenFrame AI agent\n * (Fae/Mingo). OPTIONAL. The returned endpoint MUST be byte-compatible\n * with the empty-state wire shape ({ greeting, suggestedQueries,\n * enabledRagTableIds }). When set AND `EmbeddableChat` receives an\n * `activeAgentSlug` in embed mode, the chat fetches THIS url instead of\n * `emptyStateUrl` to render the selected agent's greeting + suggested\n * prompts (the \"agent mode\" URL override). Hub: `(slug) =>\n * '/api/ai-agents/' + encodeURIComponent(slug)`. */\n aiAgentConfigUrl?: (slug: string) => string\n /** Build entity-card list URL for a content type + ids. Hub delegates\n * to the rag-table-config registry; embedded app provides its own\n * per-type URL builder against the reverse proxy. Returns null when\n * the type has no list endpoint (caller skips rendering). */\n buildListUrl: (type: string, ids: string[]) => string | null\n /** Chat-attachment endpoints — added for the v2 attachment feature.\n *\n * Three concerns:\n * - `attachmentUploadUrl` — POSTed by the chat-attachment hook\n * to mint a Supabase signed-upload-URL + HMAC view token.\n * - `attachmentViewUrlPrefix` — embedded in markdown URLs the\n * chat hosts in user message bubbles (`![]()` / `[Attached]`).\n * Stored in chat history; chosen at SEND time. In host mode the\n * relative `/api/storage/view/chat-attachments/` is sufficient\n * (same-origin); embedders supply an absolute hub URL so the\n * browser can fetch cross-origin.\n * - `identityUrl` — GET endpoint the `useChatIdentity` hook\n * hits to learn the `{authTier, source, attachmentsEnabled}`\n * capability bag for the current session. Used beyond chat\n * (tickets / contact form / any embedded surface that needs\n * to identify the proxied customer), so the name has no\n * \"chat\" prefix even though the consuming hook still does. */\n attachmentUploadUrl: string\n attachmentViewUrlPrefix: string\n identityUrl: string\n /** Optional URL prefix for the image proxy (`<prefix>?url=<external>`).\n * When unset, lib's `getProxiedImageUrl` returns the original URL\n * unchanged. Hub default: '/api/image-proxy'. Embedders that don't\n * host an image-proxy route leave this undefined → images load\n * directly cross-origin (CORS-permitting). */\n imageProxyUrlPrefix?: string\n /** Optional list of hostnames that should bypass the image proxy\n * (rendered direct). Hub uses ['openmsp.ai']; embedders typically\n * leave it unset. Matches the `skipDomains` parameter of\n * `getProxiedImageUrl`. */\n imageProxySkipDomains?: string[]\n /** Optional base URL for the branded og-placeholder image route — the\n * DEFAULT cover-image fallback for entity cards with no image. The lib\n * appends `?title=…` (+ `w`/`h` for square slots) itself, so this is\n * the base, NOT a full URL: relative (`/api/og-placeholder`) for same-\n * origin hosts, or the proxied path (`/content/api/og-placeholder`) for\n * cross-origin embedders. May carry baked-in query params (preserved when\n * the lib layers `title`/dimensions on top) — but per-platform brand\n * colors are NO LONGER baked here; the `/api/og-placeholder` route\n * resolves them server-side from the platform. Most hosts leave this unset\n * and let the lib derive the base from `imageProxyUrlPrefix`.\n *\n * OPTIONAL — when unset the lib derives the base from the sibling\n * `imageProxyUrlPrefix` (same API base, route name swapped), then falls\n * back to the relative `/api/og-placeholder`. So an embedder that already\n * proxies images needs NO og-placeholder wiring. See\n * `resolveOgPlaceholderBase` / `buildOgPlaceholderUrl` in `../utils`. */\n ogPlaceholderUrl?: string\n /** Base URL prefix for the captions route (`/api/captions` — the native\n * `<track>` VTT endpoint every video surface uses since captions stopped\n * being burned into video pixels). Plain path base, no query params.\n * Embedders point it at their proxied route (e.g. `/content/api/captions`);\n * unset ⇒ the same-origin relative `/api/captions` (the hub). Consumed via\n * `getEntityCaptionUrls` / `rebaseCaptionsUrl` in\n * `components/features/captions-url.ts`. */\n captionsUrlPrefix?: string\n /** Supabase storage origin (e.g. `https://xyz.supabase.co`) — used\n * by `useVideoWarmup` to scope the `<link rel=\"preload\" as=\"video\">`\n * hint to MP4s the deployment actually hosts. Hub wires it via\n * `getSupabaseStorageOrigin()`; embedders without a Supabase\n * storage origin leave it unset (preload is then skipped; Mux/\n * YouTube preconnect still fires). */\n supabaseStorageOrigin?: string\n }\n navigation: {\n /** ONE knob, two behaviors:\n * - 'host' = use the host page's existing click-routing untouched.\n * The chat panel calls `navigate?.()` for in-app routing.\n * - 'embed' = guest inside another app: short-circuit at the top\n * of click handlers to force new-tab + absolutize via\n * resolveExternalNavigation. */\n mode: 'host' | 'embed'\n /** Embed-only fallback origin for relative URLs whose target platform\n * can't be inferred. Used by resolveExternalNavigation when\n * `targetPlatform` is null — without this, a relative `/foo` href would\n * window.open against the embedder's origin, which is WRONG.\n * Set to your content host (e.g. 'https://hub.openframe.ai').\n * Required by the embedded app whenever mode='embed'. */\n defaultContentOrigin?: string\n /** Override for opening external URLs. MUST BE SYNCHRONOUS —\n * Safari/Firefox block popups opened outside a direct user gesture.\n * Default: window.open(href, '_blank', 'noopener,noreferrer'). */\n openExternal?: (href: string) => void\n /** Optional in-app navigation callback (host-mode only).\n * Returns `true` if the host handled the click in-app\n * (router.push + docNav.navigate); returns `false`, `undefined`,\n * or `void` → lib falls back to window.location.assign(href).\n * Hub wires this via HubRuntimeProvider's HubNavigationWiring;\n * embedders not in Next.js leave it undefined. */\n navigate?: (input: { href: string; path?: string | null; targetPlatform?: string | null }) => boolean | void\n /** Optional new-tab decision callback. Returns true → lib opens in\n * new tab; false → same tab via `navigate`. Hub wires the existing\n * `decideNewTab` logic from use-nav-link.tsx (re-imports the pure\n * helper from lib). Embedders may omit; lib defaults to:\n * same-origin/same-platform → same tab, else new tab. */\n decideNewTab?: (args: { href: string; targetPlatform?: string | null }) => boolean\n }\n /** Optional content-URL composer. Returns the platform-aware href +\n * target-platform tuple for a content entity. Hub wires this to its\n * `buildContentURL(type, slug, extractPrimaryPlatform(platforms))`\n * pipeline so the lib catalog/detail views can derive cross-\n * platform hrefs without knowing the hub's platform topology\n * (openmsp.ai / openframe.app / flamingo.run / tmcg).\n *\n * THE single content-href authority for every embeddable surface — page\n * views (onboarding catalog/detail, releases) AND chat cards / chips /\n * search results all resolve content links through this one seam, so a\n * given type lands in the SAME place regardless of where it's rendered.\n * Embedders wire `makeComposeContentUrl({ hostedTypes, contentOrigin })`;\n * omit it and lib views fall back to a same-origin relative path\n * (`buildDefaultHref`).\n *\n * Takes a single `ComposeContentUrlInput`: `type` + `identifier` (page\n * views pass the slug; chat rows pass the id + `externalUrl`, whose path\n * yields the slug for in-app routing) + optional `platforms` /\n * `externalUrl` / `targetPlatform`. */\n composeContentUrl?: ComposeContentUrl\n /** Per-`documentType` doc-viewer targets — the UNIFIED, DYNAMIC replacement for\n * the single `chipBasePlatform` prop. Maps a doc-table documentType\n * (`'markdown'`, `'data_room_doc'`, …) → `{ platform, basePath }` for the PUBLIC\n * doc viewer that hosts it. Doc chips with no `externalUrl` resolve PER ROW to\n * `getBaseUrl(platform)/<basePath>/<path>`, so a chat mixing several doc sources\n * sends EACH to its own home (markdown→flamingo/knowledge-base,\n * data_room_doc→company-hub/data-room) instead of one static fallback. The hub\n * may keep using `chipBasePlatform` (one doc source per platform); embedders that\n * surface multiple doc sources wire this. Threaded into `resolveSourceRowCTA`. */\n docPlatformTargets?: Record<string, { platform: string; basePath: string }>\n /** Chat source / platform identifier — OPTIONAL. The hub sets it from\n * `currentPlatform()`; EMBEDDERS leave it unset and stay platform-agnostic.\n *\n * It is NOT required for chat to work. The wire resolves source server-side\n * (`/docs/chat|search|commands` reject any client `source`); the\n * same-tab-vs-new-tab link decision falls back to an origin comparison when\n * it's absent (`decideNewTab` → `isCrossOriginUrl`); and the localStorage\n * history namespace falls back to a stable constant. Set it only where the\n * client legitimately needs to know its platform a priori — i.e. the hub,\n * where several platforms share related origins so \"same platform\" can't be\n * inferred from a URL alone. */\n source?: string\n // NOTE: No `user` field. The chat's display identity (greeting\n // first-name, etc.) comes from the SERVER-resolved auth via\n // `useChatIdentity()` — the same identity the server uses to\n // authorize requests. Letting embedders pass a client-side `user`\n // would let it desync from the actual auth tier, causing greetings\n // like \"Hey Bob\" while the server treats the session as\n // alice@example.com. Single source of truth: the server.\n}\n\nexport const ChatRuntimeContext = createContext<ChatRuntime | null>(null)\n\n/**\n * Returns the active runtime, or null when no provider is mounted.\n * NULL is a first-class value — it signals \"no chat runtime configured.\"\n * Optional consumers fall back to no-op behavior; strict consumers\n * use `useRequiredChatRuntime` (below).\n */\nexport function useChatRuntime(): ChatRuntime | null {\n return useContext(ChatRuntimeContext)\n}\n\n/**\n * Strict variant used INSIDE the chat panel. Throws if no provider.\n * The hub guarantees one exists by mounting `<HubRuntimeProvider>` at\n * root; the embedded app mounts its own `<ChatRuntimeContext.Provider>`\n * at the tree root. In Jest / Storybook tests that render chat\n * internals directly, wrap with `<HubRuntimeProvider>` (hub defaults)\n * or supply `<ChatRuntimeContext.Provider value={mockedRuntime}>`.\n */\nexport function useRequiredChatRuntime(): ChatRuntime {\n const v = useContext(ChatRuntimeContext)\n if (!v) {\n throw new Error(\n '[chat-runtime] hook called outside a <ChatRuntimeContext.Provider>. ' +\n 'The hub mounts <HubRuntimeProvider> at root — this only fires when ' +\n 'chat internals are rendered above the provider tree. ' +\n 'Fix: ensure the rendering subtree descends from the runtime provider. ' +\n 'In tests/Storybook: wrap with <HubRuntimeProvider> or supply ' +\n 'a <ChatRuntimeContext.Provider value={mockedRuntime}>.',\n )\n }\n return v\n}\n"],"mappings":";;;AAuBA,SAAS,eAAe,kBAAkB;AAqBnC,IAAM,0BAA0B,cAAuC,IAAI;AAO3E,SAAS,sBAA+C;AAC7D,SAAO,WAAW,uBAAuB;AAC3C;AASO,SAAS,8BAAgD;AAC9D,QAAM,IAAI,WAAW,uBAAuB;AAC5C,MAAI,CAAC,GAAG;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IAIF;AAAA,EACF;AACA,SAAO;AACT;;;ACtCA,SAAS,iBAAAA,gBAAe,cAAAC,mBAAkC;AAoOnD,IAAM,qBAAqBD,eAAkC,IAAI;AAQjE,SAAS,iBAAqC;AACnD,SAAOC,YAAW,kBAAkB;AACtC;AAUO,SAAS,yBAAsC;AACpD,QAAM,IAAIA,YAAW,kBAAkB;AACvC,MAAI,CAAC,GAAG;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IAMF;AAAA,EACF;AACA,SAAO;AACT;","names":["createContext","useContext"]}
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  init_unified_pagination,
4
4
  unified_pagination_exports
5
- } from "./chunk-QVQLNKFS.js";
5
+ } from "./chunk-P7ZENKIA.js";
6
6
  import {
7
7
  cn,
8
8
  init_cn
@@ -172,4 +172,4 @@ export {
172
172
  usePaginationLoading,
173
173
  PersistentPaginationWrapper
174
174
  };
175
- //# sourceMappingURL=chunk-ZIZJDXUI.js.map
175
+ //# sourceMappingURL=chunk-MZG3QQUR.js.map
@@ -11,11 +11,11 @@ import {
11
11
  SelectValue,
12
12
  Textarea,
13
13
  useChatAttachments
14
- } from "./chunk-EYXZF46V.js";
14
+ } from "./chunk-FE5QR7PT.js";
15
15
  import {
16
16
  useContactSubmission,
17
17
  useHumanitySignals
18
- } from "./chunk-ZNEVGXMU.js";
18
+ } from "./chunk-TXEI4PES.js";
19
19
  import {
20
20
  Input,
21
21
  Label
@@ -374,4 +374,4 @@ function ContactForm({
374
374
  export {
375
375
  ContactForm
376
376
  };
377
- //# sourceMappingURL=chunk-HB3IG2MC.js.map
377
+ //# sourceMappingURL=chunk-OS5RFMW5.js.map
@@ -2,14 +2,14 @@
2
2
  import {
3
3
  ArticleAuthorByline,
4
4
  DetailPageSkeleton
5
- } from "./chunk-DZ2Z7HRF.js";
5
+ } from "./chunk-KO333Q2B.js";
6
6
  import {
7
7
  DocSearchBar,
8
8
  useDocSearch
9
- } from "./chunk-ZXASQL3E.js";
9
+ } from "./chunk-C5GKBUT7.js";
10
10
  import {
11
11
  useSelfFetch
12
- } from "./chunk-KL6ZDLDF.js";
12
+ } from "./chunk-4NN7V443.js";
13
13
  import {
14
14
  EntityAuthorCard,
15
15
  EntityTagBadges,
@@ -26,17 +26,17 @@ import {
26
26
  toStripProfile,
27
27
  useCaptions,
28
28
  useVideoWarmup
29
- } from "./chunk-EYXZF46V.js";
29
+ } from "./chunk-FE5QR7PT.js";
30
30
  import {
31
31
  buildOgPlaceholderUrl
32
- } from "./chunk-ZNEVGXMU.js";
32
+ } from "./chunk-TXEI4PES.js";
33
33
  import {
34
34
  useRouter,
35
35
  useSearchParams
36
36
  } from "./chunk-ZJJERZUA.js";
37
37
  import {
38
38
  useChatRuntime
39
- } from "./chunk-UWY722RH.js";
39
+ } from "./chunk-MR6RRXSD.js";
40
40
 
41
41
  // src/components/onboarding-guides/onboarding-guides-catalog-view.tsx
42
42
  import { useMemo, useTransition } from "react";
@@ -398,4 +398,4 @@ export {
398
398
  useOnboardingGuide,
399
399
  useOnboardingGuideSections
400
400
  };
401
- //# sourceMappingURL=chunk-VEXTUGUA.js.map
401
+ //# sourceMappingURL=chunk-OWCN3BM6.js.map
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  Pagination,
4
4
  init_pagination
5
- } from "./chunk-EYXZF46V.js";
5
+ } from "./chunk-FE5QR7PT.js";
6
6
  import {
7
7
  init_next_navigation,
8
8
  usePathname,
@@ -210,4 +210,4 @@ export {
210
210
  unified_pagination_exports,
211
211
  init_unified_pagination
212
212
  };
213
- //# sourceMappingURL=chunk-QVQLNKFS.js.map
213
+ //# sourceMappingURL=chunk-P7ZENKIA.js.map
@@ -3,13 +3,13 @@
3
3
 
4
4
 
5
5
 
6
- var _chunk6RSKK4E7cjs = require('./chunk-6RSKK4E7.cjs');
6
+ var _chunk74DB5H5Tcjs = require('./chunk-74DB5H5T.cjs');
7
7
 
8
8
 
9
9
  var _chunkXL4V2PYGcjs = require('./chunk-XL4V2PYG.cjs');
10
10
 
11
11
 
12
- var _chunkCEAAOVCVcjs = require('./chunk-CEAAOVCV.cjs');
12
+ var _chunkAJPGQCZ2cjs = require('./chunk-AJPGQCZ2.cjs');
13
13
 
14
14
 
15
15
 
@@ -50,7 +50,7 @@ function DetailPageSkeleton({
50
50
  ] });
51
51
  if (bare) return content;
52
52
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
53
- _chunk6RSKK4E7cjs.PageLayout,
53
+ _chunk74DB5H5Tcjs.PageLayout,
54
54
  {
55
55
  showHeader: false,
56
56
  className: "bg-ods-bg max-w-[1280px] mx-auto py-6 md:py-10 px-6 md:px-20",
@@ -86,9 +86,9 @@ function ArticleAuthorByline({
86
86
  proxyImageUrl,
87
87
  className
88
88
  }) {
89
- const runtime = _chunkCEAAOVCVcjs.useChatRuntime.call(void 0, );
89
+ const runtime = _chunkAJPGQCZ2cjs.useChatRuntime.call(void 0, );
90
90
  if (!author) return null;
91
- const proxiedAvatar = avatar ? proxyImageUrl ? proxyImageUrl(avatar) : _nullishCoalesce(_chunk6RSKK4E7cjs.getProxiedImageUrl.call(void 0, avatar, {
91
+ const proxiedAvatar = avatar ? proxyImageUrl ? proxyImageUrl(avatar) : _nullishCoalesce(_chunk74DB5H5Tcjs.getProxiedImageUrl.call(void 0, avatar, {
92
92
  proxyPrefix: _optionalChain([runtime, 'optionalAccess', _2 => _2.endpoints, 'access', _3 => _3.imageProxyUrlPrefix]),
93
93
  skipDomains: _optionalChain([runtime, 'optionalAccess', _4 => _4.endpoints, 'access', _5 => _5.imageProxySkipDomains]),
94
94
  directHttps: true
@@ -96,7 +96,7 @@ function ArticleAuthorByline({
96
96
  const avatarSizeClass = size === "lg" ? "w-16 h-16" : "w-14 h-14";
97
97
  const avatarIconClass = size === "lg" ? "w-8 h-8" : "w-7 h-7";
98
98
  const avatarDim = size === "lg" ? 64 : 56;
99
- const formattedBio = _chunk6RSKK4E7cjs.formatBioText.call(void 0, _nullishCoalesce(bio, () => ( null)));
99
+ const formattedBio = _chunk74DB5H5Tcjs.formatBioText.call(void 0, _nullishCoalesce(bio, () => ( null)));
100
100
  const dateLabel = publishedAt ? formatDate(publishedAt) : "";
101
101
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
102
102
  "div",
@@ -146,4 +146,4 @@ function ArticleAuthorByline({
146
146
 
147
147
 
148
148
  exports.DetailPageSkeleton = DetailPageSkeleton; exports.ArticleAuthorByline = ArticleAuthorByline;
149
- //# sourceMappingURL=chunk-T7AE7CKV.cjs.map
149
+ //# sourceMappingURL=chunk-PCL6WYYT.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-T7AE7CKV.cjs","../src/components/shared/detail-page-skeleton.tsx","../src/components/shared/article-author-byline.tsx"],"names":["jsxs","jsx"],"mappings":"AAAA,6rBAAY;AACZ;AACE;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACE;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACF,wDAA6B;AAC7B;AACA;ACEU,+CAAA;AATH,SAAS,kBAAA,CAAmB;AAAA,EACjC,gBAAA,EAAkB,CAAA;AAAA,EAClB,iBAAA,EAAmB,IAAA;AAAA,EACnB,KAAA,EAAO;AACT,EAAA,EAA6B,CAAC,CAAA,EAAG;AAC/B,EAAA,MAAM,QAAA,kBACF,8BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,uCAAA,EAEb,QAAA,EAAA;AAAA,oBAAA,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,4BAAA,EACb,QAAA,kBAAA,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,oDAAA,CAAoD,EAAA,CACrE,CAAA;AAAA,oBAGA,8BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,6BAAA,EACb,QAAA,EAAA;AAAA,sBAAA,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,+BAAA,CAA+B,CAAA;AAAA,sBAC9C,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,+BAAA,CAA+B,CAAA;AAAA,sBAC9C,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,+BAAA,CAA+B;AAAA,IAAA,EAAA,CAChD,CAAA;AAAA,oBAGA,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAW,CAAA,8BAAA,EAAiC,eAAe,CAAA,2DAAA,CAAA,EAC7D,QAAA,EAAA,KAAA,CAAM,IAAA,CAAK,EAAE,MAAA,EAAQ,gBAAgB,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,EAAA,mBAC/C,8BAAA,KAAC,EAAA,EAAY,SAAA,EAAU,sFAAA,EACrB,QAAA,EAAA;AAAA,sBAAA,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,sCAAA,CAAsC,CAAA;AAAA,sBACrD,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,iCAAA,CAAiC;AAAA,IAAA,EAAA,CAAA,EAFxC,CAGV,CACD,EAAA,CACH,CAAA;AAAA,IAGC,iBAAA,mBACC,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,mCAAA,EACZ,QAAA,EAAA,CAAC,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,EAAA,mBACpB,6BAAA,KAAC,EAAA,EAAY,SAAA,EAAU,+EAAA,CAAA,EAAb,CAA4F,CACvG,EAAA,CACH,CAAA;AAAA,IAID,CAAC,iBAAA,mBACA,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,mDAAA,CAAmD,CAAA;AAAA,IAInE,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,OAAA,EAAA,mBACd,8BAAA,KAAC,EAAA,EAAkB,SAAA,EAAU,WAAA,EAC3B,QAAA,EAAA;AAAA,sBAAA,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,gCAAA,CAAgC,CAAA;AAAA,sBAC/C,8BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,WAAA,EACb,QAAA,EAAA;AAAA,wBAAA,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,iCAAA,CAAiC,CAAA;AAAA,wBAChD,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,iCAAA,CAAiC,CAAA;AAAA,wBAChD,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,gCAAA,CAAgC;AAAA,MAAA,EAAA,CACjD;AAAA,IAAA,EAAA,CAAA,EANQ,OAOV,CACD;AAAA,EAAA,EAAA,CACH,CAAA;AAEJ,EAAA,GAAA,CAAI,IAAA,EAAM,OAAO,OAAA;AACjB,EAAA,uBACE,6BAAA;AAAA,IAAC,4BAAA;AAAA,IAAA;AAAA,MACC,UAAA,EAAY,KAAA;AAAA,MACZ,SAAA,EAAU,8DAAA;AAAA,MAET,QAAA,EAAA;AAAA,IAAA;AAAA,EACH,CAAA;AAEJ;ADnBA;AACA;AElCA,2CAA+B;AAE/B,8CAAA,CAAA;AACA,uCAAA,CAAA;AAoGU;AA/DV,SAAS,UAAA,CAAW,KAAA,EAA8B;AAChD,EAAA,MAAM,EAAA,EAAI,OAAO,MAAA,IAAU,SAAA,EAAW,IAAI,IAAA,CAAK,KAAK,EAAA,EAAI,KAAA;AACxD,EAAA,GAAA,CAAI,MAAA,CAAO,KAAA,CAAM,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,EAAG,OAAO,EAAA;AAKtC,EAAA,OAAO,CAAA,CAAE,kBAAA,CAAmB,OAAA,EAAS;AAAA,IACnC,KAAA,EAAO,MAAA;AAAA,IACP,GAAA,EAAK,SAAA;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,QAAA,EAAU;AAAA,EACZ,CAAC,CAAA;AACH;AAEO,SAAS,mBAAA,CAAoB;AAAA,EAClC,MAAA;AAAA,EACA,MAAA;AAAA,EACA,GAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA,IAAA;AAAA,EACA,WAAA;AAAA,EACA,KAAA,EAAO,IAAA;AAAA,EACP,aAAA;AAAA,EACA;AACF,CAAA,EAA6B;AAI3B,EAAA,MAAM,QAAA,EAAU,8CAAA,CAAe;AAC/B,EAAA,GAAA,CAAI,CAAC,MAAA,EAAQ,OAAO,IAAA;AAEpB,EAAA,MAAM,cAAA,EAAgB,OAAA,EAClB,cAAA,EACE,aAAA,CAAc,MAAM,EAAA,mBACnB,kDAAA,MAAmB,EAAQ;AAAA,IAC1B,WAAA,kBAAa,OAAA,6BAAS,SAAA,qBAAU,qBAAA;AAAA,IAChC,WAAA,kBAAa,OAAA,6BAAS,SAAA,qBAAU,uBAAA;AAAA,IAChC,WAAA,EAAa;AAAA,EACf,CAAC,CAAA,UAAK,SAAA,EACR,EAAA;AAKJ,EAAA,MAAM,gBAAA,EAAkB,KAAA,IAAS,KAAA,EAAO,YAAA,EAAc,WAAA;AACtD,EAAA,MAAM,gBAAA,EAAkB,KAAA,IAAS,KAAA,EAAO,UAAA,EAAY,SAAA;AACpD,EAAA,MAAM,UAAA,EAAY,KAAA,IAAS,KAAA,EAAO,GAAA,EAAK,EAAA;AACvC,EAAA,MAAM,aAAA,EAAe,6CAAA,iBAAc,GAAA,UAAO,MAAI,CAAA;AAC9C,EAAA,MAAM,UAAA,EAAY,YAAA,EAAc,UAAA,CAAW,WAAW,EAAA,EAAI,EAAA;AAE1D,EAAA,uBACEA,8BAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,kCAAA;AAAA,QACT,qDAAA;AAAA,QACA,6CAAA;AAAA,QACA;AAAA,MACF,CAAA;AAAA,MAGA,QAAA,EAAA;AAAA,wBAAAC,6BAAAA,KAAC,EAAA,EAAI,SAAA,EAAU,eAAA,EACZ,QAAA,EAAA,OAAA,kBACCA,6BAAAA;AAAA,UAAC,oCAAA;AAAA,UAAA;AAAA,YACC,GAAA,EAAK,cAAA,GAAiB,MAAA;AAAA,YACtB,GAAA,EAAK,MAAA;AAAA,YACL,KAAA,EAAO,SAAA;AAAA,YACP,MAAA,EAAQ,SAAA;AAAA,YACR,SAAA,EAAW,kCAAA,sDAAG,EAAwD,eAAe;AAAA,UAAA;AAAA,QACvF,EAAA,kBAEAA,6BAAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,kCAAA;AAAA,cACT,oFAAA;AAAA,cACA;AAAA,YACF,CAAA;AAAA,YAEA,QAAA,kBAAAA,6BAAAA,iBAAC,EAAA,EAAK,SAAA,EAAW,kCAAA,yBAAG,EAA2B,eAAe,EAAA,CAAG;AAAA,UAAA;AAAA,QACnE,EAAA,CAEJ,CAAA;AAAA,wBAGAD,8BAAAA,KAAC,EAAA,EAAI,SAAA,EAAU,gBAAA,EACb,QAAA,EAAA;AAAA,0BAAAA,8BAAAA,KAAC,EAAA,EAAI,SAAA,EAAU,+CAAA,EACb,QAAA,EAAA;AAAA,4BAAAC,6BAAAA,IAAC,EAAA,EAAG,SAAA,EAAU,+BAAA,EACX,QAAA,EAAA,KAAA,kBACCA,6BAAAA,mCAAC,EAAA,EAAK,IAAA,EAAY,SAAA,EAAU,yCAAA,EACzB,QAAA,EAAA,OAAA,CACH,EAAA,EAEA,OAAA,CAEJ,CAAA;AAAA,YACC,UAAA,mBACCD,8BAAAA,MAAC,EAAA,EAAK,SAAA,EAAU,+EAAA,EACd,QAAA,EAAA;AAAA,8BAAAC,6BAAAA,qBAAC,EAAA,EAAS,SAAA,EAAU,UAAA,CAAU,CAAA;AAAA,cAC7B;AAAA,YAAA,EAAA,CACH;AAAA,UAAA,EAAA,CAEJ,CAAA;AAAA,UACC,SAAA,mBACCA,6BAAAA,GAAC,EAAA,EAAE,SAAA,EAAU,uDAAA,EACV,QAAA,EAAA,SAAA,CACH,CAAA;AAAA,UAED,aAAA,kBACCA,6BAAAA,GAAC,EAAA,EAAE,SAAA,EAAU,qEAAA,EACV,QAAA,EAAA,aAAA,CACH,EAAA,EACE,YAAA,kBACFA,6BAAAA,GAAC,EAAA,EAAE,SAAA,EAAU,4DAAA,EACV,QAAA,EAAA,YAAA,CACH,EAAA,EACE;AAAA,QAAA,EAAA,CACN;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,CAAA;AAEJ;AF1CA;AACA;AACE;AACA;AACF,mGAAC","file":"/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-T7AE7CKV.cjs","sourcesContent":[null,"\"use client\";\n\nimport { PageLayout } from '../layout/page-layout';\n\nexport interface DetailPageSkeletonProps {\n metadataColumns?: number; // Number of metadata grid columns (default 4)\n showImageGallery?: boolean; // Show horizontal image gallery (default true)\n /** Render only the skeleton blocks, WITHOUT the self-contained page wrapper\n * — the caller supplies its own (e.g. `<PageShell>`) so the loading state\n * matches the loaded page's width, padding, and min-height. Default false\n * (self-contained `<PageLayout>` at the hub article width). */\n bare?: boolean;\n}\n\nexport function DetailPageSkeleton({\n metadataColumns = 4,\n showImageGallery = true,\n bare = false\n}: DetailPageSkeletonProps = {}) {\n const content = (\n <div className=\"space-y-6 md:space-y-10 animate-pulse\">\n {/* Title Block */}\n <div className=\"flex flex-col gap-6 w-full\">\n <div className=\"h-16 md:h-20 w-full max-w-3xl bg-ods-card rounded\"></div>\n </div>\n\n {/* Category Tags Skeleton */}\n <div className=\"flex flex-wrap gap-2 w-full\">\n <div className=\"h-8 w-32 bg-ods-card rounded\"></div>\n <div className=\"h-8 w-28 bg-ods-card rounded\"></div>\n <div className=\"h-8 w-36 bg-ods-card rounded\"></div>\n </div>\n\n {/* Metadata Grid Skeleton */}\n <div className={`grid grid-cols-1 md:grid-cols-${metadataColumns} border border-ods-border rounded-md overflow-hidden w-full`}>\n {Array.from({ length: metadataColumns }).map((_, i) => (\n <div key={i} className=\"bg-ods-card border-b md:border-b-0 md:border-r last:border-r-0 border-ods-border p-4\">\n <div className=\"h-6 w-24 bg-ods-border rounded mb-2\"></div>\n <div className=\"h-5 w-20 bg-ods-border rounded\"></div>\n </div>\n ))}\n </div>\n\n {/* Image Gallery Skeleton */}\n {showImageGallery && (\n <div className=\"flex gap-6 overflow-x-auto w-full\">\n {[1, 2, 3, 4, 5].map((i) => (\n <div key={i} className=\"shrink-0 w-[240px] h-[200px] bg-ods-card rounded-md border border-ods-border\"></div>\n ))}\n </div>\n )}\n\n {/* Featured Image Skeleton (for case studies) */}\n {!showImageGallery && (\n <div className=\"aspect-[2560/1366] w-full bg-ods-card rounded-md\"></div>\n )}\n\n {/* Content Sections Skeleton */}\n {[1, 2, 3].map((section) => (\n <div key={section} className=\"space-y-6\">\n <div className=\"h-16 w-64 bg-ods-card rounded\"></div>\n <div className=\"space-y-3\">\n <div className=\"h-6 w-full bg-ods-card rounded\"></div>\n <div className=\"h-6 w-full bg-ods-card rounded\"></div>\n <div className=\"h-6 w-4/5 bg-ods-card rounded\"></div>\n </div>\n </div>\n ))}\n </div>\n );\n if (bare) return content;\n return (\n <PageLayout\n showHeader={false}\n className=\"bg-ods-bg max-w-[1280px] mx-auto py-6 md:py-10 px-6 md:px-20\"\n >\n {content}\n </PageLayout>\n );\n}\n","'use client'\n\n/**\n * Shared \"author byline\" card used by article-shaped detail pages\n * (blog post, product release, onboarding guide, investor update).\n *\n * MOVED from the hub so any consuming app can embed it; hub call sites\n * import it directly and pass their platform-aware copy explicitly\n * (`fallbackBio={defaultAuthorFallbackBio()}` from the hub's app-config).\n *\n * Embed-readiness contract:\n * - `Link` / `Image` render through the embed-shims (plain `<a>` / `<img>`\n * in non-Next hosts; the real Next primitives once the host registers\n * them at app init).\n * - The avatar is proxied through the OPTIONAL ambient `ChatRuntime`\n * (`endpoints.imageProxyUrlPrefix`, same config `useProxiedImageUrl`\n * reads) — when no runtime is mounted the raw URL renders as-is, so the\n * component never throws outside a provider. Hosts can also inject\n * `proxyImageUrl` to bypass the runtime entirely.\n * - `fallbackBio` is a PLAIN prop (no app-config import): the lib has no\n * platform awareness; pass copy or leave it absent to render nothing.\n *\n * Render order: avatar → name + job title + date → bio (when present).\n * Returns null when `author` is empty (no card rendered).\n */\n\nimport React from 'react'\nimport { Calendar, User } from 'lucide-react'\nimport Image from '../../embed-shims/next-image'\nimport Link from '../../embed-shims/next-link'\nimport { cn } from '../../utils/cn'\nimport { formatBioText } from '../../utils/format'\nimport { getProxiedImageUrl } from '../../utils/image-proxy'\nimport { useChatRuntime } from '../../contexts/chat-runtime-context'\n\nexport interface ArticleAuthorBylineProps {\n /** Author display name. Required — block is hidden when null/empty. */\n author: string | null\n /** Avatar URL. Falls back to a placeholder when null. */\n avatar?: string | null\n /** Optional bio paragraph rendered below the name. */\n bio?: string | null\n /** Optional job title rendered immediately under the name. */\n jobTitle?: string | null\n /** Optional published date (ISO string or Date). Rendered next to the name. */\n publishedAt?: string | Date | null\n /** Optional link target for the author name (e.g. the author page). */\n href?: string | null\n /**\n * Fallback paragraph when `bio` is empty. Plain copy — the lib has no\n * platform/config awareness, so hosts that want a branded default\n * (\"Contributing author on the {platform} platform\") pass it explicitly\n * (the hub wrapper derives it from `getAppConfig()`). Absent/null ⇒\n * nothing renders below the name when `bio` is empty.\n */\n fallbackBio?: string | null\n /** Avatar size variant. `md` = 56px (default), `lg` = 64px. */\n size?: 'md' | 'lg'\n /**\n * Host-injected avatar-URL mapper. Wins over the ambient-runtime proxy\n * resolution. Use when the host proxies images outside the `ChatRuntime`\n * config (e.g. a bespoke CDN rewrite).\n */\n proxyImageUrl?: (url: string) => string\n className?: string\n}\n\nfunction formatDate(value: string | Date): string {\n const d = typeof value === 'string' ? new Date(value) : value\n if (Number.isNaN(d.getTime())) return ''\n // `timeZone: 'UTC'` keeps the SSR (server = UTC) and client (user's local tz)\n // renders identical — without it a published_at near a midnight boundary\n // formats to a different day on each side, triggering a React #418 hydration\n // text mismatch. Matches the convention in blog-metadata.tsx / investor-update.\n return d.toLocaleDateString('en-US', {\n month: 'long',\n day: 'numeric',\n year: 'numeric',\n timeZone: 'UTC',\n })\n}\n\nexport function ArticleAuthorByline({\n author,\n avatar,\n bio,\n jobTitle,\n publishedAt,\n href,\n fallbackBio,\n size = 'md',\n proxyImageUrl,\n className,\n}: ArticleAuthorBylineProps) {\n // Optional runtime — `useChatRuntime` returns null outside a provider, so\n // the byline works in bare embeds (raw avatar URL) and proxies whenever the\n // host mounted a runtime with `imageProxyUrlPrefix` (the hub always does).\n const runtime = useChatRuntime()\n if (!author) return null\n\n const proxiedAvatar = avatar\n ? proxyImageUrl\n ? proxyImageUrl(avatar)\n : (getProxiedImageUrl(avatar, {\n proxyPrefix: runtime?.endpoints.imageProxyUrlPrefix,\n skipDomains: runtime?.endpoints.imageProxySkipDomains,\n directHttps: true,\n }) ?? avatar)\n : ''\n\n // Class-driven sizing (md = 56px, lg = 64px). The numeric pair feeds only\n // the Image element's intrinsic width/height attributes (required by the\n // Next image shim) — layout comes from the classes.\n const avatarSizeClass = size === 'lg' ? 'w-16 h-16' : 'w-14 h-14'\n const avatarIconClass = size === 'lg' ? 'w-8 h-8' : 'w-7 h-7'\n const avatarDim = size === 'lg' ? 64 : 56\n const formattedBio = formatBioText(bio ?? null)\n const dateLabel = publishedAt ? formatDate(publishedAt) : ''\n\n return (\n <div\n className={cn(\n 'bg-ods-card border border-ods-border rounded-lg p-6',\n 'flex flex-col md:flex-row gap-4 items-start',\n className,\n )}\n >\n {/* Avatar */}\n <div className=\"flex-shrink-0\">\n {avatar ? (\n <Image\n src={proxiedAvatar || avatar}\n alt={author}\n width={avatarDim}\n height={avatarDim}\n className={cn('rounded-full border-2 border-ods-border object-cover', avatarSizeClass)}\n />\n ) : (\n <div\n className={cn(\n 'rounded-full border-2 border-ods-border bg-ods-bg flex items-center justify-center',\n avatarSizeClass,\n )}\n >\n <User className={cn('text-ods-text-secondary', avatarIconClass)} />\n </div>\n )}\n </div>\n\n {/* Name + meta + bio */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex flex-wrap items-baseline gap-x-3 gap-y-1\">\n <h3 className=\"text-h5 text-ods-text-primary\">\n {href ? (\n <Link href={href} className=\"hover:text-ods-accent transition-colors\">\n {author}\n </Link>\n ) : (\n author\n )}\n </h3>\n {dateLabel && (\n <span className=\"inline-flex items-center gap-1 font-body text-body-sm text-ods-text-secondary\">\n <Calendar className=\"h-3 w-3\" />\n {dateLabel}\n </span>\n )}\n </div>\n {jobTitle && (\n <p className=\"font-body text-body-sm text-ods-text-secondary mt-0.5\">\n {jobTitle}\n </p>\n )}\n {formattedBio ? (\n <p className=\"font-body text-body-md text-ods-text-secondary leading-relaxed mt-2\">\n {formattedBio}\n </p>\n ) : fallbackBio ? (\n <p className=\"font-body text-body-md text-ods-text-secondary italic mt-2\">\n {fallbackBio}\n </p>\n ) : null}\n </div>\n </div>\n )\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-PCL6WYYT.cjs","../src/components/shared/detail-page-skeleton.tsx","../src/components/shared/article-author-byline.tsx"],"names":["jsxs","jsx"],"mappings":"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","file":"/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-PCL6WYYT.cjs","sourcesContent":[null,"\"use client\";\n\nimport { PageLayout } from '../layout/page-layout';\n\nexport interface DetailPageSkeletonProps {\n metadataColumns?: number; // Number of metadata grid columns (default 4)\n showImageGallery?: boolean; // Show horizontal image gallery (default true)\n /** Render only the skeleton blocks, WITHOUT the self-contained page wrapper\n * — the caller supplies its own (e.g. `<PageShell>`) so the loading state\n * matches the loaded page's width, padding, and min-height. Default false\n * (self-contained `<PageLayout>` at the hub article width). */\n bare?: boolean;\n}\n\nexport function DetailPageSkeleton({\n metadataColumns = 4,\n showImageGallery = true,\n bare = false\n}: DetailPageSkeletonProps = {}) {\n const content = (\n <div className=\"space-y-6 md:space-y-10 animate-pulse\">\n {/* Title Block */}\n <div className=\"flex flex-col gap-6 w-full\">\n <div className=\"h-16 md:h-20 w-full max-w-3xl bg-ods-card rounded\"></div>\n </div>\n\n {/* Category Tags Skeleton */}\n <div className=\"flex flex-wrap gap-2 w-full\">\n <div className=\"h-8 w-32 bg-ods-card rounded\"></div>\n <div className=\"h-8 w-28 bg-ods-card rounded\"></div>\n <div className=\"h-8 w-36 bg-ods-card rounded\"></div>\n </div>\n\n {/* Metadata Grid Skeleton */}\n <div className={`grid grid-cols-1 md:grid-cols-${metadataColumns} border border-ods-border rounded-md overflow-hidden w-full`}>\n {Array.from({ length: metadataColumns }).map((_, i) => (\n <div key={i} className=\"bg-ods-card border-b md:border-b-0 md:border-r last:border-r-0 border-ods-border p-4\">\n <div className=\"h-6 w-24 bg-ods-border rounded mb-2\"></div>\n <div className=\"h-5 w-20 bg-ods-border rounded\"></div>\n </div>\n ))}\n </div>\n\n {/* Image Gallery Skeleton */}\n {showImageGallery && (\n <div className=\"flex gap-6 overflow-x-auto w-full\">\n {[1, 2, 3, 4, 5].map((i) => (\n <div key={i} className=\"shrink-0 w-[240px] h-[200px] bg-ods-card rounded-md border border-ods-border\"></div>\n ))}\n </div>\n )}\n\n {/* Featured Image Skeleton (for case studies) */}\n {!showImageGallery && (\n <div className=\"aspect-[2560/1366] w-full bg-ods-card rounded-md\"></div>\n )}\n\n {/* Content Sections Skeleton */}\n {[1, 2, 3].map((section) => (\n <div key={section} className=\"space-y-6\">\n <div className=\"h-16 w-64 bg-ods-card rounded\"></div>\n <div className=\"space-y-3\">\n <div className=\"h-6 w-full bg-ods-card rounded\"></div>\n <div className=\"h-6 w-full bg-ods-card rounded\"></div>\n <div className=\"h-6 w-4/5 bg-ods-card rounded\"></div>\n </div>\n </div>\n ))}\n </div>\n );\n if (bare) return content;\n return (\n <PageLayout\n showHeader={false}\n className=\"bg-ods-bg max-w-[1280px] mx-auto py-6 md:py-10 px-6 md:px-20\"\n >\n {content}\n </PageLayout>\n );\n}\n","'use client'\n\n/**\n * Shared \"author byline\" card used by article-shaped detail pages\n * (blog post, product release, onboarding guide, investor update).\n *\n * MOVED from the hub so any consuming app can embed it; hub call sites\n * import it directly and pass their platform-aware copy explicitly\n * (`fallbackBio={defaultAuthorFallbackBio()}` from the hub's app-config).\n *\n * Embed-readiness contract:\n * - `Link` / `Image` render through the embed-shims (plain `<a>` / `<img>`\n * in non-Next hosts; the real Next primitives once the host registers\n * them at app init).\n * - The avatar is proxied through the OPTIONAL ambient `ChatRuntime`\n * (`endpoints.imageProxyUrlPrefix`, same config `useProxiedImageUrl`\n * reads) — when no runtime is mounted the raw URL renders as-is, so the\n * component never throws outside a provider. Hosts can also inject\n * `proxyImageUrl` to bypass the runtime entirely.\n * - `fallbackBio` is a PLAIN prop (no app-config import): the lib has no\n * platform awareness; pass copy or leave it absent to render nothing.\n *\n * Render order: avatar → name + job title + date → bio (when present).\n * Returns null when `author` is empty (no card rendered).\n */\n\nimport React from 'react'\nimport { Calendar, User } from 'lucide-react'\nimport Image from '../../embed-shims/next-image'\nimport Link from '../../embed-shims/next-link'\nimport { cn } from '../../utils/cn'\nimport { formatBioText } from '../../utils/format'\nimport { getProxiedImageUrl } from '../../utils/image-proxy'\nimport { useChatRuntime } from '../../contexts/chat-runtime-context'\n\nexport interface ArticleAuthorBylineProps {\n /** Author display name. Required — block is hidden when null/empty. */\n author: string | null\n /** Avatar URL. Falls back to a placeholder when null. */\n avatar?: string | null\n /** Optional bio paragraph rendered below the name. */\n bio?: string | null\n /** Optional job title rendered immediately under the name. */\n jobTitle?: string | null\n /** Optional published date (ISO string or Date). Rendered next to the name. */\n publishedAt?: string | Date | null\n /** Optional link target for the author name (e.g. the author page). */\n href?: string | null\n /**\n * Fallback paragraph when `bio` is empty. Plain copy — the lib has no\n * platform/config awareness, so hosts that want a branded default\n * (\"Contributing author on the {platform} platform\") pass it explicitly\n * (the hub wrapper derives it from `getAppConfig()`). Absent/null ⇒\n * nothing renders below the name when `bio` is empty.\n */\n fallbackBio?: string | null\n /** Avatar size variant. `md` = 56px (default), `lg` = 64px. */\n size?: 'md' | 'lg'\n /**\n * Host-injected avatar-URL mapper. Wins over the ambient-runtime proxy\n * resolution. Use when the host proxies images outside the `ChatRuntime`\n * config (e.g. a bespoke CDN rewrite).\n */\n proxyImageUrl?: (url: string) => string\n className?: string\n}\n\nfunction formatDate(value: string | Date): string {\n const d = typeof value === 'string' ? new Date(value) : value\n if (Number.isNaN(d.getTime())) return ''\n // `timeZone: 'UTC'` keeps the SSR (server = UTC) and client (user's local tz)\n // renders identical — without it a published_at near a midnight boundary\n // formats to a different day on each side, triggering a React #418 hydration\n // text mismatch. Matches the convention in blog-metadata.tsx / investor-update.\n return d.toLocaleDateString('en-US', {\n month: 'long',\n day: 'numeric',\n year: 'numeric',\n timeZone: 'UTC',\n })\n}\n\nexport function ArticleAuthorByline({\n author,\n avatar,\n bio,\n jobTitle,\n publishedAt,\n href,\n fallbackBio,\n size = 'md',\n proxyImageUrl,\n className,\n}: ArticleAuthorBylineProps) {\n // Optional runtime — `useChatRuntime` returns null outside a provider, so\n // the byline works in bare embeds (raw avatar URL) and proxies whenever the\n // host mounted a runtime with `imageProxyUrlPrefix` (the hub always does).\n const runtime = useChatRuntime()\n if (!author) return null\n\n const proxiedAvatar = avatar\n ? proxyImageUrl\n ? proxyImageUrl(avatar)\n : (getProxiedImageUrl(avatar, {\n proxyPrefix: runtime?.endpoints.imageProxyUrlPrefix,\n skipDomains: runtime?.endpoints.imageProxySkipDomains,\n directHttps: true,\n }) ?? avatar)\n : ''\n\n // Class-driven sizing (md = 56px, lg = 64px). The numeric pair feeds only\n // the Image element's intrinsic width/height attributes (required by the\n // Next image shim) — layout comes from the classes.\n const avatarSizeClass = size === 'lg' ? 'w-16 h-16' : 'w-14 h-14'\n const avatarIconClass = size === 'lg' ? 'w-8 h-8' : 'w-7 h-7'\n const avatarDim = size === 'lg' ? 64 : 56\n const formattedBio = formatBioText(bio ?? null)\n const dateLabel = publishedAt ? formatDate(publishedAt) : ''\n\n return (\n <div\n className={cn(\n 'bg-ods-card border border-ods-border rounded-lg p-6',\n 'flex flex-col md:flex-row gap-4 items-start',\n className,\n )}\n >\n {/* Avatar */}\n <div className=\"flex-shrink-0\">\n {avatar ? (\n <Image\n src={proxiedAvatar || avatar}\n alt={author}\n width={avatarDim}\n height={avatarDim}\n className={cn('rounded-full border-2 border-ods-border object-cover', avatarSizeClass)}\n />\n ) : (\n <div\n className={cn(\n 'rounded-full border-2 border-ods-border bg-ods-bg flex items-center justify-center',\n avatarSizeClass,\n )}\n >\n <User className={cn('text-ods-text-secondary', avatarIconClass)} />\n </div>\n )}\n </div>\n\n {/* Name + meta + bio */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex flex-wrap items-baseline gap-x-3 gap-y-1\">\n <h3 className=\"text-h5 text-ods-text-primary\">\n {href ? (\n <Link href={href} className=\"hover:text-ods-accent transition-colors\">\n {author}\n </Link>\n ) : (\n author\n )}\n </h3>\n {dateLabel && (\n <span className=\"inline-flex items-center gap-1 font-body text-body-sm text-ods-text-secondary\">\n <Calendar className=\"h-3 w-3\" />\n {dateLabel}\n </span>\n )}\n </div>\n {jobTitle && (\n <p className=\"font-body text-body-sm text-ods-text-secondary mt-0.5\">\n {jobTitle}\n </p>\n )}\n {formattedBio ? (\n <p className=\"font-body text-body-md text-ods-text-secondary leading-relaxed mt-2\">\n {formattedBio}\n </p>\n ) : fallbackBio ? (\n <p className=\"font-body text-body-md text-ods-text-secondary italic mt-2\">\n {fallbackBio}\n </p>\n ) : null}\n </div>\n </div>\n )\n}\n"]}
@@ -3,11 +3,11 @@ import {
3
3
  FileDownloadCard,
4
4
  GoogleSheetsViewer,
5
5
  PdfViewer
6
- } from "./chunk-ZARYIFCI.js";
6
+ } from "./chunk-3UPQAOES.js";
7
7
  import {
8
8
  DocSearchBar,
9
9
  useDocSearch
10
- } from "./chunk-ZXASQL3E.js";
10
+ } from "./chunk-C5GKBUT7.js";
11
11
  import {
12
12
  DEFAULT_FOLDER_INDEX_FILE,
13
13
  FigmaEmbed,
@@ -19,20 +19,20 @@ import {
19
19
  findDocNodeByPath,
20
20
  getDocAncestorNodeIds,
21
21
  stripFolderIndexFromPath
22
- } from "./chunk-EYXZF46V.js";
22
+ } from "./chunk-FE5QR7PT.js";
23
23
  import {
24
24
  HUB_HEADER_OFFSET_PX,
25
25
  contentFetch,
26
26
  navigateSamePageHash,
27
27
  scrollElementIntoView
28
- } from "./chunk-ZNEVGXMU.js";
28
+ } from "./chunk-TXEI4PES.js";
29
29
  import {
30
30
  init_next_navigation,
31
31
  useRouter
32
32
  } from "./chunk-ZJJERZUA.js";
33
33
  import {
34
34
  useChatRuntime
35
- } from "./chunk-UWY722RH.js";
35
+ } from "./chunk-MR6RRXSD.js";
36
36
  import {
37
37
  cn,
38
38
  init_cn
@@ -1845,4 +1845,4 @@ export {
1845
1845
  EmbedSkeleton,
1846
1846
  DocsHubPage
1847
1847
  };
1848
- //# sourceMappingURL=chunk-2LKVYI7H.js.map
1848
+ //# sourceMappingURL=chunk-PLJAOZYZ.js.map
@@ -1,7 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
2
2
 
3
3
 
4
- var _chunkNKEOD2ADcjs = require('./chunk-NKEOD2AD.cjs');
4
+ var _chunkTDYTAED2cjs = require('./chunk-TDYTAED2.cjs');
5
5
 
6
6
 
7
7
 
@@ -11,12 +11,12 @@ var _chunkNKEOD2ADcjs = require('./chunk-NKEOD2AD.cjs');
11
11
 
12
12
 
13
13
 
14
- var _chunk6RSKK4E7cjs = require('./chunk-6RSKK4E7.cjs');
14
+ var _chunk74DB5H5Tcjs = require('./chunk-74DB5H5T.cjs');
15
15
 
16
16
 
17
17
 
18
18
 
19
- var _chunkNK3M6F5Acjs = require('./chunk-NK3M6F5A.cjs');
19
+ var _chunkZ3SRMLMKcjs = require('./chunk-Z3SRMLMK.cjs');
20
20
 
21
21
 
22
22
 
@@ -70,7 +70,7 @@ function FaqAccordion({ items, defaultOpenIds = [] }) {
70
70
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
71
71
  "div",
72
72
  {
73
- id: _chunk6RSKK4E7cjs.faqItemAnchor.call(void 0, item.id),
73
+ id: _chunk74DB5H5Tcjs.faqItemAnchor.call(void 0, item.id),
74
74
  className: "scroll-mt-24 transition-colors hover:bg-ods-bg-hover",
75
75
  children: [
76
76
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
@@ -151,7 +151,7 @@ function buildFaqJsonLdFromFaqs(faqs, opts = {}) {
151
151
 
152
152
  var DEFAULT_HEADING_TEXT = "Frequently Asked Questions";
153
153
  function buildFaqsUrl(entityType, entityId, minResults, apiBaseUrl = "") {
154
- return _chunk6RSKK4E7cjs.buildSuggestionUrl.call(void 0, "/api/faqs", { apiBaseUrl, entityType, entityId, count: minResults });
154
+ return _chunk74DB5H5Tcjs.buildSuggestionUrl.call(void 0, "/api/faqs", { apiBaseUrl, entityType, entityId, count: minResults });
155
155
  }
156
156
  function groupFaqsBySection(faqs) {
157
157
  const order = [];
@@ -167,7 +167,7 @@ function groupFaqsBySection(faqs) {
167
167
  }
168
168
  let group = byName.get(name);
169
169
  if (!group) {
170
- group = { section: name, slug: _chunk6RSKK4E7cjs.faqSectionSlug.call(void 0, name), items: [] };
170
+ group = { section: name, slug: _chunk74DB5H5Tcjs.faqSectionSlug.call(void 0, name), items: [] };
171
171
  byName.set(name, group);
172
172
  order.push(name);
173
173
  }
@@ -207,7 +207,7 @@ function GroupedFaqList({
207
207
  }
208
208
  if (bestId) setActiveSlug(bestId);
209
209
  },
210
- { rootMargin: `-${_chunkNK3M6F5Acjs.STICKY_HEADER_OFFSET_PX}px 0px -55% 0px`, threshold: 0 }
210
+ { rootMargin: `-${_chunkZ3SRMLMKcjs.STICKY_HEADER_OFFSET_PX}px 0px -55% 0px`, threshold: 0 }
211
211
  );
212
212
  for (const group of navGroups) {
213
213
  const el = group.slug ? document.getElementById(group.slug) : null;
@@ -217,7 +217,7 @@ function GroupedFaqList({
217
217
  }, [slugKey]);
218
218
  const [hashTarget, setHashTarget] = _react.useState.call(void 0, null);
219
219
  _react.useEffect.call(void 0, () => {
220
- const refresh = () => setHashTarget(_chunk6RSKK4E7cjs.parseFaqHash.call(void 0, window.location.hash));
220
+ const refresh = () => setHashTarget(_chunk74DB5H5Tcjs.parseFaqHash.call(void 0, window.location.hash));
221
221
  refresh();
222
222
  window.addEventListener("hashchange", refresh);
223
223
  return () => window.removeEventListener("hashchange", refresh);
@@ -234,15 +234,15 @@ function GroupedFaqList({
234
234
  }, [groups, hashTarget]);
235
235
  const accordionKeySuffix = _optionalChain([hashTarget, 'optionalAccess', _8 => _8.kind]) === "item" ? `item:${hashTarget.rawId}` : "default";
236
236
  const scrollDep = `${groups.length}|` + (_optionalChain([hashTarget, 'optionalAccess', _9 => _9.kind]) === "item" ? `item:${hashTarget.rawId}` : _optionalChain([hashTarget, 'optionalAccess', _10 => _10.kind]) === "section" ? `section:${hashTarget.slug}` : "none");
237
- _chunkNK3M6F5Acjs.useScrollToHash.call(void 0, scrollDep, { headerOffset: _chunkNK3M6F5Acjs.STICKY_HEADER_OFFSET_PX });
237
+ _chunkZ3SRMLMKcjs.useScrollToHash.call(void 0, scrollDep, { headerOffset: _chunkZ3SRMLMKcjs.STICKY_HEADER_OFFSET_PX });
238
238
  _react.useEffect.call(void 0, () => {
239
239
  if (_optionalChain([hashTarget, 'optionalAccess', _11 => _11.kind]) === "section") setActiveSlug(hashTarget.slug);
240
240
  }, [hashTarget]);
241
241
  const handleJump = _react.useCallback.call(void 0,
242
242
  (e, slug) => {
243
243
  e.preventDefault();
244
- _chunkNK3M6F5Acjs.navigateSamePageHash.call(void 0, "#" + slug, {
245
- headerOffset: _chunkNK3M6F5Acjs.STICKY_HEADER_OFFSET_PX,
244
+ _chunkZ3SRMLMKcjs.navigateSamePageHash.call(void 0, "#" + slug, {
245
+ headerOffset: _chunkZ3SRMLMKcjs.STICKY_HEADER_OFFSET_PX,
246
246
  history: "replace"
247
247
  });
248
248
  },
@@ -274,7 +274,7 @@ function GroupedFaqList({
274
274
  id: _nullishCoalesce(group.slug, () => ( void 0)),
275
275
  className: "scroll-mt-24 space-y-4",
276
276
  children: [
277
- group.section && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CategoryHeading, { className: _chunk6RSKK4E7cjs.SECTION_HEADING_CLASS, children: group.section }),
277
+ group.section && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CategoryHeading, { className: _chunk74DB5H5Tcjs.SECTION_HEADING_CLASS, children: group.section }),
278
278
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
279
279
  FaqAccordion,
280
280
  {
@@ -315,10 +315,10 @@ function FaqSection({
315
315
  () => initialFaqs ? { faqs: initialFaqs } : void 0,
316
316
  [initialFaqs]
317
317
  );
318
- const { data, isLoading, error } = _chunkNKEOD2ADcjs.useSelfFetch.call(void 0, url, { initialData });
318
+ const { data, isLoading, error } = _chunkTDYTAED2cjs.useSelfFetch.call(void 0, url, { initialData });
319
319
  const faqs = _nullishCoalesce(_optionalChain([data, 'optionalAccess', _14 => _14.faqs]), () => ( []));
320
320
  const groups = _react.useMemo.call(void 0, () => faqs.length > 0 ? groupFaqsBySection(faqs) : [], [faqs]);
321
- const headingNode = heading === void 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: _chunk6RSKK4E7cjs.SECTION_HEADING_CLASS, children: DEFAULT_HEADING_TEXT }) : heading;
321
+ const headingNode = heading === void 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: _chunk74DB5H5Tcjs.SECTION_HEADING_CLASS, children: DEFAULT_HEADING_TEXT }) : heading;
322
322
  if (error) return null;
323
323
  if (!isLoading && faqs.length === 0) return null;
324
324
  if (isLoading && faqs.length === 0) {
@@ -334,7 +334,7 @@ function FaqSection({
334
334
  "script",
335
335
  {
336
336
  type: "application/ld+json",
337
- dangerouslySetInnerHTML: { __html: _chunk6RSKK4E7cjs.serializeJsonLd.call(void 0, schema) }
337
+ dangerouslySetInnerHTML: { __html: _chunk74DB5H5Tcjs.serializeJsonLd.call(void 0, schema) }
338
338
  }
339
339
  )
340
340
  ] });
@@ -361,7 +361,7 @@ function FaqDocumentPage({
361
361
  label: _nullishCoalesce(_optionalChain([backButton, 'optionalAccess', _15 => _15.label]), () => ( "Back to home")),
362
362
  onClick: () => router.push(_nullishCoalesce(_optionalChain([backButton, 'optionalAccess', _16 => _16.href]), () => ( "/")))
363
363
  };
364
- const inner = /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk6RSKK4E7cjs.PageLayout, { title, subtitle, backButton: backCfg, titleSize: "h1", titleWrap: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
364
+ const inner = /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk74DB5H5Tcjs.PageLayout, { title, subtitle, backButton: backCfg, titleSize: "h1", titleWrap: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
365
365
  FaqSection,
366
366
  {
367
367
  initialFaqs,
@@ -374,7 +374,7 @@ function FaqDocumentPage({
374
374
  minResults
375
375
  }
376
376
  ) });
377
- return shell ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk6RSKK4E7cjs.PageShell, { children: inner }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "page-shell-content", children: inner });
377
+ return shell ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk74DB5H5Tcjs.PageShell, { children: inner }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "page-shell-content", children: inner });
378
378
  }
379
379
 
380
380
 
@@ -382,4 +382,4 @@ function FaqDocumentPage({
382
382
 
383
383
 
384
384
  exports.FaqAccordion = FaqAccordion; exports.FaqSection = FaqSection; exports.FaqDocumentPage = FaqDocumentPage;
385
- //# sourceMappingURL=chunk-L22CSZZU.cjs.map
385
+ //# sourceMappingURL=chunk-QY3VTOB6.cjs.map