@flamingo-stack/openframe-frontend-core 0.0.315 → 0.0.316

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 (163) hide show
  1. package/dist/{chunk-7U4YFQX2.js → chunk-2Y4DLBFO.js} +96 -92
  2. package/dist/{chunk-7U4YFQX2.js.map → chunk-2Y4DLBFO.js.map} +1 -1
  3. package/dist/{chunk-HATCNFQL.cjs → chunk-4MCMPYEM.cjs} +12 -12
  4. package/dist/{chunk-HATCNFQL.cjs.map → chunk-4MCMPYEM.cjs.map} +1 -1
  5. package/dist/{chunk-VY5YF4B7.js → chunk-4NVA6W3J.js} +27 -22
  6. package/dist/chunk-4NVA6W3J.js.map +1 -0
  7. package/dist/chunk-4V3TCOFC.cjs +394 -0
  8. package/dist/chunk-4V3TCOFC.cjs.map +1 -0
  9. package/dist/{chunk-A2H6TFS4.cjs → chunk-63A53WQN.cjs} +33 -33
  10. package/dist/{chunk-A2H6TFS4.cjs.map → chunk-63A53WQN.cjs.map} +1 -1
  11. package/dist/{chunk-6W54MBU2.js → chunk-64DZ2J7Q.js} +5 -5
  12. package/dist/{chunk-47JZOP7Y.js → chunk-6KERXOFE.js} +3 -3
  13. package/dist/{chunk-JALO4TAZ.js → chunk-AI5X5JTD.js} +4 -4
  14. package/dist/chunk-CSLMCBZV.js +1464 -0
  15. package/dist/chunk-CSLMCBZV.js.map +1 -0
  16. package/dist/{chunk-BSAFGQVW.cjs → chunk-CUNMBP3A.cjs} +13 -13
  17. package/dist/{chunk-BSAFGQVW.cjs.map → chunk-CUNMBP3A.cjs.map} +1 -1
  18. package/dist/{chunk-TVNILN2F.cjs → chunk-DHVL36CA.cjs} +40 -40
  19. package/dist/{chunk-TVNILN2F.cjs.map → chunk-DHVL36CA.cjs.map} +1 -1
  20. package/dist/chunk-FCEVVNWY.cjs +1916 -0
  21. package/dist/chunk-FCEVVNWY.cjs.map +1 -0
  22. package/dist/chunk-FOVX3W3C.cjs +1464 -0
  23. package/dist/chunk-FOVX3W3C.cjs.map +1 -0
  24. package/dist/{chunk-4D37W55K.js → chunk-GHVVOST5.js} +95 -116
  25. package/dist/chunk-GHVVOST5.js.map +1 -0
  26. package/dist/{chunk-TRSDXD23.js → chunk-JAZM3A7E.js} +2 -2
  27. package/dist/{chunk-TK6OABYF.js → chunk-JEBL5PQK.js} +21 -35
  28. package/dist/{chunk-TK6OABYF.js.map → chunk-JEBL5PQK.js.map} +1 -1
  29. package/dist/{chunk-5ATH263N.cjs → chunk-L5JSGNT3.cjs} +35 -35
  30. package/dist/{chunk-5ATH263N.cjs.map → chunk-L5JSGNT3.cjs.map} +1 -1
  31. package/dist/{chunk-TQ7CMFSY.cjs → chunk-LAMDFGE3.cjs} +41 -36
  32. package/dist/chunk-LAMDFGE3.cjs.map +1 -0
  33. package/dist/{chunk-V4IIBNTA.js → chunk-LQHMXPOJ.js} +5 -5
  34. package/dist/{chunk-LGLPNWS6.cjs → chunk-LWNPMLIH.cjs} +3 -3
  35. package/dist/{chunk-LGLPNWS6.cjs.map → chunk-LWNPMLIH.cjs.map} +1 -1
  36. package/dist/chunk-M3NULYCR.js +1916 -0
  37. package/dist/chunk-M3NULYCR.js.map +1 -0
  38. package/dist/{chunk-MOOV4ORG.js → chunk-OKGZK6TT.js} +3 -3
  39. package/dist/{chunk-WFHNXCI3.cjs → chunk-OLEW7FYZ.cjs} +123 -144
  40. package/dist/chunk-OLEW7FYZ.cjs.map +1 -0
  41. package/dist/chunk-PIJ4JLJU.js +394 -0
  42. package/dist/chunk-PIJ4JLJU.js.map +1 -0
  43. package/dist/{chunk-E4CQ4RUG.js → chunk-Q4AMYLKX.js} +11 -11
  44. package/dist/{chunk-FQOTC3UU.cjs → chunk-QJGRP2YE.cjs} +4 -4
  45. package/dist/{chunk-FQOTC3UU.cjs.map → chunk-QJGRP2YE.cjs.map} +1 -1
  46. package/dist/{chunk-ZPK5HW7B.cjs → chunk-UGDGUO26.cjs} +3 -3
  47. package/dist/{chunk-ZPK5HW7B.cjs.map → chunk-UGDGUO26.cjs.map} +1 -1
  48. package/dist/{chunk-QW6OL4NY.cjs → chunk-VCE3ZEN3.cjs} +5 -5
  49. package/dist/{chunk-QW6OL4NY.cjs.map → chunk-VCE3ZEN3.cjs.map} +1 -1
  50. package/dist/{chunk-2JPSWDSM.cjs → chunk-XAQJ4ZLY.cjs} +447 -443
  51. package/dist/{chunk-2JPSWDSM.cjs.map → chunk-XAQJ4ZLY.cjs.map} +1 -1
  52. package/dist/{chunk-2MLMZAK4.js → chunk-YFGDZFUG.js} +4 -4
  53. package/dist/{chunk-VFIWQGJZ.js → chunk-Z3YORGG4.js} +2 -2
  54. package/dist/{chunk-OSEKWT6X.cjs → chunk-ZYGVJXJ5.cjs} +33 -47
  55. package/dist/chunk-ZYGVJXJ5.cjs.map +1 -0
  56. package/dist/components/case-studies/index.cjs +18 -18
  57. package/dist/components/case-studies/index.cjs.map +1 -1
  58. package/dist/components/case-studies/index.js +8 -8
  59. package/dist/components/chat/index.cjs +8 -8
  60. package/dist/components/chat/index.js +7 -7
  61. package/dist/components/contact/index.cjs +9 -9
  62. package/dist/components/contact/index.js +8 -8
  63. package/dist/components/docs/doc-viewer.d.ts +4 -0
  64. package/dist/components/docs/doc-viewer.d.ts.map +1 -1
  65. package/dist/components/docs/index.cjs +11 -11
  66. package/dist/components/docs/index.js +10 -10
  67. package/dist/components/embeds/index.cjs +9 -9
  68. package/dist/components/embeds/index.js +8 -8
  69. package/dist/components/faq/faq-document-page.d.ts +18 -20
  70. package/dist/components/faq/faq-document-page.d.ts.map +1 -1
  71. package/dist/components/faq/index.cjs +10 -10
  72. package/dist/components/faq/index.js +9 -9
  73. package/dist/components/features/index.cjs +8 -8
  74. package/dist/components/features/index.js +7 -7
  75. package/dist/components/help-center-pages/delivery-page.d.ts +27 -0
  76. package/dist/components/help-center-pages/delivery-page.d.ts.map +1 -0
  77. package/dist/components/help-center-pages/index.cjs +164 -0
  78. package/dist/components/help-center-pages/index.cjs.map +1 -0
  79. package/dist/components/help-center-pages/index.d.ts +25 -0
  80. package/dist/components/help-center-pages/index.d.ts.map +1 -0
  81. package/dist/components/help-center-pages/index.js +164 -0
  82. package/dist/components/help-center-pages/index.js.map +1 -0
  83. package/dist/components/help-center-pages/onboarding-guides-catalog-page.d.ts +41 -0
  84. package/dist/components/help-center-pages/onboarding-guides-catalog-page.d.ts.map +1 -0
  85. package/dist/components/help-center-pages/product-releases-list-page.d.ts +34 -0
  86. package/dist/components/help-center-pages/product-releases-list-page.d.ts.map +1 -0
  87. package/dist/components/help-center-pages/roadmap-page.d.ts +40 -0
  88. package/dist/components/help-center-pages/roadmap-page.d.ts.map +1 -0
  89. package/dist/components/icons/index.cjs +3 -3
  90. package/dist/components/icons/index.js +2 -2
  91. package/dist/components/index.cjs +177 -1555
  92. package/dist/components/index.cjs.map +1 -1
  93. package/dist/components/index.js +348 -1726
  94. package/dist/components/index.js.map +1 -1
  95. package/dist/components/layout/page-layout.d.ts +4 -1
  96. package/dist/components/layout/page-layout.d.ts.map +1 -1
  97. package/dist/components/layout/title-block.d.ts +5 -1
  98. package/dist/components/layout/title-block.d.ts.map +1 -1
  99. package/dist/components/navigation/index.cjs +8 -8
  100. package/dist/components/navigation/index.js +7 -7
  101. package/dist/components/onboarding-guides/index.cjs +15 -364
  102. package/dist/components/onboarding-guides/index.cjs.map +1 -1
  103. package/dist/components/onboarding-guides/index.js +20 -369
  104. package/dist/components/onboarding-guides/index.js.map +1 -1
  105. package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts +9 -1
  106. package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts.map +1 -1
  107. package/dist/components/related-content/index.cjs +10 -10
  108. package/dist/components/related-content/index.js +9 -9
  109. package/dist/components/shared/dev-section/dev-section-page.d.ts +7 -1
  110. package/dist/components/shared/dev-section/dev-section-page.d.ts.map +1 -1
  111. package/dist/components/shared/dev-section/dev-section-view.d.ts +7 -1
  112. package/dist/components/shared/dev-section/dev-section-view.d.ts.map +1 -1
  113. package/dist/components/shared/legal-document/legal-document-page.d.ts +5 -1
  114. package/dist/components/shared/legal-document/legal-document-page.d.ts.map +1 -1
  115. package/dist/components/shared/product-release/release-detail-page.d.ts +11 -2
  116. package/dist/components/shared/product-release/release-detail-page.d.ts.map +1 -1
  117. package/dist/components/tickets/help-center-list.d.ts +5 -1
  118. package/dist/components/tickets/help-center-list.d.ts.map +1 -1
  119. package/dist/components/tickets/index.cjs +15 -1882
  120. package/dist/components/tickets/index.cjs.map +1 -1
  121. package/dist/components/tickets/index.js +28 -1895
  122. package/dist/components/tickets/index.js.map +1 -1
  123. package/dist/components/ui/file-manager/index.cjs +53 -53
  124. package/dist/components/ui/file-manager/index.cjs.map +1 -1
  125. package/dist/components/ui/file-manager/index.js +4 -4
  126. package/dist/components/ui/index.cjs +8 -8
  127. package/dist/components/ui/index.cjs.map +1 -1
  128. package/dist/components/ui/index.js +7 -7
  129. package/dist/hooks/index.cjs +5 -5
  130. package/dist/hooks/index.js +4 -4
  131. package/dist/index.cjs +10 -10
  132. package/dist/index.cjs.map +1 -1
  133. package/dist/index.js +9 -9
  134. package/package.json +7 -1
  135. package/src/components/docs/doc-viewer.tsx +21 -34
  136. package/src/components/faq/faq-document-page.tsx +33 -60
  137. package/src/components/help-center-pages/delivery-page.tsx +45 -0
  138. package/src/components/help-center-pages/index.ts +41 -0
  139. package/src/components/help-center-pages/onboarding-guides-catalog-page.tsx +66 -0
  140. package/src/components/help-center-pages/product-releases-list-page.tsx +58 -0
  141. package/src/components/help-center-pages/roadmap-page.tsx +68 -0
  142. package/src/components/layout/page-layout.tsx +11 -0
  143. package/src/components/layout/title-block.tsx +15 -2
  144. package/src/components/onboarding-guides/onboarding-guide-detail-view.tsx +30 -19
  145. package/src/components/shared/dev-section/dev-section-page.tsx +29 -19
  146. package/src/components/shared/dev-section/dev-section-view.tsx +26 -19
  147. package/src/components/shared/legal-document/legal-document-page.tsx +19 -23
  148. package/src/components/shared/product-release/release-detail-page.tsx +36 -36
  149. package/src/components/tickets/help-center-list.tsx +11 -3
  150. package/dist/chunk-4D37W55K.js.map +0 -1
  151. package/dist/chunk-OSEKWT6X.cjs.map +0 -1
  152. package/dist/chunk-TQ7CMFSY.cjs.map +0 -1
  153. package/dist/chunk-VY5YF4B7.js.map +0 -1
  154. package/dist/chunk-WFHNXCI3.cjs.map +0 -1
  155. /package/dist/{chunk-6W54MBU2.js.map → chunk-64DZ2J7Q.js.map} +0 -0
  156. /package/dist/{chunk-47JZOP7Y.js.map → chunk-6KERXOFE.js.map} +0 -0
  157. /package/dist/{chunk-JALO4TAZ.js.map → chunk-AI5X5JTD.js.map} +0 -0
  158. /package/dist/{chunk-TRSDXD23.js.map → chunk-JAZM3A7E.js.map} +0 -0
  159. /package/dist/{chunk-V4IIBNTA.js.map → chunk-LQHMXPOJ.js.map} +0 -0
  160. /package/dist/{chunk-MOOV4ORG.js.map → chunk-OKGZK6TT.js.map} +0 -0
  161. /package/dist/{chunk-E4CQ4RUG.js.map → chunk-Q4AMYLKX.js.map} +0 -0
  162. /package/dist/{chunk-2MLMZAK4.js.map → chunk-YFGDZFUG.js.map} +0 -0
  163. /package/dist/{chunk-VFIWQGJZ.js.map → chunk-Z3YORGG4.js.map} +0 -0
@@ -2,19 +2,17 @@
2
2
 
3
3
  /**
4
4
  * FaqDocumentPage — the full `/faqs` page with chrome, so embedders drop in
5
- * ONE component instead of hand-assembling `PageShell` + `PageLayout` + the
6
- * FAQ hero around the bare `<FaqSection>`. Mirrors `LegalDocumentPage` /
7
- * `DevSectionPage`: the page-level layout lives in the lib, the host page is a
8
- * thin wrapper that passes only config + the SSR-resolved data.
5
+ * ONE component instead of hand-assembling `PageShell` + `PageLayout` around
6
+ * the bare `<FaqSection>`. Mirrors `LegalDocumentPage` / `DevSectionPage`: the
7
+ * page-level layout lives in the lib, the host page is a thin wrapper that
8
+ * passes only config + the SSR-resolved data.
9
9
  *
10
- * HERO: renders the canonical FAQ hero (`<h1 class="text-h1">` + accent dot +
11
- * icon + clamped subtitle) byte-identical to the multi-platform hub's local
12
- * `PageWithHeader` chrome the standalone `/faqs` page historically used. It
13
- * does NOT route through `PageLayout`'s `title`/`subtitle` (the FROZEN
14
- * `text-h2` `TitleBlock` is a different, smaller header used by OpenFrame
15
- * detail surfaces). The page owns the `<h1>`, so `<FaqSection heading={null}>`
16
- * nests its category headings as `<h2>` and the questions as `<h3>` (the
17
- * SEO-recommended FAQ document outline).
10
+ * HERO: the title + subtitle route through the canonical (frozen) `PageLayout`
11
+ * `TitleBlock` with `titleSize="h1"`the unified Help Center header (the
12
+ * `TitleBlock` element is always an `<h1>`; `titleSize` only sets its typography,
13
+ * here `text-h1`). The page owns that `<h1>`, so `<FaqSection heading={null}>`
14
+ * nests its category headings as `<h2>`/`<h3>` (the SEO-recommended FAQ document
15
+ * outline).
18
16
  *
19
17
  * DATA: pass `initialFaqs` (SSR-resolved, platform-scoped) so `FaqSection`
20
18
  * skips its client self-fetch — the standalone page's static platform-only
@@ -22,27 +20,25 @@
22
20
  * suggestion-fill instead.
23
21
  */
24
22
 
25
- import React from 'react';
26
- import { HelpCircle } from 'lucide-react';
27
23
  import type { Faq } from '../../types/faq';
28
24
  import { PageShell, PageLayout } from '../ui';
29
25
  import { useRouter } from '../../embed-shims/next-navigation';
30
- import { SECTION_HERO_ICON_CLASS } from '../../utils/page-header-constants';
31
26
  import { FaqSection } from './faq-section';
32
27
  import type { FaqSchemaOptions } from './json-ld';
33
28
 
34
29
  export interface FaqDocumentPageProps {
35
- /** Hero `<h1>`. Default "Frequently Asked Questions". */
30
+ /** Page title (frozen `PageLayout` `TitleBlock`). Default "Frequently Asked Questions". */
36
31
  title?: string;
37
- /** Subtitle under the title (auto-clamped to 2 lines). */
32
+ /** Subtitle under the title. */
38
33
  subtitle?: string;
39
- /** Icon rendered before the title. Default `<HelpCircle>` (the FAQ glyph). */
40
- titleIcon?: React.ReactNode;
41
- /** Render the yellow accent dot after the title (default true). */
42
- accentDot?: boolean;
43
34
  /** Back-button config — same pattern as `DevSectionPage` / `LegalDocumentPage`.
44
35
  * Pass `false` to hide. Default `{ label: 'Back to home', href: '/' }`. */
45
36
  backButton?: { label?: string; href?: string } | false;
37
+ /** Render the standalone `<PageShell>` (own `<main>` + bg + max-width). Default
38
+ * true. Pass false when the host layout already provides the page container
39
+ * (e.g. openframe-frontend's `AppLayout` `<main>`) — only the padding box
40
+ * renders, avoiding a nested `<main>`. */
41
+ shell?: boolean;
46
42
  /** SSR-hydrate `FaqSection` (skips the client fetch — the platform-only
47
43
  * contract for the standalone page). Omit for self-fetching embeds. */
48
44
  initialFaqs?: Faq[];
@@ -63,8 +59,6 @@ export interface FaqDocumentPageProps {
63
59
  export function FaqDocumentPage({
64
60
  title = 'Frequently Asked Questions',
65
61
  subtitle,
66
- titleIcon = <HelpCircle className={SECTION_HERO_ICON_CLASS} />,
67
- accentDot = true,
68
62
  backButton,
69
63
  initialFaqs,
70
64
  emitJsonLd,
@@ -73,6 +67,7 @@ export function FaqDocumentPage({
73
67
  entityType,
74
68
  entityId,
75
69
  minResults,
70
+ shell = true,
76
71
  }: FaqDocumentPageProps) {
77
72
  const router = useRouter();
78
73
 
@@ -87,42 +82,20 @@ export function FaqDocumentPage({
87
82
  onClick: () => router.push(backButton?.href ?? '/'),
88
83
  };
89
84
 
90
- return (
91
- <PageShell>
92
- <PageLayout backButton={backCfg}>
93
- <div className="w-full flex flex-col gap-10">
94
- {/* Canonical FAQ hero — the exact DOM/CSS the hub's local
95
- `PageWithHeader` rendered (text-h1 + accent dot + icon + clamped
96
- subtitle), inlined here so the standalone `/faqs` look is owned by
97
- the lib. Intentionally NOT the frozen `text-h2` `TitleBlock`. */}
98
- <div className="flex items-end justify-between gap-[var(--spacing-system-m)] md:flex-col md:items-start md:justify-start lg:flex-row lg:items-end lg:justify-between">
99
- <div className="flex flex-col gap-[var(--spacing-system-xs)] flex-1 min-w-0">
100
- <div className="space-y-4">
101
- <h1 className="text-h1 tracking-[-1.12px] text-ods-text-primary flex items-center gap-3">
102
- {titleIcon}
103
- <span>
104
- {title}
105
- {accentDot && <span className="text-ods-accent">.</span>}
106
- </span>
107
- </h1>
108
- <p className="font-['DM_Sans'] font-medium text-[18px] leading-[28px] text-ods-text-secondary max-w-3xl line-clamp-2 min-h-[56px]">
109
- {subtitle || ' '}
110
- </p>
111
- </div>
112
- </div>
113
- </div>
114
- <FaqSection
115
- initialFaqs={initialFaqs}
116
- heading={null}
117
- emitJsonLd={emitJsonLd}
118
- jsonLd={jsonLd}
119
- apiBaseUrl={apiBaseUrl}
120
- entityType={entityType}
121
- entityId={entityId}
122
- minResults={minResults}
123
- />
124
- </div>
125
- </PageLayout>
126
- </PageShell>
85
+ const inner = (
86
+ <PageLayout title={title} subtitle={subtitle} backButton={backCfg} titleSize="h1">
87
+ <FaqSection
88
+ initialFaqs={initialFaqs}
89
+ heading={null}
90
+ emitJsonLd={emitJsonLd}
91
+ jsonLd={jsonLd}
92
+ apiBaseUrl={apiBaseUrl}
93
+ entityType={entityType}
94
+ entityId={entityId}
95
+ minResults={minResults}
96
+ />
97
+ </PageLayout>
127
98
  );
99
+
100
+ return shell ? <PageShell>{inner}</PageShell> : <div className="page-shell-content">{inner}</div>;
128
101
  }
@@ -0,0 +1,45 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * `<DeliveryPage>` — the full bug-fixes & enhancements (`delivery`) page:
5
+ * `DevSectionPage sectionKey="delivery"` chrome wrapping the self-contained
6
+ * `<DeliveryLists>` (Recently Completed + Active Tasks tables). Hosts configure
7
+ * only the two bucket api routes.
8
+ */
9
+
10
+ import type { ReactNode } from 'react'
11
+ import { DevSectionPage } from '../shared/dev-section'
12
+ import { DeliveryLists } from '../shared/delivery'
13
+
14
+ export interface DeliveryPageProps {
15
+ /** GET endpoint for the "Recently Completed" bucket. Default `/api/delivery/completed`. */
16
+ completedEndpoint?: string
17
+ /** GET endpoint for the "Active Tasks" bucket. Default `/api/delivery/in-progress`. */
18
+ inProgressEndpoint?: string
19
+ /** Back-button config. Pass `false` to hide. Default `{ href: '/' }`. */
20
+ backButton?: { label?: string; href?: string } | false
21
+ title?: string
22
+ subtitle?: string
23
+ /** Optional slot rendered below the lists, inside the page chrome. */
24
+ belowContent?: ReactNode
25
+ /** Render the standalone `<PageShell>`. Default true. Pass false when the host
26
+ * layout already provides the page container (forwarded to `DevSectionPage`). */
27
+ shell?: boolean
28
+ }
29
+
30
+ export function DeliveryPage({
31
+ completedEndpoint,
32
+ inProgressEndpoint,
33
+ backButton,
34
+ title,
35
+ subtitle,
36
+ belowContent,
37
+ shell,
38
+ }: DeliveryPageProps) {
39
+ return (
40
+ <DevSectionPage sectionKey="delivery" backButton={backButton} title={title} subtitle={subtitle} shell={shell}>
41
+ <DeliveryLists completedApiEndpoint={completedEndpoint} inProgressApiEndpoint={inProgressEndpoint} />
42
+ {belowContent}
43
+ </DevSectionPage>
44
+ )
45
+ }
@@ -0,0 +1,41 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * Help Center pages — ready-made, full-page components (each owns the canonical
5
+ * `PageShell` + `PageLayout` chrome) so a host route is a one-line mount with NO
6
+ * local wrapper. Shared by openframe-frontend (self-fetch via the `/content`
7
+ * proxy, mounted under `/help-center/*`) and multi-platform-hub (SSR with
8
+ * server-fetched `initialData` + `generateMetadata`/JSON-LD kept in the server
9
+ * route). Endpoint config + SSR data + optional slots are passed as props.
10
+ *
11
+ * This barrel ALSO re-exports the already-existing full-pages (FAQ / Legal /
12
+ * Release detail / Onboarding detail / Docs / Tickets) so consumers have ONE
13
+ * import site for "help center pages". Re-exports are NAMED (not `export *`) to
14
+ * avoid TS2308 ambiguous-re-export collisions, and this barrel is intentionally
15
+ * NOT merged into the top-level `components/index.ts`.
16
+ */
17
+
18
+ // New combined pages. (The Help Center *index* landing is intentionally NOT
19
+ // here — it stays a host-local page; its links + icons are app-specific.)
20
+ export { RoadmapPage, type RoadmapPageProps } from './roadmap-page'
21
+ export { ProductReleasesListPage, type ProductReleasesListPageProps } from './product-releases-list-page'
22
+ export { DeliveryPage, type DeliveryPageProps } from './delivery-page'
23
+ export {
24
+ OnboardingGuidesCatalogPage,
25
+ type OnboardingGuidesCatalogPageProps,
26
+ } from './onboarding-guides-catalog-page'
27
+
28
+ // Existing full-pages re-exported for a single Help Center import site.
29
+ export { FaqDocumentPage, type FaqDocumentPageProps } from '../faq'
30
+ export { LegalDocumentPage, type LegalDocumentPageProps } from '../shared/legal-document'
31
+ export {
32
+ ReleaseDetailPage,
33
+ type ReleaseDetailPageProps,
34
+ type VideoDisplaySectionProps,
35
+ } from '../shared/product-release'
36
+ export {
37
+ OnboardingGuideDetailView,
38
+ type OnboardingGuideDetailViewProps,
39
+ } from '../onboarding-guides'
40
+ export { DocsHubPage } from '../docs'
41
+ export { HelpCenterList } from '../tickets'
@@ -0,0 +1,66 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * `<OnboardingGuidesCatalogPage>` — the full `/onboarding-guides` catalog page:
5
+ * `DevSectionPage sectionKey="onboarding"` chrome wrapping the self-contained
6
+ * `<OnboardingGuidesCatalogView>` (RAG search + section pills + guide grid).
7
+ * Supports both SSR (`initialGuides`/`initialSections`) and self-fetch
8
+ * (`guidesEndpoint`/`sectionsEndpoint`) modes — forwarded to the view verbatim.
9
+ */
10
+
11
+ import type { ReactNode } from 'react'
12
+ import type { OnboardingGuide } from '../chat/types/entities/onboarding-guide'
13
+ import { DevSectionPage } from '../shared/dev-section'
14
+ import { OnboardingGuidesCatalogView } from '../onboarding-guides'
15
+
16
+ type SectionSummary = { section: string; section_order: number; count: number }
17
+
18
+ export interface OnboardingGuidesCatalogPageProps {
19
+ /** Self-fetch: GET list endpoint (the api route). Appends `?section=`. */
20
+ guidesEndpoint?: string
21
+ /** Self-fetch: GET section-summary endpoint (the api route). */
22
+ sectionsEndpoint?: string
23
+ /** Controlled / SSR: server-fetched guides + sections + active section. */
24
+ initialGuides?: OnboardingGuide[]
25
+ initialSections?: SectionSummary[]
26
+ initialSection?: string
27
+ /** Base path the catalog is mounted under (card href prefix + `?section=` push). */
28
+ basePath?: string
29
+ /** Back-button config. Pass `false` to hide. Default `{ href: '/' }`. */
30
+ backButton?: { label?: string; href?: string } | false
31
+ title?: string
32
+ subtitle?: string
33
+ /** Optional slot rendered below the catalog, inside the page chrome. */
34
+ belowContent?: ReactNode
35
+ /** Render the standalone `<PageShell>`. Default true. Pass false when the host
36
+ * layout already provides the page container (forwarded to `DevSectionPage`). */
37
+ shell?: boolean
38
+ }
39
+
40
+ export function OnboardingGuidesCatalogPage({
41
+ guidesEndpoint,
42
+ sectionsEndpoint,
43
+ initialGuides,
44
+ initialSections,
45
+ initialSection,
46
+ basePath,
47
+ backButton,
48
+ title,
49
+ subtitle,
50
+ belowContent,
51
+ shell,
52
+ }: OnboardingGuidesCatalogPageProps) {
53
+ return (
54
+ <DevSectionPage sectionKey="onboarding" backButton={backButton} title={title} subtitle={subtitle} shell={shell}>
55
+ <OnboardingGuidesCatalogView
56
+ guidesEndpoint={guidesEndpoint}
57
+ sectionsEndpoint={sectionsEndpoint}
58
+ initialGuides={initialGuides}
59
+ initialSections={initialSections}
60
+ initialSection={initialSection}
61
+ basePath={basePath}
62
+ />
63
+ {belowContent}
64
+ </DevSectionPage>
65
+ )
66
+ }
@@ -0,0 +1,58 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * `<ProductReleasesListPage>` — the full `/releases` list page: `DevSectionPage
5
+ * sectionKey="releases"` chrome wrapping the self-contained `<ProductReleasesView>`.
6
+ * Hosts configure the api route + detail `basePath` (+ optional SSR `initialData`
7
+ * and a custom card-prop builder). Card → detail nav flows through
8
+ * `runtime.composeContentUrl`.
9
+ */
10
+
11
+ import type { ReactNode } from 'react'
12
+ import type { ProductRelease, ProductReleaseListResponse } from '../../types/product-release'
13
+ import { DevSectionPage } from '../shared/dev-section'
14
+ import { ProductReleasesView, type ProductReleaseCardExtras } from '../shared/product-release'
15
+
16
+ export interface ProductReleasesListPageProps {
17
+ /** GET list endpoint (the api route). Default `/api/releases`. */
18
+ releasesEndpoint?: string
19
+ /** Fallback detail-href prefix when `composeContentUrl` is not wired. Default `/releases`. */
20
+ basePath?: string
21
+ /** Derive the per-card prop bundle (defaults to the lib's rich builder). */
22
+ buildCardProps?: (release: ProductRelease) => ProductReleaseCardExtras
23
+ /** Optional SSR hydrate for the first page (hub server-fetch). */
24
+ initialData?: ProductReleaseListResponse
25
+ /** Back-button config. Pass `false` to hide. Default `{ href: '/' }`. */
26
+ backButton?: { label?: string; href?: string } | false
27
+ title?: string
28
+ subtitle?: string
29
+ /** Optional slot rendered below the list, inside the page chrome. */
30
+ belowContent?: ReactNode
31
+ /** Render the standalone `<PageShell>`. Default true. Pass false when the host
32
+ * layout already provides the page container (forwarded to `DevSectionPage`). */
33
+ shell?: boolean
34
+ }
35
+
36
+ export function ProductReleasesListPage({
37
+ releasesEndpoint,
38
+ basePath,
39
+ buildCardProps,
40
+ initialData,
41
+ backButton,
42
+ title,
43
+ subtitle,
44
+ belowContent,
45
+ shell,
46
+ }: ProductReleasesListPageProps) {
47
+ return (
48
+ <DevSectionPage sectionKey="releases" backButton={backButton} title={title} subtitle={subtitle} shell={shell}>
49
+ <ProductReleasesView
50
+ endpoint={releasesEndpoint}
51
+ basePath={basePath}
52
+ buildCardProps={buildCardProps}
53
+ initialData={initialData}
54
+ />
55
+ {belowContent}
56
+ </DevSectionPage>
57
+ )
58
+ }
@@ -0,0 +1,68 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * `<RoadmapPage>` — the full `/roadmap` page: `DevSectionPage sectionKey="roadmap"`
5
+ * (PageShell + PageLayout + hero + search/status chrome) wrapping the
6
+ * self-contained `<RoadmapView>` list. Hosts configure only the api routes
7
+ * (+ optional SSR `initialItems`); both openframe-frontend and the hub mount
8
+ * this instead of hand-composing `DevSectionPage` + `RoadmapView`.
9
+ */
10
+
11
+ import type { ReactNode } from 'react'
12
+ import type { RoadmapItem } from '../chat/types/entities/roadmap-item'
13
+ import { DevSectionPage } from '../shared/dev-section'
14
+ import { RoadmapView } from '../shared/roadmap'
15
+ import type { UseRoadmapVotingOptions } from '../shared/roadmap'
16
+
17
+ export interface RoadmapPageProps {
18
+ /** GET list endpoint (the api route). Default `/api/roadmap`. */
19
+ roadmapEndpoint?: string
20
+ /** Per-task refresh URL builder (after a vote). Default `/api/roadmap/<id>`. */
21
+ buildRefreshUrl?: (taskId: string) => string
22
+ /** Vote POST endpoint, forwarded to `RoadmapView` via `votingOptions`. */
23
+ voteApiEndpoint?: string
24
+ /** Full voting options override — takes precedence over `voteApiEndpoint`. */
25
+ votingOptions?: UseRoadmapVotingOptions
26
+ /** Optional SSR hydrate (hub server-fetch) — skips the initial client fetch. */
27
+ initialItems?: RoadmapItem[]
28
+ /** Indent the grid (the hub's full-page roadmap look). Default off. */
29
+ showLeftMargin?: boolean
30
+ /** Back-button config. Pass `false` to hide. Default `{ href: '/' }`. */
31
+ backButton?: { label?: string; href?: string } | false
32
+ /** Override the hero title/subtitle (defaults from `OPENFRAME_DEV_SECTIONS`). */
33
+ title?: string
34
+ subtitle?: string
35
+ /** Optional slot rendered below the list, inside the page chrome — e.g. the
36
+ * hub's related-content rail. */
37
+ belowContent?: ReactNode
38
+ /** Render the standalone `<PageShell>`. Default true. Pass false when the host
39
+ * layout already provides the page container (forwarded to `DevSectionPage`). */
40
+ shell?: boolean
41
+ }
42
+
43
+ export function RoadmapPage({
44
+ roadmapEndpoint,
45
+ buildRefreshUrl,
46
+ voteApiEndpoint,
47
+ votingOptions,
48
+ initialItems,
49
+ showLeftMargin,
50
+ backButton,
51
+ title,
52
+ subtitle,
53
+ belowContent,
54
+ shell,
55
+ }: RoadmapPageProps) {
56
+ return (
57
+ <DevSectionPage sectionKey="roadmap" backButton={backButton} title={title} subtitle={subtitle} shell={shell}>
58
+ <RoadmapView
59
+ endpoint={roadmapEndpoint}
60
+ initialItems={initialItems}
61
+ showLeftMargin={showLeftMargin}
62
+ buildRefreshUrl={buildRefreshUrl}
63
+ votingOptions={votingOptions ?? (voteApiEndpoint ? { voteApiEndpoint } : undefined)}
64
+ />
65
+ {belowContent}
66
+ </DevSectionPage>
67
+ )
68
+ }
@@ -25,6 +25,12 @@
25
25
  * If a new design genuinely needs different chrome: build a SEPARATE new
26
26
  * component for it. Never mutate this one. If you believe an edit here is
27
27
  * unavoidable, STOP and get explicit human sign-off first.
28
+ *
29
+ * SANCTIONED EXCEPTION (2026-06, explicit human sign-off): the OPTIONAL
30
+ * `titleSize` prop, forwarded to `TitleBlock`. Defaults to `'h2'` — the frozen
31
+ * baseline is unchanged for every existing caller. `titleSize="h1"` opts the
32
+ * title up to `text-h1` (the unified Help Center pages). Additive + default-
33
+ * preserving; do NOT change the default or anything else here.
28
34
  * ========================================================================== */
29
35
 
30
36
  import React from 'react'
@@ -49,6 +55,9 @@ export interface PageLayoutProps {
49
55
  className?: string
50
56
  contentClassName?: string
51
57
  showHeader?: boolean
58
+ /** Title typography size, forwarded to `TitleBlock`. Default `'h2'` (frozen
59
+ * baseline). Pass `'h1'` for the unified Help Center pages. */
60
+ titleSize?: 'h1' | 'h2'
52
61
  }
53
62
 
54
63
  /**
@@ -70,6 +79,7 @@ export function PageLayout({
70
79
  className,
71
80
  contentClassName,
72
81
  showHeader = true,
82
+ titleSize,
73
83
  }: PageLayoutProps) {
74
84
  const hasActions = actions && actions.length > 0
75
85
  const needsBottomPadding = hasActions && actionsVariant === 'primary-buttons'
@@ -88,6 +98,7 @@ export function PageLayout({
88
98
  menuActions={menuActions}
89
99
  selector={selector}
90
100
  variant={headerVariant}
101
+ titleSize={titleSize}
91
102
  />
92
103
  )}
93
104
 
@@ -22,6 +22,13 @@
22
22
  * current output. If a new design needs different chrome, build a SEPARATE new
23
23
  * component — never mutate this one. If an edit here seems unavoidable, STOP
24
24
  * and get explicit human sign-off first.
25
+ *
26
+ * SANCTIONED EXCEPTION (2026-06, explicit human sign-off): the OPTIONAL
27
+ * `titleSize` prop. It defaults to `'h2'` — i.e. the frozen baseline above is
28
+ * unchanged for EVERY existing caller. A caller may pass `titleSize="h1"` to
29
+ * opt the title typography up to `text-h1` (used by the unified Help Center
30
+ * pages). This is additive and default-preserving; do NOT change the default or
31
+ * touch anything else here.
25
32
  * ========================================================================== */
26
33
 
27
34
  import React from 'react'
@@ -59,6 +66,10 @@ export interface TitleBlockProps {
59
66
  */
60
67
  variant?: 'plain' | 'card'
61
68
  className?: string
69
+ /** Title typography size. Default `'h2'` (the frozen baseline). Pass `'h1'` to
70
+ * opt the title up to `text-h1` (the unified Help Center pages). Subtitle stays
71
+ * `text-h6` either way. */
72
+ titleSize?: 'h1' | 'h2'
62
73
  }
63
74
 
64
75
  export function TitleBlock({
@@ -72,9 +83,11 @@ export function TitleBlock({
72
83
  selector,
73
84
  variant = 'plain',
74
85
  className,
86
+ titleSize = 'h2',
75
87
  }: TitleBlockProps) {
76
88
  const hasActions = actions && actions.length > 0
77
89
  const hasMenuActions = !!menuActions && menuActions.some(g => g.items.length > 0)
90
+ const titleClass = titleSize === 'h1' ? 'text-h1' : 'text-h2'
78
91
 
79
92
  return (
80
93
  <div
@@ -113,7 +126,7 @@ export function TitleBlock({
113
126
  )}
114
127
  <div className="flex flex-col justify-center min-w-0 flex-1">
115
128
  {title && (
116
- <h1 className="text-h2 text-ods-text-primary truncate" title={title}>{title}</h1>
129
+ <h1 className={cn(titleClass, 'text-ods-text-primary truncate')} title={title}>{title}</h1>
117
130
  )}
118
131
  {subtitle && (
119
132
  <p className="text-h6 text-ods-text-secondary truncate" title={subtitle}>{subtitle}</p>
@@ -121,7 +134,7 @@ export function TitleBlock({
121
134
  </div>
122
135
  </div>
123
136
  ) : (
124
- title && <h1 className="text-h2 text-ods-text-primary">{title}</h1>
137
+ title && <h1 className={cn(titleClass, 'text-ods-text-primary')}>{title}</h1>
125
138
  )}
126
139
  </div>
127
140
 
@@ -74,6 +74,14 @@ export interface OnboardingGuideDetailViewProps {
74
74
  /** Base path the related-card hrefs default to when
75
75
  * `runtime.composeContentUrl` is not wired. Default `/onboarding-guides`. */
76
76
  basePath?: string
77
+ /** Optional slot rendered inside the page chrome, BELOW the article + related
78
+ * guides — e.g. the hub's cross-type related-content / FAQ rail. Lets the hub
79
+ * mount this view directly (no local wrapper); embedders omit it. */
80
+ relatedContent?: ReactNode
81
+ /** Render the standalone `<PageShell>`. Default true. Pass false when the host
82
+ * layout already provides the page container — only the padding box renders,
83
+ * avoiding a nested `<main>`. */
84
+ shell?: boolean
77
85
  }
78
86
 
79
87
  export function OnboardingGuideDetailView({
@@ -89,10 +97,16 @@ export function OnboardingGuideDetailView({
89
97
  backHref,
90
98
  backLabel = 'Back to Getting Started',
91
99
  basePath = '/onboarding-guides',
100
+ relatedContent,
101
+ shell = true,
92
102
  }: OnboardingGuideDetailViewProps) {
93
103
  const resolvedBackHref = backHref ?? basePath
94
104
  const runtime = useChatRuntime()
95
105
  const router = useRouter()
106
+ // `shell` true → standalone `<PageShell>`; false → padding-only box (no nested
107
+ // <main>) for hosts whose layout already provides the container.
108
+ const renderShell = (node: ReactNode) =>
109
+ shell ? <PageShell>{node}</PageShell> : <div className="page-shell-content">{node}</div>
96
110
 
97
111
  // Controlled (hub SSR `initialData`) OR self-fetch by slug (config-only embed).
98
112
  const url = initialData ? null : slug && guideEndpoint ? guideEndpoint(slug) : null
@@ -106,25 +120,19 @@ export function OnboardingGuideDetailView({
106
120
  })
107
121
 
108
122
  if (error || (!guide && !isLoading)) {
109
- return (
110
- <PageShell>
111
- <LoadError message="Guide not found." onRetry={reload} />
112
- </PageShell>
113
- )
123
+ return renderShell(<LoadError message="Guide not found." onRetry={reload} />)
114
124
  }
115
125
  if (!guide) {
116
126
  // Skeleton (not a bare "Loading…") for parity with every other shared view —
117
127
  // catalog, roadmap, releases all render a skeleton on first load, so the detail
118
128
  // page shouldn't flash text then content. `bare` + `PageShell` so the loading
119
129
  // state matches the loaded page's full width / padding / min-height.
120
- return (
121
- <PageShell>
122
- {/* Match the loaded page's top offset (TitleBlock's
123
- `pt-[var(--spacing-system-l)]`) so content doesn't jump on load. */}
124
- <div className="pt-[var(--spacing-system-l)]">
125
- <DetailPageSkeleton bare showImageGallery={false} />
126
- </div>
127
- </PageShell>
130
+ return renderShell(
131
+ // Match the loaded page's top offset (TitleBlock's
132
+ // `pt-[var(--spacing-system-l)]`) so content doesn't jump on load.
133
+ <div className="pt-[var(--spacing-system-l)]">
134
+ <DetailPageSkeleton bare showImageGallery={false} />
135
+ </div>
128
136
  )
129
137
  }
130
138
 
@@ -149,11 +157,12 @@ export function OnboardingGuideDetailView({
149
157
  }
150
158
  const renderRelatedCardFn = renderRelatedCard ?? defaultRenderRelatedCard
151
159
 
152
- return (
153
- <PageShell>
154
- <PageLayout backButton={{ label: backLabel, onClick: () => router.push(resolvedBackHref) }}>
155
- <h1 className="text-h1 tracking-[-1.12px] text-ods-text-primary">{guide.title}</h1>
156
-
160
+ return renderShell(
161
+ <PageLayout
162
+ title={guide.title}
163
+ titleSize="h1"
164
+ backButton={{ label: backLabel, onClick: () => router.push(resolvedBackHref) }}
165
+ >
157
166
  {/* Tags — flat onboarding_guide_tags[] from entity_tags. */}
158
167
  <EntityTagBadges tags={(guide as any).onboarding_guide_tags} />
159
168
 
@@ -232,7 +241,9 @@ export function OnboardingGuideDetailView({
232
241
  </ul>
233
242
  </div>
234
243
  )}
244
+
245
+ {/* Host slot — cross-type related-content / FAQ rail. */}
246
+ {relatedContent}
235
247
  </PageLayout>
236
- </PageShell>
237
248
  )
238
249
  }