@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.
- package/dist/{chunk-7U4YFQX2.js → chunk-2Y4DLBFO.js} +96 -92
- package/dist/{chunk-7U4YFQX2.js.map → chunk-2Y4DLBFO.js.map} +1 -1
- package/dist/{chunk-HATCNFQL.cjs → chunk-4MCMPYEM.cjs} +12 -12
- package/dist/{chunk-HATCNFQL.cjs.map → chunk-4MCMPYEM.cjs.map} +1 -1
- package/dist/{chunk-VY5YF4B7.js → chunk-4NVA6W3J.js} +27 -22
- package/dist/chunk-4NVA6W3J.js.map +1 -0
- package/dist/chunk-4V3TCOFC.cjs +394 -0
- package/dist/chunk-4V3TCOFC.cjs.map +1 -0
- package/dist/{chunk-A2H6TFS4.cjs → chunk-63A53WQN.cjs} +33 -33
- package/dist/{chunk-A2H6TFS4.cjs.map → chunk-63A53WQN.cjs.map} +1 -1
- package/dist/{chunk-6W54MBU2.js → chunk-64DZ2J7Q.js} +5 -5
- package/dist/{chunk-47JZOP7Y.js → chunk-6KERXOFE.js} +3 -3
- package/dist/{chunk-JALO4TAZ.js → chunk-AI5X5JTD.js} +4 -4
- package/dist/chunk-CSLMCBZV.js +1464 -0
- package/dist/chunk-CSLMCBZV.js.map +1 -0
- package/dist/{chunk-BSAFGQVW.cjs → chunk-CUNMBP3A.cjs} +13 -13
- package/dist/{chunk-BSAFGQVW.cjs.map → chunk-CUNMBP3A.cjs.map} +1 -1
- package/dist/{chunk-TVNILN2F.cjs → chunk-DHVL36CA.cjs} +40 -40
- package/dist/{chunk-TVNILN2F.cjs.map → chunk-DHVL36CA.cjs.map} +1 -1
- package/dist/chunk-FCEVVNWY.cjs +1916 -0
- package/dist/chunk-FCEVVNWY.cjs.map +1 -0
- package/dist/chunk-FOVX3W3C.cjs +1464 -0
- package/dist/chunk-FOVX3W3C.cjs.map +1 -0
- package/dist/{chunk-4D37W55K.js → chunk-GHVVOST5.js} +95 -116
- package/dist/chunk-GHVVOST5.js.map +1 -0
- package/dist/{chunk-TRSDXD23.js → chunk-JAZM3A7E.js} +2 -2
- package/dist/{chunk-TK6OABYF.js → chunk-JEBL5PQK.js} +21 -35
- package/dist/{chunk-TK6OABYF.js.map → chunk-JEBL5PQK.js.map} +1 -1
- package/dist/{chunk-5ATH263N.cjs → chunk-L5JSGNT3.cjs} +35 -35
- package/dist/{chunk-5ATH263N.cjs.map → chunk-L5JSGNT3.cjs.map} +1 -1
- package/dist/{chunk-TQ7CMFSY.cjs → chunk-LAMDFGE3.cjs} +41 -36
- package/dist/chunk-LAMDFGE3.cjs.map +1 -0
- package/dist/{chunk-V4IIBNTA.js → chunk-LQHMXPOJ.js} +5 -5
- package/dist/{chunk-LGLPNWS6.cjs → chunk-LWNPMLIH.cjs} +3 -3
- package/dist/{chunk-LGLPNWS6.cjs.map → chunk-LWNPMLIH.cjs.map} +1 -1
- package/dist/chunk-M3NULYCR.js +1916 -0
- package/dist/chunk-M3NULYCR.js.map +1 -0
- package/dist/{chunk-MOOV4ORG.js → chunk-OKGZK6TT.js} +3 -3
- package/dist/{chunk-WFHNXCI3.cjs → chunk-OLEW7FYZ.cjs} +123 -144
- package/dist/chunk-OLEW7FYZ.cjs.map +1 -0
- package/dist/chunk-PIJ4JLJU.js +394 -0
- package/dist/chunk-PIJ4JLJU.js.map +1 -0
- package/dist/{chunk-E4CQ4RUG.js → chunk-Q4AMYLKX.js} +11 -11
- package/dist/{chunk-FQOTC3UU.cjs → chunk-QJGRP2YE.cjs} +4 -4
- package/dist/{chunk-FQOTC3UU.cjs.map → chunk-QJGRP2YE.cjs.map} +1 -1
- package/dist/{chunk-ZPK5HW7B.cjs → chunk-UGDGUO26.cjs} +3 -3
- package/dist/{chunk-ZPK5HW7B.cjs.map → chunk-UGDGUO26.cjs.map} +1 -1
- package/dist/{chunk-QW6OL4NY.cjs → chunk-VCE3ZEN3.cjs} +5 -5
- package/dist/{chunk-QW6OL4NY.cjs.map → chunk-VCE3ZEN3.cjs.map} +1 -1
- package/dist/{chunk-2JPSWDSM.cjs → chunk-XAQJ4ZLY.cjs} +447 -443
- package/dist/{chunk-2JPSWDSM.cjs.map → chunk-XAQJ4ZLY.cjs.map} +1 -1
- package/dist/{chunk-2MLMZAK4.js → chunk-YFGDZFUG.js} +4 -4
- package/dist/{chunk-VFIWQGJZ.js → chunk-Z3YORGG4.js} +2 -2
- package/dist/{chunk-OSEKWT6X.cjs → chunk-ZYGVJXJ5.cjs} +33 -47
- package/dist/chunk-ZYGVJXJ5.cjs.map +1 -0
- package/dist/components/case-studies/index.cjs +18 -18
- package/dist/components/case-studies/index.cjs.map +1 -1
- package/dist/components/case-studies/index.js +8 -8
- package/dist/components/chat/index.cjs +8 -8
- package/dist/components/chat/index.js +7 -7
- package/dist/components/contact/index.cjs +9 -9
- package/dist/components/contact/index.js +8 -8
- package/dist/components/docs/doc-viewer.d.ts +4 -0
- package/dist/components/docs/doc-viewer.d.ts.map +1 -1
- package/dist/components/docs/index.cjs +11 -11
- package/dist/components/docs/index.js +10 -10
- package/dist/components/embeds/index.cjs +9 -9
- package/dist/components/embeds/index.js +8 -8
- package/dist/components/faq/faq-document-page.d.ts +18 -20
- package/dist/components/faq/faq-document-page.d.ts.map +1 -1
- package/dist/components/faq/index.cjs +10 -10
- package/dist/components/faq/index.js +9 -9
- package/dist/components/features/index.cjs +8 -8
- package/dist/components/features/index.js +7 -7
- package/dist/components/help-center-pages/delivery-page.d.ts +27 -0
- package/dist/components/help-center-pages/delivery-page.d.ts.map +1 -0
- package/dist/components/help-center-pages/index.cjs +164 -0
- package/dist/components/help-center-pages/index.cjs.map +1 -0
- package/dist/components/help-center-pages/index.d.ts +25 -0
- package/dist/components/help-center-pages/index.d.ts.map +1 -0
- package/dist/components/help-center-pages/index.js +164 -0
- package/dist/components/help-center-pages/index.js.map +1 -0
- package/dist/components/help-center-pages/onboarding-guides-catalog-page.d.ts +41 -0
- package/dist/components/help-center-pages/onboarding-guides-catalog-page.d.ts.map +1 -0
- package/dist/components/help-center-pages/product-releases-list-page.d.ts +34 -0
- package/dist/components/help-center-pages/product-releases-list-page.d.ts.map +1 -0
- package/dist/components/help-center-pages/roadmap-page.d.ts +40 -0
- package/dist/components/help-center-pages/roadmap-page.d.ts.map +1 -0
- package/dist/components/icons/index.cjs +3 -3
- package/dist/components/icons/index.js +2 -2
- package/dist/components/index.cjs +177 -1555
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +348 -1726
- package/dist/components/index.js.map +1 -1
- package/dist/components/layout/page-layout.d.ts +4 -1
- package/dist/components/layout/page-layout.d.ts.map +1 -1
- package/dist/components/layout/title-block.d.ts +5 -1
- package/dist/components/layout/title-block.d.ts.map +1 -1
- package/dist/components/navigation/index.cjs +8 -8
- package/dist/components/navigation/index.js +7 -7
- package/dist/components/onboarding-guides/index.cjs +15 -364
- package/dist/components/onboarding-guides/index.cjs.map +1 -1
- package/dist/components/onboarding-guides/index.js +20 -369
- package/dist/components/onboarding-guides/index.js.map +1 -1
- package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts +9 -1
- package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts.map +1 -1
- package/dist/components/related-content/index.cjs +10 -10
- package/dist/components/related-content/index.js +9 -9
- package/dist/components/shared/dev-section/dev-section-page.d.ts +7 -1
- package/dist/components/shared/dev-section/dev-section-page.d.ts.map +1 -1
- package/dist/components/shared/dev-section/dev-section-view.d.ts +7 -1
- package/dist/components/shared/dev-section/dev-section-view.d.ts.map +1 -1
- package/dist/components/shared/legal-document/legal-document-page.d.ts +5 -1
- package/dist/components/shared/legal-document/legal-document-page.d.ts.map +1 -1
- package/dist/components/shared/product-release/release-detail-page.d.ts +11 -2
- package/dist/components/shared/product-release/release-detail-page.d.ts.map +1 -1
- package/dist/components/tickets/help-center-list.d.ts +5 -1
- package/dist/components/tickets/help-center-list.d.ts.map +1 -1
- package/dist/components/tickets/index.cjs +15 -1882
- package/dist/components/tickets/index.cjs.map +1 -1
- package/dist/components/tickets/index.js +28 -1895
- package/dist/components/tickets/index.js.map +1 -1
- package/dist/components/ui/file-manager/index.cjs +53 -53
- package/dist/components/ui/file-manager/index.cjs.map +1 -1
- package/dist/components/ui/file-manager/index.js +4 -4
- package/dist/components/ui/index.cjs +8 -8
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.js +7 -7
- package/dist/hooks/index.cjs +5 -5
- package/dist/hooks/index.js +4 -4
- package/dist/index.cjs +10 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +9 -9
- package/package.json +7 -1
- package/src/components/docs/doc-viewer.tsx +21 -34
- package/src/components/faq/faq-document-page.tsx +33 -60
- package/src/components/help-center-pages/delivery-page.tsx +45 -0
- package/src/components/help-center-pages/index.ts +41 -0
- package/src/components/help-center-pages/onboarding-guides-catalog-page.tsx +66 -0
- package/src/components/help-center-pages/product-releases-list-page.tsx +58 -0
- package/src/components/help-center-pages/roadmap-page.tsx +68 -0
- package/src/components/layout/page-layout.tsx +11 -0
- package/src/components/layout/title-block.tsx +15 -2
- package/src/components/onboarding-guides/onboarding-guide-detail-view.tsx +30 -19
- package/src/components/shared/dev-section/dev-section-page.tsx +29 -19
- package/src/components/shared/dev-section/dev-section-view.tsx +26 -19
- package/src/components/shared/legal-document/legal-document-page.tsx +19 -23
- package/src/components/shared/product-release/release-detail-page.tsx +36 -36
- package/src/components/tickets/help-center-list.tsx +11 -3
- package/dist/chunk-4D37W55K.js.map +0 -1
- package/dist/chunk-OSEKWT6X.cjs.map +0 -1
- package/dist/chunk-TQ7CMFSY.cjs.map +0 -1
- package/dist/chunk-VY5YF4B7.js.map +0 -1
- package/dist/chunk-WFHNXCI3.cjs.map +0 -1
- /package/dist/{chunk-6W54MBU2.js.map → chunk-64DZ2J7Q.js.map} +0 -0
- /package/dist/{chunk-47JZOP7Y.js.map → chunk-6KERXOFE.js.map} +0 -0
- /package/dist/{chunk-JALO4TAZ.js.map → chunk-AI5X5JTD.js.map} +0 -0
- /package/dist/{chunk-TRSDXD23.js.map → chunk-JAZM3A7E.js.map} +0 -0
- /package/dist/{chunk-V4IIBNTA.js.map → chunk-LQHMXPOJ.js.map} +0 -0
- /package/dist/{chunk-MOOV4ORG.js.map → chunk-OKGZK6TT.js.map} +0 -0
- /package/dist/{chunk-E4CQ4RUG.js.map → chunk-Q4AMYLKX.js.map} +0 -0
- /package/dist/{chunk-2MLMZAK4.js.map → chunk-YFGDZFUG.js.map} +0 -0
- /package/dist/{chunk-VFIWQGJZ.js.map → chunk-Z3YORGG4.js.map} +0 -0
|
@@ -25,8 +25,6 @@ import {
|
|
|
25
25
|
type OpenframeDevSectionKey,
|
|
26
26
|
} from '../../../utils/dev-sections/openframe-dev-sections';
|
|
27
27
|
|
|
28
|
-
const SECTION_HERO_ICON_CLASS = 'h-10 w-10 text-ods-accent';
|
|
29
|
-
|
|
30
28
|
export interface DevSectionPageProps {
|
|
31
29
|
sectionKey: OpenframeDevSectionKey;
|
|
32
30
|
/** The page-specific list body (e.g. `<RoadmapList />`). */
|
|
@@ -48,6 +46,12 @@ export interface DevSectionPageProps {
|
|
|
48
46
|
/** Override the hero subtitle/description. Defaults to
|
|
49
47
|
* `OPENFRAME_DEV_SECTIONS[sectionKey].hero.description`. */
|
|
50
48
|
subtitle?: string;
|
|
49
|
+
/** Render the standalone `<PageShell>` (own `<main>` + bg + max-width). Default
|
|
50
|
+
* `true` — the contract for marketing/hub surfaces with no app shell. Pass
|
|
51
|
+
* `false` when the host layout already provides the page container (e.g.
|
|
52
|
+
* openframe-frontend's `AppLayout` `<main>`): then only the
|
|
53
|
+
* `page-shell-content` padding box is rendered, avoiding a nested `<main>`. */
|
|
54
|
+
shell?: boolean;
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
export function DevSectionPage({
|
|
@@ -57,10 +61,10 @@ export function DevSectionPage({
|
|
|
57
61
|
backButton,
|
|
58
62
|
title,
|
|
59
63
|
subtitle,
|
|
64
|
+
shell = true,
|
|
60
65
|
}: DevSectionPageProps) {
|
|
61
66
|
const router = useRouter();
|
|
62
67
|
const section = OPENFRAME_DEV_SECTIONS[sectionKey];
|
|
63
|
-
const Icon = section.icon;
|
|
64
68
|
|
|
65
69
|
// Back-button config — mirrors LegalDocumentPage / ReleaseDetailPage.
|
|
66
70
|
// Default: { label: 'Back to home', href: '/' }. Pass `false` to hide.
|
|
@@ -74,21 +78,27 @@ export function DevSectionPage({
|
|
|
74
78
|
onClick: () => router.push((backButton ? backButton.href : undefined) ?? '/'),
|
|
75
79
|
};
|
|
76
80
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
81
|
+
const inner = (
|
|
82
|
+
// Unified header: title/description route through the canonical (frozen)
|
|
83
|
+
// `PageLayout` `TitleBlock` (text-h2) — same as FAQ / Legal / detail pages —
|
|
84
|
+
// so every help-center surface shares one header. `DevSectionView` then
|
|
85
|
+
// renders ONLY its search + filter controls (`showHeading={false}`), no
|
|
86
|
+
// duplicate title. (The hero icon is intentionally dropped: TitleBlock is
|
|
87
|
+
// frozen and renders title-only.)
|
|
88
|
+
<PageLayout
|
|
89
|
+
title={title ?? section.hero.title}
|
|
90
|
+
subtitle={subtitle ?? section.hero.description}
|
|
91
|
+
titleSize="h1"
|
|
92
|
+
backButton={backCfg}
|
|
93
|
+
>
|
|
94
|
+
<DevSectionView sectionKey={sectionKey} showHeading={false} preControls={preControls}>
|
|
95
|
+
{children}
|
|
96
|
+
</DevSectionView>
|
|
97
|
+
</PageLayout>
|
|
93
98
|
);
|
|
99
|
+
|
|
100
|
+
// `shell` true → standalone `<PageShell>` (own <main> + bg + max-width).
|
|
101
|
+
// false → padding-only box (no nested <main>) for hosts whose layout already
|
|
102
|
+
// provides the container; both consume the host's `--page-shell-*` vars.
|
|
103
|
+
return shell ? <PageShell>{inner}</PageShell> : <div className="page-shell-content">{inner}</div>;
|
|
94
104
|
}
|
|
@@ -51,9 +51,15 @@ export interface DevSectionViewProps {
|
|
|
51
51
|
/** The page-specific list body. Reads URL params written by this
|
|
52
52
|
* component (search input + filter pills). */
|
|
53
53
|
children: ReactNode;
|
|
54
|
+
/** Render this component's own title heading (hero or compact `h2`). Default
|
|
55
|
+
* `true` — the tab context renders the compact heading itself. Pass `false`
|
|
56
|
+
* when the host already renders the title elsewhere (e.g. `DevSectionPage`
|
|
57
|
+
* routes it through the unified `PageLayout` `TitleBlock`): then only the
|
|
58
|
+
* search + filter controls + list render, with no duplicate heading. */
|
|
59
|
+
showHeading?: boolean;
|
|
54
60
|
}
|
|
55
61
|
|
|
56
|
-
export function DevSectionView({ sectionKey, hero, preControls, children }: DevSectionViewProps) {
|
|
62
|
+
export function DevSectionView({ sectionKey, hero, preControls, children, showHeading = true }: DevSectionViewProps) {
|
|
57
63
|
const section = OPENFRAME_DEV_SECTIONS[sectionKey];
|
|
58
64
|
const router = useRouter();
|
|
59
65
|
const pathname = usePathname();
|
|
@@ -94,24 +100,25 @@ export function DevSectionView({ sectionKey, hero, preControls, children }: DevS
|
|
|
94
100
|
|
|
95
101
|
return (
|
|
96
102
|
<div className="w-full flex flex-col gap-10">
|
|
97
|
-
{
|
|
98
|
-
|
|
99
|
-
<
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
103
|
+
{showHeading &&
|
|
104
|
+
(hero ? (
|
|
105
|
+
<div className="space-y-4">
|
|
106
|
+
<h1 className="text-h1 tracking-[-1.12px] text-ods-text-primary flex items-center gap-3">
|
|
107
|
+
{hero.icon}
|
|
108
|
+
{hero.title ?? section.hero.title}
|
|
109
|
+
</h1>
|
|
110
|
+
<p className="font-['DM_Sans'] font-medium text-[18px] leading-[28px] text-ods-text-secondary max-w-3xl">
|
|
111
|
+
{hero.description}
|
|
112
|
+
</p>
|
|
113
|
+
</div>
|
|
114
|
+
) : (
|
|
115
|
+
<div className="flex items-center justify-between w-full">
|
|
116
|
+
<h2 className="font-['Azeret_Mono'] font-semibold text-[32px] md:text-[40px] lg:text-[48px] leading-[40px] md:leading-[48px] lg:leading-[56px] text-ods-text-primary tracking-[-0.64px] md:tracking-[-0.8px] lg:tracking-[-0.96px]">
|
|
117
|
+
{section.hero.title}
|
|
118
|
+
<span className="text-ods-accent">:</span>
|
|
119
|
+
</h2>
|
|
120
|
+
</div>
|
|
121
|
+
))}
|
|
115
122
|
|
|
116
123
|
{preControls}
|
|
117
124
|
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import type { ComponentType } from 'react';
|
|
21
|
-
import { PageShell, PageLayout
|
|
21
|
+
import { PageShell, PageLayout } from '../../ui';
|
|
22
22
|
import { RichMarkdownRenderer } from '../../ui/rich-markdown-renderer';
|
|
23
23
|
import { useRouter } from '../../../embed-shims/next-navigation';
|
|
24
24
|
import { useLegalDocs, type LegalDocument } from './use-legal-docs';
|
|
@@ -63,6 +63,10 @@ export interface LegalDocumentPageProps {
|
|
|
63
63
|
/** Back-button config — same pattern as `DevSectionPage`. Pass `false`
|
|
64
64
|
* to hide. Default `{ label: 'Back to home', href: '/' }`. */
|
|
65
65
|
backButton?: { label?: string; href?: string } | false;
|
|
66
|
+
/** Render the standalone `<PageShell>`. Default true. Pass false when the host
|
|
67
|
+
* layout already provides the page container — only the padding box renders,
|
|
68
|
+
* avoiding a nested `<main>`. */
|
|
69
|
+
shell?: boolean;
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
export function LegalDocumentPage({
|
|
@@ -78,6 +82,7 @@ export function LegalDocumentPage({
|
|
|
78
82
|
apiEndpoint,
|
|
79
83
|
MarkdownRenderer = RichMarkdownRenderer,
|
|
80
84
|
backButton,
|
|
85
|
+
shell = true,
|
|
81
86
|
}: LegalDocumentPageProps) {
|
|
82
87
|
const router = useRouter();
|
|
83
88
|
const { data, isLoading, error } = useLegalDocs(docType, { initialData, apiEndpoint });
|
|
@@ -97,28 +102,18 @@ export function LegalDocumentPage({
|
|
|
97
102
|
data?.lastSynced != null ? formatLegalDate(data.lastSynced) : null;
|
|
98
103
|
const effectiveLastUpdatedLabel = initialLastUpdatedLabel ?? fallbackLastUpdatedLabel;
|
|
99
104
|
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
<span>{title}</span>
|
|
105
|
-
<span className="text-ods-accent">.</span>
|
|
106
|
-
</PageHeading>
|
|
107
|
-
<p className="font-['DM_Sans'] text-base md:text-lg text-ods-text-secondary max-w-2xl">
|
|
108
|
-
{effectiveLastUpdatedLabel ? `Last Updated: ${effectiveLastUpdatedLabel}` : fallbackDescription}
|
|
109
|
-
{data?.sourceFile && (
|
|
110
|
-
<span className="block text-sm mt-1 opacity-75">Source: {data.sourceFile}</span>
|
|
111
|
-
)}
|
|
112
|
-
</p>
|
|
113
|
-
</div>
|
|
114
|
-
);
|
|
105
|
+
// Subtitle routes through the frozen `PageLayout` `TitleBlock` (text-h2 title
|
|
106
|
+
// + subtitle) — unified header across all help-center pages. Shows the
|
|
107
|
+
// last-updated date when known, else the fallback description.
|
|
108
|
+
const subtitle = effectiveLastUpdatedLabel ? `Last Updated: ${effectiveLastUpdatedLabel}` : fallbackDescription;
|
|
115
109
|
|
|
116
|
-
|
|
117
|
-
<
|
|
118
|
-
|
|
119
|
-
<
|
|
110
|
+
const inner = (
|
|
111
|
+
<PageLayout title={title} subtitle={subtitle} backButton={backCfg} titleSize="h1">
|
|
112
|
+
{data?.sourceFile && (
|
|
113
|
+
<p className="font-['DM_Sans'] text-sm text-ods-text-secondary opacity-75">Source: {data.sourceFile}</p>
|
|
114
|
+
)}
|
|
120
115
|
|
|
121
|
-
|
|
116
|
+
<div className="flex flex-col lg:flex-row gap-6 lg:gap-10 items-start flex-1">
|
|
122
117
|
<div className="flex-1">
|
|
123
118
|
<div className="w-full">
|
|
124
119
|
<article className="space-y-2">
|
|
@@ -172,7 +167,8 @@ export function LegalDocumentPage({
|
|
|
172
167
|
</div>
|
|
173
168
|
</div>
|
|
174
169
|
</div>
|
|
175
|
-
|
|
176
|
-
</PageShell>
|
|
170
|
+
</PageLayout>
|
|
177
171
|
);
|
|
172
|
+
|
|
173
|
+
return shell ? <PageShell>{inner}</PageShell> : <div className="page-shell-content">{inner}</div>;
|
|
178
174
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useState, useEffect, ComponentType } from 'react';
|
|
3
|
+
import { useState, useEffect, ComponentType, type ReactNode } from 'react';
|
|
4
4
|
import Link from '../../../embed-shims/next-link';
|
|
5
5
|
import { useRouter } from '../../../embed-shims/next-navigation';
|
|
6
6
|
import { Card, CardContent } from '../../ui/card';
|
|
@@ -108,6 +108,15 @@ export interface ReleaseDetailPageProps {
|
|
|
108
108
|
/** Link target for the author name in the metadata grid — the host
|
|
109
109
|
* computes it (public author page; absent ⇒ plain text). */
|
|
110
110
|
authorHref?: string;
|
|
111
|
+
/** Optional slot rendered inside the page chrome, BELOW the article body —
|
|
112
|
+
* e.g. the hub's end-of-article author byline + related-content / FAQ rail.
|
|
113
|
+
* Lets the hub mount this page directly (no local wrapper component) while
|
|
114
|
+
* embedders that don't have those extras simply omit it. */
|
|
115
|
+
relatedContent?: ReactNode;
|
|
116
|
+
/** Render the standalone `<PageShell>`. Default true. Pass false when the host
|
|
117
|
+
* layout already provides the page container — only the padding box renders,
|
|
118
|
+
* avoiding a nested `<main>`. */
|
|
119
|
+
shell?: boolean;
|
|
111
120
|
}
|
|
112
121
|
|
|
113
122
|
// Default renderer = the lib's `RichMarkdownRenderer` so out-of-the-box
|
|
@@ -128,9 +137,15 @@ export function ReleaseDetailPage({
|
|
|
128
137
|
VideoDisplaySection,
|
|
129
138
|
roadmapApiEndpoint = '/api/roadmap',
|
|
130
139
|
deliveryApiEndpoint = '/api/delivery',
|
|
131
|
-
backButton
|
|
140
|
+
backButton,
|
|
141
|
+
relatedContent,
|
|
142
|
+
shell = true
|
|
132
143
|
}: ReleaseDetailPageProps) {
|
|
133
144
|
const router = useRouter();
|
|
145
|
+
// `shell` true → standalone `<PageShell>`; false → padding-only box (no nested
|
|
146
|
+
// <main>) for hosts whose layout already provides the container.
|
|
147
|
+
const renderShell = (node: ReactNode) =>
|
|
148
|
+
shell ? <PageShell>{node}</PageShell> : <div className="page-shell-content">{node}</div>;
|
|
134
149
|
// Use pre-fetched data if provided (admin preview), otherwise fetch via hook (public)
|
|
135
150
|
const { data: fetchedRelease, error, isLoading } = useRelease(initialData ? undefined : slug);
|
|
136
151
|
const release = (initialData || fetchedRelease) as Record<string, unknown> | undefined;
|
|
@@ -191,25 +206,21 @@ export function ReleaseDetailPage({
|
|
|
191
206
|
if (!initialData && isLoading) {
|
|
192
207
|
// `bare` + `PageShell` so the loading state matches the loaded page's full
|
|
193
208
|
// width / padding / min-height (the wrapper supplies the page chrome).
|
|
194
|
-
return (
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
<
|
|
199
|
-
|
|
200
|
-
</div>
|
|
201
|
-
</PageShell>
|
|
209
|
+
return renderShell(
|
|
210
|
+
// Match the loaded page's top offset (TitleBlock's
|
|
211
|
+
// `pt-[var(--spacing-system-l)]`) so content doesn't jump on load.
|
|
212
|
+
<div className="pt-[var(--spacing-system-l)]">
|
|
213
|
+
<DetailPageSkeleton bare metadataColumns={4} showImageGallery={true} />
|
|
214
|
+
</div>
|
|
202
215
|
);
|
|
203
216
|
}
|
|
204
217
|
|
|
205
218
|
if (error || !release) {
|
|
206
|
-
return (
|
|
207
|
-
<
|
|
208
|
-
<
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
</div>
|
|
212
|
-
</PageShell>
|
|
219
|
+
return renderShell(
|
|
220
|
+
<div className="text-center py-16">
|
|
221
|
+
<h1 className="text-4xl font-bold text-ods-text-primary mb-4">Release Not Found</h1>
|
|
222
|
+
<p className="text-xl text-ods-text-secondary">The release you're looking for doesn't exist.</p>
|
|
223
|
+
</div>
|
|
213
224
|
);
|
|
214
225
|
}
|
|
215
226
|
|
|
@@ -241,29 +252,16 @@ export function ReleaseDetailPage({
|
|
|
241
252
|
const bugFixed = release.bugs_fixed as ChangelogEntry[] | undefined;
|
|
242
253
|
const improvements = release.improvements as ChangelogEntry[] | undefined;
|
|
243
254
|
|
|
244
|
-
return (
|
|
245
|
-
<
|
|
246
|
-
|
|
255
|
+
return renderShell(
|
|
256
|
+
<PageLayout
|
|
257
|
+
title={releaseTitle}
|
|
258
|
+
subtitle={`Version: ${releaseVersion}`}
|
|
259
|
+
titleSize="h1"
|
|
247
260
|
backButton={
|
|
248
261
|
showBackButton ? { label: backLabel, onClick: () => router.push(backHref) } : undefined
|
|
249
262
|
}
|
|
250
263
|
>
|
|
251
264
|
<div className="space-y-6 md:space-y-8">
|
|
252
|
-
{/* Title Block */}
|
|
253
|
-
<div className="flex flex-col md:flex-row md:items-end gap-4 w-full">
|
|
254
|
-
<div className="flex-1 flex flex-col gap-2">
|
|
255
|
-
{/* Title */}
|
|
256
|
-
<h1 className="text-h1 tracking-[-1.12px] text-ods-text-primary">
|
|
257
|
-
{releaseTitle}
|
|
258
|
-
</h1>
|
|
259
|
-
|
|
260
|
-
{/* Version */}
|
|
261
|
-
<p className="text-h4 text-ods-text-secondary">
|
|
262
|
-
Version: {releaseVersion}
|
|
263
|
-
</p>
|
|
264
|
-
</div>
|
|
265
|
-
</div>
|
|
266
|
-
|
|
267
265
|
{/* Tags — flat product_release_tags[] from entity_tags */}
|
|
268
266
|
<EntityTagBadges tags={release.product_release_tags as TagAssoc[] | undefined} />
|
|
269
267
|
|
|
@@ -568,7 +566,9 @@ export function ReleaseDetailPage({
|
|
|
568
566
|
</div>
|
|
569
567
|
)}
|
|
570
568
|
</div>
|
|
569
|
+
|
|
570
|
+
{/* Host slot — end-of-article byline + related-content / FAQ rail. */}
|
|
571
|
+
{relatedContent}
|
|
571
572
|
</PageLayout>
|
|
572
|
-
</PageShell>
|
|
573
573
|
);
|
|
574
574
|
}
|
|
@@ -59,9 +59,13 @@ export interface HelpCenterListProps {
|
|
|
59
59
|
* the `tickets` section copy ("Help Center"). Set this to brand the surface
|
|
60
60
|
* for an embed that wants its own label (e.g. "Support Tickets"). */
|
|
61
61
|
title?: string
|
|
62
|
+
/** Render the standalone `<PageShell>` (forwarded to the internal
|
|
63
|
+
* `DevSectionPage`). Default true. Pass false when the host layout already
|
|
64
|
+
* provides the page container (avoids a nested `<main>`). */
|
|
65
|
+
shell?: boolean
|
|
62
66
|
}
|
|
63
67
|
|
|
64
|
-
export function HelpCenterList({ toast = defaultToast, backButton, title }: HelpCenterListProps = {}) {
|
|
68
|
+
export function HelpCenterList({ toast = defaultToast, backButton, title, shell }: HelpCenterListProps = {}) {
|
|
65
69
|
const identity = useChatIdentity()
|
|
66
70
|
const searchParams = useSearchParams()
|
|
67
71
|
const router = useRouter()
|
|
@@ -93,6 +97,7 @@ export function HelpCenterList({ toast = defaultToast, backButton, title }: Help
|
|
|
93
97
|
sectionKey="tickets"
|
|
94
98
|
backButton={backButton}
|
|
95
99
|
title={title}
|
|
100
|
+
shell={shell}
|
|
96
101
|
preControls={<HelpCenterCreateFormSkeleton />}
|
|
97
102
|
>
|
|
98
103
|
<DevCardRowSkeletonList />
|
|
@@ -101,7 +106,7 @@ export function HelpCenterList({ toast = defaultToast, backButton, title }: Help
|
|
|
101
106
|
}
|
|
102
107
|
if (identity.authTier === 'anon' || !identity.user?.email) {
|
|
103
108
|
return (
|
|
104
|
-
<DevSectionPage sectionKey="tickets" backButton={backButton} title={title}>
|
|
109
|
+
<DevSectionPage sectionKey="tickets" backButton={backButton} title={title} shell={shell}>
|
|
105
110
|
<EmptyState
|
|
106
111
|
type="generic"
|
|
107
112
|
title="Sign in to manage tickets"
|
|
@@ -138,6 +143,7 @@ export function HelpCenterList({ toast = defaultToast, backButton, title }: Help
|
|
|
138
143
|
sessionEmail={sessionEmail}
|
|
139
144
|
backButton={backButton}
|
|
140
145
|
title={title}
|
|
146
|
+
shell={shell}
|
|
141
147
|
/>
|
|
142
148
|
)
|
|
143
149
|
}
|
|
@@ -156,6 +162,7 @@ interface AuthedProps {
|
|
|
156
162
|
sessionEmail: string
|
|
157
163
|
backButton?: { label?: string; href?: string } | false
|
|
158
164
|
title?: string
|
|
165
|
+
shell?: boolean
|
|
159
166
|
}
|
|
160
167
|
|
|
161
168
|
function HelpCenterListAuthed({
|
|
@@ -171,6 +178,7 @@ function HelpCenterListAuthed({
|
|
|
171
178
|
sessionEmail,
|
|
172
179
|
backButton,
|
|
173
180
|
title,
|
|
181
|
+
shell,
|
|
174
182
|
}: AuthedProps) {
|
|
175
183
|
const queryClient = useQueryClient()
|
|
176
184
|
const [optimisticTickets, setOptimisticTickets] = useState<OptimisticTicket[]>([])
|
|
@@ -398,7 +406,7 @@ function HelpCenterListAuthed({
|
|
|
398
406
|
)
|
|
399
407
|
|
|
400
408
|
return (
|
|
401
|
-
<DevSectionPage sectionKey="tickets" backButton={backButton} title={title} preControls={form}>
|
|
409
|
+
<DevSectionPage sectionKey="tickets" backButton={backButton} title={title} shell={shell} preControls={form}>
|
|
402
410
|
{body}
|
|
403
411
|
</DevSectionPage>
|
|
404
412
|
)
|