@flamingo-stack/openframe-frontend-core 0.0.215 → 0.0.216

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 (228) hide show
  1. package/dist/chunk-2V4SACHE.js +302 -0
  2. package/dist/chunk-2V4SACHE.js.map +1 -0
  3. package/dist/chunk-572WQWIX.cjs +348 -0
  4. package/dist/chunk-572WQWIX.cjs.map +1 -0
  5. package/dist/{chunk-WT5JV2GS.cjs → chunk-5V6MSE3B.cjs} +39 -39
  6. package/dist/chunk-5V6MSE3B.cjs.map +1 -0
  7. package/dist/{chunk-WQZP3JIZ.js → chunk-CDLYRFDE.js} +1894 -1472
  8. package/dist/chunk-CDLYRFDE.js.map +1 -0
  9. package/dist/chunk-GVNQAGXB.js +232 -0
  10. package/dist/chunk-GVNQAGXB.js.map +1 -0
  11. package/dist/{chunk-P5EE2VJX.cjs → chunk-HOHDXYPR.cjs} +1 -1
  12. package/dist/chunk-HOHDXYPR.cjs.map +1 -0
  13. package/dist/chunk-IH76P5R6.cjs +232 -0
  14. package/dist/chunk-IH76P5R6.cjs.map +1 -0
  15. package/dist/{chunk-24KCAECR.cjs → chunk-JJR27M56.cjs} +3 -3
  16. package/dist/{chunk-24KCAECR.cjs.map → chunk-JJR27M56.cjs.map} +1 -1
  17. package/dist/chunk-K4DFAVSO.cjs +302 -0
  18. package/dist/chunk-K4DFAVSO.cjs.map +1 -0
  19. package/dist/{chunk-HICZPTRR.js → chunk-LCLTCCXS.js} +14 -14
  20. package/dist/chunk-LCLTCCXS.js.map +1 -0
  21. package/dist/{chunk-VFKQMAUF.cjs → chunk-OB45JHDY.cjs} +3 -3
  22. package/dist/{chunk-VFKQMAUF.cjs.map → chunk-OB45JHDY.cjs.map} +1 -1
  23. package/dist/{chunk-4XLJWX2N.js → chunk-ORJREQ2W.js} +4 -4
  24. package/dist/{chunk-7PCP7YQR.js → chunk-QTKU6ULP.js} +6 -6
  25. package/dist/{chunk-CIPO6DXK.js → chunk-QY75VKAS.js} +5 -5
  26. package/dist/{chunk-ZG2YY5E7.js → chunk-RFONYT63.js} +1 -1
  27. package/dist/chunk-RFONYT63.js.map +1 -0
  28. package/dist/{chunk-NGFP4RVL.cjs → chunk-SMCG2CCC.cjs} +30 -30
  29. package/dist/{chunk-NGFP4RVL.cjs.map → chunk-SMCG2CCC.cjs.map} +1 -1
  30. package/dist/{chunk-MX5MIFWA.js → chunk-UEBM4PC4.js} +5 -5
  31. package/dist/chunk-VC3ND5RB.js +348 -0
  32. package/dist/chunk-VC3ND5RB.js.map +1 -0
  33. package/dist/{chunk-UXZ3ZJ3M.cjs → chunk-XDPSSE4O.cjs} +4 -4
  34. package/dist/{chunk-UXZ3ZJ3M.cjs.map → chunk-XDPSSE4O.cjs.map} +1 -1
  35. package/dist/{chunk-D4MNFY67.cjs → chunk-ZGTDUPTW.cjs} +1316 -894
  36. package/dist/chunk-ZGTDUPTW.cjs.map +1 -0
  37. package/dist/components/chat/entity-cards/blog-card.d.ts +1 -1
  38. package/dist/components/chat/entity-cards/blog-card.d.ts.map +1 -1
  39. package/dist/components/chat/entity-cards/case-study-card.d.ts +1 -1
  40. package/dist/components/chat/entity-cards/case-study-card.d.ts.map +1 -1
  41. package/dist/components/chat/entity-cards/customer-interview-card.d.ts +1 -1
  42. package/dist/components/chat/entity-cards/customer-interview-card.d.ts.map +1 -1
  43. package/dist/components/chat/entity-cards/dispatch.d.ts.map +1 -1
  44. package/dist/components/chat/entity-cards/investor-update-card.d.ts +1 -1
  45. package/dist/components/chat/entity-cards/investor-update-card.d.ts.map +1 -1
  46. package/dist/components/chat/entity-cards/onboarding-guide-card.d.ts +1 -1
  47. package/dist/components/chat/entity-cards/onboarding-guide-card.d.ts.map +1 -1
  48. package/dist/components/chat/entity-cards/program-card.d.ts +1 -1
  49. package/dist/components/chat/entity-cards/program-card.d.ts.map +1 -1
  50. package/dist/components/chat/entity-cards/use-entity-card-link.d.ts +14 -0
  51. package/dist/components/chat/entity-cards/use-entity-card-link.d.ts.map +1 -0
  52. package/dist/components/chat/entity-cards/use-entity-card-placeholder.d.ts +13 -0
  53. package/dist/components/chat/entity-cards/use-entity-card-placeholder.d.ts.map +1 -0
  54. package/dist/components/chat/index.cjs +11 -11
  55. package/dist/components/chat/index.js +10 -10
  56. package/dist/components/contact/index.cjs +12 -12
  57. package/dist/components/contact/index.js +11 -11
  58. package/dist/components/features/captions-url.d.ts +18 -0
  59. package/dist/components/features/captions-url.d.ts.map +1 -0
  60. package/dist/components/features/index.cjs +23 -11
  61. package/dist/components/features/index.cjs.map +1 -1
  62. package/dist/components/features/index.d.ts +2 -0
  63. package/dist/components/features/index.d.ts.map +1 -1
  64. package/dist/components/features/index.js +24 -12
  65. package/dist/components/features/mux-origins.cjs +10 -0
  66. package/dist/components/features/mux-origins.cjs.map +1 -0
  67. package/dist/components/features/mux-origins.d.ts +26 -0
  68. package/dist/components/features/mux-origins.d.ts.map +1 -0
  69. package/dist/components/features/mux-origins.js +7 -0
  70. package/dist/components/features/mux-origins.js.map +1 -0
  71. package/dist/components/features/notifications/index.d.ts +2 -0
  72. package/dist/components/features/notifications/index.d.ts.map +1 -1
  73. package/dist/components/features/notifications/notification-drawer.d.ts +2 -1
  74. package/dist/components/features/notifications/notification-drawer.d.ts.map +1 -1
  75. package/dist/components/features/notifications/notification-popups.d.ts +10 -0
  76. package/dist/components/features/notifications/notification-popups.d.ts.map +1 -0
  77. package/dist/components/features/notifications/notifications-context.d.ts +8 -1
  78. package/dist/components/features/notifications/notifications-context.d.ts.map +1 -1
  79. package/dist/components/features/notifications/types.d.ts +1 -0
  80. package/dist/components/features/notifications/types.d.ts.map +1 -1
  81. package/dist/components/features/use-video-warmup.d.ts +53 -0
  82. package/dist/components/features/use-video-warmup.d.ts.map +1 -0
  83. package/dist/components/icons/index.cjs +3 -3
  84. package/dist/components/icons/index.js +2 -2
  85. package/dist/components/icons-v2-generated/index.cjs +2 -2
  86. package/dist/components/icons-v2-generated/index.cjs.map +1 -1
  87. package/dist/components/icons-v2-generated/index.js +4 -4
  88. package/dist/components/index.cjs +132 -102
  89. package/dist/components/index.cjs.map +1 -1
  90. package/dist/components/index.d.ts +1 -0
  91. package/dist/components/index.d.ts.map +1 -1
  92. package/dist/components/index.js +94 -64
  93. package/dist/components/index.js.map +1 -1
  94. package/dist/components/navigation/index.cjs +11 -11
  95. package/dist/components/navigation/index.js +10 -10
  96. package/dist/components/onboarding-guides/build-default-href.d.ts +15 -0
  97. package/dist/components/onboarding-guides/build-default-href.d.ts.map +1 -0
  98. package/dist/components/onboarding-guides/hooks/use-onboarding-guides.d.ts +28 -0
  99. package/dist/components/onboarding-guides/hooks/use-onboarding-guides.d.ts.map +1 -0
  100. package/dist/components/onboarding-guides/index.cjs +373 -0
  101. package/dist/components/onboarding-guides/index.cjs.map +1 -0
  102. package/dist/components/onboarding-guides/index.d.ts +25 -0
  103. package/dist/components/onboarding-guides/index.d.ts.map +1 -0
  104. package/dist/components/onboarding-guides/index.js +373 -0
  105. package/dist/components/onboarding-guides/index.js.map +1 -0
  106. package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts +52 -0
  107. package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts.map +1 -0
  108. package/dist/components/onboarding-guides/onboarding-guides-catalog-skeleton.d.ts +17 -0
  109. package/dist/components/onboarding-guides/onboarding-guides-catalog-skeleton.d.ts.map +1 -0
  110. package/dist/components/onboarding-guides/onboarding-guides-catalog-view.d.ts +43 -0
  111. package/dist/components/onboarding-guides/onboarding-guides-catalog-view.d.ts.map +1 -0
  112. package/dist/components/shared/doc-search/doc-search-bar.d.ts +59 -0
  113. package/dist/components/shared/doc-search/doc-search-bar.d.ts.map +1 -0
  114. package/dist/components/shared/doc-search/doc-search-result-row.d.ts +18 -0
  115. package/dist/components/shared/doc-search/doc-search-result-row.d.ts.map +1 -0
  116. package/dist/components/shared/doc-search/format-relative-path.d.ts +10 -0
  117. package/dist/components/shared/doc-search/format-relative-path.d.ts.map +1 -0
  118. package/dist/components/shared/doc-search/index.d.ts +8 -0
  119. package/dist/components/shared/doc-search/index.d.ts.map +1 -0
  120. package/dist/components/shared/doc-search/map-doc-search-results.d.ts +15 -0
  121. package/dist/components/shared/doc-search/map-doc-search-results.d.ts.map +1 -0
  122. package/dist/components/shared/doc-search/resolve-search-result-action.d.ts +37 -0
  123. package/dist/components/shared/doc-search/resolve-search-result-action.d.ts.map +1 -0
  124. package/dist/components/shared/doc-search/types.d.ts +29 -0
  125. package/dist/components/shared/doc-search/types.d.ts.map +1 -0
  126. package/dist/components/shared/doc-search/use-doc-search.d.ts +46 -0
  127. package/dist/components/shared/doc-search/use-doc-search.d.ts.map +1 -0
  128. package/dist/components/tickets/help-center-card.d.ts +5 -1
  129. package/dist/components/tickets/help-center-card.d.ts.map +1 -1
  130. package/dist/components/tickets/hooks/use-ticket-actions.d.ts +8 -0
  131. package/dist/components/tickets/hooks/use-ticket-actions.d.ts.map +1 -1
  132. package/dist/components/tickets/index.cjs +316 -145
  133. package/dist/components/tickets/index.cjs.map +1 -1
  134. package/dist/components/tickets/index.js +237 -66
  135. package/dist/components/tickets/index.js.map +1 -1
  136. package/dist/components/tickets/ticket-detail-drawer.d.ts +11 -2
  137. package/dist/components/tickets/ticket-detail-drawer.d.ts.map +1 -1
  138. package/dist/components/tickets/types.d.ts +50 -1
  139. package/dist/components/tickets/types.d.ts.map +1 -1
  140. package/dist/components/ui/file-manager/index.cjs +51 -51
  141. package/dist/components/ui/file-manager/index.cjs.map +1 -1
  142. package/dist/components/ui/file-manager/index.js +2 -2
  143. package/dist/components/ui/filter-pill-row.d.ts +20 -0
  144. package/dist/components/ui/filter-pill-row.d.ts.map +1 -0
  145. package/dist/components/ui/index.cjs +16 -14
  146. package/dist/components/ui/index.cjs.map +1 -1
  147. package/dist/components/ui/index.d.ts +1 -0
  148. package/dist/components/ui/index.d.ts.map +1 -1
  149. package/dist/components/ui/index.js +21 -19
  150. package/dist/components/ui/simple-markdown-renderer.d.ts.map +1 -1
  151. package/dist/contexts/chat-runtime-context.d.ts +42 -0
  152. package/dist/contexts/chat-runtime-context.d.ts.map +1 -1
  153. package/dist/contexts/index.cjs +2 -2
  154. package/dist/contexts/index.js +1 -1
  155. package/dist/embed-shims/index.cjs +3 -3
  156. package/dist/embed-shims/index.cjs.map +1 -1
  157. package/dist/embed-shims/index.js +5 -5
  158. package/dist/hooks/index.cjs +6 -6
  159. package/dist/hooks/index.js +5 -5
  160. package/dist/index.cjs +28 -14
  161. package/dist/index.cjs.map +1 -1
  162. package/dist/index.js +59 -45
  163. package/dist/utils/dev-sections/openframe-dev-sections.d.ts +2 -2
  164. package/dist/utils/dev-sections/openframe-dev-sections.d.ts.map +1 -1
  165. package/dist/utils/index.cjs +11 -5
  166. package/dist/utils/index.cjs.map +1 -1
  167. package/dist/utils/index.js +11 -5
  168. package/dist/utils/index.js.map +1 -1
  169. package/package.json +13 -1
  170. package/src/components/chat/entity-cards/blog-card.tsx +17 -5
  171. package/src/components/chat/entity-cards/case-study-card.tsx +23 -1
  172. package/src/components/chat/entity-cards/customer-interview-card.tsx +23 -1
  173. package/src/components/chat/entity-cards/dispatch.tsx +21 -0
  174. package/src/components/chat/entity-cards/investor-update-card.tsx +23 -1
  175. package/src/components/chat/entity-cards/onboarding-guide-card.tsx +30 -4
  176. package/src/components/chat/entity-cards/program-card.tsx +17 -3
  177. package/src/components/chat/entity-cards/use-entity-card-link.ts +66 -0
  178. package/src/components/chat/entity-cards/use-entity-card-placeholder.ts +50 -0
  179. package/src/components/features/captions-url.ts +25 -0
  180. package/src/components/features/index.ts +2 -0
  181. package/src/components/features/mux-origins.ts +27 -0
  182. package/src/components/features/notifications/index.ts +2 -0
  183. package/src/components/features/notifications/notification-drawer.tsx +100 -16
  184. package/src/components/features/notifications/notification-popups.tsx +105 -0
  185. package/src/components/features/notifications/notifications-context.tsx +16 -0
  186. package/src/components/features/notifications/types.ts +1 -0
  187. package/src/components/features/use-video-warmup.ts +176 -0
  188. package/src/components/index.ts +5 -0
  189. package/src/components/onboarding-guides/build-default-href.ts +16 -0
  190. package/src/components/onboarding-guides/hooks/use-onboarding-guides.ts +90 -0
  191. package/src/components/onboarding-guides/index.ts +39 -0
  192. package/src/components/onboarding-guides/onboarding-guide-detail-view.tsx +215 -0
  193. package/src/components/onboarding-guides/onboarding-guides-catalog-skeleton.tsx +62 -0
  194. package/src/components/onboarding-guides/onboarding-guides-catalog-view.tsx +230 -0
  195. package/src/components/shared/doc-search/doc-search-bar.tsx +100 -0
  196. package/src/components/shared/doc-search/doc-search-result-row.tsx +73 -0
  197. package/src/components/shared/doc-search/format-relative-path.ts +17 -0
  198. package/src/components/shared/doc-search/index.ts +24 -0
  199. package/src/components/shared/doc-search/map-doc-search-results.ts +113 -0
  200. package/src/components/shared/doc-search/resolve-search-result-action.ts +68 -0
  201. package/src/components/shared/doc-search/types.ts +28 -0
  202. package/src/components/shared/doc-search/use-doc-search.ts +263 -0
  203. package/src/components/tickets/help-center-card.tsx +8 -0
  204. package/src/components/tickets/help-center-list.tsx +17 -3
  205. package/src/components/tickets/hooks/use-ticket-actions.ts +210 -14
  206. package/src/components/tickets/ticket-detail-drawer.tsx +145 -5
  207. package/src/components/tickets/types.ts +55 -0
  208. package/src/components/ui/filter-pill-row.tsx +72 -0
  209. package/src/components/ui/index.ts +1 -0
  210. package/src/components/ui/simple-markdown-renderer.tsx +24 -1
  211. package/src/components/ui/toaster.tsx +3 -3
  212. package/src/contexts/chat-runtime-context.tsx +41 -0
  213. package/src/stories/NotificationDrawer.stories.tsx +18 -2
  214. package/src/utils/dev-sections/openframe-dev-sections.ts +12 -5
  215. package/dist/chunk-2G3NXF6J.cjs +0 -521
  216. package/dist/chunk-2G3NXF6J.cjs.map +0 -1
  217. package/dist/chunk-D4MNFY67.cjs.map +0 -1
  218. package/dist/chunk-HICZPTRR.js.map +0 -1
  219. package/dist/chunk-P5EE2VJX.cjs.map +0 -1
  220. package/dist/chunk-R6MLPU4A.js +0 -521
  221. package/dist/chunk-R6MLPU4A.js.map +0 -1
  222. package/dist/chunk-WQZP3JIZ.js.map +0 -1
  223. package/dist/chunk-WT5JV2GS.cjs.map +0 -1
  224. package/dist/chunk-ZG2YY5E7.js.map +0 -1
  225. /package/dist/{chunk-4XLJWX2N.js.map → chunk-ORJREQ2W.js.map} +0 -0
  226. /package/dist/{chunk-7PCP7YQR.js.map → chunk-QTKU6ULP.js.map} +0 -0
  227. /package/dist/{chunk-CIPO6DXK.js.map → chunk-QY75VKAS.js.map} +0 -0
  228. /package/dist/{chunk-MX5MIFWA.js.map → chunk-UEBM4PC4.js.map} +0 -0
@@ -0,0 +1,373 @@
1
+ "use client";
2
+ import {
3
+ DocSearchBar,
4
+ useDocSearch
5
+ } from "../../chunk-VC3ND5RB.js";
6
+ import {
7
+ DevSectionPage
8
+ } from "../../chunk-GVNQAGXB.js";
9
+ import "../../chunk-ORJREQ2W.js";
10
+ import {
11
+ ArticleDetailLayout,
12
+ EntityAuthorCard,
13
+ EntityVideoSection,
14
+ FilterPillRow,
15
+ OnboardingGuideCard,
16
+ OnboardingGuideCardSkeleton,
17
+ SimpleMarkdownRenderer,
18
+ VideoBitesDisplay,
19
+ getCaptionsUrl,
20
+ useVideoWarmup
21
+ } from "../../chunk-CDLYRFDE.js";
22
+ import "../../chunk-LXC6P2EO.js";
23
+ import "../../chunk-EL5YVPD5.js";
24
+ import "../../chunk-UEBM4PC4.js";
25
+ import {
26
+ next_link_default
27
+ } from "../../chunk-OHPI2HRK.js";
28
+ import "../../chunk-LCLTCCXS.js";
29
+ import {
30
+ useRouter,
31
+ useSearchParams
32
+ } from "../../chunk-PLJLE4A4.js";
33
+ import "../../chunk-QY75VKAS.js";
34
+ import "../../chunk-KSOOKNBG.js";
35
+ import "../../chunk-EDW2NVRV.js";
36
+ import "../../chunk-6U3IUD57.js";
37
+ import "../../chunk-W72U7OU7.js";
38
+ import {
39
+ useChatRuntime
40
+ } from "../../chunk-RFONYT63.js";
41
+ import "../../chunk-MJNXIEV2.js";
42
+ import "../../chunk-CZR7ARBA.js";
43
+ import "../../chunk-GGWZFCYS.js";
44
+
45
+ // src/components/onboarding-guides/onboarding-guides-catalog-view.tsx
46
+ import { useMemo, useTransition } from "react";
47
+ import { GraduationCap } from "lucide-react";
48
+
49
+ // src/components/onboarding-guides/build-default-href.ts
50
+ function buildDefaultHref(basePath, slug) {
51
+ return { href: `${basePath}/${slug}`, targetPlatform: null };
52
+ }
53
+
54
+ // src/components/onboarding-guides/onboarding-guides-catalog-view.tsx
55
+ import { jsx, jsxs } from "react/jsx-runtime";
56
+ function OnboardingGuidesCatalogView({
57
+ initialGuides,
58
+ initialSections,
59
+ initialSection = "",
60
+ renderCard,
61
+ basePath = "/onboarding-guides"
62
+ }) {
63
+ const router = useRouter();
64
+ const searchParams = useSearchParams();
65
+ const [isPending, startTransition] = useTransition();
66
+ const runtime = useChatRuntime();
67
+ const activeSection = initialSection || "all";
68
+ const grouped = useMemo(() => {
69
+ const map = /* @__PURE__ */ new Map();
70
+ for (const g of initialGuides) {
71
+ const existing = map.get(g.section);
72
+ if (existing) {
73
+ if (g.section_order < existing.section_order)
74
+ existing.section_order = g.section_order;
75
+ existing.guides.push(g);
76
+ } else {
77
+ map.set(g.section, { section_order: g.section_order, guides: [g] });
78
+ }
79
+ }
80
+ for (const entry of map.values()) {
81
+ entry.guides.sort(
82
+ (a, b) => a.step_order - b.step_order || a.title.localeCompare(b.title)
83
+ );
84
+ }
85
+ return Array.from(map.entries()).map(([section, info]) => ({ section, ...info })).sort(
86
+ (a, b) => a.section_order - b.section_order || a.section.localeCompare(b.section)
87
+ );
88
+ }, [initialGuides]);
89
+ const sectionFilterOptions = useMemo(
90
+ () => [
91
+ { value: "all", label: `All (${initialGuides.length})` },
92
+ ...initialSections.map((s) => ({
93
+ value: s.section,
94
+ label: `${s.section} (${s.count})`
95
+ }))
96
+ ],
97
+ [initialGuides.length, initialSections]
98
+ );
99
+ const setSection = (value) => {
100
+ const params = new URLSearchParams(searchParams.toString());
101
+ if (value === "all") {
102
+ params.delete("section");
103
+ } else {
104
+ params.set("section", value);
105
+ }
106
+ const qs = params.toString();
107
+ startTransition(() => {
108
+ router.push(qs ? `${basePath}?${qs}` : basePath);
109
+ });
110
+ };
111
+ const source = runtime?.source ?? "openframe";
112
+ const docSearch = useDocSearch({
113
+ source,
114
+ baseRoute: basePath,
115
+ onNavigate: (path) => router.push(path),
116
+ tableIds: ["onboarding-guides"]
117
+ });
118
+ const defaultRenderCard = (guide) => {
119
+ const cta = runtime?.composeContentUrl ? runtime.composeContentUrl(
120
+ "onboarding_guide",
121
+ guide.slug,
122
+ guide.onboarding_guide_platforms
123
+ ) : buildDefaultHref(basePath, guide.slug);
124
+ return /* @__PURE__ */ jsx(
125
+ OnboardingGuideCard,
126
+ {
127
+ guide,
128
+ href: cta.href,
129
+ targetPlatform: cta.targetPlatform,
130
+ size: "catalog"
131
+ }
132
+ );
133
+ };
134
+ const renderCardFn = renderCard ?? defaultRenderCard;
135
+ const preControls = /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
136
+ /* @__PURE__ */ jsx(
137
+ DocSearchBar,
138
+ {
139
+ placeholder: "Search onboarding guides, releases, case studies\u2026",
140
+ query: docSearch.query,
141
+ onQueryChange: docSearch.setQuery,
142
+ results: docSearch.results,
143
+ isLoading: docSearch.isLoading,
144
+ onResultSelect: docSearch.handleResultSelect,
145
+ showDropdown: docSearch.keepDropdownOpen
146
+ }
147
+ ),
148
+ initialSections.length > 0 && /* @__PURE__ */ jsx(
149
+ FilterPillRow,
150
+ {
151
+ label: "Section",
152
+ selectedValue: activeSection,
153
+ onValueChange: setSection,
154
+ options: sectionFilterOptions
155
+ }
156
+ )
157
+ ] });
158
+ return /* @__PURE__ */ jsx(DevSectionPage, { sectionKey: "onboarding", preControls, children: initialGuides.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-16", children: [
159
+ /* @__PURE__ */ jsx(GraduationCap, { className: "h-12 w-12 text-ods-text-secondary mx-auto mb-4" }),
160
+ /* @__PURE__ */ jsx("h2", { className: "text-ods-text-primary font-['DM_Sans'] text-[20px] font-semibold mb-2", children: "No onboarding guides found" }),
161
+ /* @__PURE__ */ jsx("p", { className: "text-ods-text-secondary font-['DM_Sans'] text-[14px]", children: activeSection !== "all" ? "No guides in this section yet." : "We're working on the onboarding library. Check back soon." })
162
+ ] }) : /* @__PURE__ */ jsx(
163
+ "div",
164
+ {
165
+ className: isPending ? "opacity-60 transition-opacity space-y-10" : "space-y-10",
166
+ children: grouped.map((sec) => /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
167
+ /* @__PURE__ */ jsxs("h2", { className: "text-h3 tracking-[-0.36px] text-ods-text-primary flex items-center gap-2", children: [
168
+ sec.section,
169
+ /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center rounded-full bg-ods-text-secondary/20 text-ods-text-secondary text-xs font-medium px-2 py-0.5", children: sec.guides.length })
170
+ ] }),
171
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-4", children: sec.guides.map((guide) => /* @__PURE__ */ jsx("li", { children: renderCardFn(guide) }, guide.id)) })
172
+ ] }, sec.section))
173
+ }
174
+ ) });
175
+ }
176
+
177
+ // src/components/onboarding-guides/onboarding-guide-detail-view.tsx
178
+ import { ArrowLeft } from "lucide-react";
179
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
180
+ function OnboardingGuideDetailView({
181
+ initialData: guide,
182
+ related = [],
183
+ MarkdownRenderer = SimpleMarkdownRenderer,
184
+ renderRelatedCard,
185
+ backHref,
186
+ backLabel = "Back to Getting Started",
187
+ basePath = "/onboarding-guides"
188
+ }) {
189
+ const resolvedBackHref = backHref ?? basePath;
190
+ const runtime = useChatRuntime();
191
+ const { ref: videoWarmupRef } = useVideoWarmup({
192
+ videoUrl: guide.main_video_url,
193
+ supabaseStorageOrigin: runtime?.endpoints.supabaseStorageOrigin
194
+ });
195
+ const captionsUrl = getCaptionsUrl(
196
+ "onboarding_guide",
197
+ guide.id,
198
+ guide.srt_content
199
+ );
200
+ const videoPoster = guide.main_video_thumbnail || guide.featured_image || guide.og_image_url || runtime?.resolvePlaceholderUrl?.(guide.title, { aspect: "wide" }) || void 0;
201
+ const defaultRenderRelatedCard = (g) => {
202
+ const cta = runtime?.composeContentUrl ? runtime.composeContentUrl(
203
+ "onboarding_guide",
204
+ g.slug,
205
+ g.onboarding_guide_platforms
206
+ ) : buildDefaultHref(basePath, g.slug);
207
+ return /* @__PURE__ */ jsx2(
208
+ OnboardingGuideCard,
209
+ {
210
+ guide: g,
211
+ href: cta.href,
212
+ targetPlatform: cta.targetPlatform
213
+ }
214
+ );
215
+ };
216
+ const renderRelatedCardFn = renderRelatedCard ?? defaultRenderRelatedCard;
217
+ return /* @__PURE__ */ jsx2(ArticleDetailLayout, { children: /* @__PURE__ */ jsxs2("div", { className: "space-y-6 md:space-y-8", children: [
218
+ /* @__PURE__ */ jsxs2(
219
+ next_link_default,
220
+ {
221
+ href: resolvedBackHref,
222
+ className: "inline-flex items-center gap-2 text-ods-text-secondary hover:text-ods-accent transition-colors",
223
+ children: [
224
+ /* @__PURE__ */ jsx2(ArrowLeft, { className: "h-4 w-4" }),
225
+ /* @__PURE__ */ jsx2("span", { className: "text-h5", children: backLabel })
226
+ ]
227
+ }
228
+ ),
229
+ /* @__PURE__ */ jsx2("h1", { className: "text-h1 tracking-[-1.12px] text-ods-text-primary", children: guide.title }),
230
+ /* @__PURE__ */ jsx2(
231
+ EntityAuthorCard,
232
+ {
233
+ author: guide.author,
234
+ publishedAt: guide.published_at,
235
+ extraCells: [
236
+ {
237
+ value: `${guide.section} \xB7 Step ${guide.step_order}`,
238
+ label: "Section",
239
+ uppercase: false
240
+ }
241
+ ]
242
+ }
243
+ ),
244
+ (guide.main_video_url || guide.youtube_url) && /* @__PURE__ */ jsx2("div", { ref: videoWarmupRef, children: /* @__PURE__ */ jsx2(
245
+ EntityVideoSection,
246
+ {
247
+ mainVideoUrl: guide.main_video_url,
248
+ youtubeUrl: guide.youtube_url || void 0,
249
+ highlightVideoUrl: guide.highlight_video_url,
250
+ mainVideoPoster: videoPoster,
251
+ highlightVideoThumbnail: guide.highlight_video_thumbnail || void 0,
252
+ videoSummary: void 0,
253
+ videoBites: void 0,
254
+ title: guide.title,
255
+ srtContent: guide.srt_content,
256
+ captionsUrl,
257
+ MarkdownRenderer
258
+ }
259
+ ) }),
260
+ guide.content && /* @__PURE__ */ jsx2("div", { className: "space-y-4", children: /* @__PURE__ */ jsx2(MarkdownRenderer, { content: guide.content }) }),
261
+ guide.video_bites && guide.video_bites.length > 0 && /* @__PURE__ */ jsx2(
262
+ VideoBitesDisplay,
263
+ {
264
+ bites: guide.video_bites,
265
+ filterPublished: true,
266
+ showTitle: false
267
+ }
268
+ ),
269
+ related.length > 0 && /* @__PURE__ */ jsxs2("div", { className: "space-y-4 pt-8 border-t border-ods-border", children: [
270
+ /* @__PURE__ */ jsxs2("h2", { className: "text-h3 tracking-[-0.36px] text-ods-text-primary", children: [
271
+ "More in ",
272
+ guide.section
273
+ ] }),
274
+ /* @__PURE__ */ jsx2("ul", { className: "flex flex-col gap-3", children: related.map((r) => /* @__PURE__ */ jsx2("li", { children: renderRelatedCardFn(r) }, r.id)) })
275
+ ] })
276
+ ] }) });
277
+ }
278
+
279
+ // src/components/onboarding-guides/onboarding-guides-catalog-skeleton.tsx
280
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
281
+ function OnboardingGuidesCatalogSkeleton() {
282
+ return /* @__PURE__ */ jsx3(
283
+ DevSectionPage,
284
+ {
285
+ sectionKey: "onboarding",
286
+ preControls: /* @__PURE__ */ jsxs3("div", { className: "space-y-4 animate-pulse", children: [
287
+ /* @__PURE__ */ jsx3("div", { className: "h-12 w-full bg-ods-card border border-ods-border rounded-md" }),
288
+ /* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap items-center gap-3 p-4 bg-ods-card border border-ods-border rounded-lg", children: [
289
+ /* @__PURE__ */ jsx3("div", { className: "h-4 w-14 bg-ods-border/60 rounded" }),
290
+ [0, 1, 2, 3].map((i) => /* @__PURE__ */ jsx3(
291
+ "div",
292
+ {
293
+ className: "h-10 w-24 bg-ods-card border border-ods-border rounded-md"
294
+ },
295
+ i
296
+ ))
297
+ ] })
298
+ ] }),
299
+ children: /* @__PURE__ */ jsx3("div", { className: "space-y-10 animate-pulse", children: [4, 3, 3].map((cardCount, sectionIdx) => /* @__PURE__ */ jsxs3("section", { className: "space-y-4", children: [
300
+ /* @__PURE__ */ jsxs3("h2", { className: "text-h3 tracking-[-0.36px] text-ods-text-primary flex items-center gap-2", children: [
301
+ /* @__PURE__ */ jsx3("span", { className: "h-6 w-40 bg-ods-border/70 rounded" }),
302
+ /* @__PURE__ */ jsx3("span", { className: "h-5 w-8 bg-ods-text-secondary/20 rounded-full" })
303
+ ] }),
304
+ /* @__PURE__ */ jsx3("ul", { className: "flex flex-col gap-4", children: Array.from({ length: cardCount }).map((_, cardIdx) => /* @__PURE__ */ jsx3("li", { children: /* @__PURE__ */ jsx3(OnboardingGuideCardSkeleton, { size: "catalog" }) }, cardIdx)) })
305
+ ] }, sectionIdx)) })
306
+ }
307
+ );
308
+ }
309
+
310
+ // src/components/onboarding-guides/hooks/use-onboarding-guides.ts
311
+ import { useQuery } from "@tanstack/react-query";
312
+ var onboardingGuideKeys = {
313
+ all: ["onboarding-guides"],
314
+ lists: () => [...onboardingGuideKeys.all, "list"],
315
+ list: (filters) => [...onboardingGuideKeys.lists(), filters],
316
+ details: () => [...onboardingGuideKeys.all, "detail"],
317
+ detail: (slug) => [...onboardingGuideKeys.details(), slug],
318
+ sections: () => [...onboardingGuideKeys.all, "sections"],
319
+ admin: {
320
+ all: ["admin", "onboarding-guides"],
321
+ lists: () => ["admin", "onboarding-guides", "list"],
322
+ detail: (slug) => ["admin", "onboarding-guide", slug],
323
+ stats: () => ["admin", "onboarding-guides", "stats"]
324
+ }
325
+ };
326
+ function useOnboardingGuides(filters) {
327
+ return useQuery({
328
+ queryKey: onboardingGuideKeys.list(filters || {}),
329
+ queryFn: async () => {
330
+ const params = new URLSearchParams();
331
+ if (filters?.search) params.set("search", filters.search);
332
+ if (filters?.section) params.set("section", filters.section);
333
+ if (filters?.limit) params.set("limit", filters.limit.toString());
334
+ if (filters?.offset) params.set("offset", filters.offset.toString());
335
+ const res = await fetch(`/api/onboarding-guides?${params}`);
336
+ if (!res.ok) throw new Error("Failed to fetch onboarding guides");
337
+ return res.json();
338
+ }
339
+ });
340
+ }
341
+ function useOnboardingGuide(slug) {
342
+ return useQuery({
343
+ queryKey: onboardingGuideKeys.detail(slug || ""),
344
+ queryFn: async () => {
345
+ const res = await fetch(`/api/onboarding-guides/${slug}`);
346
+ if (!res.ok) throw new Error("Failed to fetch onboarding guide");
347
+ return res.json();
348
+ },
349
+ enabled: !!slug
350
+ });
351
+ }
352
+ function useOnboardingGuideSections() {
353
+ return useQuery({
354
+ queryKey: onboardingGuideKeys.sections(),
355
+ queryFn: async () => {
356
+ const res = await fetch("/api/onboarding-guides/sections");
357
+ if (!res.ok)
358
+ throw new Error("Failed to fetch onboarding-guide sections");
359
+ return res.json();
360
+ },
361
+ staleTime: 0
362
+ });
363
+ }
364
+ export {
365
+ OnboardingGuideDetailView,
366
+ OnboardingGuidesCatalogSkeleton,
367
+ OnboardingGuidesCatalogView,
368
+ onboardingGuideKeys,
369
+ useOnboardingGuide,
370
+ useOnboardingGuideSections,
371
+ useOnboardingGuides
372
+ };
373
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/onboarding-guides/onboarding-guides-catalog-view.tsx","../../../src/components/onboarding-guides/build-default-href.ts","../../../src/components/onboarding-guides/onboarding-guide-detail-view.tsx","../../../src/components/onboarding-guides/onboarding-guides-catalog-skeleton.tsx","../../../src/components/onboarding-guides/hooks/use-onboarding-guides.ts"],"sourcesContent":["'use client'\n\n/**\n * Public-facing catalog view for `/onboarding-guides` on openframe.\n *\n * Self-contained: every concern that used to require a hub-side\n * wrapper now flows through lib primitives + the ChatRuntime context.\n *\n * - Chrome: `<DevSectionPage sectionKey=\"onboarding\">` (same lib\n * primitive every other dev-center surface uses).\n * - Search bar: lib `<DocSearchBar>` + `useDocSearch` directly,\n * pre-scoped to `tableIds: ['onboarding-guides']`. The chat\n * runtime's `source` discriminates the RAG namespace.\n * - Section filter: lib `<FilterSection>` + URL push via embed-shim\n * `useRouter`/`useSearchParams`.\n * - Cards: lib `<OnboardingGuideCard>` with hrefs composed via\n * `runtime.composeContentUrl?.('onboarding_guide', slug, platforms)`.\n * Falls back to a same-origin relative path when no composer is\n * wired (single-platform embedders).\n *\n * No hub-side wrapper file required.\n */\n\nimport { useMemo, useTransition, type ReactNode } from 'react'\nimport { GraduationCap } from 'lucide-react'\n\nimport { useRouter, useSearchParams } from '../../embed-shims'\nimport { DevSectionPage } from '../shared/dev-section'\nimport { DocSearchBar, useDocSearch } from '../shared/doc-search'\nimport { FilterPillRow } from '../ui/filter-pill-row'\nimport { OnboardingGuideCard } from '../chat/entity-cards/onboarding-guide-card'\nimport { useChatRuntime } from '../../contexts/chat-runtime-context'\nimport type { OnboardingGuide } from '../chat/types/entities/onboarding-guide'\nimport { buildDefaultHref } from './build-default-href'\n\nexport interface OnboardingGuidesCatalogViewProps {\n initialGuides: OnboardingGuide[]\n initialSections: Array<{\n section: string\n section_order: number\n count: number\n }>\n initialSection?: string\n /** Optional per-row card renderer override. When omitted, lib\n * renders `<OnboardingGuideCard>` with runtime-composed href.\n * Embedders only override to swap the card shape entirely. */\n renderCard?: (guide: OnboardingGuide) => ReactNode\n /** Base path the catalog is mounted under. Used as the fallback\n * `href` prefix for card hrefs when `runtime.composeContentUrl` is\n * not wired. Embedders mounting at `/docs/onboarding/` instead of\n * `/onboarding-guides/` should override. Also used by `setSection`\n * for the `?section=` URL push. Default `/onboarding-guides`. */\n basePath?: string\n}\n\nexport function OnboardingGuidesCatalogView({\n initialGuides,\n initialSections,\n initialSection = '',\n renderCard,\n basePath = '/onboarding-guides',\n}: OnboardingGuidesCatalogViewProps) {\n const router = useRouter()\n const searchParams = useSearchParams()\n const [isPending, startTransition] = useTransition()\n const runtime = useChatRuntime()\n const activeSection = initialSection || 'all'\n\n // Section grouping. Data arrives already filtered server-side via\n // `?section=`; this just buckets the visible rows for the section-\n // header layout — no client-side `.filter()`.\n const grouped = useMemo(() => {\n const map = new Map<\n string,\n { section_order: number; guides: OnboardingGuide[] }\n >()\n for (const g of initialGuides) {\n const existing = map.get(g.section)\n if (existing) {\n if (g.section_order < existing.section_order)\n existing.section_order = g.section_order\n existing.guides.push(g)\n } else {\n map.set(g.section, { section_order: g.section_order, guides: [g] })\n }\n }\n for (const entry of map.values()) {\n entry.guides.sort(\n (a, b) =>\n a.step_order - b.step_order || a.title.localeCompare(b.title),\n )\n }\n return Array.from(map.entries())\n .map(([section, info]) => ({ section, ...info }))\n .sort(\n (a, b) =>\n a.section_order - b.section_order ||\n a.section.localeCompare(b.section),\n )\n }, [initialGuides])\n\n // Section-filter options for the lib `<FilterSection>` row.\n const sectionFilterOptions = useMemo(\n () => [\n { value: 'all', label: `All (${initialGuides.length})` },\n ...initialSections.map((s) => ({\n value: s.section,\n label: `${s.section} (${s.count})`,\n })),\n ],\n [initialGuides.length, initialSections],\n )\n\n // Section pill change → push `?section=X` so the host RSC re-\n // fetches against the DAL. Wrapped in `useTransition` so the\n // results grid dims while the new payload is in flight.\n const setSection = (value: string) => {\n const params = new URLSearchParams(searchParams.toString())\n if (value === 'all') {\n params.delete('section')\n } else {\n params.set('section', value)\n }\n const qs = params.toString()\n startTransition(() => {\n router.push(qs ? `${basePath}?${qs}` : basePath)\n })\n }\n\n // Search bar — scoped to onboarding-guides only via the RAG-search\n // `tableIds` parameter. The hook calls `/api/docs/search` directly;\n // hub or embedder must expose that endpoint (reverse-proxy on\n // non-Next.js hosts).\n const source = runtime?.source ?? 'openframe'\n const docSearch = useDocSearch({\n source,\n baseRoute: basePath,\n onNavigate: (path) => router.push(path),\n tableIds: ['onboarding-guides'],\n })\n\n // Per-row card renderer — uses runtime-composed href for cross-\n // platform navigation. Falls back to a same-origin relative URL\n // when no composer is wired.\n const defaultRenderCard = (guide: OnboardingGuide) => {\n const cta = runtime?.composeContentUrl\n ? runtime.composeContentUrl(\n 'onboarding_guide',\n guide.slug,\n guide.onboarding_guide_platforms,\n )\n : buildDefaultHref(basePath, guide.slug)\n return (\n <OnboardingGuideCard\n guide={guide}\n href={cta.href}\n targetPlatform={cta.targetPlatform}\n size=\"catalog\"\n />\n )\n }\n const renderCardFn = renderCard ?? defaultRenderCard\n\n const preControls = (\n <div className=\"space-y-4\">\n <DocSearchBar\n placeholder=\"Search onboarding guides, releases, case studies…\"\n query={docSearch.query}\n onQueryChange={docSearch.setQuery}\n results={docSearch.results}\n isLoading={docSearch.isLoading}\n onResultSelect={docSearch.handleResultSelect}\n showDropdown={docSearch.keepDropdownOpen}\n />\n {initialSections.length > 0 && (\n <FilterPillRow\n label=\"Section\"\n selectedValue={activeSection}\n onValueChange={setSection}\n options={sectionFilterOptions}\n />\n )}\n </div>\n )\n\n return (\n <DevSectionPage sectionKey=\"onboarding\" preControls={preControls}>\n {initialGuides.length === 0 ? (\n <div className=\"text-center py-16\">\n <GraduationCap className=\"h-12 w-12 text-ods-text-secondary mx-auto mb-4\" />\n <h2 className=\"text-ods-text-primary font-['DM_Sans'] text-[20px] font-semibold mb-2\">\n No onboarding guides found\n </h2>\n <p className=\"text-ods-text-secondary font-['DM_Sans'] text-[14px]\">\n {activeSection !== 'all'\n ? 'No guides in this section yet.'\n : \"We're working on the onboarding library. Check back soon.\"}\n </p>\n </div>\n ) : (\n <div\n className={\n isPending\n ? 'opacity-60 transition-opacity space-y-10'\n : 'space-y-10'\n }\n >\n {grouped.map((sec) => (\n <section key={sec.section} className=\"space-y-4\">\n <h2 className=\"text-h3 tracking-[-0.36px] text-ods-text-primary flex items-center gap-2\">\n {sec.section}\n <span className=\"inline-flex items-center justify-center rounded-full bg-ods-text-secondary/20 text-ods-text-secondary text-xs font-medium px-2 py-0.5\">\n {sec.guides.length}\n </span>\n </h2>\n {/* HORIZONTAL catalog list — single column so consecutive\n steps read top-to-bottom (Step 1 above Step 2 above\n Step 3); a grid would visually reorder them. */}\n <ul className=\"flex flex-col gap-4\">\n {sec.guides.map((guide) => (\n <li key={guide.id}>{renderCardFn(guide)}</li>\n ))}\n </ul>\n </section>\n ))}\n </div>\n )}\n </DevSectionPage>\n )\n}\n","/**\n * Lib-internal helper — default href shape for onboarding-guide cards\n * when `runtime.composeContentUrl` is not wired (single-platform\n * embedders without cross-platform topology).\n *\n * Shared between `OnboardingGuidesCatalogView` (per-card href) and\n * `OnboardingGuideDetailView` (per-related-card href) so both views\n * compose hrefs from the same `basePath`-derived shape — no parallel\n * 4-line helper to drift apart.\n */\nexport function buildDefaultHref(\n basePath: string,\n slug: string,\n): { href: string; targetPlatform: string | null } {\n return { href: `${basePath}/${slug}`, targetPlatform: null }\n}\n","'use client'\n\n/**\n * Public-facing detail view for `/onboarding-guides/<slug>` on\n * openframe.\n *\n * Self-contained: every concern that used to require a hub-side\n * wrapper now flows through lib primitives + the ChatRuntime context.\n *\n * - Markdown: lib `<SimpleMarkdownRenderer>` (already lib-resident).\n * - Video warmup: lib `useVideoWarmup` (reads Supabase storage\n * origin from `runtime.endpoints.supabaseStorageOrigin`; Mux\n * origins are hardcoded public CDN hosts).\n * - Captions URL: lib `getCaptionsUrl` (pure URL builder).\n * - Video poster: inline priority chain\n * (`main_video_thumbnail || featured_image || og_image_url`) —\n * same fallbacks the card uses.\n * - Related card hrefs: `runtime.composeContentUrl?.(\n * 'onboarding_guide', slug, platforms)` — falls back to same-\n * origin relative path when no composer is wired.\n *\n * No hub-side wrapper file required. Optional `MarkdownRenderer`\n * prop lets hosts swap in a renderer with extra plugins (Reddit /\n * Twitter / X embeds) when needed.\n */\n\nimport { type ComponentType, type ReactNode } from 'react'\nimport { ArrowLeft } from 'lucide-react'\n\nimport { Link } from '../../embed-shims'\nimport { ArticleDetailLayout } from '../layout/article-detail-layout'\nimport { EntityVideoSection } from '../features/entity-video-section'\nimport { VideoBitesDisplay } from '../features/video-bites-display'\nimport { useVideoWarmup } from '../features/use-video-warmup'\nimport { getCaptionsUrl } from '../features/captions-url'\nimport { SimpleMarkdownRenderer } from '../ui/simple-markdown-renderer'\nimport { EntityAuthorCard } from '../chat/entity-cards/entity-author-card'\nimport { OnboardingGuideCard } from '../chat/entity-cards/onboarding-guide-card'\nimport { useChatRuntime } from '../../contexts/chat-runtime-context'\nimport type { OnboardingGuide } from '../chat/types/entities/onboarding-guide'\nimport type { VideoTeaser } from '../../types/video-processing'\nimport { buildDefaultHref } from './build-default-href'\n\nexport interface OnboardingGuideDetailViewProps {\n initialData: OnboardingGuide\n related?: OnboardingGuide[]\n /** Optional markdown renderer override. Defaults to lib\n * `<SimpleMarkdownRenderer>`. Hosts override when they need extra\n * plugins (Reddit / Twitter / X / code-block enhancements). */\n MarkdownRenderer?: ComponentType<{ content: string }>\n /** Optional per-row related-card renderer override. When omitted,\n * lib renders `<OnboardingGuideCard>` with runtime-composed href. */\n renderRelatedCard?: (guide: OnboardingGuide) => ReactNode\n /** Back-link target. Defaults to `basePath` so the link returns to\n * the catalog the embedder is hosting (no drift when `basePath`\n * is overridden). The admin preview explicitly overrides to\n * `/admin/onboarding-guides`. */\n backHref?: string\n /** Back-link label. Defaults to \"Back to Getting Started\". */\n backLabel?: string\n /** Base path the related-card hrefs default to when\n * `runtime.composeContentUrl` is not wired. Embedders mounting at\n * `/docs/onboarding/` instead of `/onboarding-guides/` should\n * override. Default `/onboarding-guides`. */\n basePath?: string\n}\n\nexport function OnboardingGuideDetailView({\n initialData: guide,\n related = [],\n MarkdownRenderer = SimpleMarkdownRenderer,\n renderRelatedCard,\n backHref,\n backLabel = 'Back to Getting Started',\n basePath = '/onboarding-guides',\n}: OnboardingGuideDetailViewProps) {\n // Resolve `backHref` from `basePath` when not explicitly set — so\n // an embedder overriding `basePath=\"/docs/onboarding\"` automatically\n // gets the right back link without remembering to thread `backHref`\n // too. Admin preview still wins via its explicit `backHref` override.\n const resolvedBackHref = backHref ?? basePath\n const runtime = useChatRuntime()\n\n // Video warmup — preconnect always fires; preload only when the\n // container scrolls within ~1 viewport AND the URL is on the\n // configured Supabase storage origin. No origin in runtime ⇒\n // preconnect-only path (Mux/YouTube unaffected).\n const { ref: videoWarmupRef } = useVideoWarmup<HTMLDivElement>({\n videoUrl: guide.main_video_url,\n supabaseStorageOrigin: runtime?.endpoints.supabaseStorageOrigin,\n })\n\n const captionsUrl = getCaptionsUrl(\n 'onboarding_guide',\n guide.id,\n guide.srt_content,\n )\n\n // Video poster — fallback chain:\n // 1. Entity-owned thumbnails (main_video_thumbnail / featured_image / og_image_url)\n // 2. Branded OG placeholder from `runtime.resolvePlaceholderUrl(title)`\n // — restores the hub's prior behavior where a video without a\n // thumbnail still showed a branded poster instead of a black\n // frame.\n // 3. `undefined` (player picks its own default poster — usually\n // first-frame extraction).\n const videoPoster =\n guide.main_video_thumbnail ||\n guide.featured_image ||\n guide.og_image_url ||\n runtime?.resolvePlaceholderUrl?.(guide.title, { aspect: 'wide' }) ||\n undefined\n\n // Default related-card renderer — runtime-composed cross-platform href.\n const defaultRenderRelatedCard = (g: OnboardingGuide) => {\n const cta = runtime?.composeContentUrl\n ? runtime.composeContentUrl(\n 'onboarding_guide',\n g.slug,\n g.onboarding_guide_platforms,\n )\n : buildDefaultHref(basePath, g.slug)\n return (\n <OnboardingGuideCard\n guide={g}\n href={cta.href}\n targetPlatform={cta.targetPlatform}\n />\n )\n }\n const renderRelatedCardFn = renderRelatedCard ?? defaultRenderRelatedCard\n\n return (\n <ArticleDetailLayout>\n <div className=\"space-y-6 md:space-y-8\">\n {/* Back link */}\n <Link\n href={resolvedBackHref}\n className=\"inline-flex items-center gap-2 text-ods-text-secondary hover:text-ods-accent transition-colors\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n <span className=\"text-h5\">{backLabel}</span>\n </Link>\n\n <h1 className=\"text-h1 tracking-[-1.12px] text-ods-text-primary\">\n {guide.title}\n </h1>\n\n {/* Metadata grid — Section · Step | Published | Author. */}\n <EntityAuthorCard\n author={guide.author}\n publishedAt={guide.published_at}\n extraCells={[\n {\n value: `${guide.section} · Step ${guide.step_order}`,\n label: 'Section',\n uppercase: false,\n },\n ]}\n />\n\n {/* Video. `main_video_url` (Mux/MP4) and `youtube_url` are\n independent columns — either one populated should render\n the player. `EntityVideoSection` routes accordingly. */}\n {(guide.main_video_url || guide.youtube_url) && (\n <div ref={videoWarmupRef}>\n <EntityVideoSection\n mainVideoUrl={guide.main_video_url}\n youtubeUrl={guide.youtube_url || undefined}\n highlightVideoUrl={guide.highlight_video_url}\n mainVideoPoster={videoPoster}\n highlightVideoThumbnail={guide.highlight_video_thumbnail || undefined}\n videoSummary={undefined}\n videoBites={undefined}\n title={guide.title}\n srtContent={guide.srt_content}\n captionsUrl={captionsUrl}\n MarkdownRenderer={MarkdownRenderer}\n />\n </div>\n )}\n\n {/* Markdown body */}\n {guide.content && (\n <div className=\"space-y-4\">\n <MarkdownRenderer content={guide.content} />\n </div>\n )}\n\n {/* Video Bites */}\n {guide.video_bites && guide.video_bites.length > 0 && (\n <VideoBitesDisplay\n bites={guide.video_bites as VideoTeaser[]}\n filterPublished={true}\n showTitle={false}\n />\n )}\n\n {/* Related — same-section, ordered by step. */}\n {related.length > 0 && (\n <div className=\"space-y-4 pt-8 border-t border-ods-border\">\n <h2 className=\"text-h3 tracking-[-0.36px] text-ods-text-primary\">\n More in {guide.section}\n </h2>\n <ul className=\"flex flex-col gap-3\">\n {related.map((r) => (\n <li key={r.id}>{renderRelatedCardFn(r)}</li>\n ))}\n </ul>\n </div>\n )}\n </div>\n </ArticleDetailLayout>\n )\n}\n","'use client'\n\nimport { DevSectionPage } from '../shared/dev-section'\nimport { OnboardingGuideCardSkeleton } from '../chat/entity-cards/onboarding-guide-card'\n\n/**\n * Page-level Suspense fallback for `/onboarding-guides`.\n *\n * Mirrors the loaded `<OnboardingGuidesCatalogView>` shape — both\n * mount the same `<DevSectionPage sectionKey=\"onboarding\">` so the\n * hero, back button, and overall page scaffold render identically.\n *\n * The `preControls` slot reserves space for the search bar (h-12)\n * plus the section pill row (~74px including padding) so the\n * Suspense → loaded transition doesn't shift vertically.\n *\n * Card distribution `4 + 3 + 3 = 10` matches the typical openframe\n * onboarding dataset; per-card height (288 px) is byte-identical to\n * the loaded card so per-card shifts on resolve are zero.\n */\nexport function OnboardingGuidesCatalogSkeleton() {\n return (\n <DevSectionPage\n sectionKey=\"onboarding\"\n preControls={\n <div className=\"space-y-4 animate-pulse\">\n {/* Search input placeholder — matches `<SearchInput>` h-12. */}\n <div className=\"h-12 w-full bg-ods-card border border-ods-border rounded-md\" />\n {/* Section pill row placeholder — same wrapper class set the\n hub-side `<FilterSection>` uses (~74 px). */}\n <div className=\"flex flex-wrap items-center gap-3 p-4 bg-ods-card border border-ods-border rounded-lg\">\n <div className=\"h-4 w-14 bg-ods-border/60 rounded\" />\n {[0, 1, 2, 3].map((i) => (\n <div\n key={i}\n className=\"h-10 w-24 bg-ods-card border border-ods-border rounded-md\"\n />\n ))}\n </div>\n </div>\n }\n >\n <div className=\"space-y-10 animate-pulse\">\n {[4, 3, 3].map((cardCount, sectionIdx) => (\n <section key={sectionIdx} className=\"space-y-4\">\n <h2 className=\"text-h3 tracking-[-0.36px] text-ods-text-primary flex items-center gap-2\">\n <span className=\"h-6 w-40 bg-ods-border/70 rounded\" />\n <span className=\"h-5 w-8 bg-ods-text-secondary/20 rounded-full\" />\n </h2>\n <ul className=\"flex flex-col gap-4\">\n {Array.from({ length: cardCount }).map((_, cardIdx) => (\n <li key={cardIdx}>\n <OnboardingGuideCardSkeleton size=\"catalog\" />\n </li>\n ))}\n </ul>\n </section>\n ))}\n </div>\n </DevSectionPage>\n )\n}\n","'use client'\n\n/**\n * React Query hooks for Onboarding Guides — PUBLIC reads only.\n *\n * Admin mutations (create/update/delete/publish/stats/save-highlight)\n * stay HUB-side in `hooks/use-onboarding-guides.ts` and import the\n * `onboardingGuideKeys.admin` sub-namespace from this module so the\n * cache namespace `['onboarding-guides']` has a single source of truth.\n *\n * Endpoints (`/api/onboarding-guides*`) are host-supplied — non-Next.js\n * embedders must reverse-proxy the same routes. Same precedent as the\n * tickets list hook.\n */\n\nimport { useQuery } from '@tanstack/react-query'\n\nimport type {\n OnboardingGuide,\n OnboardingGuideFilters,\n OnboardingGuideListResponse,\n OnboardingGuideSectionSummary,\n} from '../../chat/types/entities/onboarding-guide'\n\n/**\n * Cache key builder for the `['onboarding-guides']` namespace.\n *\n * Includes BOTH public-read sub-keys (`lists`, `list`, `details`,\n * `detail`, `sections`) AND the `admin` sub-namespace. Admin mutations\n * live hub-side but invalidate against this same builder so a single\n * `qc.invalidateQueries({ queryKey: onboardingGuideKeys.all })` from\n * an admin hook also clears the public read cache.\n */\nexport const onboardingGuideKeys = {\n all: ['onboarding-guides'] as const,\n lists: () => [...onboardingGuideKeys.all, 'list'] as const,\n list: (filters: OnboardingGuideFilters) =>\n [...onboardingGuideKeys.lists(), filters] as const,\n details: () => [...onboardingGuideKeys.all, 'detail'] as const,\n detail: (slug: string) => [...onboardingGuideKeys.details(), slug] as const,\n sections: () => [...onboardingGuideKeys.all, 'sections'] as const,\n admin: {\n all: ['admin', 'onboarding-guides'] as const,\n lists: () => ['admin', 'onboarding-guides', 'list'] as const,\n detail: (slug: string) =>\n ['admin', 'onboarding-guide', slug] as const,\n stats: () => ['admin', 'onboarding-guides', 'stats'] as const,\n },\n}\n\nexport function useOnboardingGuides(filters?: OnboardingGuideFilters) {\n return useQuery({\n queryKey: onboardingGuideKeys.list(filters || {}),\n queryFn: async (): Promise<OnboardingGuideListResponse> => {\n const params = new URLSearchParams()\n if (filters?.search) params.set('search', filters.search)\n if (filters?.section) params.set('section', filters.section)\n if (filters?.limit) params.set('limit', filters.limit.toString())\n if (filters?.offset) params.set('offset', filters.offset.toString())\n const res = await fetch(`/api/onboarding-guides?${params}`)\n if (!res.ok) throw new Error('Failed to fetch onboarding guides')\n return res.json()\n },\n })\n}\n\nexport function useOnboardingGuide(slug: string | undefined) {\n return useQuery({\n queryKey: onboardingGuideKeys.detail(slug || ''),\n queryFn: async (): Promise<OnboardingGuide> => {\n const res = await fetch(`/api/onboarding-guides/${slug}`)\n if (!res.ok) throw new Error('Failed to fetch onboarding guide')\n return res.json()\n },\n enabled: !!slug,\n })\n}\n\nexport function useOnboardingGuideSections() {\n return useQuery({\n queryKey: onboardingGuideKeys.sections(),\n queryFn: async (): Promise<OnboardingGuideSectionSummary[]> => {\n const res = await fetch('/api/onboarding-guides/sections')\n if (!res.ok)\n throw new Error('Failed to fetch onboarding-guide sections')\n return res.json()\n },\n staleTime: 0,\n })\n}\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs"]}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Public-facing detail view for `/onboarding-guides/<slug>` on
3
+ * openframe.
4
+ *
5
+ * Self-contained: every concern that used to require a hub-side
6
+ * wrapper now flows through lib primitives + the ChatRuntime context.
7
+ *
8
+ * - Markdown: lib `<SimpleMarkdownRenderer>` (already lib-resident).
9
+ * - Video warmup: lib `useVideoWarmup` (reads Supabase storage
10
+ * origin from `runtime.endpoints.supabaseStorageOrigin`; Mux
11
+ * origins are hardcoded public CDN hosts).
12
+ * - Captions URL: lib `getCaptionsUrl` (pure URL builder).
13
+ * - Video poster: inline priority chain
14
+ * (`main_video_thumbnail || featured_image || og_image_url`) —
15
+ * same fallbacks the card uses.
16
+ * - Related card hrefs: `runtime.composeContentUrl?.(
17
+ * 'onboarding_guide', slug, platforms)` — falls back to same-
18
+ * origin relative path when no composer is wired.
19
+ *
20
+ * No hub-side wrapper file required. Optional `MarkdownRenderer`
21
+ * prop lets hosts swap in a renderer with extra plugins (Reddit /
22
+ * Twitter / X embeds) when needed.
23
+ */
24
+ import { type ComponentType, type ReactNode } from 'react';
25
+ import type { OnboardingGuide } from '../chat/types/entities/onboarding-guide';
26
+ export interface OnboardingGuideDetailViewProps {
27
+ initialData: OnboardingGuide;
28
+ related?: OnboardingGuide[];
29
+ /** Optional markdown renderer override. Defaults to lib
30
+ * `<SimpleMarkdownRenderer>`. Hosts override when they need extra
31
+ * plugins (Reddit / Twitter / X / code-block enhancements). */
32
+ MarkdownRenderer?: ComponentType<{
33
+ content: string;
34
+ }>;
35
+ /** Optional per-row related-card renderer override. When omitted,
36
+ * lib renders `<OnboardingGuideCard>` with runtime-composed href. */
37
+ renderRelatedCard?: (guide: OnboardingGuide) => ReactNode;
38
+ /** Back-link target. Defaults to `basePath` so the link returns to
39
+ * the catalog the embedder is hosting (no drift when `basePath`
40
+ * is overridden). The admin preview explicitly overrides to
41
+ * `/admin/onboarding-guides`. */
42
+ backHref?: string;
43
+ /** Back-link label. Defaults to "Back to Getting Started". */
44
+ backLabel?: string;
45
+ /** Base path the related-card hrefs default to when
46
+ * `runtime.composeContentUrl` is not wired. Embedders mounting at
47
+ * `/docs/onboarding/` instead of `/onboarding-guides/` should
48
+ * override. Default `/onboarding-guides`. */
49
+ basePath?: string;
50
+ }
51
+ export declare function OnboardingGuideDetailView({ initialData: guide, related, MarkdownRenderer, renderRelatedCard, backHref, backLabel, basePath, }: OnboardingGuideDetailViewProps): import("react/jsx-runtime").JSX.Element;
52
+ //# sourceMappingURL=onboarding-guide-detail-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboarding-guide-detail-view.d.ts","sourceRoot":"","sources":["../../../src/components/onboarding-guides/onboarding-guide-detail-view.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAa1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAA;AAI9E,MAAM,WAAW,8BAA8B;IAC7C,WAAW,EAAE,eAAe,CAAA;IAC5B,OAAO,CAAC,EAAE,eAAe,EAAE,CAAA;IAC3B;;oEAEgE;IAChE,gBAAgB,CAAC,EAAE,aAAa,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACrD;0EACsE;IACtE,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,SAAS,CAAA;IACzD;;;sCAGkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;kDAG8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,yBAAyB,CAAC,EACxC,WAAW,EAAE,KAAK,EAClB,OAAY,EACZ,gBAAyC,EACzC,iBAAiB,EACjB,QAAQ,EACR,SAAqC,EACrC,QAA+B,GAChC,EAAE,8BAA8B,2CA2IhC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Page-level Suspense fallback for `/onboarding-guides`.
3
+ *
4
+ * Mirrors the loaded `<OnboardingGuidesCatalogView>` shape — both
5
+ * mount the same `<DevSectionPage sectionKey="onboarding">` so the
6
+ * hero, back button, and overall page scaffold render identically.
7
+ *
8
+ * The `preControls` slot reserves space for the search bar (h-12)
9
+ * plus the section pill row (~74px including padding) so the
10
+ * Suspense → loaded transition doesn't shift vertically.
11
+ *
12
+ * Card distribution `4 + 3 + 3 = 10` matches the typical openframe
13
+ * onboarding dataset; per-card height (288 px) is byte-identical to
14
+ * the loaded card so per-card shifts on resolve are zero.
15
+ */
16
+ export declare function OnboardingGuidesCatalogSkeleton(): import("react/jsx-runtime").JSX.Element;
17
+ //# sourceMappingURL=onboarding-guides-catalog-skeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboarding-guides-catalog-skeleton.d.ts","sourceRoot":"","sources":["../../../src/components/onboarding-guides/onboarding-guides-catalog-skeleton.tsx"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,+BAA+B,4CAyC9C"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Public-facing catalog view for `/onboarding-guides` on openframe.
3
+ *
4
+ * Self-contained: every concern that used to require a hub-side
5
+ * wrapper now flows through lib primitives + the ChatRuntime context.
6
+ *
7
+ * - Chrome: `<DevSectionPage sectionKey="onboarding">` (same lib
8
+ * primitive every other dev-center surface uses).
9
+ * - Search bar: lib `<DocSearchBar>` + `useDocSearch` directly,
10
+ * pre-scoped to `tableIds: ['onboarding-guides']`. The chat
11
+ * runtime's `source` discriminates the RAG namespace.
12
+ * - Section filter: lib `<FilterSection>` + URL push via embed-shim
13
+ * `useRouter`/`useSearchParams`.
14
+ * - Cards: lib `<OnboardingGuideCard>` with hrefs composed via
15
+ * `runtime.composeContentUrl?.('onboarding_guide', slug, platforms)`.
16
+ * Falls back to a same-origin relative path when no composer is
17
+ * wired (single-platform embedders).
18
+ *
19
+ * No hub-side wrapper file required.
20
+ */
21
+ import { type ReactNode } from 'react';
22
+ import type { OnboardingGuide } from '../chat/types/entities/onboarding-guide';
23
+ export interface OnboardingGuidesCatalogViewProps {
24
+ initialGuides: OnboardingGuide[];
25
+ initialSections: Array<{
26
+ section: string;
27
+ section_order: number;
28
+ count: number;
29
+ }>;
30
+ initialSection?: string;
31
+ /** Optional per-row card renderer override. When omitted, lib
32
+ * renders `<OnboardingGuideCard>` with runtime-composed href.
33
+ * Embedders only override to swap the card shape entirely. */
34
+ renderCard?: (guide: OnboardingGuide) => ReactNode;
35
+ /** Base path the catalog is mounted under. Used as the fallback
36
+ * `href` prefix for card hrefs when `runtime.composeContentUrl` is
37
+ * not wired. Embedders mounting at `/docs/onboarding/` instead of
38
+ * `/onboarding-guides/` should override. Also used by `setSection`
39
+ * for the `?section=` URL push. Default `/onboarding-guides`. */
40
+ basePath?: string;
41
+ }
42
+ export declare function OnboardingGuidesCatalogView({ initialGuides, initialSections, initialSection, renderCard, basePath, }: OnboardingGuidesCatalogViewProps): import("react/jsx-runtime").JSX.Element;
43
+ //# sourceMappingURL=onboarding-guides-catalog-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboarding-guides-catalog-view.d.ts","sourceRoot":"","sources":["../../../src/components/onboarding-guides/onboarding-guides-catalog-view.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAS9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAA;AAG9E,MAAM,WAAW,gCAAgC;IAC/C,aAAa,EAAE,eAAe,EAAE,CAAA;IAChC,eAAe,EAAE,KAAK,CAAC;QACrB,OAAO,EAAE,MAAM,CAAA;QACf,aAAa,EAAE,MAAM,CAAA;QACrB,KAAK,EAAE,MAAM,CAAA;KACd,CAAC,CAAA;IACF,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;mEAE+D;IAC/D,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,SAAS,CAAA;IAClD;;;;sEAIkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,2BAA2B,CAAC,EAC1C,aAAa,EACb,eAAe,EACf,cAAmB,EACnB,UAAU,EACV,QAA+B,GAChC,EAAE,gCAAgC,2CAwKlC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * `<DocSearchBar>` — the canonical RAG-search dropdown surface.
3
+ *
4
+ * Mounted by every doc-search consumer (data-room sidebar, onboarding-
5
+ * guide catalog, and any future surface that needs typeahead against
6
+ * `/api/docs/search`). Wraps `<SearchInput>` with the lib's standard
7
+ * `<DocSearchResultRow>` so the dropdown looks identical everywhere.
8
+ *
9
+ * ## Why a presentation component, not a "search bar that owns its
10
+ * own hook"
11
+ *
12
+ * The data-fetching hook (`useDocSearch`) lives hub-side because it
13
+ * depends on hub-only context (`useDocNavigation`, the rag-table-
14
+ * config registry, the hub's `decideNewTab` helper). Moving the hook
15
+ * would cascade ~5 more file migrations into the lib.
16
+ *
17
+ * Instead, the hook stays hub-side and callers pass its result into
18
+ * this component as plain props. Both consumers shrink to ~5 lines.
19
+ */
20
+ import type { ReactNode } from 'react';
21
+ import { type SearchResult } from '../../ui/search-input';
22
+ export interface DocSearchBarProps {
23
+ placeholder: string;
24
+ query: string;
25
+ onQueryChange: (value: string) => void;
26
+ /** Hook-fetched results. Reuses the lib's `<SearchInput>` `SearchResult`
27
+ * shape directly so callers don't translate. */
28
+ results: SearchResult[];
29
+ isLoading: boolean;
30
+ /** Result selection handler. Mirrors `<SearchInput>` — the second
31
+ * `modifiers` argument is preserved so cmd-click / shift-click on
32
+ * a result row still forces new-tab behavior. Hub `useDocSearch`
33
+ * reads these to short-circuit to `window.open()`. */
34
+ onResultSelect: (result: SearchResult, modifiers?: {
35
+ metaKey?: boolean;
36
+ ctrlKey?: boolean;
37
+ shiftKey?: boolean;
38
+ altKey?: boolean;
39
+ button?: number;
40
+ }) => void;
41
+ /** Lets the caller's hook force the dropdown open after a recent
42
+ * internal action (e.g. result navigation). `undefined` falls back
43
+ * to `<SearchInput>`'s built-in focus/hover heuristics. */
44
+ showDropdown?: boolean;
45
+ /** Defaults to 2 — matches the existing data-room and onboarding-
46
+ * guide consumers. Override only if a surface needs different
47
+ * typeahead semantics. */
48
+ minQueryLength?: number;
49
+ /** Defaults to 0 — both existing consumers debounce inside the
50
+ * hook, not the input. */
51
+ debounceMs?: number;
52
+ className?: string;
53
+ /** Optional row-renderer override. Defaults to the lib's standard
54
+ * `<DocSearchResultRow>` (source icon + title + path breadcrumb).
55
+ * Override only when a surface needs custom row chrome. */
56
+ renderResult?: (result: SearchResult, isHighlighted: boolean) => ReactNode;
57
+ }
58
+ export declare function DocSearchBar({ placeholder, query, onQueryChange, results, isLoading, onResultSelect, showDropdown, minQueryLength, debounceMs, className, renderResult, }: DocSearchBarProps): import("react/jsx-runtime").JSX.Element;
59
+ //# sourceMappingURL=doc-search-bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-search-bar.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/doc-search/doc-search-bar.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAGtE,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC;qDACiD;IACjD,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,SAAS,EAAE,OAAO,CAAA;IAClB;;;2DAGuD;IACvD,cAAc,EAAE,CACd,MAAM,EAAE,YAAY,EACpB,SAAS,CAAC,EAAE;QACV,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,KACE,IAAI,CAAA;IACT;;gEAE4D;IAC5D,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;+BAE2B;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;+BAC2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;gEAE4D;IAC5D,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,KAAK,SAAS,CAAA;CAC3E;AAED,wBAAgB,YAAY,CAAC,EAC3B,WAAW,EACX,KAAK,EACL,aAAa,EACb,OAAO,EACP,SAAS,EACT,cAAc,EACd,YAAY,EACZ,cAAkB,EAClB,UAAc,EACd,SAAoB,EACpB,YAAY,GACb,EAAE,iBAAiB,2CAqBnB"}