@flamingo-stack/openframe-frontend-core 0.0.295 → 0.0.296-snapshot.20260621021605
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/README.md +9 -0
- package/dist/{chunk-7RIYT7ZH.js → chunk-2QG57XOJ.js} +1067 -205
- package/dist/chunk-2QG57XOJ.js.map +1 -0
- package/dist/{chunk-7KXD7CWD.js → chunk-3JIQVE7T.js} +9 -15
- package/dist/{chunk-7KXD7CWD.js.map → chunk-3JIQVE7T.js.map} +1 -1
- package/dist/{chunk-FT4FCV7L.cjs → chunk-4PSQS3SW.cjs} +7 -9
- package/dist/chunk-4PSQS3SW.cjs.map +1 -0
- package/dist/{chunk-OOKKGOPQ.js → chunk-4TLE6VLU.js} +30 -24
- package/dist/chunk-4TLE6VLU.js.map +1 -0
- package/dist/{chunk-6IBA2MQV.cjs → chunk-53FUMSZ5.cjs} +40 -46
- package/dist/chunk-53FUMSZ5.cjs.map +1 -0
- package/dist/{chunk-D3LEFMOA.cjs → chunk-54KNMC2R.cjs} +3 -3
- package/dist/{chunk-D3LEFMOA.cjs.map → chunk-54KNMC2R.cjs.map} +1 -1
- package/dist/{chunk-EYEW6PTA.cjs → chunk-6C526VNN.cjs} +358 -118
- package/dist/chunk-6C526VNN.cjs.map +1 -0
- package/dist/{chunk-5O6N3BKR.cjs → chunk-7OVGB2DQ.cjs} +19 -25
- package/dist/chunk-7OVGB2DQ.cjs.map +1 -0
- package/dist/{chunk-6GCI7JOE.js → chunk-AD6C23QY.js} +8 -7
- package/dist/{chunk-6GCI7JOE.js.map → chunk-AD6C23QY.js.map} +1 -1
- package/dist/chunk-F5OB2YAL.cjs +144 -0
- package/dist/chunk-F5OB2YAL.cjs.map +1 -0
- package/dist/chunk-FBWXMMRB.cjs +2 -0
- package/dist/chunk-FBWXMMRB.cjs.map +1 -0
- package/dist/{chunk-YIGPRLQY.cjs → chunk-FCDQNTDG.cjs} +21 -20
- package/dist/chunk-FCDQNTDG.cjs.map +1 -0
- package/dist/{chunk-XXI7BNB6.cjs → chunk-FQOTC3UU.cjs} +321 -18
- package/dist/chunk-FQOTC3UU.cjs.map +1 -0
- package/dist/{chunk-INDQMNP6.cjs → chunk-GUTS7HGA.cjs} +11658 -2146
- package/dist/chunk-GUTS7HGA.cjs.map +1 -0
- package/dist/chunk-GZ4C3XW6.js +2 -0
- package/dist/chunk-GZ4C3XW6.js.map +1 -0
- package/dist/{chunk-HOVJGXF7.js → chunk-IL47XWV5.js} +8 -14
- package/dist/{chunk-HOVJGXF7.js.map → chunk-IL47XWV5.js.map} +1 -1
- package/dist/{chunk-LCNMR277.js → chunk-IZ7JSBFP.js} +1 -1
- package/dist/chunk-IZ7JSBFP.js.map +1 -0
- package/dist/{chunk-5IJ46KAV.js → chunk-JALO4TAZ.js} +360 -57
- package/dist/chunk-JALO4TAZ.js.map +1 -0
- package/dist/{chunk-AQOWFSMB.cjs → chunk-L6PSSIUQ.cjs} +1 -1
- package/dist/chunk-L6PSSIUQ.cjs.map +1 -0
- package/dist/{chunk-J3RDKZ32.js → chunk-L7ULJKG7.js} +6 -10
- package/dist/{chunk-J3RDKZ32.js.map → chunk-L7ULJKG7.js.map} +1 -1
- package/dist/{chunk-6BZEAPNT.js → chunk-PC746XCO.js} +15120 -5608
- package/dist/chunk-PC746XCO.js.map +1 -0
- package/dist/{chunk-3ZXUQQL4.js → chunk-PI4WSYQV.js} +2 -2
- package/dist/{chunk-E4XABBSU.js → chunk-PWQUAVA3.js} +338 -98
- package/dist/chunk-PWQUAVA3.js.map +1 -0
- package/dist/chunk-SA2WPJVO.js +144 -0
- package/dist/chunk-SA2WPJVO.js.map +1 -0
- package/dist/{chunk-ETACGX2A.cjs → chunk-UNVE2SDJ.cjs} +37 -31
- package/dist/chunk-UNVE2SDJ.cjs.map +1 -0
- package/dist/{chunk-5E2HOSSH.cjs → chunk-WMSTJAZT.cjs} +913 -51
- package/dist/chunk-WMSTJAZT.cjs.map +1 -0
- package/dist/{chunk-EJXHZX2E.js → chunk-X4DOXQRT.js} +4 -6
- package/dist/{chunk-EJXHZX2E.js.map → chunk-X4DOXQRT.js.map} +1 -1
- package/dist/{chunk-A2YL7QRX.cjs → chunk-YBYI62OE.cjs} +33 -37
- package/dist/chunk-YBYI62OE.cjs.map +1 -0
- package/dist/components/case-studies/index.cjs +126 -0
- package/dist/components/case-studies/index.cjs.map +1 -0
- package/dist/components/case-studies/index.d.ts +2 -0
- package/dist/components/case-studies/index.d.ts.map +1 -0
- package/dist/components/case-studies/index.js +126 -0
- package/dist/components/case-studies/index.js.map +1 -0
- package/dist/components/case-studies/share-experience-section.d.ts +48 -0
- package/dist/components/case-studies/share-experience-section.d.ts.map +1 -0
- package/dist/components/chat/chat-container.d.ts.map +1 -1
- package/dist/components/chat/error-message-display.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +8 -18
- package/dist/components/chat/index.cjs.map +1 -1
- package/dist/components/chat/index.js +75 -85
- package/dist/components/chat/types/component.types.d.ts +2 -0
- package/dist/components/chat/types/component.types.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +8 -15
- package/dist/components/contact/index.cjs.map +1 -1
- package/dist/components/contact/index.js +7 -14
- package/dist/components/docs/doc-viewer.d.ts +39 -2
- package/dist/components/docs/doc-viewer.d.ts.map +1 -1
- package/dist/components/docs/docs-hub-page.d.ts +46 -0
- package/dist/components/docs/docs-hub-page.d.ts.map +1 -0
- package/dist/components/docs/index.cjs +17 -9
- package/dist/components/docs/index.cjs.map +1 -1
- package/dist/components/docs/index.d.ts +4 -0
- package/dist/components/docs/index.d.ts.map +1 -1
- package/dist/components/docs/index.js +16 -8
- package/dist/components/docs/skeletons.d.ts +32 -0
- package/dist/components/docs/skeletons.d.ts.map +1 -0
- package/dist/components/docs/use-docs-resolve-link.d.ts +20 -0
- package/dist/components/docs/use-docs-resolve-link.d.ts.map +1 -0
- package/dist/components/docs/use-document-tree.d.ts.map +1 -1
- package/dist/components/embeds/embed-container.d.ts +37 -0
- package/dist/components/embeds/embed-container.d.ts.map +1 -0
- package/dist/components/embeds/embed-iframe.d.ts.map +1 -1
- package/dist/components/embeds/file-download-card.d.ts +18 -0
- package/dist/components/embeds/file-download-card.d.ts.map +1 -0
- package/dist/components/embeds/index.cjs +38 -15
- package/dist/components/embeds/index.cjs.map +1 -1
- package/dist/components/embeds/index.d.ts +8 -0
- package/dist/components/embeds/index.d.ts.map +1 -1
- package/dist/components/embeds/index.js +40 -17
- package/dist/components/embeds/linkedin-embed-client.d.ts +8 -0
- package/dist/components/embeds/linkedin-embed-client.d.ts.map +1 -0
- package/dist/components/embeds/markdown-image.d.ts +5 -0
- package/dist/components/embeds/markdown-image.d.ts.map +1 -0
- package/dist/components/embeds/reddit-embed-client.d.ts +7 -0
- package/dist/components/embeds/reddit-embed-client.d.ts.map +1 -0
- package/dist/components/embeds/rich-markdown-runtime.d.ts +46 -0
- package/dist/components/embeds/rich-markdown-runtime.d.ts.map +1 -0
- package/dist/components/embeds/twitter-embed-client.d.ts +8 -0
- package/dist/components/embeds/twitter-embed-client.d.ts.map +1 -0
- package/dist/components/faq/index.cjs +9 -16
- package/dist/components/faq/index.cjs.map +1 -1
- package/dist/components/faq/index.js +8 -15
- package/dist/components/features/index.cjs +8 -16
- package/dist/components/features/index.cjs.map +1 -1
- package/dist/components/features/index.js +24 -32
- package/dist/components/features/notifications/notification-drawer.d.ts.map +1 -1
- package/dist/components/features/notifications/notifications-context.d.ts +5 -1
- package/dist/components/features/notifications/notifications-context.d.ts.map +1 -1
- package/dist/components/index.cjs +257 -452
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +781 -976
- package/dist/components/index.js.map +1 -1
- package/dist/components/layout/page-header.d.ts +78 -0
- package/dist/components/layout/page-header.d.ts.map +1 -0
- package/dist/components/layout/page-layout.d.ts +10 -1
- package/dist/components/layout/page-layout.d.ts.map +1 -1
- package/dist/components/layout/page-with-header.d.ts +67 -0
- package/dist/components/layout/page-with-header.d.ts.map +1 -0
- package/dist/components/layout/title-block.d.ts +17 -1
- package/dist/components/layout/title-block.d.ts.map +1 -1
- package/dist/components/navigation/index.cjs +7 -15
- package/dist/components/navigation/index.cjs.map +1 -1
- package/dist/components/navigation/index.js +9 -17
- package/dist/components/onboarding-guides/index.cjs +35 -36
- package/dist/components/onboarding-guides/index.cjs.map +1 -1
- package/dist/components/onboarding-guides/index.js +13 -14
- package/dist/components/onboarding-guides/index.js.map +1 -1
- package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts +1 -1
- package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts.map +1 -1
- package/dist/components/related-content/index.cjs +9 -16
- package/dist/components/related-content/index.cjs.map +1 -1
- package/dist/components/related-content/index.js +8 -15
- package/dist/components/shared/dev-section/dev-section-page.d.ts +9 -0
- 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.map +1 -1
- package/dist/components/shared/dev-section/index.d.ts +1 -1
- package/dist/components/shared/dev-section/index.d.ts.map +1 -1
- package/dist/components/shared/doc-search/use-doc-search.d.ts.map +1 -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.map +1 -1
- package/dist/components/tickets/index.cjs +100 -112
- package/dist/components/tickets/index.cjs.map +1 -1
- package/dist/components/tickets/index.js +20 -32
- package/dist/components/tickets/index.js.map +1 -1
- package/dist/components/ui/button/split-button.d.ts.map +1 -1
- package/dist/components/ui/file-manager/index.cjs +50 -52
- package/dist/components/ui/file-manager/index.cjs.map +1 -1
- package/dist/components/ui/file-manager/index.js +4 -6
- package/dist/components/ui/file-manager/index.js.map +1 -1
- package/dist/components/ui/index.cjs +13 -19
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.d.ts +2 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +133 -139
- package/dist/components/ui/release-changelog-section.d.ts +6 -2
- package/dist/components/ui/release-changelog-section.d.ts.map +1 -1
- package/dist/components/ui/rich-markdown-renderer.d.ts +34 -0
- package/dist/components/ui/rich-markdown-renderer.d.ts.map +1 -0
- package/dist/components/ui/simple-markdown-renderer.d.ts +2 -8
- package/dist/components/ui/simple-markdown-renderer.d.ts.map +1 -1
- package/dist/contexts/chat-runtime-context.d.ts +14 -0
- package/dist/contexts/chat-runtime-context.d.ts.map +1 -1
- package/dist/contexts/index.cjs +3 -3
- package/dist/contexts/index.js +5 -5
- package/dist/embed-shims/index.cjs +3 -3
- package/dist/embed-shims/index.cjs.map +1 -1
- package/dist/embed-shims/index.js +4 -4
- package/dist/hooks/index.cjs +4 -9
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.js +6 -11
- package/dist/index.cjs +14 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +362 -368
- package/dist/types/doc-source.d.ts +31 -1
- package/dist/types/doc-source.d.ts.map +1 -1
- package/dist/utils/index.cjs +4 -0
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/page-header-constants.d.ts +15 -0
- package/dist/utils/page-header-constants.d.ts.map +1 -0
- package/dist/utils/social-embed-cache.d.ts +29 -0
- package/dist/utils/social-embed-cache.d.ts.map +1 -0
- package/package.json +7 -1
- package/src/components/case-studies/index.ts +4 -0
- package/src/components/case-studies/share-experience-section.tsx +185 -0
- package/src/components/chat/chat-container.tsx +5 -7
- package/src/components/chat/embeddable-chat.tsx +1 -1
- package/src/components/chat/error-message-display.tsx +49 -31
- package/src/components/chat/types/component.types.ts +2 -0
- package/src/components/docs/doc-viewer.tsx +111 -19
- package/src/components/docs/docs-hub-page.tsx +149 -0
- package/src/components/docs/index.ts +17 -0
- package/src/components/docs/skeletons.tsx +138 -0
- package/src/components/docs/use-docs-resolve-link.ts +52 -0
- package/src/components/docs/use-document-tree.ts +21 -0
- package/src/components/embeds/embed-container.tsx +80 -0
- package/src/components/embeds/embed-iframe.tsx +7 -9
- package/src/components/embeds/file-download-card.tsx +54 -0
- package/src/components/embeds/index.ts +30 -0
- package/src/components/embeds/linkedin-embed-client.tsx +100 -0
- package/src/components/embeds/markdown-image.tsx +88 -0
- package/src/components/embeds/og-link-preview.tsx +13 -13
- package/src/components/embeds/reddit-embed-client.tsx +550 -0
- package/src/components/embeds/rich-markdown-runtime.tsx +79 -0
- package/src/components/embeds/twitter-embed-client.tsx +308 -0
- package/src/components/features/notifications/notification-drawer.tsx +18 -7
- package/src/components/features/notifications/notifications-context.tsx +7 -0
- package/src/components/layout/page-header.tsx +182 -0
- package/src/components/layout/page-layout.tsx +14 -1
- package/src/components/layout/page-with-header.tsx +110 -0
- package/src/components/layout/title-block.tsx +40 -62
- package/src/components/onboarding-guides/onboarding-guide-detail-view.tsx +3 -3
- package/src/components/shared/dev-section/dev-section-page.tsx +9 -1
- package/src/components/shared/dev-section/dev-section-view.tsx +14 -9
- package/src/components/shared/dev-section/index.ts +1 -1
- package/src/components/shared/doc-search/use-doc-search.ts +7 -3
- package/src/components/shared/legal-document/legal-document-page.tsx +2 -2
- package/src/components/shared/product-release/release-detail-page.tsx +6 -4
- package/src/components/ui/button/split-button.tsx +5 -2
- package/src/components/ui/index.ts +2 -0
- package/src/components/ui/release-changelog-section.tsx +7 -2
- package/src/components/ui/rich-markdown-renderer.tsx +1203 -0
- package/src/components/ui/simple-markdown-renderer.tsx +7 -11
- package/src/contexts/chat-runtime-context.tsx +14 -0
- package/src/stories/NotificationDrawer.stories.tsx +2 -0
- package/src/types/doc-source.ts +33 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/page-header-constants.ts +15 -0
- package/src/utils/social-embed-cache.ts +391 -0
- package/dist/chunk-26PKDALD.js +0 -2379
- package/dist/chunk-26PKDALD.js.map +0 -1
- package/dist/chunk-3MCHAFHB.js +0 -89
- package/dist/chunk-3MCHAFHB.js.map +0 -1
- package/dist/chunk-3XIB4VKS.cjs +0 -619
- package/dist/chunk-3XIB4VKS.cjs.map +0 -1
- package/dist/chunk-4W7NYJ3B.cjs +0 -3009
- package/dist/chunk-4W7NYJ3B.cjs.map +0 -1
- package/dist/chunk-5E2HOSSH.cjs.map +0 -1
- package/dist/chunk-5IJ46KAV.js.map +0 -1
- package/dist/chunk-5O6N3BKR.cjs.map +0 -1
- package/dist/chunk-6BZEAPNT.js.map +0 -1
- package/dist/chunk-6IBA2MQV.cjs.map +0 -1
- package/dist/chunk-6JINAOI7.cjs +0 -311
- package/dist/chunk-6JINAOI7.cjs.map +0 -1
- package/dist/chunk-7RIYT7ZH.js.map +0 -1
- package/dist/chunk-A2YL7QRX.cjs.map +0 -1
- package/dist/chunk-AQOWFSMB.cjs.map +0 -1
- package/dist/chunk-E4XABBSU.js.map +0 -1
- package/dist/chunk-ETACGX2A.cjs.map +0 -1
- package/dist/chunk-EYEW6PTA.cjs.map +0 -1
- package/dist/chunk-FQJK446R.js +0 -1606
- package/dist/chunk-FQJK446R.js.map +0 -1
- package/dist/chunk-FT4FCV7L.cjs.map +0 -1
- package/dist/chunk-INDQMNP6.cjs.map +0 -1
- package/dist/chunk-J54Z3OCR.cjs +0 -1606
- package/dist/chunk-J54Z3OCR.cjs.map +0 -1
- package/dist/chunk-KXCRGTRN.cjs +0 -2379
- package/dist/chunk-KXCRGTRN.cjs.map +0 -1
- package/dist/chunk-LCNMR277.js.map +0 -1
- package/dist/chunk-LFGGF7OT.cjs +0 -449
- package/dist/chunk-LFGGF7OT.cjs.map +0 -1
- package/dist/chunk-M2OCXTNT.js +0 -311
- package/dist/chunk-M2OCXTNT.js.map +0 -1
- package/dist/chunk-NSPOYUBH.js +0 -3009
- package/dist/chunk-NSPOYUBH.js.map +0 -1
- package/dist/chunk-OOKKGOPQ.js.map +0 -1
- package/dist/chunk-OQ6X7ZOC.js +0 -449
- package/dist/chunk-OQ6X7ZOC.js.map +0 -1
- package/dist/chunk-POKKCWKF.js +0 -354
- package/dist/chunk-POKKCWKF.js.map +0 -1
- package/dist/chunk-TFSYSWPS.cjs +0 -89
- package/dist/chunk-TFSYSWPS.cjs.map +0 -1
- package/dist/chunk-XXI7BNB6.cjs.map +0 -1
- package/dist/chunk-YD43AKI5.js +0 -619
- package/dist/chunk-YD43AKI5.js.map +0 -1
- package/dist/chunk-YETA25JW.cjs +0 -354
- package/dist/chunk-YETA25JW.cjs.map +0 -1
- package/dist/chunk-YIGPRLQY.cjs.map +0 -1
- /package/dist/{chunk-3ZXUQQL4.js.map → chunk-PI4WSYQV.js.map} +0 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { useRouter } from '../../embed-shims/next-navigation'
|
|
5
|
+
import { PageShell } from './article-detail-layout'
|
|
6
|
+
import { PageLayout } from './page-layout'
|
|
7
|
+
import { PageHeader, type PageHeaderProps } from './page-header'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* `<PageWithHeader>` — the canonical 4-layer unified-chrome wrapper that
|
|
11
|
+
* every public lib/hub page now uses (Knowledge Hub, Roadmap, FAQs,
|
|
12
|
+
* Authors, Blog, Vendors, Case Studies, Interviews, Investor Updates,
|
|
13
|
+
* /webinars-/podcasts-/events, hub admin-but-public pages, …).
|
|
14
|
+
*
|
|
15
|
+
* Renders the same JSX tree every consumer was hand-rolling individually
|
|
16
|
+
* before this helper landed:
|
|
17
|
+
*
|
|
18
|
+
* PageShell ← bg-ods-bg, min-h-screen, max-w-[1920px],
|
|
19
|
+
* page-shell-px/pt/pb gutters
|
|
20
|
+
* PageLayout backButton ← TitleBlock → PageHeader #1 (back-btn row
|
|
21
|
+
* only, pt-l + mb-l)
|
|
22
|
+
* div.w-full.flex-col.gap-10 ← matches DevSectionView's hero container
|
|
23
|
+
* PageHeader title/subtitle ← PageHeader #2 (noTopPadding +
|
|
24
|
+
* titleIcon accentDot noBottomMargin so PageLayout's gap-l owns
|
|
25
|
+
* noTopPadding the spacing between #1 and #2)
|
|
26
|
+
* noBottomMargin
|
|
27
|
+
* children ← page-specific body (search, lists, forms)
|
|
28
|
+
*
|
|
29
|
+
* Why this exists: 15+ pages copy-pasted the EXACT same nesting + the
|
|
30
|
+
* EXACT same `noTopPadding + noBottomMargin + accentDot` triplet on the
|
|
31
|
+
* inner `<PageHeader>`. Forgetting one of those flags collapsed the gap
|
|
32
|
+
* to ~8px (the FAQs-vs-Onboarding-Guides bug). Centralizing the chain
|
|
33
|
+
* here makes the spacing invariant compiler-enforced — consumers can't
|
|
34
|
+
* pick the wrong combination.
|
|
35
|
+
*
|
|
36
|
+
* **Back button is config-driven by default.** Consumers don't have to
|
|
37
|
+
* thread `useRouter()` + `() => router.push('/')` themselves anymore —
|
|
38
|
+
* the helper supplies a sane default (`{ label: 'Back to home', href: '/' }`).
|
|
39
|
+
* Hosts whose `/` lives elsewhere should pass their own `href`. Pass
|
|
40
|
+
* `backButton={false}` to suppress entirely (the lib's own
|
|
41
|
+
* `<DocsHubPage>` does this on the platform-home docs landing).
|
|
42
|
+
*/
|
|
43
|
+
export interface PageWithHeaderProps {
|
|
44
|
+
/** Title — passed straight to inner `<PageHeader>`. */
|
|
45
|
+
title?: string
|
|
46
|
+
/** Inline icon rendered before the title (lucide / SVG node). Wrap with
|
|
47
|
+
* `SECTION_HERO_ICON_CLASS` at the call site, or use the lib's
|
|
48
|
+
* `<PageHeader>`'s `titleIcon` ReactNode signature directly. */
|
|
49
|
+
titleIcon?: PageHeaderProps['titleIcon']
|
|
50
|
+
/** Subtitle (1-2 lines, auto-clamped to 2 + min-h-[56px]). */
|
|
51
|
+
subtitle?: string
|
|
52
|
+
/** Render yellow accent dot after the title (default true — matches every
|
|
53
|
+
* unified surface). Pass `false` to opt out. */
|
|
54
|
+
accentDot?: boolean
|
|
55
|
+
/** Back-button config. Defaults to `{ label: 'Back to home', href: '/' }`.
|
|
56
|
+
* Pass `false` to hide entirely (platform-home docs landings). */
|
|
57
|
+
backButton?: { label?: string; href?: string } | false
|
|
58
|
+
/** Optional image (entity-image-style — onboarding guides etc.). */
|
|
59
|
+
image?: PageHeaderProps['image']
|
|
60
|
+
/** Optional actions slot (right side of header). */
|
|
61
|
+
actions?: React.ReactNode
|
|
62
|
+
/** Page body — search bars, lists, forms, sections. Rendered INSIDE the
|
|
63
|
+
* gap-10 flex column so it shares gutters + vertical rhythm with the
|
|
64
|
+
* header. */
|
|
65
|
+
children: React.ReactNode
|
|
66
|
+
/** Extra class applied to the gap-10 content wrapper. */
|
|
67
|
+
contentClassName?: string
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function PageWithHeader({
|
|
71
|
+
title,
|
|
72
|
+
titleIcon,
|
|
73
|
+
subtitle,
|
|
74
|
+
accentDot = true,
|
|
75
|
+
backButton,
|
|
76
|
+
image,
|
|
77
|
+
actions,
|
|
78
|
+
children,
|
|
79
|
+
contentClassName,
|
|
80
|
+
}: PageWithHeaderProps) {
|
|
81
|
+
const router = useRouter()
|
|
82
|
+
|
|
83
|
+
const backCfg =
|
|
84
|
+
backButton === false
|
|
85
|
+
? undefined
|
|
86
|
+
: {
|
|
87
|
+
label: backButton?.label ?? 'Back to home',
|
|
88
|
+
onClick: () => router.push(backButton?.href ?? '/'),
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<PageShell>
|
|
93
|
+
<PageLayout backButton={backCfg}>
|
|
94
|
+
<div className={`w-full flex flex-col gap-10${contentClassName ? ` ${contentClassName}` : ''}`}>
|
|
95
|
+
<PageHeader
|
|
96
|
+
title={title}
|
|
97
|
+
titleIcon={titleIcon}
|
|
98
|
+
subtitle={subtitle}
|
|
99
|
+
accentDot={accentDot}
|
|
100
|
+
image={image}
|
|
101
|
+
actions={actions}
|
|
102
|
+
noTopPadding
|
|
103
|
+
noBottomMargin
|
|
104
|
+
/>
|
|
105
|
+
{children}
|
|
106
|
+
</div>
|
|
107
|
+
</PageLayout>
|
|
108
|
+
</PageShell>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import React from 'react'
|
|
4
|
-
import { cn } from '../../utils/cn'
|
|
5
4
|
import type { ActionsMenuGroup } from '../ui/actions-menu'
|
|
6
|
-
import { EntityImage } from '../ui/entity-image'
|
|
7
5
|
import { PageActions, type PageActionButton } from '../ui/page-actions'
|
|
8
|
-
import {
|
|
6
|
+
import { PageHeader } from './page-header'
|
|
9
7
|
|
|
8
|
+
/**
|
|
9
|
+
* `<TitleBlock>` — thin adapter over `<PageHeader>` that turns the
|
|
10
|
+
* `actions: PageActionButton[]` / `menuActions` / `selector` API into
|
|
11
|
+
* a `ReactNode` slot that PageHeader can render. Kept as a separate
|
|
12
|
+
* component for backwards compatibility (`PageLayout` consumes it,
|
|
13
|
+
* external callers may too) — all the DOM/CSS lives in PageHeader.
|
|
14
|
+
*
|
|
15
|
+
* If a new consumer doesn't need the `PageActions` wiring, prefer
|
|
16
|
+
* `<PageHeader>` directly.
|
|
17
|
+
*/
|
|
10
18
|
export interface TitleBlockProps {
|
|
11
19
|
title?: string
|
|
12
20
|
subtitle?: string
|
|
21
|
+
/** Inline icon rendered before the title text (e.g. HelpCircle on /faqs,
|
|
22
|
+
* BookOpen on /knowledge-base, Map on /roadmap). Forwarded verbatim to
|
|
23
|
+
* `<PageHeader>`. */
|
|
24
|
+
titleIcon?: React.ReactNode
|
|
25
|
+
/** Yellow accent dot after the title — same flag as PageHeader. */
|
|
26
|
+
accentDot?: boolean
|
|
13
27
|
image?: { src: string; alt?: string }
|
|
14
28
|
backButton?: { label?: string; onClick: () => void }
|
|
15
29
|
actions?: PageActionButton[]
|
|
@@ -29,6 +43,8 @@ export interface TitleBlockProps {
|
|
|
29
43
|
export function TitleBlock({
|
|
30
44
|
title,
|
|
31
45
|
subtitle,
|
|
46
|
+
titleIcon,
|
|
47
|
+
accentDot,
|
|
32
48
|
image,
|
|
33
49
|
backButton,
|
|
34
50
|
actions,
|
|
@@ -40,67 +56,29 @@ export function TitleBlock({
|
|
|
40
56
|
}: TitleBlockProps) {
|
|
41
57
|
const hasActions = actions && actions.length > 0
|
|
42
58
|
const hasMenuActions = !!menuActions && menuActions.some(g => g.items.length > 0)
|
|
59
|
+
const hasActionsSlot = hasActions || hasMenuActions || !!selector
|
|
43
60
|
|
|
44
|
-
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
'bg-ods-card border-b border-ods-border',
|
|
53
|
-
'px-[var(--spacing-system-l)] pb-[var(--spacing-system-l)]',
|
|
54
|
-
'md:bg-transparent md:border-b-0',
|
|
55
|
-
'md:px-0 md:pb-0',
|
|
56
|
-
'md:mb-[var(--spacing-system-l)]',
|
|
57
|
-
)
|
|
58
|
-
: 'mb-[var(--spacing-system-l)]',
|
|
59
|
-
className,
|
|
60
|
-
)}
|
|
61
|
-
>
|
|
62
|
-
<div className="flex flex-col gap-[var(--spacing-system-xs)] flex-1 min-w-0">
|
|
63
|
-
{backButton && (
|
|
64
|
-
<BackButton
|
|
65
|
-
onClick={backButton.onClick}
|
|
66
|
-
label={backButton.label}
|
|
67
|
-
className="hidden md:inline-flex"
|
|
68
|
-
/>
|
|
69
|
-
)}
|
|
70
|
-
{(image || subtitle) ? (
|
|
71
|
-
<div className="flex items-center gap-[var(--spacing-system-m)] min-w-0 w-full">
|
|
72
|
-
{image && (
|
|
73
|
-
<EntityImage
|
|
74
|
-
src={image.src}
|
|
75
|
-
alt={image.alt}
|
|
76
|
-
fallbackText={image.alt || title}
|
|
77
|
-
/>
|
|
78
|
-
)}
|
|
79
|
-
<div className="flex flex-col justify-center min-w-0 flex-1">
|
|
80
|
-
{title && (
|
|
81
|
-
<h1 className="text-h2 text-ods-text-primary truncate" title={title}>{title}</h1>
|
|
82
|
-
)}
|
|
83
|
-
{subtitle && (
|
|
84
|
-
<p className="text-h6 text-ods-text-secondary truncate" title={subtitle}>{subtitle}</p>
|
|
85
|
-
)}
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
88
|
-
) : (
|
|
89
|
-
title && <h1 className="text-h2 text-ods-text-primary">{title}</h1>
|
|
90
|
-
)}
|
|
91
|
-
</div>
|
|
61
|
+
const actionsNode = hasActionsSlot ? (
|
|
62
|
+
<PageActions
|
|
63
|
+
variant={actionsVariant}
|
|
64
|
+
actions={actions ?? []}
|
|
65
|
+
menuActions={menuActions}
|
|
66
|
+
selector={selector}
|
|
67
|
+
/>
|
|
68
|
+
) : undefined
|
|
92
69
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
70
|
+
return (
|
|
71
|
+
<PageHeader
|
|
72
|
+
title={title}
|
|
73
|
+
titleIcon={titleIcon}
|
|
74
|
+
subtitle={subtitle}
|
|
75
|
+
accentDot={accentDot}
|
|
76
|
+
image={image}
|
|
77
|
+
backButton={backButton}
|
|
78
|
+
actions={actionsNode}
|
|
79
|
+
variant={variant}
|
|
80
|
+
className={className}
|
|
81
|
+
/>
|
|
104
82
|
)
|
|
105
83
|
}
|
|
106
84
|
|
|
@@ -29,7 +29,7 @@ import { EntityVideoSection } from '../features/entity-video-section'
|
|
|
29
29
|
import { VideoBitesDisplay } from '../features/video-bites-display'
|
|
30
30
|
import { useVideoWarmup } from '../features/use-video-warmup'
|
|
31
31
|
import { getCaptionsUrl } from '../features/captions-url'
|
|
32
|
-
import {
|
|
32
|
+
import { RichMarkdownRenderer } from '../ui/rich-markdown-renderer'
|
|
33
33
|
import { EntityTagBadges } from '../features/entity-tag-badges'
|
|
34
34
|
import { LoadError } from '../ui/error-state'
|
|
35
35
|
import { ArticleAuthorByline } from '../shared/article-author-byline'
|
|
@@ -62,7 +62,7 @@ export interface OnboardingGuideDetailViewProps {
|
|
|
62
62
|
* byline renders nothing below the name when the bio is empty. */
|
|
63
63
|
fallbackBio?: string | null
|
|
64
64
|
/** Optional markdown renderer override. Defaults to lib
|
|
65
|
-
* `<
|
|
65
|
+
* `<RichMarkdownRenderer>`. */
|
|
66
66
|
MarkdownRenderer?: ComponentType<{ content: string }>
|
|
67
67
|
/** Optional per-row related-card renderer override. */
|
|
68
68
|
renderRelatedCard?: (guide: OnboardingGuide) => ReactNode
|
|
@@ -83,7 +83,7 @@ export function OnboardingGuideDetailView({
|
|
|
83
83
|
slug,
|
|
84
84
|
guideEndpoint,
|
|
85
85
|
related = [],
|
|
86
|
-
MarkdownRenderer =
|
|
86
|
+
MarkdownRenderer = RichMarkdownRenderer,
|
|
87
87
|
renderRelatedCard,
|
|
88
88
|
backHref,
|
|
89
89
|
backLabel = 'Back to Getting Started',
|
|
@@ -25,7 +25,15 @@ import {
|
|
|
25
25
|
type OpenframeDevSectionKey,
|
|
26
26
|
} from '../../../utils/dev-sections/openframe-dev-sections';
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
/** Re-export the constant so existing dev-section call sites keep their
|
|
29
|
+
* old import path. The canonical home is `src/utils/page-header-constants.ts`
|
|
30
|
+
* (NOT a `'use client'` module) so server modules can import it without
|
|
31
|
+
* Next.js turning it into a client reference proxy — that proxy is what
|
|
32
|
+
* blew up lucide's `mergeClasses().trim()` when used as
|
|
33
|
+
* `<Icon className={SECTION_HERO_ICON_CLASS} />` inside a hub
|
|
34
|
+
* server-component preset. */
|
|
35
|
+
import { SECTION_HERO_ICON_CLASS } from '../../../utils/page-header-constants';
|
|
36
|
+
export { SECTION_HERO_ICON_CLASS };
|
|
29
37
|
|
|
30
38
|
export interface DevSectionPageProps {
|
|
31
39
|
sectionKey: OpenframeDevSectionKey;
|
|
@@ -19,6 +19,7 @@ import { useState, useEffect } from 'react';
|
|
|
19
19
|
import { useRouter, useSearchParams, usePathname } from '../../../embed-shims';
|
|
20
20
|
import { SearchInput } from '../../ui';
|
|
21
21
|
import { StatusFilterComponent } from '../../features';
|
|
22
|
+
import { PageHeader } from '../../layout/page-header';
|
|
22
23
|
import {
|
|
23
24
|
OPENFRAME_DEV_SECTIONS,
|
|
24
25
|
type OpenframeDevSectionKey,
|
|
@@ -95,15 +96,19 @@ export function DevSectionView({ sectionKey, hero, preControls, children }: DevS
|
|
|
95
96
|
return (
|
|
96
97
|
<div className="w-full flex flex-col gap-10">
|
|
97
98
|
{hero ? (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
// Render through the shared `<PageHeader>` primitive so the dev-
|
|
100
|
+
// section hero (Releases, Roadmap, Onboarding catalog) and the
|
|
101
|
+
// docs-hub hero (Knowledge Hub, Data Room) are LITERALLY the same
|
|
102
|
+
// component rendering the same DOM/CSS. `noBottomMargin` because
|
|
103
|
+
// the parent `gap-10` already supplies the spacing to the next
|
|
104
|
+
// sibling (preControls / search / filter).
|
|
105
|
+
<PageHeader
|
|
106
|
+
title={hero.title ?? section.hero.title}
|
|
107
|
+
titleIcon={hero.icon}
|
|
108
|
+
subtitle={hero.description}
|
|
109
|
+
noBottomMargin
|
|
110
|
+
noTopPadding
|
|
111
|
+
/>
|
|
107
112
|
) : (
|
|
108
113
|
<div className="flex items-center justify-between w-full">
|
|
109
114
|
<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]">
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { DevSectionView, type DevSectionViewProps } from './dev-section-view';
|
|
2
|
-
export { DevSectionPage, type DevSectionPageProps } from './dev-section-page';
|
|
2
|
+
export { DevSectionPage, type DevSectionPageProps, SECTION_HERO_ICON_CLASS } from './dev-section-page';
|
|
3
3
|
export {
|
|
4
4
|
DevCardRowContent,
|
|
5
5
|
DevCardRowSkeleton,
|
|
@@ -80,7 +80,7 @@ export function useDocSearch(config: UseDocSearchConfig) {
|
|
|
80
80
|
onNavigate,
|
|
81
81
|
tableIds,
|
|
82
82
|
onInPageSwap,
|
|
83
|
-
searchEndpoint
|
|
83
|
+
searchEndpoint,
|
|
84
84
|
} = config
|
|
85
85
|
const tableIdsKey = tableIds && tableIds.length > 0 ? tableIds.join(',') : ''
|
|
86
86
|
|
|
@@ -88,7 +88,11 @@ export function useDocSearch(config: UseDocSearchConfig) {
|
|
|
88
88
|
// Optional chat-runtime read — when present and mode='embed' the
|
|
89
89
|
// search-result row click short-circuits to a new-tab open against
|
|
90
90
|
// the absolutized URL. Null/host preserves today's behavior.
|
|
91
|
+
// Also used as the proxy-prefix fallback for `searchEndpoint`, matching
|
|
92
|
+
// how tickets resolves `findTicketUrl`.
|
|
91
93
|
const runtime = useChatRuntime()
|
|
94
|
+
const resolvedSearchEndpoint =
|
|
95
|
+
searchEndpoint ?? runtime?.endpoints.docsSearchUrl ?? '/api/docs/search'
|
|
92
96
|
|
|
93
97
|
const [query, setQuery] = useState('')
|
|
94
98
|
const [results, setResults] = useState<SearchResult[]>([])
|
|
@@ -114,7 +118,7 @@ export function useDocSearch(config: UseDocSearchConfig) {
|
|
|
114
118
|
})
|
|
115
119
|
if (tableIdsKey) params.set('tableIds', tableIdsKey)
|
|
116
120
|
|
|
117
|
-
const response = await fetch(`${
|
|
121
|
+
const response = await fetch(`${resolvedSearchEndpoint}?${params.toString()}`)
|
|
118
122
|
if (!response.ok) {
|
|
119
123
|
throw new Error(`Search request failed: ${response.status}`)
|
|
120
124
|
}
|
|
@@ -142,7 +146,7 @@ export function useDocSearch(config: UseDocSearchConfig) {
|
|
|
142
146
|
return () => {
|
|
143
147
|
cancelled = true
|
|
144
148
|
}
|
|
145
|
-
}, [debouncedQuery, source, tableIdsKey,
|
|
149
|
+
}, [debouncedQuery, source, tableIdsKey, resolvedSearchEndpoint])
|
|
146
150
|
|
|
147
151
|
// Derived loading state — single source of truth for "should the
|
|
148
152
|
// dropdown show 'Loading...' instead of 'No results found'":
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
import type { ComponentType } from 'react';
|
|
21
21
|
import { PageShell, PageLayout, PageHeading } from '../../ui';
|
|
22
|
-
import {
|
|
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';
|
|
25
25
|
import { formatLegalDate } from '../../../utils/format';
|
|
@@ -76,7 +76,7 @@ export function LegalDocumentPage({
|
|
|
76
76
|
initialData = null,
|
|
77
77
|
initialLastUpdatedLabel = null,
|
|
78
78
|
apiEndpoint,
|
|
79
|
-
MarkdownRenderer =
|
|
79
|
+
MarkdownRenderer = RichMarkdownRenderer,
|
|
80
80
|
backButton,
|
|
81
81
|
}: LegalDocumentPageProps) {
|
|
82
82
|
const router = useRouter();
|
|
@@ -10,6 +10,7 @@ import { Card, CardContent } from '../../ui/card';
|
|
|
10
10
|
import { PageShell } from '../../layout/article-detail-layout';
|
|
11
11
|
import { PageLayout } from '../../layout/page-layout';
|
|
12
12
|
import { ReleaseChangelogSection } from '../../ui/release-changelog-section';
|
|
13
|
+
import { RichMarkdownRenderer } from '../../ui/rich-markdown-renderer';
|
|
13
14
|
import { EntityTagBadges } from '../../features/entity-tag-badges';
|
|
14
15
|
import { EntityMetadataAuthorCell } from '../../chat/entity-cards/entity-author-card';
|
|
15
16
|
import type { EntityAuthor } from '../../../types/entity-author';
|
|
@@ -109,10 +110,11 @@ export interface ReleaseDetailPageProps {
|
|
|
109
110
|
authorHref?: string;
|
|
110
111
|
}
|
|
111
112
|
|
|
112
|
-
// Default
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
// Default renderer = the lib's `RichMarkdownRenderer` so out-of-the-box
|
|
114
|
+
// release pages get full rich-link previews, embedded media, social cards,
|
|
115
|
+
// etc. Hosts that want a different rendering (or a Supabase-aware preset)
|
|
116
|
+
// override via the `MarkdownRenderer` prop.
|
|
117
|
+
const DefaultMarkdownRenderer = RichMarkdownRenderer;
|
|
116
118
|
|
|
117
119
|
export function ReleaseDetailPage({
|
|
118
120
|
authorHref,
|
|
@@ -106,13 +106,15 @@ interface HalfOptions {
|
|
|
106
106
|
prefetch?: boolean
|
|
107
107
|
onClick?: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>
|
|
108
108
|
disabled?: boolean
|
|
109
|
+
/** Stretch this half to fill the group's free space (the icon half stays fixed-width). */
|
|
110
|
+
grow?: boolean
|
|
109
111
|
type?: "button" | "submit" | "reset"
|
|
110
112
|
ariaLabel?: string
|
|
111
113
|
children: React.ReactNode
|
|
112
114
|
}
|
|
113
115
|
|
|
114
|
-
function Half({ variant, size, side, href, openInNewTab, prefetch, onClick, disabled, type = "button", ariaLabel, children }: HalfOptions) {
|
|
115
|
-
const classes = splitHalfVariants({ variant, size, side })
|
|
116
|
+
function Half({ variant, size, side, href, openInNewTab, prefetch, onClick, disabled, grow, type = "button", ariaLabel, children }: HalfOptions) {
|
|
117
|
+
const classes = cn(splitHalfVariants({ variant, size, side }), grow && "flex-1")
|
|
116
118
|
|
|
117
119
|
if (href) {
|
|
118
120
|
return (
|
|
@@ -183,6 +185,7 @@ const SplitButton = React.forwardRef<HTMLDivElement, SplitButtonProps>(function
|
|
|
183
185
|
prefetch={prefetch}
|
|
184
186
|
onClick={onClick}
|
|
185
187
|
disabled={disabled || mainDisabled}
|
|
188
|
+
grow={fullWidth}
|
|
186
189
|
type={type}
|
|
187
190
|
ariaLabel={ariaLabel}
|
|
188
191
|
>
|
|
@@ -61,6 +61,7 @@ export * from './hover-dropdown'
|
|
|
61
61
|
export * from '../chat'
|
|
62
62
|
export * from '../layout/list-page-layout'
|
|
63
63
|
export * from '../layout/page-container'
|
|
64
|
+
export * from '../layout/page-header'
|
|
64
65
|
export * from '../layout/page-heading'
|
|
65
66
|
export * from '../layout/page-layout'
|
|
66
67
|
export * from '../layout/article-detail-layout'
|
|
@@ -160,5 +161,6 @@ export * from './ticket-attachments-list'
|
|
|
160
161
|
export * from './ticket-note-card'
|
|
161
162
|
export * from './ticket-notes-section'
|
|
162
163
|
export * from './simple-markdown-renderer'
|
|
164
|
+
export { RichMarkdownRenderer, type RichMarkdownRendererProps } from './rich-markdown-renderer'
|
|
163
165
|
export * from './filter-pill-row'
|
|
164
166
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import React, { useState, useRef, useEffect } from 'react';
|
|
4
4
|
import { Badge } from './badge';
|
|
5
5
|
import { ChevronDown } from 'lucide-react';
|
|
6
|
+
import { RichMarkdownRenderer } from './rich-markdown-renderer';
|
|
6
7
|
import type { ChangelogEntry } from '../../types/product-release';
|
|
7
8
|
|
|
8
9
|
interface ReleaseChangelogSectionProps {
|
|
@@ -31,7 +32,11 @@ interface ReleaseChangelogSectionProps {
|
|
|
31
32
|
* visual taxonomy across catalog and detail. Inherits the title's color
|
|
32
33
|
* (secondary for normal sections, red for breaking). */
|
|
33
34
|
icon?: React.ReactNode;
|
|
34
|
-
|
|
35
|
+
/** Markdown renderer for each entry's description. Optional — defaults to
|
|
36
|
+
* the lib's `RichMarkdownRenderer` so changelog rich-link previews
|
|
37
|
+
* (YouTube, OG cards, etc.) work out of the box. Hosts that already
|
|
38
|
+
* wrap with a Supabase-aware preset can keep passing their own. */
|
|
39
|
+
SimpleMarkdownRenderer?: React.ComponentType<{ content: string }>;
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
// Collapsed height for the preview-first mode. ~120px shows the first
|
|
@@ -47,7 +52,7 @@ export function ReleaseChangelogSection({
|
|
|
47
52
|
defaultCollapsed = true,
|
|
48
53
|
previewFirst = false,
|
|
49
54
|
icon,
|
|
50
|
-
SimpleMarkdownRenderer
|
|
55
|
+
SimpleMarkdownRenderer = RichMarkdownRenderer,
|
|
51
56
|
}: ReleaseChangelogSectionProps) {
|
|
52
57
|
const [collapsed, setCollapsed] = useState(collapsible ? defaultCollapsed : false);
|
|
53
58
|
const [previewExpanded, setPreviewExpanded] = useState(false);
|