{"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-TOXJS4HN.cjs","../src/components/shared/detail-page-skeleton.tsx","../src/components/shared/article-author-byline.tsx"],"names":["jsxs","jsx"],"mappings":"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","file":"/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-TOXJS4HN.cjs","sourcesContent":[null,"'use client';\n\nimport { PageLayout } from '../layout/page-layout';\n\nexport interface DetailPageSkeletonProps {\n  metadataColumns?: number; // Number of metadata grid columns (default 4)\n  showImageGallery?: boolean; // Show horizontal image gallery (default true)\n  /** Render only the skeleton blocks, WITHOUT the self-contained page wrapper\n   *  — the caller supplies its own (e.g. `<PageShell>`) so the loading state\n   *  matches the loaded page's width, padding, and min-height. Default false\n   *  (self-contained `<PageLayout>` at the hub article width). */\n  bare?: boolean;\n}\n\nexport function DetailPageSkeleton({\n  metadataColumns = 4,\n  showImageGallery = true,\n  bare = false,\n}: DetailPageSkeletonProps = {}) {\n  const content = (\n    <div className=\"animate-pulse space-y-6 md:space-y-10\">\n      {/* Title Block */}\n      <div className=\"flex w-full flex-col gap-6\">\n        <div className=\"h-16 w-full max-w-3xl rounded bg-ods-card md:h-20\"></div>\n      </div>\n\n      {/* Category Tags Skeleton */}\n      <div className=\"flex w-full flex-wrap gap-2\">\n        <div className=\"h-8 w-32 rounded bg-ods-card\"></div>\n        <div className=\"h-8 w-28 rounded bg-ods-card\"></div>\n        <div className=\"h-8 w-36 rounded bg-ods-card\"></div>\n      </div>\n\n      {/* Metadata Grid Skeleton */}\n      <div\n        className={`grid grid-cols-1 md:grid-cols-${metadataColumns} w-full overflow-hidden rounded-md border border-ods-border`}\n      >\n        {Array.from({ length: metadataColumns }).map((_, i) => (\n          <div key={i} className=\"border-b border-ods-border bg-ods-card p-4 last:border-r-0 md:border-b-0 md:border-r\">\n            <div className=\"mb-2 h-6 w-24 rounded bg-ods-border\"></div>\n            <div className=\"h-5 w-20 rounded bg-ods-border\"></div>\n          </div>\n        ))}\n      </div>\n\n      {/* Image Gallery Skeleton */}\n      {showImageGallery && (\n        <div className=\"flex w-full gap-6 overflow-x-auto\">\n          {[1, 2, 3, 4, 5].map(i => (\n            <div key={i} className=\"h-[200px] w-[240px] shrink-0 rounded-md border border-ods-border bg-ods-card\"></div>\n          ))}\n        </div>\n      )}\n\n      {/* Featured Image Skeleton (for case studies) */}\n      {!showImageGallery && <div className=\"aspect-[2560/1366] w-full rounded-md bg-ods-card\"></div>}\n\n      {/* Content Sections Skeleton */}\n      {[1, 2, 3].map(section => (\n        <div key={section} className=\"space-y-6\">\n          <div className=\"h-16 w-64 rounded bg-ods-card\"></div>\n          <div className=\"space-y-3\">\n            <div className=\"h-6 w-full rounded bg-ods-card\"></div>\n            <div className=\"h-6 w-full rounded bg-ods-card\"></div>\n            <div className=\"h-6 w-4/5 rounded bg-ods-card\"></div>\n          </div>\n        </div>\n      ))}\n    </div>\n  );\n  if (bare) return content;\n  return (\n    <PageLayout showHeader={false} className=\"mx-auto max-w-[1280px] bg-ods-bg px-6 py-6 md:px-20 md:py-10\">\n      {content}\n    </PageLayout>\n  );\n}\n","'use client';\n\n/**\n * Shared \"author byline\" card used by article-shaped detail pages\n * (blog post, product release, onboarding guide, investor update).\n *\n * MOVED from the hub so any consuming app can embed it; hub call sites\n * import it directly and pass their platform-aware copy explicitly\n * (`fallbackBio={defaultAuthorFallbackBio()}` from the hub's app-config).\n *\n * Embed-readiness contract:\n *   - `Link` / `Image` render through the embed-shims (plain `<a>` / `<img>`\n *     in non-Next hosts; the real Next primitives once the host registers\n *     them at app init).\n *   - The avatar is proxied through the OPTIONAL ambient `ChatRuntime`\n *     (`endpoints.imageProxyUrlPrefix`, same config `useProxiedImageUrl`\n *     reads) — when no runtime is mounted the raw URL renders as-is, so the\n *     component never throws outside a provider. Hosts can also inject\n *     `proxyImageUrl` to bypass the runtime entirely.\n *   - `fallbackBio` is a PLAIN prop (no app-config import): the lib has no\n *     platform awareness; pass copy or leave it absent to render nothing.\n *\n * Render order: avatar → name + job title + date → bio (when present).\n * Returns null when `author` is empty (no card rendered).\n */\n\nimport { Calendar, User } from 'lucide-react';\nimport { useChatRuntime } from '../../contexts/chat-runtime-context';\nimport Image from '../../embed-shims/next-image';\nimport Link from '../../embed-shims/next-link';\nimport { cn } from '../../utils/cn';\nimport { formatBioText } from '../../utils/format';\nimport { getProxiedImageUrl } from '../../utils/image-proxy';\n\nexport interface ArticleAuthorBylineProps {\n  /** Author display name. Required — block is hidden when null/empty. */\n  author: string | null;\n  /** Avatar URL. Falls back to a placeholder when null. */\n  avatar?: string | null;\n  /** Optional bio paragraph rendered below the name. */\n  bio?: string | null;\n  /** Optional job title rendered immediately under the name. */\n  jobTitle?: string | null;\n  /** Optional published date (ISO string or Date). Rendered next to the name. */\n  publishedAt?: string | Date | null;\n  /** Optional link target for the author name (e.g. the author page). */\n  href?: string | null;\n  /**\n   * Fallback paragraph when `bio` is empty. Plain copy — the lib has no\n   * platform/config awareness, so hosts that want a branded default\n   * (\"Contributing author on the {platform} platform\") pass it explicitly\n   * (the hub wrapper derives it from `getAppConfig()`). Absent/null ⇒\n   * nothing renders below the name when `bio` is empty.\n   */\n  fallbackBio?: string | null;\n  /** Avatar size variant. `md` = 56px (default), `lg` = 64px. */\n  size?: 'md' | 'lg';\n  /**\n   * Host-injected avatar-URL mapper. Wins over the ambient-runtime proxy\n   * resolution. Use when the host proxies images outside the `ChatRuntime`\n   * config (e.g. a bespoke CDN rewrite).\n   */\n  proxyImageUrl?: (url: string) => string;\n  className?: string;\n}\n\nfunction formatDate(value: string | Date): string {\n  const d = typeof value === 'string' ? new Date(value) : value;\n  if (Number.isNaN(d.getTime())) return '';\n  // `timeZone: 'UTC'` keeps the SSR (server = UTC) and client (user's local tz)\n  // renders identical — without it a published_at near a midnight boundary\n  // formats to a different day on each side, triggering a React #418 hydration\n  // text mismatch. Matches the convention in blog-metadata.tsx / investor-update.\n  return d.toLocaleDateString('en-US', {\n    month: 'long',\n    day: 'numeric',\n    year: 'numeric',\n    timeZone: 'UTC',\n  });\n}\n\nexport function ArticleAuthorByline({\n  author,\n  avatar,\n  bio,\n  jobTitle,\n  publishedAt,\n  href,\n  fallbackBio,\n  size = 'md',\n  proxyImageUrl,\n  className,\n}: ArticleAuthorBylineProps) {\n  // Optional runtime — `useChatRuntime` returns null outside a provider, so\n  // the byline works in bare embeds (raw avatar URL) and proxies whenever the\n  // host mounted a runtime with `imageProxyUrlPrefix` (the hub always does).\n  const runtime = useChatRuntime();\n  if (!author) return null;\n\n  const proxiedAvatar = avatar\n    ? proxyImageUrl\n      ? proxyImageUrl(avatar)\n      : (getProxiedImageUrl(avatar, {\n          proxyPrefix: runtime?.endpoints.imageProxyUrlPrefix,\n          skipDomains: runtime?.endpoints.imageProxySkipDomains,\n          directHttps: true,\n        }) ?? avatar)\n    : '';\n\n  // Class-driven sizing (md = 56px, lg = 64px). The numeric pair feeds only\n  // the Image element's intrinsic width/height attributes (required by the\n  // Next image shim) — layout comes from the classes.\n  const avatarSizeClass = size === 'lg' ? 'w-16 h-16' : 'w-14 h-14';\n  const avatarIconClass = size === 'lg' ? 'w-8 h-8' : 'w-7 h-7';\n  const avatarDim = size === 'lg' ? 64 : 56;\n  const formattedBio = formatBioText(bio ?? null);\n  const dateLabel = publishedAt ? formatDate(publishedAt) : '';\n\n  return (\n    <div\n      className={cn(\n        'rounded-lg border border-ods-border bg-ods-card p-6',\n        'flex flex-col items-start gap-4 md:flex-row',\n        className,\n      )}\n    >\n      {/* Avatar */}\n      <div className=\"flex-shrink-0\">\n        {avatar ? (\n          <Image\n            src={proxiedAvatar || avatar}\n            alt={author}\n            width={avatarDim}\n            height={avatarDim}\n            className={cn('rounded-full border-2 border-ods-border object-cover', avatarSizeClass)}\n          />\n        ) : (\n          <div\n            className={cn(\n              'flex items-center justify-center rounded-full border-2 border-ods-border bg-ods-bg',\n              avatarSizeClass,\n            )}\n          >\n            <User className={cn('text-ods-text-secondary', avatarIconClass)} />\n          </div>\n        )}\n      </div>\n\n      {/* Name + meta + bio */}\n      <div className=\"min-w-0 flex-1\">\n        <div className=\"flex flex-wrap items-baseline gap-x-3 gap-y-1\">\n          <h3 className=\"text-ods-text-primary text-h5\">\n            {href ? (\n              <Link href={href} className=\"transition-colors hover:text-ods-accent\">\n                {author}\n              </Link>\n            ) : (\n              author\n            )}\n          </h3>\n          {dateLabel && (\n            <span className=\"text-body-sm inline-flex items-center gap-1 font-body text-ods-text-secondary\">\n              <Calendar className=\"h-3 w-3\" />\n              {dateLabel}\n            </span>\n          )}\n        </div>\n        {jobTitle && <p className=\"text-body-sm mt-0.5 font-body text-ods-text-secondary\">{jobTitle}</p>}\n        {formattedBio ? (\n          <p className=\"text-body-md mt-2 font-body leading-relaxed text-ods-text-secondary\">{formattedBio}</p>\n        ) : fallbackBio ? (\n          <p className=\"text-body-md mt-2 font-body italic text-ods-text-secondary\">{fallbackBio}</p>\n        ) : null}\n      </div>\n    </div>\n  );\n}\n"]}