@flamingo-stack/openframe-frontend-core 0.0.405 → 0.0.406-snapshot.20260711131925

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 (136) hide show
  1. package/dist/{chunk-3KEBI6TP.cjs → chunk-2B6773QM.cjs} +1 -1
  2. package/dist/chunk-2B6773QM.cjs.map +1 -0
  3. package/dist/{chunk-RIGB7LP7.js → chunk-43H2WOAW.js} +3 -3
  4. package/dist/{chunk-QYTGHN2T.js → chunk-4UZH3MT2.js} +4 -4
  5. package/dist/{chunk-LREN3G7R.cjs → chunk-5M5W6XDY.cjs} +7 -7
  6. package/dist/{chunk-LREN3G7R.cjs.map → chunk-5M5W6XDY.cjs.map} +1 -1
  7. package/dist/{chunk-WEZIVLCO.cjs → chunk-74FWQI73.cjs} +18 -18
  8. package/dist/{chunk-WEZIVLCO.cjs.map → chunk-74FWQI73.cjs.map} +1 -1
  9. package/dist/{chunk-E6YHDT3D.js → chunk-7Q52HP45.js} +2 -2
  10. package/dist/chunk-7Q52HP45.js.map +1 -0
  11. package/dist/{chunk-3XCNFTFV.js → chunk-7XVFSGQA.js} +3 -3
  12. package/dist/{chunk-QAFRLO5N.cjs → chunk-CUN4CJUN.cjs} +10 -11
  13. package/dist/chunk-CUN4CJUN.cjs.map +1 -0
  14. package/dist/{chunk-ICJRSNBM.js → chunk-CVYSW33D.js} +199 -189
  15. package/dist/chunk-CVYSW33D.js.map +1 -0
  16. package/dist/{chunk-FOJRR647.cjs → chunk-DOBNDDNE.cjs} +75 -75
  17. package/dist/{chunk-FOJRR647.cjs.map → chunk-DOBNDDNE.cjs.map} +1 -1
  18. package/dist/{chunk-FFYEDIAG.cjs → chunk-GGDM5J4B.cjs} +332 -322
  19. package/dist/chunk-GGDM5J4B.cjs.map +1 -0
  20. package/dist/{chunk-UN2BJ7XW.js → chunk-GJSLKATJ.js} +2 -2
  21. package/dist/{chunk-GT7AJXKH.js → chunk-GMZL4T7C.js} +3 -3
  22. package/dist/{chunk-BK7QCB5J.js → chunk-H66L2265.js} +6 -6
  23. package/dist/{chunk-F3YLM5PO.js → chunk-HB63TQQO.js} +2 -2
  24. package/dist/{chunk-5XZEY34X.js → chunk-HJIRG7R6.js} +4 -4
  25. package/dist/{chunk-NA7XJRWB.js → chunk-KFQXO7QB.js} +1 -1
  26. package/dist/chunk-KFQXO7QB.js.map +1 -0
  27. package/dist/{chunk-Q2KKEE6W.js → chunk-KLBEIJVZ.js} +7 -7
  28. package/dist/{chunk-M6BGJVDY.cjs → chunk-LC6RRLFA.cjs} +15 -15
  29. package/dist/{chunk-M6BGJVDY.cjs.map → chunk-LC6RRLFA.cjs.map} +1 -1
  30. package/dist/{chunk-VFWEFR3Q.cjs → chunk-LPC3C7MG.cjs} +40 -40
  31. package/dist/{chunk-VFWEFR3Q.cjs.map → chunk-LPC3C7MG.cjs.map} +1 -1
  32. package/dist/{chunk-PNJ5LMVK.js → chunk-NO2KT42M.js} +9 -10
  33. package/dist/{chunk-PNJ5LMVK.js.map → chunk-NO2KT42M.js.map} +1 -1
  34. package/dist/{chunk-RC35ITSR.js → chunk-NSF7JUXF.js} +7 -7
  35. package/dist/{chunk-V4MOB3AD.cjs → chunk-PRKMOF2U.cjs} +14 -14
  36. package/dist/{chunk-V4MOB3AD.cjs.map → chunk-PRKMOF2U.cjs.map} +1 -1
  37. package/dist/{chunk-DHIYBC5Z.cjs → chunk-Q2MC3CBI.cjs} +35 -35
  38. package/dist/{chunk-DHIYBC5Z.cjs.map → chunk-Q2MC3CBI.cjs.map} +1 -1
  39. package/dist/{chunk-BS6O4HLJ.cjs → chunk-R4MXLJUS.cjs} +42 -42
  40. package/dist/{chunk-BS6O4HLJ.cjs.map → chunk-R4MXLJUS.cjs.map} +1 -1
  41. package/dist/{chunk-CCIBZ7TO.cjs → chunk-STGWQFYT.cjs} +5 -5
  42. package/dist/chunk-STGWQFYT.cjs.map +1 -0
  43. package/dist/{chunk-6OQ7YOX5.cjs → chunk-SY3QS2E5.cjs} +29 -29
  44. package/dist/{chunk-6OQ7YOX5.cjs.map → chunk-SY3QS2E5.cjs.map} +1 -1
  45. package/dist/{chunk-ELLTTMPE.cjs → chunk-WCPUJA3Y.cjs} +7 -7
  46. package/dist/{chunk-ELLTTMPE.cjs.map → chunk-WCPUJA3Y.cjs.map} +1 -1
  47. package/dist/{chunk-UIAQXIA6.js → chunk-XFP43YKG.js} +6 -6
  48. package/dist/{chunk-ACJ4CM6H.cjs → chunk-YX7C5JD7.cjs} +77 -77
  49. package/dist/{chunk-ACJ4CM6H.cjs.map → chunk-YX7C5JD7.cjs.map} +1 -1
  50. package/dist/components/announcement-bar.d.ts.map +1 -1
  51. package/dist/components/case-studies/index.cjs +10 -10
  52. package/dist/components/case-studies/index.js +4 -4
  53. package/dist/components/chat/index.cjs +4 -4
  54. package/dist/components/chat/index.js +3 -3
  55. package/dist/components/contact/index.cjs +5 -5
  56. package/dist/components/contact/index.js +4 -4
  57. package/dist/components/docs/index.cjs +7 -7
  58. package/dist/components/docs/index.js +6 -6
  59. package/dist/components/embeds/index.cjs +5 -5
  60. package/dist/components/embeds/index.js +4 -4
  61. package/dist/components/faq/index.cjs +6 -6
  62. package/dist/components/faq/index.js +5 -5
  63. package/dist/components/features/index.cjs +4 -4
  64. package/dist/components/features/index.js +3 -3
  65. package/dist/components/help-center-pages/index.cjs +23 -23
  66. package/dist/components/help-center-pages/index.js +14 -14
  67. package/dist/components/index.cjs +185 -179
  68. package/dist/components/index.cjs.map +1 -1
  69. package/dist/components/index.js +38 -32
  70. package/dist/components/index.js.map +1 -1
  71. package/dist/components/navigation/index.cjs +4 -4
  72. package/dist/components/navigation/index.js +3 -3
  73. package/dist/components/onboarding-guides/index.cjs +8 -8
  74. package/dist/components/onboarding-guides/index.js +7 -7
  75. package/dist/components/related-content/index.cjs +6 -6
  76. package/dist/components/related-content/index.js +5 -5
  77. package/dist/components/tickets/index.cjs +7 -7
  78. package/dist/components/tickets/index.js +6 -6
  79. package/dist/components/ui/index.cjs +4 -4
  80. package/dist/components/ui/index.js +3 -3
  81. package/dist/contexts/endpoints-runtime-context.d.ts +1 -1
  82. package/dist/contexts/endpoints-runtime-context.d.ts.map +1 -1
  83. package/dist/contexts/index.cjs +2 -2
  84. package/dist/contexts/index.js +1 -1
  85. package/dist/hooks/index.cjs +3 -3
  86. package/dist/hooks/index.js +2 -2
  87. package/dist/hooks/use-self-fetch.d.ts.map +1 -1
  88. package/dist/index.cjs +4 -4
  89. package/dist/index.cjs.map +1 -1
  90. package/dist/index.js +5 -5
  91. package/dist/types/announcement.cjs.map +1 -1
  92. package/dist/types/announcement.d.ts +0 -6
  93. package/dist/types/announcement.d.ts.map +1 -1
  94. package/dist/types/announcement.js.map +1 -1
  95. package/dist/types/index.cjs.map +1 -1
  96. package/dist/types/index.js.map +1 -1
  97. package/dist/utils/announcement-storage.d.ts +3 -0
  98. package/dist/utils/announcement-storage.d.ts.map +1 -1
  99. package/dist/utils/app-config.d.ts.map +1 -1
  100. package/dist/utils/color-analysis.d.ts +0 -4
  101. package/dist/utils/color-analysis.d.ts.map +1 -1
  102. package/dist/utils/index.cjs +186 -177
  103. package/dist/utils/index.cjs.map +1 -1
  104. package/dist/utils/index.js +185 -176
  105. package/dist/utils/index.js.map +1 -1
  106. package/dist/utils/ods-color-utils.d.ts +2 -1
  107. package/dist/utils/ods-color-utils.d.ts.map +1 -1
  108. package/package.json +1 -1
  109. package/src/components/announcement-bar.tsx +38 -21
  110. package/src/components/features/video.tsx +8 -0
  111. package/src/contexts/endpoints-runtime-context.tsx +1 -1
  112. package/src/hooks/use-self-fetch.ts +10 -9
  113. package/src/stories/AnnouncementBar.stories.tsx +8 -14
  114. package/src/types/announcement.ts +0 -8
  115. package/src/utils/announcement-storage.ts +17 -0
  116. package/src/utils/app-config.ts +3 -2
  117. package/src/utils/color-analysis.ts +5 -2
  118. package/src/utils/ods-color-utils.ts +4 -7
  119. package/dist/chunk-3KEBI6TP.cjs.map +0 -1
  120. package/dist/chunk-CCIBZ7TO.cjs.map +0 -1
  121. package/dist/chunk-E6YHDT3D.js.map +0 -1
  122. package/dist/chunk-FFYEDIAG.cjs.map +0 -1
  123. package/dist/chunk-ICJRSNBM.js.map +0 -1
  124. package/dist/chunk-NA7XJRWB.js.map +0 -1
  125. package/dist/chunk-QAFRLO5N.cjs.map +0 -1
  126. /package/dist/{chunk-RIGB7LP7.js.map → chunk-43H2WOAW.js.map} +0 -0
  127. /package/dist/{chunk-QYTGHN2T.js.map → chunk-4UZH3MT2.js.map} +0 -0
  128. /package/dist/{chunk-3XCNFTFV.js.map → chunk-7XVFSGQA.js.map} +0 -0
  129. /package/dist/{chunk-UN2BJ7XW.js.map → chunk-GJSLKATJ.js.map} +0 -0
  130. /package/dist/{chunk-GT7AJXKH.js.map → chunk-GMZL4T7C.js.map} +0 -0
  131. /package/dist/{chunk-BK7QCB5J.js.map → chunk-H66L2265.js.map} +0 -0
  132. /package/dist/{chunk-F3YLM5PO.js.map → chunk-HB63TQQO.js.map} +0 -0
  133. /package/dist/{chunk-5XZEY34X.js.map → chunk-HJIRG7R6.js.map} +0 -0
  134. /package/dist/{chunk-Q2KKEE6W.js.map → chunk-KLBEIJVZ.js.map} +0 -0
  135. /package/dist/{chunk-RC35ITSR.js.map → chunk-NSF7JUXF.js.map} +0 -0
  136. /package/dist/{chunk-UIAQXIA6.js.map → chunk-XFP43YKG.js.map} +0 -0
@@ -6,14 +6,14 @@
6
6
 
7
7
 
8
8
 
9
- var _chunkFFYEDIAGcjs = require('./chunk-FFYEDIAG.cjs');
9
+ var _chunkGGDM5J4Bcjs = require('./chunk-GGDM5J4B.cjs');
10
10
 
11
11
 
12
12
 
13
- var _chunkCCIBZ7TOcjs = require('./chunk-CCIBZ7TO.cjs');
13
+ var _chunkSTGWQFYTcjs = require('./chunk-STGWQFYT.cjs');
14
14
 
15
15
 
16
- var _chunk3KEBI6TPcjs = require('./chunk-3KEBI6TP.cjs');
16
+ var _chunk2B6773QMcjs = require('./chunk-2B6773QM.cjs');
17
17
 
18
18
 
19
19
  var _chunkG7UE6RKVcjs = require('./chunk-G7UE6RKV.cjs');
@@ -34,7 +34,7 @@ function DocSearchResultRow({
34
34
  }) {
35
35
  const docType = _optionalChain([result, 'access', _ => _.metadata, 'optionalAccess', _2 => _2.documentType]) || void 0;
36
36
  const sourceRepo = _optionalChain([result, 'access', _3 => _3.metadata, 'optionalAccess', _4 => _4.sourceRepo]) || void 0;
37
- const { Icon: SourceIcon, label: iconLabel } = _chunkFFYEDIAGcjs.resolveSourceIcon.call(void 0, {
37
+ const { Icon: SourceIcon, label: iconLabel } = _chunkGGDM5J4Bcjs.resolveSourceIcon.call(void 0, {
38
38
  sourceRepo,
39
39
  documentType: docType
40
40
  });
@@ -77,7 +77,7 @@ function DocSearchBar({
77
77
  renderResult
78
78
  }) {
79
79
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
80
- _chunkFFYEDIAGcjs.SearchInput,
80
+ _chunkGGDM5J4Bcjs.SearchInput,
81
81
  {
82
82
  placeholder,
83
83
  value: query,
@@ -186,7 +186,7 @@ function resolveSearchResultAction(result, source, runtimeMode) {
186
186
  const externalUrl = meta.externalUrl;
187
187
  if (externalUrl) {
188
188
  const targetPlatform = meta.targetPlatform;
189
- const isNewTab = _chunkFFYEDIAGcjs.decideNewTab.call(void 0, {
189
+ const isNewTab = _chunkGGDM5J4Bcjs.decideNewTab.call(void 0, {
190
190
  href: externalUrl,
191
191
  targetPlatform,
192
192
  surface: "useUnifiedNav",
@@ -226,12 +226,12 @@ function useDocSearch(config) {
226
226
  } = config;
227
227
  const tableIdsKey = tableIds && tableIds.length > 0 ? tableIds.join(",") : "";
228
228
  const router = _chunkG7UE6RKVcjs.useRouter.call(void 0, );
229
- const runtime = _chunk3KEBI6TPcjs.useChatRuntime.call(void 0, );
229
+ const runtime = _chunk2B6773QMcjs.useChatRuntime.call(void 0, );
230
230
  const resolvedSearchEndpoint = _nullishCoalesce(_nullishCoalesce(searchEndpoint, () => ( _optionalChain([runtime, 'optionalAccess', _10 => _10.endpoints, 'access', _11 => _11.docsSearchUrl]))), () => ( "/api/docs/search"));
231
231
  const [query, setQuery] = _react.useState.call(void 0, "");
232
232
  const [results, setResults] = _react.useState.call(void 0, []);
233
233
  const [isFetching, setIsFetching] = _react.useState.call(void 0, false);
234
- const debouncedQuery = _chunkCCIBZ7TOcjs.useDebounce.call(void 0, query, 300);
234
+ const debouncedQuery = _chunkSTGWQFYTcjs.useDebounce.call(void 0, query, 300);
235
235
  _react.useEffect.call(void 0, () => {
236
236
  if (!debouncedQuery || debouncedQuery.trim().length < 2) {
237
237
  setResults([]);
@@ -248,7 +248,7 @@ function useDocSearch(config) {
248
248
  limit: "10"
249
249
  });
250
250
  if (tableIdsKey) params.set("tableIds", tableIdsKey);
251
- const response = await _chunkCCIBZ7TOcjs.contentFetch.call(void 0, `${resolvedSearchEndpoint}?${params.toString()}`);
251
+ const response = await _chunkSTGWQFYTcjs.contentFetch.call(void 0, `${resolvedSearchEndpoint}?${params.toString()}`);
252
252
  if (!response.ok) {
253
253
  throw new Error(`Search request failed: ${response.status}`);
254
254
  }
@@ -288,7 +288,7 @@ function useDocSearch(config) {
288
288
  if (_optionalChain([runtime, 'optionalAccess', _14 => _14.navigation, 'access', _15 => _15.mode]) === "embed") {
289
289
  setKeepOpen(true);
290
290
  const targetPlatform = _nullishCoalesce(_optionalChain([result, 'access', _16 => _16.metadata, 'optionalAccess', _17 => _17.targetPlatform]), () => ( null));
291
- _chunkFFYEDIAGcjs.resolveExternalNavigation.call(void 0, {
291
+ _chunkGGDM5J4Bcjs.resolveExternalNavigation.call(void 0, {
292
292
  href: action.href,
293
293
  targetPlatform,
294
294
  runtime
@@ -297,18 +297,18 @@ function useDocSearch(config) {
297
297
  }
298
298
  if (wantsNewTab) {
299
299
  setKeepOpen(true);
300
- window.open(action.href, "_blank", _chunkFFYEDIAGcjs.NEW_TAB_FEATURES);
300
+ window.open(action.href, "_blank", _chunkGGDM5J4Bcjs.NEW_TAB_FEATURES);
301
301
  return;
302
302
  }
303
303
  setKeepOpen(false);
304
304
  const path = baseRoute && action.href.startsWith(`${baseRoute}/`) ? action.href.slice(baseRoute.length + 1) : null;
305
305
  if (path && _optionalChain([onInPageSwap, 'optionalCall', _18 => _18(path)])) return;
306
- router.push(_chunkFFYEDIAGcjs.stripSameOriginToPath.call(void 0, action.href));
306
+ router.push(_chunkGGDM5J4Bcjs.stripSameOriginToPath.call(void 0, action.href));
307
307
  return;
308
308
  }
309
309
  case "navigate-new-tab":
310
310
  setKeepOpen(true);
311
- window.open(action.href, "_blank", _chunkFFYEDIAGcjs.NEW_TAB_FEATURES);
311
+ window.open(action.href, "_blank", _chunkGGDM5J4Bcjs.NEW_TAB_FEATURES);
312
312
  return;
313
313
  case "ask-ai":
314
314
  setKeepOpen(false);
@@ -347,4 +347,4 @@ function useDocSearch(config) {
347
347
 
348
348
 
349
349
  exports.formatRelativePath = formatRelativePath; exports.DocSearchResultRow = DocSearchResultRow; exports.DocSearchBar = DocSearchBar; exports.mapDocSearchResults = mapDocSearchResults; exports.resolveSearchResultAction = resolveSearchResultAction; exports.useDocSearch = useDocSearch;
350
- //# sourceMappingURL=chunk-V4MOB3AD.cjs.map
350
+ //# sourceMappingURL=chunk-PRKMOF2U.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-V4MOB3AD.cjs","../src/components/shared/doc-search/format-relative-path.ts","../src/components/shared/doc-search/doc-search-result-row.tsx","../src/components/shared/doc-search/doc-search-bar.tsx","../src/components/shared/doc-search/map-doc-search-results.ts","../src/components/shared/doc-search/resolve-search-result-action.ts","../src/components/shared/doc-search/use-doc-search.ts"],"names":["jsx"],"mappings":"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","file":"/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-V4MOB3AD.cjs","sourcesContent":[null,"/**\n * Format a full document path as a breadcrumb trail.\n * Shows parent folders only (excludes the last segment / filename).\n *\n * @example\n * formatRelativePath('openframe-oss-tenant/architecture/api-controllers.md')\n * // → 'Openframe oss tenant / Architecture'\n */\nexport function formatRelativePath(fullPath: string): string {\n if (!fullPath) return ''\n const segments = fullPath.replace(/\\.md$/, '').split('/')\n // Show only parent path (exclude the filename itself since the title already shows it)\n const parentSegments = segments.length > 1 ? segments.slice(0, -1) : segments\n return parentSegments\n .map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1).replace(/-/g, ' '))\n .join(' / ')\n}\n","'use client'\n\n/**\n * Single row in the `<SearchInput>` dropdown — the standard layout\n * used by every doc-search-backed surface (company-hub data-room\n * search bar, onboarding-guide catalog search, …). Single source of\n * truth for the row appearance so search dropdowns are visually\n * identical everywhere.\n *\n * Resolves the source icon via the same `resolveSourceIcon()`\n * registry the inline chat-card refs use, so a row pointing at e.g.\n * an onboarding-guide surfaces the SAME `<GraduationCap>` glyph the\n * chat card surfaces — no cross-surface drift.\n */\n\nimport { resolveSourceIcon } from '../../chat/utils/source-row-cta'\nimport { formatRelativePath } from './format-relative-path'\n\n/**\n * Minimal result shape this row renders. Compatible with any\n * doc-search hook whose result type exposes `{ title?, path?,\n * metadata? }`. The two hub consumers (onboarding-guide catalog,\n * data-room sidebar) both satisfy this shape via their\n * `useDocSearch` hook result.\n */\nexport interface DocSearchResultRowEntry {\n title?: string\n path?: string\n metadata?: Record<string, unknown>\n}\n\nexport interface DocSearchResultRowProps {\n result: DocSearchResultRowEntry\n isHighlighted: boolean\n}\n\nexport function DocSearchResultRow({\n result,\n isHighlighted,\n}: DocSearchResultRowProps) {\n const docType = (result.metadata?.documentType as string) || undefined\n const sourceRepo = (result.metadata?.sourceRepo as string) || undefined\n const { Icon: SourceIcon, label: iconLabel } = resolveSourceIcon({\n sourceRepo,\n documentType: docType,\n })\n const isGroup = result.metadata?.isGroup as boolean | undefined\n\n return (\n <div className=\"flex items-center gap-3 w-full min-w-0\">\n <span\n className=\"flex-shrink-0 text-ods-text-secondary\"\n title={iconLabel}\n >\n <SourceIcon className=\"size-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div\n className={`text-sm font-medium leading-5 truncate ${\n isHighlighted ? 'text-ods-accent' : 'text-ods-text-primary'\n }`}\n >\n {result.title || result.path}\n </div>\n {!isGroup && result.path?.includes('/') && (\n <div className=\"text-xs leading-4 text-ods-text-secondary truncate mt-0.5\">\n {formatRelativePath(result.path)}\n </div>\n )}\n </div>\n </div>\n )\n}\n","'use client'\n\n/**\n * `<DocSearchBar>` — the canonical RAG-search dropdown surface.\n *\n * Mounted by every doc-search consumer (data-room sidebar, onboarding-\n * guide catalog, and any future surface that needs typeahead against\n * `/api/docs/search`). Wraps `<SearchInput>` with the lib's standard\n * `<DocSearchResultRow>` so the dropdown looks identical everywhere.\n *\n * ## Why a presentation component, not a \"search bar that owns its\n * own hook\"\n *\n * The data-fetching hook (`useDocSearch`) lives hub-side because it\n * depends on hub-only context (`useDocNavigation`, the rag-table-\n * config registry, the hub's `decideNewTab` helper). Moving the hook\n * would cascade ~5 more file migrations into the lib.\n *\n * Instead, the hook stays hub-side and callers pass its result into\n * this component as plain props. Both consumers shrink to ~5 lines.\n */\n\nimport type { ReactNode } from 'react'\nimport { SearchInput, type SearchResult } from '../../ui/search-input'\nimport { DocSearchResultRow } from './doc-search-result-row'\n\nexport interface DocSearchBarProps {\n placeholder: string\n query: string\n onQueryChange: (value: string) => void\n /** Hook-fetched results. Reuses the lib's `<SearchInput>` `SearchResult`\n * shape directly so callers don't translate. */\n results: SearchResult[]\n isLoading: boolean\n /** Result selection handler. Mirrors `<SearchInput>` — the second\n * `modifiers` argument is preserved so cmd-click / shift-click on\n * a result row still forces new-tab behavior. Hub `useDocSearch`\n * reads these to short-circuit to `window.open()`. */\n onResultSelect: (\n result: SearchResult,\n modifiers?: {\n metaKey?: boolean\n ctrlKey?: boolean\n shiftKey?: boolean\n altKey?: boolean\n button?: number\n },\n ) => void\n /** Lets the caller's hook force the dropdown open after a recent\n * internal action (e.g. result navigation). `undefined` falls back\n * to `<SearchInput>`'s built-in focus/hover heuristics. */\n showDropdown?: boolean\n /** Defaults to 2 — matches the existing data-room and onboarding-\n * guide consumers. Override only if a surface needs different\n * typeahead semantics. */\n minQueryLength?: number\n /** Defaults to 0 — both existing consumers debounce inside the\n * hook, not the input. */\n debounceMs?: number\n className?: string\n /** Optional row-renderer override. Defaults to the lib's standard\n * `<DocSearchResultRow>` (source icon + title + path breadcrumb).\n * Override only when a surface needs custom row chrome. */\n renderResult?: (result: SearchResult, isHighlighted: boolean) => ReactNode\n}\n\nexport function DocSearchBar({\n placeholder,\n query,\n onQueryChange,\n results,\n isLoading,\n onResultSelect,\n showDropdown,\n minQueryLength = 2,\n debounceMs = 0,\n className = 'w-full',\n renderResult,\n}: DocSearchBarProps) {\n return (\n <SearchInput\n placeholder={placeholder}\n value={query}\n onChange={onQueryChange}\n results={results}\n isLoading={isLoading}\n onResultSelect={onResultSelect}\n showDropdown={showDropdown || undefined}\n debounceMs={debounceMs}\n minQueryLength={minQueryLength}\n className={className}\n renderResult={\n renderResult ??\n ((result, isHighlighted) => (\n <DocSearchResultRow result={result} isHighlighted={isHighlighted} />\n ))\n }\n />\n )\n}\n","/**\n * Map RAG `/api/docs/search` wire results into the `<DocSearchBar>`\n * dropdown's row shape, collapsing entity-table rows into grouped\n * results so the dropdown lists ONE \"Cap Table (12 records)\" row\n * instead of 12 individual rows.\n *\n * Pure transform — no telemetry, no navigation, no React deps. Lifted\n * from the hub's `hooks/use-docs.ts:mapDocSearchResults` (the hub's\n * `traceCompose` call was hub-only telemetry and is intentionally\n * dropped — callers that want logging can wrap this helper).\n */\n\nimport type { SearchResult } from '../../ui/search-input'\nimport type { DocSearchResult } from './types'\n\n/** Source repos that should be collapsed into grouped results in the search bar.\n * Only financial tables (all rows link to the same admin page).\n * Content tables (blog, webinar, podcast, etc.) stay individual since each has a unique URL. */\nconst SEARCH_GROUP_REPOS = new Set([\n 'financial-cap-table',\n 'financial-kpis',\n 'financial-pnl',\n 'financial-balance-sheet',\n 'financial-cash-flow',\n])\n\nconst ENTITY_LABELS: Record<string, string> = {\n 'financial-cap-table': 'Cap Table',\n 'financial-kpis': 'Financial KPIs',\n 'financial-pnl': 'Profit & Loss',\n 'financial-balance-sheet': 'Balance Sheets',\n 'financial-cash-flow': 'Cash Flow',\n 'blog-posts': 'Blog Posts',\n 'product-releases': 'Product Releases',\n 'case-studies': 'Case Studies',\n webinars: 'Webinars',\n events: 'Events',\n podcasts: 'Podcasts',\n}\n\nexport function mapDocSearchResults(docs: DocSearchResult[]): SearchResult[] {\n const entityGroups = new Map<string, DocSearchResult[]>()\n // Track insertion order — groups appear where the FIRST row of that\n // repo appeared in the response.\n const order: Array<\n { type: 'entity'; repo: string } | { type: 'doc'; doc: DocSearchResult }\n > = []\n const seenRepos = new Set<string>()\n\n for (const doc of docs) {\n if (doc.sourceRepo && SEARCH_GROUP_REPOS.has(doc.sourceRepo)) {\n const group = entityGroups.get(doc.sourceRepo) || []\n group.push(doc)\n entityGroups.set(doc.sourceRepo, group)\n if (!seenRepos.has(doc.sourceRepo)) {\n seenRepos.add(doc.sourceRepo)\n order.push({ type: 'entity', repo: doc.sourceRepo })\n }\n } else {\n order.push({ type: 'doc', doc })\n }\n }\n\n const results: SearchResult[] = []\n for (const entry of order) {\n if (entry.type === 'entity') {\n const rows = entityGroups.get(entry.repo)!\n const label = ENTITY_LABELS[entry.repo] || entry.repo\n results.push({\n id: `group-${entry.repo}`,\n title: `${label} (${rows.length} ${rows.length === 1 ? 'record' : 'records'})`,\n path: rows[0].path,\n type: 'file',\n metadata: {\n documentType: rows[0].documentType,\n externalUrl: rows[0].externalUrl,\n sourceRepo: entry.repo,\n id: rows[0].entityId,\n isGroup: true,\n items: rows.map((r) => ({\n name: r.name,\n externalUrl: r.externalUrl,\n id: r.entityId,\n sourceRepo: r.sourceRepo,\n documentType: r.documentType,\n })),\n },\n })\n } else {\n const doc = entry.doc\n const isNonMarkdown = doc.documentType && doc.documentType !== 'markdown'\n results.push({\n id: doc.path,\n title: doc.name,\n description: isNonMarkdown ? doc.name : doc.snippet,\n path: doc.path,\n type: doc.type,\n metadata: {\n matchType: doc.matchType,\n ...(doc.documentType ? { documentType: doc.documentType } : {}),\n ...(doc.externalUrl ? { externalUrl: doc.externalUrl } : {}),\n ...(doc.targetPlatform != null\n ? { targetPlatform: doc.targetPlatform }\n : {}),\n ...(doc.sourceRepo ? { sourceRepo: doc.sourceRepo } : {}),\n ...(doc.entityId ? { id: doc.entityId } : {}),\n },\n })\n }\n }\n\n return results\n}\n","/**\n * Resolve what should happen when the user picks a search result.\n * Returns one of five typed actions so the caller is a single switch.\n *\n * Resolution order:\n * 1. `externalUrl` present → use `decideNewTab` to choose same-tab vs\n * new-tab against the row's `targetPlatform`.\n * 2. Row has `id` + `sourceRepo` + `documentType` → synth an Ask-AI\n * action (entity drill-in via primary key, no URL).\n * 3. Row has only `path` → legacy navigation fallback.\n * 4. Nothing actionable → noop.\n *\n * Lifted from the hub's `hooks/use-docs.ts:resolveSearchResultAction`.\n * Pure — no React, no telemetry.\n */\n\nimport type { SearchResult } from '../../ui/search-input'\nimport type { ChatRef } from '../../chat/chat-ref.types'\nimport { decideNewTab } from '../../chat/utils/decide-new-tab'\n\nexport type SearchResultAction =\n | { kind: 'navigate-same-tab'; href: string }\n | { kind: 'navigate-new-tab'; href: string }\n | { kind: 'ask-ai'; detail: { source: string; ref: ChatRef } }\n | { kind: 'route'; path: string }\n | { kind: 'noop' }\n\nexport function resolveSearchResultAction(\n result: SearchResult,\n source: string,\n runtimeMode?: 'host' | 'embed',\n): SearchResultAction {\n const meta = result.metadata ?? {}\n const externalUrl = meta.externalUrl as string | undefined\n if (externalUrl) {\n // Same pure helper `useNavLink` and `useUnifiedNav` call — single\n // decision rule across cards, chips, and autocomplete rows. Thread\n // the caller's `source` as `currentSource` so the platform-vs-\n // platform comparison matches the hub's pre-migration behavior.\n const targetPlatform = meta.targetPlatform as string | null | undefined\n const isNewTab = decideNewTab({\n href: externalUrl,\n targetPlatform,\n surface: 'useUnifiedNav',\n runtimeMode,\n currentSource: source,\n })\n return isNewTab\n ? { kind: 'navigate-new-tab', href: externalUrl }\n : { kind: 'navigate-same-tab', href: externalUrl }\n }\n const rowId = meta.id as string | undefined\n const sourceRepo = meta.sourceRepo as string | undefined\n const documentType = meta.documentType as string | undefined\n if (rowId && sourceRepo && documentType) {\n return {\n kind: 'ask-ai',\n detail: {\n source,\n ref: { type: documentType, id: rowId, title: result.title, url: null },\n },\n }\n }\n if (result.path) {\n return { kind: 'route', path: result.path }\n }\n return { kind: 'noop' }\n}\n","'use client'\n\n/**\n * `useDocSearch` — debounced RAG-search hook against `/api/docs/search`.\n *\n * Pure fetch + navigation glue. Embedders can mount this directly\n * (any host with a reverse-proxy that exposes `/api/docs/search` will\n * work). Hub callers wire it into the lib `<DocSearchBar>` for the\n * canonical typeahead dropdown.\n *\n * ## What moved from hub to lib\n *\n * Lifted from `multi-platform-hub/hooks/use-docs.ts:useDocSearch`. Two\n * hub-only concerns are now optional injection points instead of\n * direct imports:\n *\n * - `useDocNavigation()` (hub's in-page doc-tree swap) → optional\n * `onInPageSwap?: (path: string) => boolean` config callback. When\n * present and returns true, the hook treats a same-origin result\n * click as \"handled in-page\"; when absent or returns false, the\n * hook falls back to `onNavigate(path)` (`router.push` on hub,\n * `window.location.assign` on bare embedders).\n * - `traceCompose` (hub-only telemetry) → dropped. The lib has no\n * equivalent runtime-context yet; bring it back when there is one.\n *\n * Everything else (debounce, `useChatRuntime` for embed-mode short-\n * circuit, embed-shim router, the action-resolver + result-mapper) is\n * now lib-resident.\n */\n\nimport { useState, useEffect, useCallback } from 'react'\nimport { useRouter } from '../../../embed-shims'\nimport { useDebounce } from '../../../hooks/ui/use-debounce'\nimport { useChatRuntime } from '../../../contexts/chat-runtime-context'\nimport { contentFetch } from '../../../utils/embed-content-fetch'\nimport type { SearchResult } from '../../ui/search-input'\nimport {\n resolveExternalNavigation,\n stripSameOriginToPath,\n NEW_TAB_FEATURES,\n} from '../../chat/utils/chat-nav-resolution'\nimport type { DocSearchResult } from './types'\nimport { mapDocSearchResults } from './map-doc-search-results'\nimport { resolveSearchResultAction } from './resolve-search-result-action'\n\nexport interface UseDocSearchConfig {\n /** Discriminator passed to `/api/docs/search?source=` (e.g.\n * `'openframe'`). Embedders set it to whatever discriminator their\n * reverse-proxy expects. */\n source: string\n /** Base route prefix this search lives under (e.g. `'/onboarding-guides'`).\n * When a result's href starts with `${baseRoute}/`, the hook\n * attempts the optional in-page swap path before falling through\n * to a full nav. */\n baseRoute: string\n /** Imperative navigation fallback. Called when no override\n * (in-page swap, new-tab) applies. Hub callers pass\n * `(path) => router.push(path)`; embedders pass an equivalent. */\n onNavigate: (path: string) => void\n /** Optional `RagTableConfig.id` list to narrow the search to specific\n * tables (e.g. `['onboarding-guides']`). Forwarded to\n * `/api/docs/search?tableIds=…` which intersects with the source's\n * standing set. */\n tableIds?: string[]\n /** Optional in-page swap callback. When the result's href is under\n * `baseRoute` AND this callback returns true, the hook treats the\n * click as handled in-page (no router push). Hub's\n * `<DocumentationSection>` wires this to\n * `useDocNavigation().navigate(path)`. */\n onInPageSwap?: (path: string) => boolean\n /** Optional endpoint override. Defaults to `'/api/docs/search'`\n * (the hub's reverse-proxy route). Embedders with a different\n * path can override. */\n searchEndpoint?: string\n}\n\nexport function useDocSearch(config: UseDocSearchConfig) {\n const {\n source,\n baseRoute,\n onNavigate,\n tableIds,\n onInPageSwap,\n searchEndpoint,\n } = config\n const tableIdsKey = tableIds && tableIds.length > 0 ? tableIds.join(',') : ''\n\n const router = useRouter()\n // Optional chat-runtime read — when present and mode='embed' the\n // search-result row click short-circuits to a new-tab open against\n // the absolutized URL. Null/host preserves today's behavior.\n // Also used as the proxy-prefix fallback for `searchEndpoint`, matching\n // how tickets resolves `findTicketUrl`.\n const runtime = useChatRuntime()\n const resolvedSearchEndpoint =\n searchEndpoint ?? runtime?.endpoints.docsSearchUrl ?? '/api/docs/search'\n\n const [query, setQuery] = useState('')\n const [results, setResults] = useState<SearchResult[]>([])\n const [isFetching, setIsFetching] = useState(false)\n const debouncedQuery = useDebounce(query, 300)\n\n useEffect(() => {\n if (!debouncedQuery || debouncedQuery.trim().length < 2) {\n setResults([])\n setIsFetching(false)\n return\n }\n\n let cancelled = false\n\n async function fetchResults() {\n setIsFetching(true)\n try {\n const params = new URLSearchParams({\n q: debouncedQuery,\n source,\n limit: '10',\n })\n if (tableIdsKey) params.set('tableIds', tableIdsKey)\n\n const response = await contentFetch(`${resolvedSearchEndpoint}?${params.toString()}`)\n if (!response.ok) {\n throw new Error(`Search request failed: ${response.status}`)\n }\n\n const json = await response.json()\n\n if (!cancelled && json.success && Array.isArray(json.data)) {\n const mapped = mapDocSearchResults(json.data as DocSearchResult[])\n setResults(mapped)\n }\n } catch (error) {\n console.error('Doc search error:', error)\n if (!cancelled) {\n setResults([])\n }\n } finally {\n if (!cancelled) {\n setIsFetching(false)\n }\n }\n }\n\n fetchResults()\n\n return () => {\n cancelled = true\n }\n }, [debouncedQuery, source, tableIdsKey, resolvedSearchEndpoint])\n\n // Derived loading state — single source of truth for \"should the\n // dropdown show 'Loading...' instead of 'No results found'\":\n const isLoading =\n query.trim().length >= 2 && (query !== debouncedQuery || isFetching)\n\n // Track whether dropdown should stay open (external link opened in new tab).\n const [keepOpen, setKeepOpen] = useState(false)\n\n const handleResultSelect = useCallback(\n (\n result: SearchResult,\n modifiers?: {\n metaKey?: boolean\n ctrlKey?: boolean\n shiftKey?: boolean\n altKey?: boolean\n button?: number\n },\n ) => {\n const action = resolveSearchResultAction(\n result,\n source,\n runtime?.navigation.mode,\n )\n // Modifier / non-primary mouse click → force new tab regardless of\n // same-tab/new-tab decision. The dropdown row is a `<div>`, not an\n // `<a target=\"_blank\">`, so the browser doesn't background-tab\n // natively on cmd-click. Honor it explicitly here for parity with\n // the anchor-based surfaces (cards, chips, related-content). Plain\n // Enter from the keyboard passes `modifiers === undefined`.\n const wantsNewTab =\n modifiers &&\n (modifiers.metaKey ||\n modifiers.ctrlKey ||\n modifiers.shiftKey ||\n modifiers.altKey ||\n (typeof modifiers.button === 'number' && modifiers.button !== 0))\n switch (action.kind) {\n case 'navigate-same-tab': {\n // Embed-mode short-circuit — autocomplete row clicked while\n // the chat panel is hosted inside an embedding app.\n if (runtime?.navigation.mode === 'embed') {\n setKeepOpen(true)\n const targetPlatform =\n (result.metadata?.targetPlatform as string | null | undefined) ?? null\n resolveExternalNavigation({\n href: action.href,\n targetPlatform,\n runtime,\n }).open()\n return\n }\n if (wantsNewTab) {\n setKeepOpen(true)\n window.open(action.href, '_blank', NEW_TAB_FEATURES)\n return\n }\n // Same-origin click:\n // 1. If the href is under the current doc-tree's baseRoute AND\n // an `onInPageSwap` callback is wired AND returns true →\n // consider in-page swap handled.\n // 2. Otherwise → embed-shim `router.push()` (soft RSC nav on\n // Next.js hosts, window.location.assign on bare hosts).\n setKeepOpen(false)\n const path =\n baseRoute && action.href.startsWith(`${baseRoute}/`)\n ? action.href.slice(baseRoute.length + 1)\n : null\n if (path && onInPageSwap?.(path)) return\n router.push(stripSameOriginToPath(action.href))\n return\n }\n case 'navigate-new-tab':\n // Cross-origin (e.g. clicking a flamingo.run release from\n // product-hub) — open in a new tab. Keep dropdown open so the\n // user can pick another result without re-searching.\n setKeepOpen(true)\n window.open(action.href, '_blank', NEW_TAB_FEATURES)\n return\n case 'ask-ai':\n // Row is searchable-but-not-openable (cap_table positions,\n // financial-kpi snapshots, anything backed by\n // `resolveUrl: () => null`). Dispatch a CustomEvent that\n // GlobalAskAI listens for — opens chat + drills via\n // `entityIdFilter` (primary-key only, same as inline-card Ask).\n setKeepOpen(false)\n window.dispatchEvent(\n new CustomEvent('ask-ai:open-with-ref', { detail: action.detail }),\n )\n return\n case 'route':\n // Final fallback: legacy navigation by path. Hits when a row\n // has neither URL nor pk metadata — a mapper/API regression.\n setKeepOpen(false)\n onNavigate(action.path)\n return\n case 'noop':\n return\n }\n },\n [onNavigate, source, baseRoute, router, onInPageSwap, runtime],\n )\n\n // Reset keepOpen when query changes.\n useEffect(() => {\n setKeepOpen(false)\n }, [query])\n\n return {\n query,\n setQuery,\n results,\n isLoading,\n handleResultSelect,\n keepDropdownOpen: keepOpen,\n }\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-PRKMOF2U.cjs","../src/components/shared/doc-search/format-relative-path.ts","../src/components/shared/doc-search/doc-search-result-row.tsx","../src/components/shared/doc-search/doc-search-bar.tsx","../src/components/shared/doc-search/map-doc-search-results.ts","../src/components/shared/doc-search/resolve-search-result-action.ts","../src/components/shared/doc-search/use-doc-search.ts"],"names":["jsx"],"mappings":"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","file":"/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-PRKMOF2U.cjs","sourcesContent":[null,"/**\n * Format a full document path as a breadcrumb trail.\n * Shows parent folders only (excludes the last segment / filename).\n *\n * @example\n * formatRelativePath('openframe-oss-tenant/architecture/api-controllers.md')\n * // → 'Openframe oss tenant / Architecture'\n */\nexport function formatRelativePath(fullPath: string): string {\n if (!fullPath) return ''\n const segments = fullPath.replace(/\\.md$/, '').split('/')\n // Show only parent path (exclude the filename itself since the title already shows it)\n const parentSegments = segments.length > 1 ? segments.slice(0, -1) : segments\n return parentSegments\n .map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1).replace(/-/g, ' '))\n .join(' / ')\n}\n","'use client'\n\n/**\n * Single row in the `<SearchInput>` dropdown — the standard layout\n * used by every doc-search-backed surface (company-hub data-room\n * search bar, onboarding-guide catalog search, …). Single source of\n * truth for the row appearance so search dropdowns are visually\n * identical everywhere.\n *\n * Resolves the source icon via the same `resolveSourceIcon()`\n * registry the inline chat-card refs use, so a row pointing at e.g.\n * an onboarding-guide surfaces the SAME `<GraduationCap>` glyph the\n * chat card surfaces — no cross-surface drift.\n */\n\nimport { resolveSourceIcon } from '../../chat/utils/source-row-cta'\nimport { formatRelativePath } from './format-relative-path'\n\n/**\n * Minimal result shape this row renders. Compatible with any\n * doc-search hook whose result type exposes `{ title?, path?,\n * metadata? }`. The two hub consumers (onboarding-guide catalog,\n * data-room sidebar) both satisfy this shape via their\n * `useDocSearch` hook result.\n */\nexport interface DocSearchResultRowEntry {\n title?: string\n path?: string\n metadata?: Record<string, unknown>\n}\n\nexport interface DocSearchResultRowProps {\n result: DocSearchResultRowEntry\n isHighlighted: boolean\n}\n\nexport function DocSearchResultRow({\n result,\n isHighlighted,\n}: DocSearchResultRowProps) {\n const docType = (result.metadata?.documentType as string) || undefined\n const sourceRepo = (result.metadata?.sourceRepo as string) || undefined\n const { Icon: SourceIcon, label: iconLabel } = resolveSourceIcon({\n sourceRepo,\n documentType: docType,\n })\n const isGroup = result.metadata?.isGroup as boolean | undefined\n\n return (\n <div className=\"flex items-center gap-3 w-full min-w-0\">\n <span\n className=\"flex-shrink-0 text-ods-text-secondary\"\n title={iconLabel}\n >\n <SourceIcon className=\"size-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div\n className={`text-sm font-medium leading-5 truncate ${\n isHighlighted ? 'text-ods-accent' : 'text-ods-text-primary'\n }`}\n >\n {result.title || result.path}\n </div>\n {!isGroup && result.path?.includes('/') && (\n <div className=\"text-xs leading-4 text-ods-text-secondary truncate mt-0.5\">\n {formatRelativePath(result.path)}\n </div>\n )}\n </div>\n </div>\n )\n}\n","'use client'\n\n/**\n * `<DocSearchBar>` — the canonical RAG-search dropdown surface.\n *\n * Mounted by every doc-search consumer (data-room sidebar, onboarding-\n * guide catalog, and any future surface that needs typeahead against\n * `/api/docs/search`). Wraps `<SearchInput>` with the lib's standard\n * `<DocSearchResultRow>` so the dropdown looks identical everywhere.\n *\n * ## Why a presentation component, not a \"search bar that owns its\n * own hook\"\n *\n * The data-fetching hook (`useDocSearch`) lives hub-side because it\n * depends on hub-only context (`useDocNavigation`, the rag-table-\n * config registry, the hub's `decideNewTab` helper). Moving the hook\n * would cascade ~5 more file migrations into the lib.\n *\n * Instead, the hook stays hub-side and callers pass its result into\n * this component as plain props. Both consumers shrink to ~5 lines.\n */\n\nimport type { ReactNode } from 'react'\nimport { SearchInput, type SearchResult } from '../../ui/search-input'\nimport { DocSearchResultRow } from './doc-search-result-row'\n\nexport interface DocSearchBarProps {\n placeholder: string\n query: string\n onQueryChange: (value: string) => void\n /** Hook-fetched results. Reuses the lib's `<SearchInput>` `SearchResult`\n * shape directly so callers don't translate. */\n results: SearchResult[]\n isLoading: boolean\n /** Result selection handler. Mirrors `<SearchInput>` — the second\n * `modifiers` argument is preserved so cmd-click / shift-click on\n * a result row still forces new-tab behavior. Hub `useDocSearch`\n * reads these to short-circuit to `window.open()`. */\n onResultSelect: (\n result: SearchResult,\n modifiers?: {\n metaKey?: boolean\n ctrlKey?: boolean\n shiftKey?: boolean\n altKey?: boolean\n button?: number\n },\n ) => void\n /** Lets the caller's hook force the dropdown open after a recent\n * internal action (e.g. result navigation). `undefined` falls back\n * to `<SearchInput>`'s built-in focus/hover heuristics. */\n showDropdown?: boolean\n /** Defaults to 2 — matches the existing data-room and onboarding-\n * guide consumers. Override only if a surface needs different\n * typeahead semantics. */\n minQueryLength?: number\n /** Defaults to 0 — both existing consumers debounce inside the\n * hook, not the input. */\n debounceMs?: number\n className?: string\n /** Optional row-renderer override. Defaults to the lib's standard\n * `<DocSearchResultRow>` (source icon + title + path breadcrumb).\n * Override only when a surface needs custom row chrome. */\n renderResult?: (result: SearchResult, isHighlighted: boolean) => ReactNode\n}\n\nexport function DocSearchBar({\n placeholder,\n query,\n onQueryChange,\n results,\n isLoading,\n onResultSelect,\n showDropdown,\n minQueryLength = 2,\n debounceMs = 0,\n className = 'w-full',\n renderResult,\n}: DocSearchBarProps) {\n return (\n <SearchInput\n placeholder={placeholder}\n value={query}\n onChange={onQueryChange}\n results={results}\n isLoading={isLoading}\n onResultSelect={onResultSelect}\n showDropdown={showDropdown || undefined}\n debounceMs={debounceMs}\n minQueryLength={minQueryLength}\n className={className}\n renderResult={\n renderResult ??\n ((result, isHighlighted) => (\n <DocSearchResultRow result={result} isHighlighted={isHighlighted} />\n ))\n }\n />\n )\n}\n","/**\n * Map RAG `/api/docs/search` wire results into the `<DocSearchBar>`\n * dropdown's row shape, collapsing entity-table rows into grouped\n * results so the dropdown lists ONE \"Cap Table (12 records)\" row\n * instead of 12 individual rows.\n *\n * Pure transform — no telemetry, no navigation, no React deps. Lifted\n * from the hub's `hooks/use-docs.ts:mapDocSearchResults` (the hub's\n * `traceCompose` call was hub-only telemetry and is intentionally\n * dropped — callers that want logging can wrap this helper).\n */\n\nimport type { SearchResult } from '../../ui/search-input'\nimport type { DocSearchResult } from './types'\n\n/** Source repos that should be collapsed into grouped results in the search bar.\n * Only financial tables (all rows link to the same admin page).\n * Content tables (blog, webinar, podcast, etc.) stay individual since each has a unique URL. */\nconst SEARCH_GROUP_REPOS = new Set([\n 'financial-cap-table',\n 'financial-kpis',\n 'financial-pnl',\n 'financial-balance-sheet',\n 'financial-cash-flow',\n])\n\nconst ENTITY_LABELS: Record<string, string> = {\n 'financial-cap-table': 'Cap Table',\n 'financial-kpis': 'Financial KPIs',\n 'financial-pnl': 'Profit & Loss',\n 'financial-balance-sheet': 'Balance Sheets',\n 'financial-cash-flow': 'Cash Flow',\n 'blog-posts': 'Blog Posts',\n 'product-releases': 'Product Releases',\n 'case-studies': 'Case Studies',\n webinars: 'Webinars',\n events: 'Events',\n podcasts: 'Podcasts',\n}\n\nexport function mapDocSearchResults(docs: DocSearchResult[]): SearchResult[] {\n const entityGroups = new Map<string, DocSearchResult[]>()\n // Track insertion order — groups appear where the FIRST row of that\n // repo appeared in the response.\n const order: Array<\n { type: 'entity'; repo: string } | { type: 'doc'; doc: DocSearchResult }\n > = []\n const seenRepos = new Set<string>()\n\n for (const doc of docs) {\n if (doc.sourceRepo && SEARCH_GROUP_REPOS.has(doc.sourceRepo)) {\n const group = entityGroups.get(doc.sourceRepo) || []\n group.push(doc)\n entityGroups.set(doc.sourceRepo, group)\n if (!seenRepos.has(doc.sourceRepo)) {\n seenRepos.add(doc.sourceRepo)\n order.push({ type: 'entity', repo: doc.sourceRepo })\n }\n } else {\n order.push({ type: 'doc', doc })\n }\n }\n\n const results: SearchResult[] = []\n for (const entry of order) {\n if (entry.type === 'entity') {\n const rows = entityGroups.get(entry.repo)!\n const label = ENTITY_LABELS[entry.repo] || entry.repo\n results.push({\n id: `group-${entry.repo}`,\n title: `${label} (${rows.length} ${rows.length === 1 ? 'record' : 'records'})`,\n path: rows[0].path,\n type: 'file',\n metadata: {\n documentType: rows[0].documentType,\n externalUrl: rows[0].externalUrl,\n sourceRepo: entry.repo,\n id: rows[0].entityId,\n isGroup: true,\n items: rows.map((r) => ({\n name: r.name,\n externalUrl: r.externalUrl,\n id: r.entityId,\n sourceRepo: r.sourceRepo,\n documentType: r.documentType,\n })),\n },\n })\n } else {\n const doc = entry.doc\n const isNonMarkdown = doc.documentType && doc.documentType !== 'markdown'\n results.push({\n id: doc.path,\n title: doc.name,\n description: isNonMarkdown ? doc.name : doc.snippet,\n path: doc.path,\n type: doc.type,\n metadata: {\n matchType: doc.matchType,\n ...(doc.documentType ? { documentType: doc.documentType } : {}),\n ...(doc.externalUrl ? { externalUrl: doc.externalUrl } : {}),\n ...(doc.targetPlatform != null\n ? { targetPlatform: doc.targetPlatform }\n : {}),\n ...(doc.sourceRepo ? { sourceRepo: doc.sourceRepo } : {}),\n ...(doc.entityId ? { id: doc.entityId } : {}),\n },\n })\n }\n }\n\n return results\n}\n","/**\n * Resolve what should happen when the user picks a search result.\n * Returns one of five typed actions so the caller is a single switch.\n *\n * Resolution order:\n * 1. `externalUrl` present → use `decideNewTab` to choose same-tab vs\n * new-tab against the row's `targetPlatform`.\n * 2. Row has `id` + `sourceRepo` + `documentType` → synth an Ask-AI\n * action (entity drill-in via primary key, no URL).\n * 3. Row has only `path` → legacy navigation fallback.\n * 4. Nothing actionable → noop.\n *\n * Lifted from the hub's `hooks/use-docs.ts:resolveSearchResultAction`.\n * Pure — no React, no telemetry.\n */\n\nimport type { SearchResult } from '../../ui/search-input'\nimport type { ChatRef } from '../../chat/chat-ref.types'\nimport { decideNewTab } from '../../chat/utils/decide-new-tab'\n\nexport type SearchResultAction =\n | { kind: 'navigate-same-tab'; href: string }\n | { kind: 'navigate-new-tab'; href: string }\n | { kind: 'ask-ai'; detail: { source: string; ref: ChatRef } }\n | { kind: 'route'; path: string }\n | { kind: 'noop' }\n\nexport function resolveSearchResultAction(\n result: SearchResult,\n source: string,\n runtimeMode?: 'host' | 'embed',\n): SearchResultAction {\n const meta = result.metadata ?? {}\n const externalUrl = meta.externalUrl as string | undefined\n if (externalUrl) {\n // Same pure helper `useNavLink` and `useUnifiedNav` call — single\n // decision rule across cards, chips, and autocomplete rows. Thread\n // the caller's `source` as `currentSource` so the platform-vs-\n // platform comparison matches the hub's pre-migration behavior.\n const targetPlatform = meta.targetPlatform as string | null | undefined\n const isNewTab = decideNewTab({\n href: externalUrl,\n targetPlatform,\n surface: 'useUnifiedNav',\n runtimeMode,\n currentSource: source,\n })\n return isNewTab\n ? { kind: 'navigate-new-tab', href: externalUrl }\n : { kind: 'navigate-same-tab', href: externalUrl }\n }\n const rowId = meta.id as string | undefined\n const sourceRepo = meta.sourceRepo as string | undefined\n const documentType = meta.documentType as string | undefined\n if (rowId && sourceRepo && documentType) {\n return {\n kind: 'ask-ai',\n detail: {\n source,\n ref: { type: documentType, id: rowId, title: result.title, url: null },\n },\n }\n }\n if (result.path) {\n return { kind: 'route', path: result.path }\n }\n return { kind: 'noop' }\n}\n","'use client'\n\n/**\n * `useDocSearch` — debounced RAG-search hook against `/api/docs/search`.\n *\n * Pure fetch + navigation glue. Embedders can mount this directly\n * (any host with a reverse-proxy that exposes `/api/docs/search` will\n * work). Hub callers wire it into the lib `<DocSearchBar>` for the\n * canonical typeahead dropdown.\n *\n * ## What moved from hub to lib\n *\n * Lifted from `multi-platform-hub/hooks/use-docs.ts:useDocSearch`. Two\n * hub-only concerns are now optional injection points instead of\n * direct imports:\n *\n * - `useDocNavigation()` (hub's in-page doc-tree swap) → optional\n * `onInPageSwap?: (path: string) => boolean` config callback. When\n * present and returns true, the hook treats a same-origin result\n * click as \"handled in-page\"; when absent or returns false, the\n * hook falls back to `onNavigate(path)` (`router.push` on hub,\n * `window.location.assign` on bare embedders).\n * - `traceCompose` (hub-only telemetry) → dropped. The lib has no\n * equivalent runtime-context yet; bring it back when there is one.\n *\n * Everything else (debounce, `useChatRuntime` for embed-mode short-\n * circuit, embed-shim router, the action-resolver + result-mapper) is\n * now lib-resident.\n */\n\nimport { useState, useEffect, useCallback } from 'react'\nimport { useRouter } from '../../../embed-shims'\nimport { useDebounce } from '../../../hooks/ui/use-debounce'\nimport { useChatRuntime } from '../../../contexts/chat-runtime-context'\nimport { contentFetch } from '../../../utils/embed-content-fetch'\nimport type { SearchResult } from '../../ui/search-input'\nimport {\n resolveExternalNavigation,\n stripSameOriginToPath,\n NEW_TAB_FEATURES,\n} from '../../chat/utils/chat-nav-resolution'\nimport type { DocSearchResult } from './types'\nimport { mapDocSearchResults } from './map-doc-search-results'\nimport { resolveSearchResultAction } from './resolve-search-result-action'\n\nexport interface UseDocSearchConfig {\n /** Discriminator passed to `/api/docs/search?source=` (e.g.\n * `'openframe'`). Embedders set it to whatever discriminator their\n * reverse-proxy expects. */\n source: string\n /** Base route prefix this search lives under (e.g. `'/onboarding-guides'`).\n * When a result's href starts with `${baseRoute}/`, the hook\n * attempts the optional in-page swap path before falling through\n * to a full nav. */\n baseRoute: string\n /** Imperative navigation fallback. Called when no override\n * (in-page swap, new-tab) applies. Hub callers pass\n * `(path) => router.push(path)`; embedders pass an equivalent. */\n onNavigate: (path: string) => void\n /** Optional `RagTableConfig.id` list to narrow the search to specific\n * tables (e.g. `['onboarding-guides']`). Forwarded to\n * `/api/docs/search?tableIds=…` which intersects with the source's\n * standing set. */\n tableIds?: string[]\n /** Optional in-page swap callback. When the result's href is under\n * `baseRoute` AND this callback returns true, the hook treats the\n * click as handled in-page (no router push). Hub's\n * `<DocumentationSection>` wires this to\n * `useDocNavigation().navigate(path)`. */\n onInPageSwap?: (path: string) => boolean\n /** Optional endpoint override. Defaults to `'/api/docs/search'`\n * (the hub's reverse-proxy route). Embedders with a different\n * path can override. */\n searchEndpoint?: string\n}\n\nexport function useDocSearch(config: UseDocSearchConfig) {\n const {\n source,\n baseRoute,\n onNavigate,\n tableIds,\n onInPageSwap,\n searchEndpoint,\n } = config\n const tableIdsKey = tableIds && tableIds.length > 0 ? tableIds.join(',') : ''\n\n const router = useRouter()\n // Optional chat-runtime read — when present and mode='embed' the\n // search-result row click short-circuits to a new-tab open against\n // the absolutized URL. Null/host preserves today's behavior.\n // Also used as the proxy-prefix fallback for `searchEndpoint`, matching\n // how tickets resolves `findTicketUrl`.\n const runtime = useChatRuntime()\n const resolvedSearchEndpoint =\n searchEndpoint ?? runtime?.endpoints.docsSearchUrl ?? '/api/docs/search'\n\n const [query, setQuery] = useState('')\n const [results, setResults] = useState<SearchResult[]>([])\n const [isFetching, setIsFetching] = useState(false)\n const debouncedQuery = useDebounce(query, 300)\n\n useEffect(() => {\n if (!debouncedQuery || debouncedQuery.trim().length < 2) {\n setResults([])\n setIsFetching(false)\n return\n }\n\n let cancelled = false\n\n async function fetchResults() {\n setIsFetching(true)\n try {\n const params = new URLSearchParams({\n q: debouncedQuery,\n source,\n limit: '10',\n })\n if (tableIdsKey) params.set('tableIds', tableIdsKey)\n\n const response = await contentFetch(`${resolvedSearchEndpoint}?${params.toString()}`)\n if (!response.ok) {\n throw new Error(`Search request failed: ${response.status}`)\n }\n\n const json = await response.json()\n\n if (!cancelled && json.success && Array.isArray(json.data)) {\n const mapped = mapDocSearchResults(json.data as DocSearchResult[])\n setResults(mapped)\n }\n } catch (error) {\n console.error('Doc search error:', error)\n if (!cancelled) {\n setResults([])\n }\n } finally {\n if (!cancelled) {\n setIsFetching(false)\n }\n }\n }\n\n fetchResults()\n\n return () => {\n cancelled = true\n }\n }, [debouncedQuery, source, tableIdsKey, resolvedSearchEndpoint])\n\n // Derived loading state — single source of truth for \"should the\n // dropdown show 'Loading...' instead of 'No results found'\":\n const isLoading =\n query.trim().length >= 2 && (query !== debouncedQuery || isFetching)\n\n // Track whether dropdown should stay open (external link opened in new tab).\n const [keepOpen, setKeepOpen] = useState(false)\n\n const handleResultSelect = useCallback(\n (\n result: SearchResult,\n modifiers?: {\n metaKey?: boolean\n ctrlKey?: boolean\n shiftKey?: boolean\n altKey?: boolean\n button?: number\n },\n ) => {\n const action = resolveSearchResultAction(\n result,\n source,\n runtime?.navigation.mode,\n )\n // Modifier / non-primary mouse click → force new tab regardless of\n // same-tab/new-tab decision. The dropdown row is a `<div>`, not an\n // `<a target=\"_blank\">`, so the browser doesn't background-tab\n // natively on cmd-click. Honor it explicitly here for parity with\n // the anchor-based surfaces (cards, chips, related-content). Plain\n // Enter from the keyboard passes `modifiers === undefined`.\n const wantsNewTab =\n modifiers &&\n (modifiers.metaKey ||\n modifiers.ctrlKey ||\n modifiers.shiftKey ||\n modifiers.altKey ||\n (typeof modifiers.button === 'number' && modifiers.button !== 0))\n switch (action.kind) {\n case 'navigate-same-tab': {\n // Embed-mode short-circuit — autocomplete row clicked while\n // the chat panel is hosted inside an embedding app.\n if (runtime?.navigation.mode === 'embed') {\n setKeepOpen(true)\n const targetPlatform =\n (result.metadata?.targetPlatform as string | null | undefined) ?? null\n resolveExternalNavigation({\n href: action.href,\n targetPlatform,\n runtime,\n }).open()\n return\n }\n if (wantsNewTab) {\n setKeepOpen(true)\n window.open(action.href, '_blank', NEW_TAB_FEATURES)\n return\n }\n // Same-origin click:\n // 1. If the href is under the current doc-tree's baseRoute AND\n // an `onInPageSwap` callback is wired AND returns true →\n // consider in-page swap handled.\n // 2. Otherwise → embed-shim `router.push()` (soft RSC nav on\n // Next.js hosts, window.location.assign on bare hosts).\n setKeepOpen(false)\n const path =\n baseRoute && action.href.startsWith(`${baseRoute}/`)\n ? action.href.slice(baseRoute.length + 1)\n : null\n if (path && onInPageSwap?.(path)) return\n router.push(stripSameOriginToPath(action.href))\n return\n }\n case 'navigate-new-tab':\n // Cross-origin (e.g. clicking a flamingo.run release from\n // product-hub) — open in a new tab. Keep dropdown open so the\n // user can pick another result without re-searching.\n setKeepOpen(true)\n window.open(action.href, '_blank', NEW_TAB_FEATURES)\n return\n case 'ask-ai':\n // Row is searchable-but-not-openable (cap_table positions,\n // financial-kpi snapshots, anything backed by\n // `resolveUrl: () => null`). Dispatch a CustomEvent that\n // GlobalAskAI listens for — opens chat + drills via\n // `entityIdFilter` (primary-key only, same as inline-card Ask).\n setKeepOpen(false)\n window.dispatchEvent(\n new CustomEvent('ask-ai:open-with-ref', { detail: action.detail }),\n )\n return\n case 'route':\n // Final fallback: legacy navigation by path. Hits when a row\n // has neither URL nor pk metadata — a mapper/API regression.\n setKeepOpen(false)\n onNavigate(action.path)\n return\n case 'noop':\n return\n }\n },\n [onNavigate, source, baseRoute, router, onInPageSwap, runtime],\n )\n\n // Reset keepOpen when query changes.\n useEffect(() => {\n setKeepOpen(false)\n }, [query])\n\n return {\n query,\n setQuery,\n results,\n isLoading,\n handleResultSelect,\n keepDropdownOpen: keepOpen,\n }\n}\n"]}
@@ -2,14 +2,14 @@
2
2
 
3
3
 
4
4
 
5
- var _chunkELLTTMPEcjs = require('./chunk-ELLTTMPE.cjs');
5
+ var _chunkWCPUJA3Ycjs = require('./chunk-WCPUJA3Y.cjs');
6
6
 
7
7
 
8
8
 
9
- var _chunkV4MOB3ADcjs = require('./chunk-V4MOB3AD.cjs');
9
+ var _chunkPRKMOF2Ucjs = require('./chunk-PRKMOF2U.cjs');
10
10
 
11
11
 
12
- var _chunkQAFRLO5Ncjs = require('./chunk-QAFRLO5N.cjs');
12
+ var _chunkCUN4CJUNcjs = require('./chunk-CUN4CJUN.cjs');
13
13
 
14
14
 
15
15
 
@@ -26,13 +26,13 @@ var _chunkQAFRLO5Ncjs = require('./chunk-QAFRLO5N.cjs');
26
26
 
27
27
 
28
28
 
29
- var _chunkFFYEDIAGcjs = require('./chunk-FFYEDIAG.cjs');
29
+ var _chunkGGDM5J4Bcjs = require('./chunk-GGDM5J4B.cjs');
30
30
 
31
31
 
32
- var _chunkCCIBZ7TOcjs = require('./chunk-CCIBZ7TO.cjs');
32
+ var _chunkSTGWQFYTcjs = require('./chunk-STGWQFYT.cjs');
33
33
 
34
34
 
35
- var _chunk3KEBI6TPcjs = require('./chunk-3KEBI6TP.cjs');
35
+ var _chunk2B6773QMcjs = require('./chunk-2B6773QM.cjs');
36
36
 
37
37
 
38
38
 
@@ -64,7 +64,7 @@ function OnboardingGuidesCatalogSkeleton() {
64
64
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "h-6 w-40 bg-ods-border/70 rounded" }),
65
65
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "h-5 w-8 bg-ods-text-secondary/20 rounded-full" })
66
66
  ] }),
67
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "ul", { className: "flex flex-col gap-4", children: Array.from({ length: cardCount }).map((_, cardIdx) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "li", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFFYEDIAGcjs.OnboardingGuideCardSkeleton, { size: "catalog" }) }, cardIdx)) })
67
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "ul", { className: "flex flex-col gap-4", children: Array.from({ length: cardCount }).map((_, cardIdx) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "li", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkGGDM5J4Bcjs.OnboardingGuideCardSkeleton, { size: "catalog" }) }, cardIdx)) })
68
68
  ] }, sectionIdx)) })
69
69
  ] });
70
70
  }
@@ -83,15 +83,15 @@ function OnboardingGuidesCatalogView({
83
83
  const router = _chunkG7UE6RKVcjs.useRouter.call(void 0, );
84
84
  const searchParams = _chunkG7UE6RKVcjs.useSearchParams.call(void 0, );
85
85
  const [isPending, startTransition] = _react.useTransition.call(void 0, );
86
- const runtime = _chunk3KEBI6TPcjs.useChatRuntime.call(void 0, );
86
+ const runtime = _chunk2B6773QMcjs.useChatRuntime.call(void 0, );
87
87
  const selfFetch = initialGuides === void 0 && guidesEndpoint !== void 0;
88
88
  const sectionValue = selfFetch ? _nullishCoalesce(searchParams.get("section"), () => ( "")) : initialSection;
89
89
  const activeSection = sectionValue || "all";
90
90
  const guidesQs = sectionValue ? `?section=${encodeURIComponent(sectionValue)}` : "";
91
- const guidesRes = _chunkQAFRLO5Ncjs.useSelfFetch.call(void 0,
91
+ const guidesRes = _chunkCUN4CJUNcjs.useSelfFetch.call(void 0,
92
92
  selfFetch && guidesEndpoint ? `${guidesEndpoint}${guidesQs}` : null
93
93
  );
94
- const sectionsRes = _chunkQAFRLO5Ncjs.useSelfFetch.call(void 0,
94
+ const sectionsRes = _chunkCUN4CJUNcjs.useSelfFetch.call(void 0,
95
95
  selfFetch && sectionsEndpoint ? sectionsEndpoint : null
96
96
  );
97
97
  const guides = _nullishCoalesce(_nullishCoalesce(initialGuides, () => ( _optionalChain([guidesRes, 'access', _2 => _2.data, 'optionalAccess', _3 => _3.data]))), () => ( []));
@@ -133,21 +133,21 @@ function OnboardingGuidesCatalogView({
133
133
  });
134
134
  };
135
135
  const source = _nullishCoalesce(_optionalChain([runtime, 'optionalAccess', _4 => _4.source]), () => ( "openframe"));
136
- const docSearch = _chunkV4MOB3ADcjs.useDocSearch.call(void 0, {
136
+ const docSearch = _chunkPRKMOF2Ucjs.useDocSearch.call(void 0, {
137
137
  source,
138
138
  baseRoute: basePath,
139
139
  onNavigate: (path) => router.push(path),
140
140
  tableIds: ["onboarding-guides"]
141
141
  });
142
142
  const defaultRenderCard = (guide) => {
143
- const cta = _chunkFFYEDIAGcjs.resolveContentHref.call(void 0, _optionalChain([runtime, 'optionalAccess', _5 => _5.composeContentUrl]), {
143
+ const cta = _chunkGGDM5J4Bcjs.resolveContentHref.call(void 0, _optionalChain([runtime, 'optionalAccess', _5 => _5.composeContentUrl]), {
144
144
  type: "onboarding_guide",
145
145
  slug: guide.slug,
146
146
  basePath,
147
147
  platforms: guide.onboarding_guide_platforms
148
148
  });
149
149
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
150
- _chunkFFYEDIAGcjs.OnboardingGuideCard,
150
+ _chunkGGDM5J4Bcjs.OnboardingGuideCard,
151
151
  {
152
152
  guide,
153
153
  href: cta.href,
@@ -159,7 +159,7 @@ function OnboardingGuidesCatalogView({
159
159
  const renderCardFn = _nullishCoalesce(renderCard, () => ( defaultRenderCard));
160
160
  const preControls = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-4", children: [
161
161
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
162
- _chunkV4MOB3ADcjs.DocSearchBar,
162
+ _chunkPRKMOF2Ucjs.DocSearchBar,
163
163
  {
164
164
  placeholder: "Search onboarding guides, releases, case studies\u2026",
165
165
  query: docSearch.query,
@@ -171,7 +171,7 @@ function OnboardingGuidesCatalogView({
171
171
  }
172
172
  ),
173
173
  sections.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
174
- _chunkFFYEDIAGcjs.FilterPillRow,
174
+ _chunkGGDM5J4Bcjs.FilterPillRow,
175
175
  {
176
176
  label: "Section",
177
177
  selectedValue: activeSection,
@@ -181,7 +181,7 @@ function OnboardingGuidesCatalogView({
181
181
  )
182
182
  ] });
183
183
  if (selfFetch && guidesRes.error) {
184
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFFYEDIAGcjs.LoadError, { message: "Failed to load onboarding guides.", onRetry: guidesRes.reload });
184
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkGGDM5J4Bcjs.LoadError, { message: "Failed to load onboarding guides.", onRetry: guidesRes.reload });
185
185
  }
186
186
  if (selfFetch && guidesRes.data == null && isLoading) {
187
187
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, OnboardingGuidesCatalogSkeleton, {});
@@ -212,7 +212,7 @@ function OnboardingGuideDetailView({
212
212
  slug,
213
213
  guideEndpoint,
214
214
  related = [],
215
- MarkdownRenderer = _chunkFFYEDIAGcjs.RichMarkdownRenderer,
215
+ MarkdownRenderer = _chunkGGDM5J4Bcjs.RichMarkdownRenderer,
216
216
  renderRelatedCard,
217
217
  backHref,
218
218
  backLabel = "Back to Getting Started",
@@ -221,51 +221,51 @@ function OnboardingGuideDetailView({
221
221
  shell = true
222
222
  }) {
223
223
  const resolvedBackHref = _nullishCoalesce(backHref, () => ( basePath));
224
- const runtime = _chunk3KEBI6TPcjs.useChatRuntime.call(void 0, );
224
+ const runtime = _chunk2B6773QMcjs.useChatRuntime.call(void 0, );
225
225
  const router = _chunkG7UE6RKVcjs.useRouter.call(void 0, );
226
- const renderShell = (node) => shell ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFFYEDIAGcjs.PageShell, { children: node }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "page-shell-content", children: node });
226
+ const renderShell = (node) => shell ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkGGDM5J4Bcjs.PageShell, { children: node }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "page-shell-content", children: node });
227
227
  const url = initialData ? null : slug && guideEndpoint ? guideEndpoint(slug) : null;
228
- const { data: guide, isLoading, error, reload } = _chunkQAFRLO5Ncjs.useSelfFetch.call(void 0, url, { initialData });
229
- const { ref: videoWarmupRef } = _chunkFFYEDIAGcjs.useVideoWarmup.call(void 0, {
228
+ const { data: guide, isLoading, error, reload } = _chunkCUN4CJUNcjs.useSelfFetch.call(void 0, url, { initialData });
229
+ const { ref: videoWarmupRef } = _chunkGGDM5J4Bcjs.useVideoWarmup.call(void 0, {
230
230
  videoUrl: _optionalChain([guide, 'optionalAccess', _6 => _6.main_video_url]),
231
231
  supabaseStorageOrigin: _optionalChain([runtime, 'optionalAccess', _7 => _7.endpoints, 'access', _8 => _8.supabaseStorageOrigin])
232
232
  });
233
233
  if (error || !guide && !isLoading) {
234
- return renderShell(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFFYEDIAGcjs.LoadError, { message: "Guide not found.", onRetry: reload }));
234
+ return renderShell(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkGGDM5J4Bcjs.LoadError, { message: "Guide not found.", onRetry: reload }));
235
235
  }
236
236
  if (!guide) {
237
237
  return renderShell(
238
238
  // Match the loaded page's top offset (TitleBlock's
239
239
  // `pt-[var(--spacing-system-l)]`) so content doesn't jump on load.
240
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pt-[var(--spacing-system-l)]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkELLTTMPEcjs.DetailPageSkeleton, { bare: true, showImageGallery: false }) })
240
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pt-[var(--spacing-system-l)]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkWCPUJA3Ycjs.DetailPageSkeleton, { bare: true, showImageGallery: false }) })
241
241
  );
242
242
  }
243
- const captionsUrl = _chunkFFYEDIAGcjs.getCaptionsUrl.call(void 0, "onboarding_guide", guide.id, guide.srt_content);
243
+ const captionsUrl = _chunkGGDM5J4Bcjs.getCaptionsUrl.call(void 0, "onboarding_guide", guide.id, guide.srt_content);
244
244
  const videoPoster = guide.main_video_thumbnail || guide.featured_image || guide.og_image_url || // `buildOgPlaceholderUrl` always returns a usable string (relative route at
245
245
  // worst), so it's the terminal fallback — no trailing `|| undefined` needed.
246
- _chunkCCIBZ7TOcjs.buildOgPlaceholderUrl.call(void 0, _optionalChain([runtime, 'optionalAccess', _9 => _9.endpoints]), guide.title, { aspect: "wide" });
246
+ _chunkSTGWQFYTcjs.buildOgPlaceholderUrl.call(void 0, _optionalChain([runtime, 'optionalAccess', _9 => _9.endpoints]), guide.title, { aspect: "wide" });
247
247
  const defaultRenderRelatedCard = (g) => {
248
- const cta = _chunkFFYEDIAGcjs.resolveContentHref.call(void 0, _optionalChain([runtime, 'optionalAccess', _10 => _10.composeContentUrl]), {
248
+ const cta = _chunkGGDM5J4Bcjs.resolveContentHref.call(void 0, _optionalChain([runtime, 'optionalAccess', _10 => _10.composeContentUrl]), {
249
249
  type: "onboarding_guide",
250
250
  slug: g.slug,
251
251
  basePath,
252
252
  platforms: g.onboarding_guide_platforms
253
253
  });
254
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFFYEDIAGcjs.OnboardingGuideCard, { guide: g, href: cta.href, targetPlatform: cta.targetPlatform });
254
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkGGDM5J4Bcjs.OnboardingGuideCard, { guide: g, href: cta.href, targetPlatform: cta.targetPlatform });
255
255
  };
256
256
  const renderRelatedCardFn = _nullishCoalesce(renderRelatedCard, () => ( defaultRenderRelatedCard));
257
257
  return renderShell(
258
258
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
259
- _chunkFFYEDIAGcjs.PageLayout,
259
+ _chunkGGDM5J4Bcjs.PageLayout,
260
260
  {
261
261
  title: guide.title,
262
262
  titleSize: "h1",
263
263
  titleWrap: true,
264
264
  backButton: { label: backLabel, onClick: () => router.push(resolvedBackHref) },
265
265
  children: [
266
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFFYEDIAGcjs.EntityTagBadges, { tags: guide.onboarding_guide_tags }),
266
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkGGDM5J4Bcjs.EntityTagBadges, { tags: guide.onboarding_guide_tags }),
267
267
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
268
- _chunkFFYEDIAGcjs.EntityAuthorCard,
268
+ _chunkGGDM5J4Bcjs.EntityAuthorCard,
269
269
  {
270
270
  author: guide.author,
271
271
  authorHref,
@@ -280,7 +280,7 @@ function OnboardingGuideDetailView({
280
280
  }
281
281
  ),
282
282
  (guide.main_video_url || guide.youtube_url) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { ref: videoWarmupRef, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
283
- _chunkFFYEDIAGcjs.EntityVideoSection,
283
+ _chunkGGDM5J4Bcjs.EntityVideoSection,
284
284
  {
285
285
  mainVideoUrl: guide.main_video_url,
286
286
  youtubeUrl: guide.youtube_url || void 0,
@@ -297,17 +297,17 @@ function OnboardingGuideDetailView({
297
297
  ) }),
298
298
  guide.content && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "space-y-4", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MarkdownRenderer, { content: guide.content }) }),
299
299
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
300
- _chunkFFYEDIAGcjs.VideoBitesStrip,
300
+ _chunkGGDM5J4Bcjs.VideoBitesStrip,
301
301
  {
302
302
  bites: _nullishCoalesce(guide.video_bites, () => ( [])),
303
303
  filterPublished: true,
304
304
  showTitle: false,
305
- profile: _chunkFFYEDIAGcjs.toStripProfile.call(void 0, guide.author),
305
+ profile: _chunkGGDM5J4Bcjs.toStripProfile.call(void 0, guide.author),
306
306
  href: `/onboarding-guides/${guide.slug}`
307
307
  }
308
308
  ),
309
309
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
310
- _chunkELLTTMPEcjs.ArticleAuthorByline,
310
+ _chunkWCPUJA3Ycjs.ArticleAuthorByline,
311
311
  {
312
312
  author: _nullishCoalesce(_optionalChain([guide, 'access', _11 => _11.author, 'optionalAccess', _12 => _12.full_name]), () => ( null)),
313
313
  avatar: _optionalChain([guide, 'access', _13 => _13.author, 'optionalAccess', _14 => _14.avatar_url]),
@@ -395,4 +395,4 @@ function useOnboardingGuideSections() {
395
395
 
396
396
 
397
397
  exports.OnboardingGuidesCatalogSkeleton = OnboardingGuidesCatalogSkeleton; exports.OnboardingGuidesCatalogView = OnboardingGuidesCatalogView; exports.OnboardingGuideDetailView = OnboardingGuideDetailView; exports.onboardingGuideKeys = onboardingGuideKeys; exports.useOnboardingGuides = useOnboardingGuides; exports.useOnboardingGuide = useOnboardingGuide; exports.useOnboardingGuideSections = useOnboardingGuideSections;
398
- //# sourceMappingURL=chunk-DHIYBC5Z.cjs.map
398
+ //# sourceMappingURL=chunk-Q2MC3CBI.cjs.map