{"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-MXBLRXVV.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-MXBLRXVV.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=\"space-y-6 md:space-y-10 animate-pulse\">\n        {/* Title Block */}\n        <div className=\"flex flex-col gap-6 w-full\">\n          <div className=\"h-16 md:h-20 w-full max-w-3xl bg-ods-card rounded\"></div>\n        </div>\n\n        {/* Category Tags Skeleton */}\n        <div className=\"flex flex-wrap gap-2 w-full\">\n          <div className=\"h-8 w-32 bg-ods-card rounded\"></div>\n          <div className=\"h-8 w-28 bg-ods-card rounded\"></div>\n          <div className=\"h-8 w-36 bg-ods-card rounded\"></div>\n        </div>\n\n        {/* Metadata Grid Skeleton */}\n        <div className={`grid grid-cols-1 md:grid-cols-${metadataColumns} border border-ods-border rounded-md overflow-hidden w-full`}>\n          {Array.from({ length: metadataColumns }).map((_, i) => (\n            <div key={i} className=\"bg-ods-card border-b md:border-b-0 md:border-r last:border-r-0 border-ods-border p-4\">\n              <div className=\"h-6 w-24 bg-ods-border rounded mb-2\"></div>\n              <div className=\"h-5 w-20 bg-ods-border rounded\"></div>\n            </div>\n          ))}\n        </div>\n\n        {/* Image Gallery Skeleton */}\n        {showImageGallery && (\n          <div className=\"flex gap-6 overflow-x-auto w-full\">\n            {[1, 2, 3, 4, 5].map((i) => (\n              <div key={i} className=\"shrink-0 w-[240px] h-[200px] bg-ods-card rounded-md border border-ods-border\"></div>\n            ))}\n          </div>\n        )}\n\n        {/* Featured Image Skeleton (for case studies) */}\n        {!showImageGallery && (\n          <div className=\"aspect-[2560/1366] w-full bg-ods-card rounded-md\"></div>\n        )}\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 bg-ods-card rounded\"></div>\n            <div className=\"space-y-3\">\n              <div className=\"h-6 w-full bg-ods-card rounded\"></div>\n              <div className=\"h-6 w-full bg-ods-card rounded\"></div>\n              <div className=\"h-6 w-4/5 bg-ods-card rounded\"></div>\n            </div>\n          </div>\n        ))}\n      </div>\n  );\n  if (bare) return content;\n  return (\n    <PageLayout\n      showHeader={false}\n      className=\"bg-ods-bg max-w-[1280px] mx-auto py-6 md:py-10 px-6 md:px-20\"\n    >\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 React from 'react'\nimport { Calendar, User } from 'lucide-react'\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'\nimport { useChatRuntime } from '../../contexts/chat-runtime-context'\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        'bg-ods-card border border-ods-border rounded-lg p-6',\n        'flex flex-col md:flex-row gap-4 items-start',\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              'rounded-full border-2 border-ods-border bg-ods-bg flex items-center justify-center',\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=\"flex-1 min-w-0\">\n        <div className=\"flex flex-wrap items-baseline gap-x-3 gap-y-1\">\n          <h3 className=\"text-h5 text-ods-text-primary\">\n            {href ? (\n              <Link href={href} className=\"hover:text-ods-accent transition-colors\">\n                {author}\n              </Link>\n            ) : (\n              author\n            )}\n          </h3>\n          {dateLabel && (\n            <span className=\"inline-flex items-center gap-1 font-body text-body-sm text-ods-text-secondary\">\n              <Calendar className=\"h-3 w-3\" />\n              {dateLabel}\n            </span>\n          )}\n        </div>\n        {jobTitle && (\n          <p className=\"font-body text-body-sm text-ods-text-secondary mt-0.5\">\n            {jobTitle}\n          </p>\n        )}\n        {formattedBio ? (\n          <p className=\"font-body text-body-md text-ods-text-secondary leading-relaxed mt-2\">\n            {formattedBio}\n          </p>\n        ) : fallbackBio ? (\n          <p className=\"font-body text-body-md text-ods-text-secondary italic mt-2\">\n            {fallbackBio}\n          </p>\n        ) : null}\n      </div>\n    </div>\n  )\n}\n"]}