@flamingo-stack/openframe-frontend-core 0.0.257 → 0.0.258
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-IJHORDN5.js → chunk-ACJPRIZC.js} +1 -1
- package/dist/{chunk-IJHORDN5.js.map → chunk-ACJPRIZC.js.map} +1 -1
- package/dist/{chunk-4MXBBBHB.cjs → chunk-KQQDN2WK.cjs} +1 -1
- package/dist/{chunk-4MXBBBHB.cjs.map → chunk-KQQDN2WK.cjs.map} +1 -1
- package/dist/components/authors/author-detail-view.d.ts +34 -0
- package/dist/components/authors/author-detail-view.d.ts.map +1 -0
- package/dist/components/index.cjs +58 -4
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +55 -1
- package/dist/components/index.js.map +1 -1
- package/dist/components/onboarding-guides/index.cjs +5 -5
- package/dist/components/onboarding-guides/index.js +1 -1
- package/dist/components/shared/article-author-byline.d.ts +3 -4
- package/dist/components/shared/article-author-byline.d.ts.map +1 -1
- package/dist/types/entity-author.d.ts +25 -0
- package/dist/types/entity-author.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/authors/author-detail-view.tsx +130 -0
- package/src/components/index.ts +7 -2
- package/src/components/shared/article-author-byline.tsx +3 -4
- package/src/types/entity-author.ts +27 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
var
|
|
7
|
+
var _chunkKQQDN2WKcjs = require('../../chunk-KQQDN2WK.cjs');
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
var _chunkT7AJBKZPcjs = require('../../chunk-T7AJBKZP.cjs');
|
|
@@ -140,7 +140,7 @@ function OnboardingGuidesCatalogView({
|
|
|
140
140
|
});
|
|
141
141
|
};
|
|
142
142
|
const source = _nullishCoalesce(_optionalChain([runtime, 'optionalAccess', _4 => _4.source]), () => ( "openframe"));
|
|
143
|
-
const docSearch =
|
|
143
|
+
const docSearch = _chunkKQQDN2WKcjs.useDocSearch.call(void 0, {
|
|
144
144
|
source,
|
|
145
145
|
baseRoute: basePath,
|
|
146
146
|
onNavigate: (path) => router.push(path),
|
|
@@ -166,7 +166,7 @@ function OnboardingGuidesCatalogView({
|
|
|
166
166
|
const renderCardFn = _nullishCoalesce(renderCard, () => ( defaultRenderCard));
|
|
167
167
|
const preControls = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-4", children: [
|
|
168
168
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
169
|
-
|
|
169
|
+
_chunkKQQDN2WKcjs.DocSearchBar,
|
|
170
170
|
{
|
|
171
171
|
placeholder: "Search onboarding guides, releases, case studies\u2026",
|
|
172
172
|
query: docSearch.query,
|
|
@@ -238,7 +238,7 @@ function OnboardingGuideDetailView({
|
|
|
238
238
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEB76VWM4cjs.LoadError, { message: "Guide not found.", onRetry: reload });
|
|
239
239
|
}
|
|
240
240
|
if (!guide) {
|
|
241
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
241
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkKQQDN2WKcjs.DetailPageSkeleton, { showImageGallery: false });
|
|
242
242
|
}
|
|
243
243
|
const captionsUrl = _chunkEB76VWM4cjs.getCaptionsUrl.call(void 0, "onboarding_guide", guide.id, guide.srt_content);
|
|
244
244
|
const videoPoster = guide.main_video_thumbnail || guide.featured_image || guide.og_image_url || _optionalChain([runtime, 'optionalAccess', _9 => _9.resolvePlaceholderUrl, 'optionalCall', _10 => _10(guide.title, { aspect: "wide" })]) || void 0;
|
|
@@ -307,7 +307,7 @@ function OnboardingGuideDetailView({
|
|
|
307
307
|
}
|
|
308
308
|
),
|
|
309
309
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
310
|
-
|
|
310
|
+
_chunkKQQDN2WKcjs.ArticleAuthorByline,
|
|
311
311
|
{
|
|
312
312
|
author: _nullishCoalesce(_optionalChain([guide, 'access', _12 => _12.author, 'optionalAccess', _13 => _13.full_name]), () => ( null)),
|
|
313
313
|
avatar: _optionalChain([guide, 'access', _14 => _14.author, 'optionalAccess', _15 => _15.avatar_url]),
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
* Shared "author byline" card used by article-shaped detail pages
|
|
3
3
|
* (blog post, product release, onboarding guide, investor update).
|
|
4
4
|
*
|
|
5
|
-
* MOVED from the hub
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* from `getAppConfig()`).
|
|
5
|
+
* MOVED from the hub so any consuming app can embed it; hub call sites
|
|
6
|
+
* import it directly and pass their platform-aware copy explicitly
|
|
7
|
+
* (`fallbackBio={defaultAuthorFallbackBio()}` from the hub's app-config).
|
|
9
8
|
*
|
|
10
9
|
* Embed-readiness contract:
|
|
11
10
|
* - `Link` / `Image` render through the embed-shims (plain `<a>` / `<img>`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"article-author-byline.d.ts","sourceRoot":"","sources":["../../../src/components/shared/article-author-byline.tsx"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"article-author-byline.d.ts","sourceRoot":"","sources":["../../../src/components/shared/article-author-byline.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;IAClC,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,+DAA+D;IAC/D,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;IAClB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IACvC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAiBD,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,MAAM,EACN,GAAG,EACH,QAAQ,EACR,WAAW,EACX,IAAI,EACJ,WAAW,EACX,IAAW,EACX,aAAa,EACb,SAAS,GACV,EAAE,wBAAwB,4BA4F1B"}
|
|
@@ -18,4 +18,29 @@ export interface EntityAuthor {
|
|
|
18
18
|
/** Present only on server/admin payloads — public DALs strip it. */
|
|
19
19
|
email?: string | null;
|
|
20
20
|
}
|
|
21
|
+
/** One curated social link on an author profile (host junction:
|
|
22
|
+
* `profile_social_links` ordered by display_order in the hub). */
|
|
23
|
+
export interface AuthorSocialLink {
|
|
24
|
+
/** Platform key fed to `SocialIconRow` (e.g. 'linkedin', 'x'). */
|
|
25
|
+
platform: string;
|
|
26
|
+
url: string;
|
|
27
|
+
username?: string | null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Public author-page view model — what `<AuthorDetailView>` renders. The
|
|
31
|
+
* hub's `PublicAuthor` (authors DAL) extends this with server-side extras
|
|
32
|
+
* (`updatedAt`); embedders construct it from whatever directory they have.
|
|
33
|
+
*/
|
|
34
|
+
export interface AuthorProfile {
|
|
35
|
+
id: string;
|
|
36
|
+
slug: string;
|
|
37
|
+
fullName: string;
|
|
38
|
+
avatarUrl: string | null;
|
|
39
|
+
about: string | null;
|
|
40
|
+
jobTitle: string | null;
|
|
41
|
+
company: string | null;
|
|
42
|
+
knowsAbout: string[];
|
|
43
|
+
/** Ordered by display_order. */
|
|
44
|
+
socialLinks: AuthorSocialLink[];
|
|
45
|
+
}
|
|
21
46
|
//# sourceMappingURL=entity-author.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-author.d.ts","sourceRoot":"","sources":["../../src/types/entity-author.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB;2EACuE;IACvE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB;8EAC0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB"}
|
|
1
|
+
{"version":3,"file":"entity-author.d.ts","sourceRoot":"","sources":["../../src/types/entity-author.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB;2EACuE;IACvE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB;8EAC0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED;mEACmE;AACnE,MAAM,WAAW,gBAAgB;IAC/B,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,gCAAgC;IAChC,WAAW,EAAE,gBAAgB,EAAE,CAAA;CAChC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Author detail-page body — identity header (avatar → name → job title →
|
|
5
|
+
* socials), bio, expertise badges, and a `children` slot for the authored-
|
|
6
|
+
* content rail. THE one implementation behind the hub's `/authors/[slug]`
|
|
7
|
+
* page AND embedded author pages (react-embedding-example) — hosts fetch
|
|
8
|
+
* the `AuthorProfile` however they like and drill it in.
|
|
9
|
+
*
|
|
10
|
+
* Embed-readiness contract (same rules as ArticleAuthorByline):
|
|
11
|
+
* - `Image` renders through the embed shim (plain `<img>` in non-Next
|
|
12
|
+
* hosts; the real `next/image` once registered at app init).
|
|
13
|
+
* - Avatar proxying rides the OPTIONAL ambient `ChatRuntime`
|
|
14
|
+
* (`endpoints.imageProxyUrlPrefix`) — no provider ⇒ raw URL, never
|
|
15
|
+
* throws. `proxyImageUrl` prop wins over the runtime.
|
|
16
|
+
* - The authored-content rail is a SLOT (`children`), not a baked-in
|
|
17
|
+
* fetch: the hub passes its pre-bound `RelatedContentSection` with SSR
|
|
18
|
+
* `initialItems`; embedders pass the lib section with `apiBaseUrl`.
|
|
19
|
+
* The view stays data-in, markup-out.
|
|
20
|
+
*
|
|
21
|
+
* Heading semantics are the HOST's: the view renders the name as a styled
|
|
22
|
+
* `<p>` (like the hub profile header) so a hosting page can own its `<h1>`
|
|
23
|
+
* (the hub uses an sr-only h1 for crawlers).
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import React from 'react'
|
|
27
|
+
import Image from '../../embed-shims/next-image'
|
|
28
|
+
import { cn } from '../../utils/cn'
|
|
29
|
+
import { formatBioText } from '../../utils/format'
|
|
30
|
+
import { getProxiedImageUrl } from '../../utils/image-proxy'
|
|
31
|
+
import { useChatRuntime } from '../../contexts/chat-runtime-context'
|
|
32
|
+
import { SocialIconRow } from '../social-icon-row'
|
|
33
|
+
import { StatusBadge } from '../ui/status-badge'
|
|
34
|
+
import type { AuthorProfile } from '../../types/entity-author'
|
|
35
|
+
|
|
36
|
+
export interface AuthorDetailViewProps {
|
|
37
|
+
author: AuthorProfile
|
|
38
|
+
/** Host-injected avatar-URL mapper — wins over the ambient runtime. */
|
|
39
|
+
proxyImageUrl?: (url: string) => string
|
|
40
|
+
/** Authored-content rail (or anything else) rendered below the profile. */
|
|
41
|
+
children?: React.ReactNode
|
|
42
|
+
className?: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function AuthorDetailView({
|
|
46
|
+
author,
|
|
47
|
+
proxyImageUrl,
|
|
48
|
+
children,
|
|
49
|
+
className,
|
|
50
|
+
}: AuthorDetailViewProps) {
|
|
51
|
+
// Optional runtime — null-safe outside a provider (bare embeds render the
|
|
52
|
+
// raw avatar URL; the hub's app-wide HubRuntimeProvider supplies the proxy).
|
|
53
|
+
const runtime = useChatRuntime()
|
|
54
|
+
|
|
55
|
+
const proxiedAvatar = author.avatarUrl
|
|
56
|
+
? proxyImageUrl
|
|
57
|
+
? proxyImageUrl(author.avatarUrl)
|
|
58
|
+
: (getProxiedImageUrl(author.avatarUrl, {
|
|
59
|
+
proxyPrefix: runtime?.endpoints.imageProxyUrlPrefix,
|
|
60
|
+
skipDomains: runtime?.endpoints.imageProxySkipDomains,
|
|
61
|
+
directHttps: true,
|
|
62
|
+
}) ?? author.avatarUrl)
|
|
63
|
+
: null
|
|
64
|
+
|
|
65
|
+
const subtitle = [author.jobTitle, author.company].filter(Boolean).join(' @ ')
|
|
66
|
+
const bioText = formatBioText(author.about)
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<div className={cn('flex flex-col gap-5 md:gap-6', className)}>
|
|
70
|
+
{/* Identity header: avatar left; name → subtitle → socials stacked right. */}
|
|
71
|
+
<div className="flex gap-6 w-full items-start">
|
|
72
|
+
<div className="relative shrink-0 h-24 w-24">
|
|
73
|
+
<div className="rounded-full overflow-hidden bg-ods-bg-secondary border border-ods-border w-full h-full relative">
|
|
74
|
+
{proxiedAvatar ? (
|
|
75
|
+
<Image
|
|
76
|
+
src={proxiedAvatar}
|
|
77
|
+
alt={author.fullName}
|
|
78
|
+
fill
|
|
79
|
+
className="object-cover"
|
|
80
|
+
unoptimized
|
|
81
|
+
/>
|
|
82
|
+
) : (
|
|
83
|
+
<div className="flex items-center justify-center h-full w-full text-3xl text-ods-text-secondary font-['Azeret_Mono']">
|
|
84
|
+
{author.fullName.charAt(0).toUpperCase()}
|
|
85
|
+
</div>
|
|
86
|
+
)}
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<div className="min-w-0 flex flex-col justify-center gap-2">
|
|
91
|
+
<p className="text-h2 text-ods-text-primary leading-none truncate">
|
|
92
|
+
{author.fullName}
|
|
93
|
+
</p>
|
|
94
|
+
{subtitle && (
|
|
95
|
+
<p className="font-body text-lg text-ods-text-secondary leading-none truncate">
|
|
96
|
+
{subtitle}
|
|
97
|
+
</p>
|
|
98
|
+
)}
|
|
99
|
+
{author.socialLinks.length > 0 && (
|
|
100
|
+
// Ghost compact row (transparent 32px) — metadata, not CTAs.
|
|
101
|
+
<SocialIconRow
|
|
102
|
+
compact
|
|
103
|
+
links={author.socialLinks.map((link) => ({
|
|
104
|
+
platform: link.platform,
|
|
105
|
+
href: link.url,
|
|
106
|
+
label: `${author.fullName}'s ${link.platform}`,
|
|
107
|
+
}))}
|
|
108
|
+
/>
|
|
109
|
+
)}
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
{bioText && (
|
|
114
|
+
<p className="font-body text-base leading-relaxed text-ods-text-secondary">
|
|
115
|
+
{bioText}
|
|
116
|
+
</p>
|
|
117
|
+
)}
|
|
118
|
+
|
|
119
|
+
{author.knowsAbout.length > 0 && (
|
|
120
|
+
<div className="flex flex-wrap gap-2">
|
|
121
|
+
{author.knowsAbout.map((topic) => (
|
|
122
|
+
<StatusBadge key={topic} text={topic} variant="button" colorScheme="cyan" singleLine />
|
|
123
|
+
))}
|
|
124
|
+
</div>
|
|
125
|
+
)}
|
|
126
|
+
|
|
127
|
+
{children}
|
|
128
|
+
</div>
|
|
129
|
+
)
|
|
130
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -91,9 +91,14 @@ export * from './shared/legal-document'
|
|
|
91
91
|
export { DetailPageSkeleton, type DetailPageSkeletonProps } from './shared/detail-page-skeleton'
|
|
92
92
|
|
|
93
93
|
// Author byline card (end-of-article author description) — embeddable via
|
|
94
|
-
// embed-shims + optional-runtime avatar proxying;
|
|
95
|
-
//
|
|
94
|
+
// embed-shims + optional-runtime avatar proxying; hosts pass their own
|
|
95
|
+
// fallbackBio copy (the hub uses defaultAuthorFallbackBio()).
|
|
96
96
|
export { ArticleAuthorByline, type ArticleAuthorBylineProps } from './shared/article-author-byline'
|
|
97
97
|
|
|
98
|
+
// Author detail-page body (identity + socials + bio + expertise, rail as
|
|
99
|
+
// children) — the one implementation behind /authors/[slug] and embedded
|
|
100
|
+
// author pages.
|
|
101
|
+
export { AuthorDetailView, type AuthorDetailViewProps } from './authors/author-detail-view'
|
|
102
|
+
|
|
98
103
|
// Priority UI components that exist in main components directory
|
|
99
104
|
// Note: These are re-exported from ./ui already, no need to duplicate
|
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
* Shared "author byline" card used by article-shaped detail pages
|
|
5
5
|
* (blog post, product release, onboarding guide, investor update).
|
|
6
6
|
*
|
|
7
|
-
* MOVED from the hub
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* from `getAppConfig()`).
|
|
7
|
+
* MOVED from the hub so any consuming app can embed it; hub call sites
|
|
8
|
+
* import it directly and pass their platform-aware copy explicitly
|
|
9
|
+
* (`fallbackBio={defaultAuthorFallbackBio()}` from the hub's app-config).
|
|
11
10
|
*
|
|
12
11
|
* Embed-readiness contract:
|
|
13
12
|
* - `Link` / `Image` render through the embed-shims (plain `<a>` / `<img>`
|
|
@@ -18,3 +18,30 @@ export interface EntityAuthor {
|
|
|
18
18
|
/** Present only on server/admin payloads — public DALs strip it. */
|
|
19
19
|
email?: string | null
|
|
20
20
|
}
|
|
21
|
+
|
|
22
|
+
/** One curated social link on an author profile (host junction:
|
|
23
|
+
* `profile_social_links` ordered by display_order in the hub). */
|
|
24
|
+
export interface AuthorSocialLink {
|
|
25
|
+
/** Platform key fed to `SocialIconRow` (e.g. 'linkedin', 'x'). */
|
|
26
|
+
platform: string
|
|
27
|
+
url: string
|
|
28
|
+
username?: string | null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Public author-page view model — what `<AuthorDetailView>` renders. The
|
|
33
|
+
* hub's `PublicAuthor` (authors DAL) extends this with server-side extras
|
|
34
|
+
* (`updatedAt`); embedders construct it from whatever directory they have.
|
|
35
|
+
*/
|
|
36
|
+
export interface AuthorProfile {
|
|
37
|
+
id: string
|
|
38
|
+
slug: string
|
|
39
|
+
fullName: string
|
|
40
|
+
avatarUrl: string | null
|
|
41
|
+
about: string | null
|
|
42
|
+
jobTitle: string | null
|
|
43
|
+
company: string | null
|
|
44
|
+
knowsAbout: string[]
|
|
45
|
+
/** Ordered by display_order. */
|
|
46
|
+
socialLinks: AuthorSocialLink[]
|
|
47
|
+
}
|