@alfadocs/ui-kit-debug 1.62.0 → 1.63.0
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/_chunks/{balance-badge-cell-F7p_ZKEg.js → balance-badge-cell-tB4u0Nr4.js} +2 -2
- package/dist/_chunks/{balance-badge-cell-F7p_ZKEg.js.map → balance-badge-cell-tB4u0Nr4.js.map} +1 -1
- package/dist/_chunks/{calendar-workspace-Dvfl9Vf6.js → calendar-workspace-BgcqB0PI.js} +5 -5
- package/dist/_chunks/{calendar-workspace-Dvfl9Vf6.js.map → calendar-workspace-BgcqB0PI.js.map} +1 -1
- package/dist/_chunks/{care-plan-card-BU3p5cLr.js → care-plan-card-DJzbwJLl.js} +2 -2
- package/dist/_chunks/{care-plan-card-BU3p5cLr.js.map → care-plan-card-DJzbwJLl.js.map} +1 -1
- package/dist/_chunks/{care-plan-header-CgFjQLBd.js → care-plan-header-1HzbkYcR.js} +2 -2
- package/dist/_chunks/{care-plan-header-CgFjQLBd.js.map → care-plan-header-1HzbkYcR.js.map} +1 -1
- package/dist/_chunks/chart-BAeJ7pvD.js +1120 -0
- package/dist/_chunks/chart-BAeJ7pvD.js.map +1 -0
- package/dist/_chunks/{clinical-note-card-BgURrgL5.js → clinical-note-card-D2bbWksq.js} +2 -2
- package/dist/_chunks/{clinical-note-card-BgURrgL5.js.map → clinical-note-card-D2bbWksq.js.map} +1 -1
- package/dist/_chunks/{contact-card-C8rEsC4Q.js → contact-card-Czu60UvU.js} +2 -2
- package/dist/_chunks/{contact-card-C8rEsC4Q.js.map → contact-card-Czu60UvU.js.map} +1 -1
- package/dist/_chunks/{contact-profile-card-VTCAmQqj.js → contact-profile-card-B4sjoIqf.js} +2 -2
- package/dist/_chunks/{contact-profile-card-VTCAmQqj.js.map → contact-profile-card-B4sjoIqf.js.map} +1 -1
- package/dist/_chunks/{data-table-m7GbLJZy.js → data-table-Ck2rIwWF.js} +1 -1
- package/dist/_chunks/{data-table-m7GbLJZy.js.map → data-table-Ck2rIwWF.js.map} +1 -1
- package/dist/_chunks/{entity-summary-DXIr5_x2.js → entity-summary-BQ9_KA8S.js} +2 -2
- package/dist/_chunks/{entity-summary-DXIr5_x2.js.map → entity-summary-BQ9_KA8S.js.map} +1 -1
- package/dist/_chunks/{file-manager-G0t8MWbE.js → file-manager-k85OOFr4.js} +2 -2
- package/dist/_chunks/{file-manager-G0t8MWbE.js.map → file-manager-k85OOFr4.js.map} +1 -1
- package/dist/_chunks/{heatmap-Bb0-M88T.js → heatmap-Cp8Gn9q-.js} +2 -2
- package/dist/_chunks/{heatmap-Bb0-M88T.js.map → heatmap-Cp8Gn9q-.js.map} +1 -1
- package/dist/_chunks/{link-gRw3NtOt.js → link-N5_YpLtm.js} +7 -6
- package/dist/_chunks/link-N5_YpLtm.js.map +1 -0
- package/dist/_chunks/{nav-grid-Byx8PxuB.js → nav-grid-Oc4aCPrg.js} +2 -2
- package/dist/_chunks/{nav-grid-Byx8PxuB.js.map → nav-grid-Oc4aCPrg.js.map} +1 -1
- package/dist/_chunks/{note-attachment-DoVWvjWR.js → note-attachment-D8V7PUiR.js} +2 -2
- package/dist/_chunks/{note-attachment-DoVWvjWR.js.map → note-attachment-D8V7PUiR.js.map} +1 -1
- package/dist/_chunks/{note-timeline-B7l3t5DZ.js → note-timeline-CwxPQ2Ak.js} +2 -2
- package/dist/_chunks/{note-timeline-B7l3t5DZ.js.map → note-timeline-CwxPQ2Ak.js.map} +1 -1
- package/dist/_chunks/{notes-panel-CTmvrqQn.js → notes-panel-BRLc2ozF.js} +2 -2
- package/dist/_chunks/{notes-panel-CTmvrqQn.js.map → notes-panel-BRLc2ozF.js.map} +1 -1
- package/dist/_chunks/{patient-details-BNDS69Zx.js → patient-details-BY8Rwwpi.js} +2 -2
- package/dist/_chunks/{patient-details-BNDS69Zx.js.map → patient-details-BY8Rwwpi.js.map} +1 -1
- package/dist/_chunks/{patient-field-row-BLBi-PjO.js → patient-field-row-C8ymfffP.js} +2 -2
- package/dist/_chunks/{patient-field-row-BLBi-PjO.js.map → patient-field-row-C8ymfffP.js.map} +1 -1
- package/dist/_chunks/{patient-summary-card-T9umuZJF.js → patient-summary-card-cmqjIXMk.js} +3 -3
- package/dist/_chunks/{patient-summary-card-T9umuZJF.js.map → patient-summary-card-cmqjIXMk.js.map} +1 -1
- package/dist/_chunks/{payment-request-card-BmzNMY2a.js → payment-request-card-0DjQgVgX.js} +2 -2
- package/dist/_chunks/{payment-request-card-BmzNMY2a.js.map → payment-request-card-0DjQgVgX.js.map} +1 -1
- package/dist/_chunks/{product-hub-panel-D-UELdo0.js → product-hub-panel-C_ZosrBt.js} +2 -2
- package/dist/_chunks/{product-hub-panel-D-UELdo0.js.map → product-hub-panel-C_ZosrBt.js.map} +1 -1
- package/dist/_chunks/{public-footer-ZWTEG1Rq.js → public-footer-CXOrdAaS.js} +2 -2
- package/dist/_chunks/{public-footer-ZWTEG1Rq.js.map → public-footer-CXOrdAaS.js.map} +1 -1
- package/dist/_chunks/{signed-out-frame-D5DzqATh.js → signed-out-frame-Rg_GVDnl.js} +2 -2
- package/dist/_chunks/{signed-out-frame-D5DzqATh.js.map → signed-out-frame-Rg_GVDnl.js.map} +1 -1
- package/dist/_chunks/{use-appointment-details-read-Gu0ehyxj.js → use-appointment-details-read-D6Gb_OuN.js} +4 -4
- package/dist/_chunks/{use-appointment-details-read-Gu0ehyxj.js.map → use-appointment-details-read-D6Gb_OuN.js.map} +1 -1
- package/dist/agent-catalog.json +1 -1
- package/dist/components/_shared/use-apex-legend-scroll.d.ts +7 -3
- package/dist/components/_shared/use-apex-legend-scroll.d.ts.map +1 -1
- package/dist/components/_shared/use-apex-x-label-spacing.d.ts +11 -0
- package/dist/components/_shared/use-apex-x-label-spacing.d.ts.map +1 -0
- package/dist/components/appointment-details-panel/index.js +1 -1
- package/dist/components/care-plan-card/index.js +1 -1
- package/dist/components/care-plan-header/index.js +1 -1
- package/dist/components/chart/chart.d.ts.map +1 -1
- package/dist/components/chart/index.js +1 -1
- package/dist/components/clinical-note-card/index.js +1 -1
- package/dist/components/contact-card/index.js +1 -1
- package/dist/components/contact-profile-card/index.js +1 -1
- package/dist/components/data-table/index.js +1 -1
- package/dist/components/entity-summary/index.js +1 -1
- package/dist/components/file-manager/index.js +1 -1
- package/dist/components/heatmap/index.js +1 -1
- package/dist/components/link/index.js +1 -1
- package/dist/components/link/link.d.ts.map +1 -1
- package/dist/components/nav-grid/index.js +1 -1
- package/dist/components/note-timeline/index.js +1 -1
- package/dist/components/notes-panel/index.js +1 -1
- package/dist/components/patient-details/index.js +1 -1
- package/dist/components/patient-summary-card/index.js +1 -1
- package/dist/components/patient-table/index.js +1 -1
- package/dist/components/payment-card/index.js +1 -1
- package/dist/components/product-hub-tray/index.js +1 -1
- package/dist/components/public-footer/index.js +1 -1
- package/dist/index.js +23 -23
- package/dist/patterns/calendar/index.js +1 -1
- package/dist/patterns/signed-out-frame/index.js +1 -1
- package/dist/tokens.css +6 -4
- package/package.json +1 -1
- package/dist/_chunks/chart-DgYHN8Xq.js +0 -991
- package/dist/_chunks/chart-DgYHN8Xq.js.map +0 -1
- package/dist/_chunks/link-gRw3NtOt.js.map +0 -1
package/dist/_chunks/{product-hub-panel-D-UELdo0.js.map → product-hub-panel-C_ZosrBt.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-hub-panel-D-UELdo0.js","sources":["../../node_modules/lucide-react/dist/esm/icons/gift.mjs","../../src/components/product-hub-tray/product-hub-tray.agent.ts","../../src/components/product-hub-tray/product-hub-tray.tsx","../../src/components/product-hub-tray/product-hub-panel.agent.ts","../../src/components/product-hub-tray/product-hub-panel.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 7v14\", key: \"1akyts\" }],\n [\"path\", { d: \"M20 11v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-8\", key: \"1sqzm4\" }],\n [\n \"path\",\n { d: \"M7.5 7a1 1 0 0 1 0-5A4.8 8 0 0 1 12 7a4.8 8 0 0 1 4.5-5 1 1 0 0 1 0 5\", key: \"kc0143\" }\n ],\n [\"rect\", { x: \"3\", y: \"7\", width: \"18\", height: \"4\", rx: \"1\", key: \"1hberx\" }]\n];\nconst Gift = createLucideIcon(\"gift\", __iconNode);\n\nexport { __iconNode, Gift as default };\n//# sourceMappingURL=gift.mjs.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — ProductHubTray. */\n/* */\n/* Tray-level surface: an agent can open / close the dropdown panel and */\n/* read the unseen-release count. Release content (titles, summaries, */\n/* URLs) is never exposed — counts and booleans only. All actions are */\n/* routed through the curated imperative handle; the adapter never */\n/* touches the DOM directly. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { ProductHubTrayHandle } from './product-hub-tray';\n\nexport const productHubTrayAgent: AgentAdapter<ProductHubTrayHandle> = {\n id: 'product-hub-tray',\n capabilities: ['open', 'close'],\n state: {\n unseenCount: {\n type: 'number',\n descriptionKey: 'ui.agent.productHubTray.state.unseenCount',\n description:\n 'Number of unseen product releases — the trigger badge count.',\n read: (handle) => handle.getUnseenCount(),\n },\n },\n actions: {\n open: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.productHubTray.actions.open',\n description: 'Open the product-updates panel.',\n invoke: (handle) => {\n handle.open();\n },\n },\n close: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.productHubTray.actions.close',\n description: 'Close the product-updates panel.',\n invoke: (handle) => {\n handle.close();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'product-hub-tray',\n description: 'Marks the ProductHubTray wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific tray from the agent.',\n },\n item: {\n attr: 'data-update-id',\n description:\n 'Stable release id emitted on each rendered release row inside the tray.',\n },\n },\n};\n","import {\n forwardRef,\n useImperativeHandle,\n useMemo,\n useRef,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport * as RadixPopover from '@radix-ui/react-popover';\nimport {\n findPopoverTrigger,\n useNonModalTabExit,\n} from '../_shared/non-modal-tab-exit';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Gift, X } from 'lucide-react';\nimport { useControllableState } from '../../hooks/use-controllable-state';\nimport { IconButton } from '../button/icon-button';\nimport { Link } from '../link';\nimport { ScrollArea } from '../scroll-area/scroll-area';\nimport { Separator } from '../separator/separator';\nimport { Skeleton } from '../skeleton/skeleton';\nimport { Timestamp } from '../timestamp';\nimport { isSafeEntityUrl } from '../_shared/is-safe-url';\nimport { safeImageSrc } from '../_shared/safe-image-src';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { productHubTrayAgent } from './product-hub-tray.agent';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\n/**\n * One product-hub release entry. The kit is purely presentational —\n * the consumer fetches releases (Supabase, REST, …) and maps them into\n * this shape.\n */\nexport interface ProductHubItem {\n /** Unique identifier for the release. */\n id: string;\n /** Release title — rendered bold on the first line. */\n title: string;\n /** Short release summary — rendered as plain text, clamped to 2 lines. */\n summary?: string;\n /** ISO-8601 publish date — rendered as a localised, italic absolute date. */\n dateIso?: string;\n /**\n * Thumbnail URL. Guarded through the shared `safeImageSrc` allow-list\n * and rendered with `referrerPolicy=\"no-referrer\"`. Unsafe or missing\n * sources fall back to a Gift glyph tile.\n */\n imageUrl?: string;\n /**\n * Release deep link. Guarded through `isSafeEntityUrl`; safe URLs make\n * the row title an anchor that opens in a new tab. Unsafe URLs render\n * the title as plain text.\n */\n url?: string;\n /** Marks the release as not yet seen — highlights the row and counts toward the trigger badge. */\n unseen?: boolean;\n}\n\n/**\n * Curated imperative handle for ProductHubTray. Exposed to the agent\n * registry so a future MCP UI bridge can drive the tray without touching\n * the DOM. See `product-hub-tray.agent.ts`.\n */\nexport interface ProductHubTrayHandle {\n open: () => void;\n close: () => void;\n getUnseenCount: () => number;\n}\n\nexport interface ProductHubTrayProps\n extends\n Omit<\n HTMLAttributes<HTMLDivElement>,\n 'onClick' | 'children' | 'role' | 'id'\n >,\n VariantProps<typeof productHubTrayVariants> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so\n * an agent / MCP UI bridge can address this specific tray.\n */\n id?: string;\n /** Releases rendered in the dropdown panel, newest first. */\n items: ProductHubItem[];\n /**\n * Product-hub landing URL. When set (and safe) the panel renders a\n * pinned \"Open in Product Hub\" footer link that opens in a new tab.\n */\n hubUrl?: string;\n /** When true the panel shows skeleton placeholders. */\n loading?: boolean;\n /** Error-state slot — rendered inside the panel instead of the list. */\n error?: ReactNode;\n /**\n * Unseen-release count override. Defaults to the number of `items`\n * with `unseen: true`. Drives the trigger badge.\n */\n unseenCount?: number;\n /** Fires when the open state changes. */\n onOpenChange?: (open: boolean) => void;\n /**\n * Analytics hook — fires when a row is activated. Navigation itself is\n * owned by the row anchor (new tab); this callback must not be relied\n * on for routing.\n */\n onItemActivate?: (item: ProductHubItem) => void;\n /** Override for the trigger's accessible label. */\n triggerLabel?: string;\n /** Number of releases rendered before the rest are cut off. Default 10. */\n maxVisible?: number;\n /** Empty-state slot — replaces the built-in \"No product updates yet\" panel. */\n emptyState?: ReactNode;\n /** Open the panel on first mount (uncontrolled). */\n defaultOpen?: boolean;\n /** BCP-47 locale override for the per-row dates. Falls back to `i18n.language`. */\n locale?: string;\n /** Panel alignment relative to the trigger. Default `'end'`. */\n align?: 'start' | 'center' | 'end';\n /** Side of the trigger to open on. Default `'bottom'`. */\n side?: 'top' | 'bottom';\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst productHubTrayVariants = cva(\n 'ds:relative ds:inline-flex ds:items-center',\n {\n variants: {\n size: {\n sm: '',\n md: '',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n);\n\nconst panelVariants = cva(\n [\n 'ds:flex ds:flex-col',\n 'ds:bg-[var(--popover)] ds:text-[var(--popover-foreground)]',\n 'ds:border ds:border-[color:var(--card-border)]',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:shadow-[var(--shadow-lg)]',\n 'ds:z-[var(--z-popover)]',\n // Fluid below the design cap so narrow viewports keep a gutter on\n // both sides of the panel (shadow included).\n 'ds:w-[min(24rem,calc(100vw-2*var(--spacing-md)))]',\n // Near-full-screen sheet below `sm`; auto above, where the list's\n // own `--product-hub-tray-max-block-size` cap governs the height.\n 'ds:h-[calc(100dvh-6rem)] ds:sm:h-auto',\n 'ds:data-[state=open]:animate-in ds:data-[state=closed]:animate-out',\n 'ds:data-[state=closed]:fade-out-0 ds:data-[state=open]:fade-in-0',\n 'ds:data-[state=closed]:zoom-out-95 ds:data-[state=open]:zoom-in-95',\n 'ds:motion-reduce:transition-none ds:motion-reduce:animate-none',\n 'ds:focus-visible:outline-none',\n 'ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:p-[var(--spacing-xs)]',\n md: 'ds:p-[var(--spacing-sm)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n);\n\nconst badgeVariants = cva(\n [\n // Anchored to the top-end corner of the trigger, nudged outward so\n // the gift glyph isn't covered.\n 'ds:absolute ds:-top-[var(--spacing-xs)] ds:-end-[var(--spacing-xs)]',\n 'ds:inline-flex ds:items-center ds:justify-center',\n // Circle at 1-2 digits; widens into a pill only for \"99+\".\n 'ds:min-w-[calc(var(--spacing-md)+var(--spacing-xs))] ds:h-[calc(var(--spacing-md)+var(--spacing-xs))] ds:ps-[calc(var(--spacing-xs)/1.5)] ds:pe-[calc(var(--spacing-xs)/1.5)]',\n 'ds:rounded-[var(--radius-full)]',\n // One red unseen-count chip across every header tray — matches the\n // platform header and the NotificationTray badge convention.\n 'ds:bg-[color:var(--destructive)] ds:text-[color:var(--destructive-foreground)]',\n 'ds:text-[length:var(--font-size-xs)] ds:font-semibold ds:leading-none',\n 'ds:pointer-events-none ds:select-none',\n 'ds:forced-colors:outline ds:forced-colors:outline-1 ds:forced-colors:outline-[CanvasText]',\n ].join(' '),\n);\n\n/* ------------------------------------------------------------------ */\n/* Shared release row — used by both ProductHubTray (compact) and */\n/* ProductHubPanel (roomier). Internal seam, not part of the barrel. */\n/* ------------------------------------------------------------------ */\n\nconst rowVariants = cva(\n [\n // `group` so the hover/focus-revealed close button can react to the whole\n // row, not just itself.\n 'ds:group ds:relative ds:flex ds:items-start',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:text-start',\n 'ds:transition-colors ds:motion-reduce:transition-none',\n ].join(' '),\n {\n variants: {\n density: {\n tray: 'ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)]',\n panel: 'ds:gap-[var(--spacing-md)] ds:p-[var(--spacing-md)]',\n },\n // Unseen no longer tints the background — the read/new state is carried\n // by the leading-corner Gift indicator instead, matching the\n // notification / message cards.\n unseen: {\n true: 'ds:hover:bg-[color:var(--muted)]/40',\n false: 'ds:hover:bg-[color:var(--muted)]/40',\n },\n // Row chrome: flat (inside a bordered tray/panel) vs elevated (own card\n // on a rail). Mirrors AppointmentCard / NotificationCard so the Inbox\n // feed reads consistently with the other rail panels.\n surface: {\n flat: '',\n elevated:\n 'ds:[:where(&)]:border-[length:var(--surface-border-width,var(--border-width-sm))] ds:border-[color:var(--card-border)] ds:shadow-[var(--shadow-sm)]',\n },\n },\n defaultVariants: {\n density: 'tray',\n unseen: false,\n surface: 'flat',\n },\n },\n);\n\nconst thumbVariants = cva(\n [\n 'ds:shrink-0 ds:rounded-[var(--radius-sm)] ds:object-cover',\n // Tile backdrop so transparent / still-loading thumbnails keep a\n // visible square instead of collapsing into whitespace.\n 'ds:bg-[color:var(--muted)]',\n 'ds:forced-colors:border ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n density: {\n tray: 'ds:size-10',\n panel: 'ds:size-12',\n },\n },\n defaultVariants: {\n density: 'tray',\n },\n },\n);\n\nconst stretchedLinkClass = [\n 'ds:focus-visible:outline-none',\n \"ds:after:content-[''] ds:after:absolute ds:after:inset-0 ds:after:rounded-[var(--radius-sm)]\",\n 'ds:after:pointer-events-auto',\n 'ds:focus-visible:after:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:after:outline-solid',\n 'ds:focus-visible:after:outline-[color:var(--ring)]',\n 'ds:focus-visible:after:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:after:outline-[CanvasText]',\n].join(' ');\n\nexport interface ProductHubUpdateRowProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'onClick' | 'role' | 'title'\n> {\n /** The release to render. */\n item: ProductHubItem;\n /** `tray` — compact dropdown row. `panel` — roomier dashboard row. */\n density?: 'tray' | 'panel';\n /**\n * Row chrome. `'flat'` (default) — chrome-less row inside a bordered\n * tray/panel. `'elevated'` — own card chrome (border + `--shadow-sm`) for\n * rail feeds (e.g. the Inbox), matching the sibling notification/message\n * cards.\n */\n surface?: 'flat' | 'elevated';\n /** BCP-47 locale override for the date. */\n locale?: string;\n /** Analytics hook — navigation is owned by the row anchor. */\n onActivate?: (item: ProductHubItem) => void;\n /**\n * When supplied, renders a close affordance (revealed on row hover / focus)\n * that fires with this item — e.g. dismissing the update from an Inbox feed.\n */\n onDismiss?: (item: ProductHubItem) => void;\n}\n\n/**\n * @internal Shared row between ProductHubTray and ProductHubPanel.\n * Exported for the sibling panel only — import the trays, not this.\n */\nexport function ProductHubUpdateRow({\n item,\n density = 'tray',\n surface = 'flat',\n locale,\n onActivate,\n onDismiss,\n className,\n ...rest\n}: ProductHubUpdateRowProps) {\n const { t } = useTranslation('ui');\n const safeSrc = safeImageSrc(item.imageUrl);\n const hasSafeUrl = !!item.url && isSafeEntityUrl(item.url);\n const unseen = !!item.unseen;\n\n // Close insets track the row padding so it aligns with the title's first\n // line at either density.\n const closeInset =\n density === 'panel'\n ? 'ds:top-[var(--spacing-md)] ds:end-[var(--spacing-md)]'\n : 'ds:top-[var(--spacing-sm)] ds:end-[var(--spacing-sm)]';\n\n // Read after the title when the row gets focus / is traversed:\n // \"<title>, new, (opens in a new tab)\". The unseen dot itself is\n // decorative — state never relies on colour alone.\n const unseenHint = unseen ? (\n <span className=\"ds:sr-only\">\n {t('productHubTray.unseenLabel', ', new')}\n </span>\n ) : null;\n\n return (\n <div\n role=\"listitem\"\n data-component=\"product-hub-update\"\n data-update-id={item.id}\n data-unseen={unseen ? 'true' : 'false'}\n className={rowVariants({ density, unseen, surface, className })}\n {...rest}\n >\n <span className=\"ds:relative ds:shrink-0\">\n {safeSrc ? (\n <img\n src={safeSrc}\n alt=\"\"\n aria-hidden=\"true\"\n referrerPolicy=\"no-referrer\"\n loading=\"lazy\"\n className={thumbVariants({ density })}\n />\n ) : (\n <span\n aria-hidden=\"true\"\n className={`${thumbVariants({ density })} ds:inline-flex ds:items-center ds:justify-center ds:text-[color:var(--muted-foreground)] ds:[&>svg]:size-5`}\n >\n <Gift />\n </span>\n )}\n {/* Unseen \"new\" marker — a dot on the thumbnail corner (the read /\n unread indicator moved inline-start). Decorative; the title link\n carries the sr-only \"new\" hint for assistive tech. */}\n {unseen ? (\n <span\n aria-hidden=\"true\"\n data-testid=\"product-hub-unseen-dot\"\n className=\"ds:absolute ds:top-[calc(var(--spacing-xs)*-1)] ds:end-[calc(var(--spacing-xs)*-1)] ds:z-[1] ds:block ds:size-[calc(var(--spacing-sm)+var(--spacing-xs))] ds:rounded-[var(--radius-full)] ds:bg-[color:var(--primary)] ds:ring-2 ds:ring-[color:var(--card)] ds:forced-colors:bg-[Highlight]\"\n />\n ) : null}\n </span>\n\n <div className=\"ds:min-w-0 ds:flex-1 ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <span className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)] type-title-item ds:text-[color:var(--foreground)]\">\n {hasSafeUrl ? (\n // A real (non-display:contents) anchor so the row is reliably\n // keyboard-focusable; the ::after stretch keeps the whole row\n // clickable and carries the focus ring.\n <a\n href={item.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`${stretchedLinkClass} ds:min-w-0 ds:flex-1 ds:no-underline ds:text-[color:var(--foreground)]`}\n onClick={() => onActivate?.(item)}\n >\n <span className=\"ds:block ds:truncate ds:font-semibold\">\n {item.title}\n </span>\n {unseenHint}\n <span className=\"ds:sr-only\">\n {t('productHubTray.opensInNewTab', '(opens in a new tab)')}\n </span>\n </a>\n ) : (\n <>\n <span className=\"ds:min-w-0 ds:flex-1 ds:truncate ds:font-semibold\">\n {item.title}\n </span>\n {unseenHint}\n </>\n )}\n </span>\n\n {item.summary ? (\n <p className=\"ds:m-0 type-body-sm ds:text-[color:var(--muted-foreground)] ds:[overflow:hidden] ds:[display:-webkit-box] ds:[-webkit-box-orient:vertical] ds:[-webkit-line-clamp:2] ds:break-words\">\n {item.summary}\n </p>\n ) : null}\n\n {item.dateIso ? (\n <Timestamp\n value={item.dateIso}\n format=\"absolute\"\n locale={locale}\n className=\"ds:italic ds:text-[color:var(--muted-foreground)]\"\n />\n ) : null}\n </div>\n\n {/* Close — inline-end, hover/focus-revealed. Absolutely positioned so it\n claims no width at rest: the title fills the row and there's no empty\n gap when the row isn't hovered. */}\n {onDismiss ? (\n <span\n className={\n 'ds:absolute ds:z-[2] ds:opacity-0 ds:pointer-events-none ds:transition-opacity ds:motion-reduce:transition-none ds:group-hover:opacity-100 ds:group-hover:pointer-events-auto ds:group-focus-within:opacity-100 ds:group-focus-within:pointer-events-auto ' +\n closeInset\n }\n >\n <IconButton\n icon={<X />}\n intent=\"ghost\"\n size=\"sm\"\n aria-label={t('productHubTray.dismiss', 'Dismiss update')}\n onClick={() => onDismiss(item)}\n />\n </span>\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Shared loading / status helpers (also consumed by ProductHubPanel) */\n/* ------------------------------------------------------------------ */\n\n/** @internal Skeleton placeholder mirroring the row layout. */\nexport function UpdateSkeletonRow({\n density = 'tray',\n}: {\n density?: 'tray' | 'panel';\n}) {\n return (\n <div\n aria-hidden=\"true\"\n className={\n density === 'panel'\n ? 'ds:flex ds:items-start ds:gap-[var(--spacing-md)] ds:p-[var(--spacing-md)]'\n : 'ds:flex ds:items-start ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)]'\n }\n >\n <Skeleton\n variant=\"rounded\"\n width={density === 'panel' ? '3rem' : '2.5rem'}\n height={density === 'panel' ? '3rem' : '2.5rem'}\n />\n <div className=\"ds:flex-1 ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <Skeleton variant=\"text\" size=\"md\" width=\"60%\" />\n <Skeleton variant=\"text\" size=\"sm\" width=\"90%\" />\n <Skeleton variant=\"text\" size=\"sm\" width=\"30%\" />\n </div>\n </div>\n );\n}\n\n/** @internal Centered status container for error / consumer-slot states. */\nexport function UpdateStatusPanel({ children }: { children: ReactNode }) {\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"ds:flex ds:flex-col ds:items-center ds:justify-center ds:gap-[var(--spacing-xs)] ds:p-[var(--spacing-lg)] ds:text-center type-body-sm ds:text-[color:var(--muted-foreground)]\"\n >\n {children}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\nfunction formatBadgeCount(count: number, overflowLabel: string): string {\n return count > 99 ? overflowLabel : String(count);\n}\n\nfunction EmptyPanel() {\n const { t } = useTranslation('ui');\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"ds:flex ds:flex-col ds:items-center ds:justify-center ds:gap-[var(--spacing-xs)] ds:p-[var(--spacing-lg)] ds:text-center\"\n >\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-flex ds:items-center ds:justify-center ds:size-10 ds:rounded-[var(--radius-full)] ds:bg-[color:var(--muted)] ds:text-[color:var(--muted-foreground)] ds:[&>svg]:size-5\"\n >\n <Gift />\n </span>\n <p className=\"type-title-item ds:text-[color:var(--foreground)]\">\n {t('productHubTray.emptyTitle', 'No product updates yet')}\n </p>\n <p className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {t(\n 'productHubTray.emptyDescription',\n 'New releases and improvements will appear here.',\n )}\n </p>\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Root */\n/* ------------------------------------------------------------------ */\n\nexport const ProductHubTray = forwardRef<HTMLDivElement, ProductHubTrayProps>(\n (\n {\n id,\n items,\n hubUrl,\n loading = false,\n error,\n unseenCount,\n onOpenChange,\n onItemActivate,\n triggerLabel,\n maxVisible = 10,\n emptyState,\n defaultOpen = false,\n locale,\n align = 'end',\n side = 'bottom',\n size = 'md',\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n\n const [isOpenRaw, handleOpenChange] = useControllableState<boolean>({\n defaultValue: defaultOpen,\n onChange: onOpenChange,\n });\n const isOpen = isOpenRaw ?? false;\n\n const displayCount = unseenCount ?? items.filter((i) => i.unseen).length;\n const resolvedTriggerLabel =\n triggerLabel ??\n (displayCount > 0\n ? t('productHubTray.triggerLabel', {\n count: displayCount,\n defaultValue: \"What's new, {{count}} unseen updates\",\n })\n : t('productHubTray.triggerLabelNone', \"What's new\"));\n\n const badgeLabel = formatBadgeCount(\n displayCount,\n t('productHubTray.badgeCountOverflow', '99+'),\n );\n\n const visible = items.slice(0, Math.max(0, maxVisible));\n const showList = !error && !loading && visible.length > 0;\n const safeHubUrl = hubUrl && isSafeEntityUrl(hubUrl) ? hubUrl : undefined;\n\n /* Curated handle — refs keep the look-ups current without\n * re-memoising on every items update. */\n const itemsRef = useRef<ProductHubItem[]>(items);\n itemsRef.current = items;\n const unseenRef = useRef<number | undefined>(unseenCount);\n unseenRef.current = unseenCount;\n\n const handle = useMemo<ProductHubTrayHandle>(\n () => ({\n open: () => handleOpenChange(true),\n close: () => handleOpenChange(false),\n getUnseenCount: () =>\n unseenRef.current ?? itemsRef.current.filter((i) => i.unseen).length,\n }),\n [handleOpenChange],\n );\n\n const rootRef = useRef<HTMLDivElement>(null);\n useImperativeHandle(ref, () => rootRef.current as HTMLDivElement, []);\n useAgentRegistration(productHubTrayAgent, handle, id);\n\n let body: ReactNode;\n if (error) {\n body = <UpdateStatusPanel>{error}</UpdateStatusPanel>;\n } else if (loading) {\n body = (\n <>\n <UpdateSkeletonRow />\n <UpdateSkeletonRow />\n <UpdateSkeletonRow />\n </>\n );\n } else if (visible.length === 0) {\n body = emptyState ?? <EmptyPanel />;\n } else {\n body = visible.map((item) => (\n <ProductHubUpdateRow\n key={item.id}\n item={item}\n density=\"tray\"\n locale={locale}\n onActivate={onItemActivate}\n />\n ));\n }\n\n const exitOnTab = useNonModalTabExit(true, {\n getAnchor: findPopoverTrigger,\n onReturnToTrigger: () => handleOpenChange(false),\n });\n\n return (\n <div\n ref={rootRef}\n data-component=\"product-hub-tray\"\n data-component-id={id}\n className={[productHubTrayVariants({ size }), className]\n .filter(Boolean)\n .join(' ')}\n {...rest}\n >\n <RadixPopover.Root open={isOpen} onOpenChange={handleOpenChange}>\n <RadixPopover.Trigger asChild>\n <IconButton\n icon={<Gift />}\n intent=\"outline\"\n size={size === 'sm' ? 'sm' : 'md'}\n aria-label={resolvedTriggerLabel}\n aria-haspopup=\"dialog\"\n />\n </RadixPopover.Trigger>\n {displayCount > 0 ? (\n <span\n aria-hidden=\"true\"\n data-testid=\"product-hub-tray-badge\"\n className={badgeVariants()}\n >\n {badgeLabel}\n </span>\n ) : null}\n <RadixPopover.Portal>\n <RadixPopover.Content\n role=\"dialog\"\n onKeyDown={exitOnTab}\n aria-label={t('productHubTray.panelTitle', \"What's new\")}\n side={side}\n align={align}\n sideOffset={8}\n // Keeps Radix's collision-avoidance from flush-mounting the\n // panel against the viewport edge on narrow screens.\n collisionPadding={16}\n className={panelVariants({ size })}\n >\n <div className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)] ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:pb-[var(--spacing-xs)]\">\n <h3 className=\"ds:m-0 type-title-card ds:text-[color:var(--foreground)]\">\n {t('productHubTray.panelTitle', \"What's new\")}\n </h3>\n </div>\n <Separator />\n {/* The release list is the ONLY scroll region. `role=\"list\"`\n requires `listitem` children, so it is applied only when\n rows render (axe aria-required-children). Consumers\n override the height cap via the\n `--product-hub-tray-max-block-size` custom property. */}\n <ScrollArea\n orientation=\"vertical\"\n className=\"ds:flex-1 ds:sm:flex-none ds:sm:[max-block-size:var(--product-hub-tray-max-block-size,24rem)]\"\n >\n <div\n role={showList ? 'list' : undefined}\n data-max-visible={maxVisible}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:pt-[var(--spacing-xs)]\"\n >\n {body}\n </div>\n </ScrollArea>\n {safeHubUrl ? (\n <>\n <Separator />\n <div className=\"ds:flex ds:justify-center ds:pt-[var(--spacing-sm)] ds:pb-[var(--spacing-xs)]\">\n <Link href={safeHubUrl} external>\n {t('productHubTray.openHub', 'Open in Product Hub')}\n </Link>\n </div>\n </>\n ) : null}\n </RadixPopover.Content>\n </RadixPopover.Portal>\n </RadixPopover.Root>\n </div>\n );\n },\n);\n\nProductHubTray.displayName = 'ProductHubTray';\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — ProductHubPanel. */\n/* */\n/* Read-mostly dashboard surface: an agent can read the displayed */\n/* release ids + unseen flags (never titles / summaries / URLs) and */\n/* route a per-item activation through the curated handle. The adapter */\n/* never touches the DOM directly. */\n/* */\n/* NOTE: catalog discovery only picks up `<dirName>.agent.ts`, so this */\n/* sibling adapter is registered at runtime but not yet listed in */\n/* dist/agent-catalog.json (same situation as appointment-tray inside */\n/* the appointment-card directory). */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { ProductHubPanelHandle } from './product-hub-panel';\n\nexport const productHubPanelAgent: AgentAdapter<ProductHubPanelHandle> = {\n id: 'product-hub-panel',\n // selectItem activates one release row (fires the host hook) without\n // persisting a stored selection → `pick`, not `select_single`.\n capabilities: ['pick'],\n state: {\n items: {\n type: 'Array<{ id: string; unseen: boolean }>',\n descriptionKey: 'ui.agent.productHubPanel.state.items',\n description:\n 'Currently-displayed releases. Ids + unseen flag only — no content.',\n read: (handle) => handle.getItems(),\n },\n unseenCount: {\n type: 'number',\n descriptionKey: 'ui.agent.productHubPanel.state.unseenCount',\n description: 'Number of displayed releases still marked unseen.',\n read: (handle) => handle.getUnseenCount(),\n },\n },\n actions: {\n select_item: {\n safety: 'read',\n argsType: '{ id: string }',\n argsSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Stable release id (the data-update-id of the row).',\n },\n },\n required: ['id'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.productHubPanel.actions.selectItem',\n description:\n 'Activate the release with the given id (fires the host analytics hook).',\n examples: [\n { args: { id: 'rel-0680' }, note: 'Activate a specific release row.' },\n ],\n invoke: (handle, args: { id: string }) => {\n handle.selectItem(args.id);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'product-hub-panel',\n description: 'Marks the ProductHubPanel section.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific panel from the agent.',\n },\n item: {\n attr: 'data-update-id',\n description:\n 'Stable release id emitted on each rendered release row inside the panel.',\n },\n },\n};\n","import {\n forwardRef,\n useImperativeHandle,\n useMemo,\n useRef,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Gift } from 'lucide-react';\nimport { EmptyState } from '../empty-state/empty-state';\nimport { Link } from '../link';\nimport { Separator } from '../separator/separator';\nimport { isSafeEntityUrl } from '../_shared/is-safe-url';\nimport { useAgentRegistration } from '../../agent/registry';\nimport {\n ProductHubUpdateRow,\n UpdateSkeletonRow,\n UpdateStatusPanel,\n type ProductHubItem,\n} from './product-hub-tray';\nimport { productHubPanelAgent } from './product-hub-panel.agent';\n\n/* -------------------------------------------------------------------- */\n/* ProductHubPanel */\n/* */\n/* Dashboard-panel sibling of ProductHubTray: a titled, bordered card */\n/* (model: AgendaTray + the dashboard \"Recent notifications\" panel) */\n/* listing the same release rows at a roomier density — no popover. */\n/* The consumer fetches the data; loading / empty / error are props. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA */\n/* -------------------------------------------------------------------- */\n\nconst productHubPanelVariants = cva(\n [\n 'ds:flex ds:flex-col',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:[:where(&)]:border-[length:var(--surface-border-width,var(--border-width-sm))] ds:border-[color:var(--card-border)]',\n 'ds:bg-[color:var(--card)] ds:text-[color:var(--card-foreground)]',\n 'ds:overflow-hidden',\n 'ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n surface: {\n flat: '',\n elevated: 'ds:shadow-[var(--shadow-card)]',\n },\n },\n defaultVariants: {\n surface: 'elevated',\n },\n },\n);\n\n/* -------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------- */\n\n/**\n * Curated imperative handle for ProductHubPanel — read-only ids / counts\n * plus a select delegation. See `product-hub-panel.agent.ts`.\n */\nexport interface ProductHubPanelHandle {\n getItems: () => Array<{ id: string; unseen: boolean }>;\n getUnseenCount: () => number;\n selectItem: (id: string) => void;\n}\n\nexport interface ProductHubPanelProps\n extends\n Omit<HTMLAttributes<HTMLElement>, 'onClick' | 'children' | 'id'>,\n VariantProps<typeof productHubPanelVariants> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so\n * an agent / MCP UI bridge can address this specific panel.\n */\n id?: string;\n /** Releases rendered in the panel, newest first. */\n items: ProductHubItem[];\n /**\n * Product-hub landing URL. When set (and safe) the panel renders an\n * \"Open in Product Hub\" footer link that opens in a new tab.\n */\n hubUrl?: string;\n /** When true the panel shows skeleton placeholders. */\n loading?: boolean;\n /** Error-state slot — rendered instead of the list. */\n error?: ReactNode;\n /** Panel heading. Defaults to the localised \"What's new\". */\n title?: string;\n /** Optional sub-heading rendered under the title. */\n description?: string;\n /** Number of releases rendered before the rest are cut off. Default 5. */\n maxVisible?: number;\n /** Empty-state slot — replaces the built-in EmptyState. */\n emptyState?: ReactNode;\n /**\n * Analytics hook — fires when a row is activated. Navigation itself is\n * owned by the row anchor (new tab).\n */\n onItemActivate?: (item: ProductHubItem) => void;\n /** BCP-47 locale override for the per-row dates. */\n locale?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const ProductHubPanel = forwardRef<HTMLElement, ProductHubPanelProps>(\n (\n {\n id,\n items,\n hubUrl,\n loading = false,\n error,\n title,\n description,\n maxVisible = 5,\n emptyState,\n onItemActivate,\n locale,\n surface = 'elevated',\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const heading = title ?? t('productHubPanel.title', \"What's new\");\n\n const visible = items.slice(0, Math.max(0, maxVisible));\n const safeHubUrl = hubUrl && isSafeEntityUrl(hubUrl) ? hubUrl : undefined;\n\n let body: ReactNode;\n if (error) {\n body = <UpdateStatusPanel>{error}</UpdateStatusPanel>;\n } else if (loading) {\n body = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:p-[var(--spacing-sm)] ds:pt-0\">\n {[0, 1, 2].map((i) => (\n <UpdateSkeletonRow key={i} density=\"panel\" />\n ))}\n </div>\n );\n } else if (visible.length === 0) {\n body = emptyState ?? (\n <div className=\"ds:p-[var(--spacing-md)]\">\n <EmptyState\n variant=\"first-use\"\n size=\"sm\"\n title={t('productHubPanel.emptyTitle', 'No product updates yet')}\n description={t(\n 'productHubPanel.emptyDescription',\n 'New releases and improvements will appear here.',\n )}\n />\n </div>\n );\n } else {\n body = (\n <div\n role=\"list\"\n data-max-visible={maxVisible}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:p-[var(--spacing-sm)] ds:pt-0\"\n >\n {visible.map((item) => (\n <ProductHubUpdateRow\n key={item.id}\n item={item}\n density=\"panel\"\n locale={locale}\n onActivate={onItemActivate}\n />\n ))}\n </div>\n );\n }\n\n /* Curated imperative handle for agent integration. */\n const itemsRef = useRef<ProductHubItem[]>(items);\n itemsRef.current = items;\n\n const handle = useMemo<ProductHubPanelHandle>(\n () => ({\n getItems: () =>\n itemsRef.current.map((i) => ({ id: i.id, unseen: !!i.unseen })),\n getUnseenCount: () => itemsRef.current.filter((i) => i.unseen).length,\n selectItem: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onItemActivate?.(found);\n },\n }),\n [onItemActivate],\n );\n\n const innerRef = useRef<HTMLElement>(null);\n useImperativeHandle(ref, () => innerRef.current as HTMLElement, []);\n useAgentRegistration(productHubPanelAgent, handle, id);\n\n return (\n <section\n ref={innerRef}\n aria-label={heading}\n data-component=\"product-hub-panel\"\n data-component-id={id}\n className={productHubPanelVariants({ surface, className })}\n {...rest}\n >\n <header className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)] ds:p-[var(--spacing-md)] ds:pb-[var(--spacing-sm)]\">\n {/* h2 — visual peer of the dashboard's other titled regions.\n Heading ladder: h1 (page) → h2 (this panel) → row titles. */}\n <h2 className=\"ds:m-0 ds:flex ds:items-center ds:gap-[var(--spacing-xs)] ds:text-start type-title-section ds:text-[color:var(--foreground)]\">\n <Gift aria-hidden=\"true\" className=\"ds:size-5 ds:shrink-0\" />\n {heading}\n </h2>\n {description ? (\n <p className=\"ds:m-0 ds:text-start type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {description}\n </p>\n ) : null}\n </header>\n {body}\n {safeHubUrl ? (\n <>\n <Separator />\n <div className=\"ds:flex ds:justify-center ds:p-[var(--spacing-sm)]\">\n <Link href={safeHubUrl} external>\n {t('productHubPanel.openHub', 'Open in Product Hub')}\n </Link>\n </div>\n </>\n ) : null}\n </section>\n );\n },\n);\n\nProductHubPanel.displayName = 'ProductHubPanel';\n"],"names":["__iconNode","Gift","createLucideIcon","productHubTrayAgent","handle","productHubTrayVariants","cva","panelVariants","badgeVariants","rowVariants","thumbVariants","stretchedLinkClass","ProductHubUpdateRow","item","density","surface","locale","onActivate","onDismiss","className","rest","t","useTranslation","safeSrc","safeImageSrc","hasSafeUrl","isSafeEntityUrl","unseen","closeInset","unseenHint","jsx","jsxs","Fragment","Timestamp","IconButton","X","UpdateSkeletonRow","Skeleton","UpdateStatusPanel","children","formatBadgeCount","count","overflowLabel","EmptyPanel","ProductHubTray","forwardRef","id","items","hubUrl","loading","error","unseenCount","onOpenChange","onItemActivate","triggerLabel","maxVisible","emptyState","defaultOpen","align","side","size","ref","isOpenRaw","handleOpenChange","useControllableState","isOpen","displayCount","i","resolvedTriggerLabel","badgeLabel","visible","showList","safeHubUrl","itemsRef","useRef","unseenRef","useMemo","rootRef","useImperativeHandle","useAgentRegistration","body","exitOnTab","useNonModalTabExit","findPopoverTrigger","RadixPopover","Separator","ScrollArea","Link","productHubPanelAgent","args","productHubPanelVariants","ProductHubPanel","title","description","heading","EmptyState","targetId","found","innerRef"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"product-hub-panel-C_ZosrBt.js","sources":["../../node_modules/lucide-react/dist/esm/icons/gift.mjs","../../src/components/product-hub-tray/product-hub-tray.agent.ts","../../src/components/product-hub-tray/product-hub-tray.tsx","../../src/components/product-hub-tray/product-hub-panel.agent.ts","../../src/components/product-hub-tray/product-hub-panel.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 7v14\", key: \"1akyts\" }],\n [\"path\", { d: \"M20 11v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-8\", key: \"1sqzm4\" }],\n [\n \"path\",\n { d: \"M7.5 7a1 1 0 0 1 0-5A4.8 8 0 0 1 12 7a4.8 8 0 0 1 4.5-5 1 1 0 0 1 0 5\", key: \"kc0143\" }\n ],\n [\"rect\", { x: \"3\", y: \"7\", width: \"18\", height: \"4\", rx: \"1\", key: \"1hberx\" }]\n];\nconst Gift = createLucideIcon(\"gift\", __iconNode);\n\nexport { __iconNode, Gift as default };\n//# sourceMappingURL=gift.mjs.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — ProductHubTray. */\n/* */\n/* Tray-level surface: an agent can open / close the dropdown panel and */\n/* read the unseen-release count. Release content (titles, summaries, */\n/* URLs) is never exposed — counts and booleans only. All actions are */\n/* routed through the curated imperative handle; the adapter never */\n/* touches the DOM directly. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { ProductHubTrayHandle } from './product-hub-tray';\n\nexport const productHubTrayAgent: AgentAdapter<ProductHubTrayHandle> = {\n id: 'product-hub-tray',\n capabilities: ['open', 'close'],\n state: {\n unseenCount: {\n type: 'number',\n descriptionKey: 'ui.agent.productHubTray.state.unseenCount',\n description:\n 'Number of unseen product releases — the trigger badge count.',\n read: (handle) => handle.getUnseenCount(),\n },\n },\n actions: {\n open: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.productHubTray.actions.open',\n description: 'Open the product-updates panel.',\n invoke: (handle) => {\n handle.open();\n },\n },\n close: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.productHubTray.actions.close',\n description: 'Close the product-updates panel.',\n invoke: (handle) => {\n handle.close();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'product-hub-tray',\n description: 'Marks the ProductHubTray wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific tray from the agent.',\n },\n item: {\n attr: 'data-update-id',\n description:\n 'Stable release id emitted on each rendered release row inside the tray.',\n },\n },\n};\n","import {\n forwardRef,\n useImperativeHandle,\n useMemo,\n useRef,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport * as RadixPopover from '@radix-ui/react-popover';\nimport {\n findPopoverTrigger,\n useNonModalTabExit,\n} from '../_shared/non-modal-tab-exit';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Gift, X } from 'lucide-react';\nimport { useControllableState } from '../../hooks/use-controllable-state';\nimport { IconButton } from '../button/icon-button';\nimport { Link } from '../link';\nimport { ScrollArea } from '../scroll-area/scroll-area';\nimport { Separator } from '../separator/separator';\nimport { Skeleton } from '../skeleton/skeleton';\nimport { Timestamp } from '../timestamp';\nimport { isSafeEntityUrl } from '../_shared/is-safe-url';\nimport { safeImageSrc } from '../_shared/safe-image-src';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { productHubTrayAgent } from './product-hub-tray.agent';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\n/**\n * One product-hub release entry. The kit is purely presentational —\n * the consumer fetches releases (Supabase, REST, …) and maps them into\n * this shape.\n */\nexport interface ProductHubItem {\n /** Unique identifier for the release. */\n id: string;\n /** Release title — rendered bold on the first line. */\n title: string;\n /** Short release summary — rendered as plain text, clamped to 2 lines. */\n summary?: string;\n /** ISO-8601 publish date — rendered as a localised, italic absolute date. */\n dateIso?: string;\n /**\n * Thumbnail URL. Guarded through the shared `safeImageSrc` allow-list\n * and rendered with `referrerPolicy=\"no-referrer\"`. Unsafe or missing\n * sources fall back to a Gift glyph tile.\n */\n imageUrl?: string;\n /**\n * Release deep link. Guarded through `isSafeEntityUrl`; safe URLs make\n * the row title an anchor that opens in a new tab. Unsafe URLs render\n * the title as plain text.\n */\n url?: string;\n /** Marks the release as not yet seen — highlights the row and counts toward the trigger badge. */\n unseen?: boolean;\n}\n\n/**\n * Curated imperative handle for ProductHubTray. Exposed to the agent\n * registry so a future MCP UI bridge can drive the tray without touching\n * the DOM. See `product-hub-tray.agent.ts`.\n */\nexport interface ProductHubTrayHandle {\n open: () => void;\n close: () => void;\n getUnseenCount: () => number;\n}\n\nexport interface ProductHubTrayProps\n extends\n Omit<\n HTMLAttributes<HTMLDivElement>,\n 'onClick' | 'children' | 'role' | 'id'\n >,\n VariantProps<typeof productHubTrayVariants> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so\n * an agent / MCP UI bridge can address this specific tray.\n */\n id?: string;\n /** Releases rendered in the dropdown panel, newest first. */\n items: ProductHubItem[];\n /**\n * Product-hub landing URL. When set (and safe) the panel renders a\n * pinned \"Open in Product Hub\" footer link that opens in a new tab.\n */\n hubUrl?: string;\n /** When true the panel shows skeleton placeholders. */\n loading?: boolean;\n /** Error-state slot — rendered inside the panel instead of the list. */\n error?: ReactNode;\n /**\n * Unseen-release count override. Defaults to the number of `items`\n * with `unseen: true`. Drives the trigger badge.\n */\n unseenCount?: number;\n /** Fires when the open state changes. */\n onOpenChange?: (open: boolean) => void;\n /**\n * Analytics hook — fires when a row is activated. Navigation itself is\n * owned by the row anchor (new tab); this callback must not be relied\n * on for routing.\n */\n onItemActivate?: (item: ProductHubItem) => void;\n /** Override for the trigger's accessible label. */\n triggerLabel?: string;\n /** Number of releases rendered before the rest are cut off. Default 10. */\n maxVisible?: number;\n /** Empty-state slot — replaces the built-in \"No product updates yet\" panel. */\n emptyState?: ReactNode;\n /** Open the panel on first mount (uncontrolled). */\n defaultOpen?: boolean;\n /** BCP-47 locale override for the per-row dates. Falls back to `i18n.language`. */\n locale?: string;\n /** Panel alignment relative to the trigger. Default `'end'`. */\n align?: 'start' | 'center' | 'end';\n /** Side of the trigger to open on. Default `'bottom'`. */\n side?: 'top' | 'bottom';\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst productHubTrayVariants = cva(\n 'ds:relative ds:inline-flex ds:items-center',\n {\n variants: {\n size: {\n sm: '',\n md: '',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n);\n\nconst panelVariants = cva(\n [\n 'ds:flex ds:flex-col',\n 'ds:bg-[var(--popover)] ds:text-[var(--popover-foreground)]',\n 'ds:border ds:border-[color:var(--card-border)]',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:shadow-[var(--shadow-lg)]',\n 'ds:z-[var(--z-popover)]',\n // Fluid below the design cap so narrow viewports keep a gutter on\n // both sides of the panel (shadow included).\n 'ds:w-[min(24rem,calc(100vw-2*var(--spacing-md)))]',\n // Near-full-screen sheet below `sm`; auto above, where the list's\n // own `--product-hub-tray-max-block-size` cap governs the height.\n 'ds:h-[calc(100dvh-6rem)] ds:sm:h-auto',\n 'ds:data-[state=open]:animate-in ds:data-[state=closed]:animate-out',\n 'ds:data-[state=closed]:fade-out-0 ds:data-[state=open]:fade-in-0',\n 'ds:data-[state=closed]:zoom-out-95 ds:data-[state=open]:zoom-in-95',\n 'ds:motion-reduce:transition-none ds:motion-reduce:animate-none',\n 'ds:focus-visible:outline-none',\n 'ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:p-[var(--spacing-xs)]',\n md: 'ds:p-[var(--spacing-sm)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n);\n\nconst badgeVariants = cva(\n [\n // Anchored to the top-end corner of the trigger, nudged outward so\n // the gift glyph isn't covered.\n 'ds:absolute ds:-top-[var(--spacing-xs)] ds:-end-[var(--spacing-xs)]',\n 'ds:inline-flex ds:items-center ds:justify-center',\n // Circle at 1-2 digits; widens into a pill only for \"99+\".\n 'ds:min-w-[calc(var(--spacing-md)+var(--spacing-xs))] ds:h-[calc(var(--spacing-md)+var(--spacing-xs))] ds:ps-[calc(var(--spacing-xs)/1.5)] ds:pe-[calc(var(--spacing-xs)/1.5)]',\n 'ds:rounded-[var(--radius-full)]',\n // One red unseen-count chip across every header tray — matches the\n // platform header and the NotificationTray badge convention.\n 'ds:bg-[color:var(--destructive)] ds:text-[color:var(--destructive-foreground)]',\n 'ds:text-[length:var(--font-size-xs)] ds:font-semibold ds:leading-none',\n 'ds:pointer-events-none ds:select-none',\n 'ds:forced-colors:outline ds:forced-colors:outline-1 ds:forced-colors:outline-[CanvasText]',\n ].join(' '),\n);\n\n/* ------------------------------------------------------------------ */\n/* Shared release row — used by both ProductHubTray (compact) and */\n/* ProductHubPanel (roomier). Internal seam, not part of the barrel. */\n/* ------------------------------------------------------------------ */\n\nconst rowVariants = cva(\n [\n // `group` so the hover/focus-revealed close button can react to the whole\n // row, not just itself.\n 'ds:group ds:relative ds:flex ds:items-start',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:text-start',\n 'ds:transition-colors ds:motion-reduce:transition-none',\n ].join(' '),\n {\n variants: {\n density: {\n tray: 'ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)]',\n panel: 'ds:gap-[var(--spacing-md)] ds:p-[var(--spacing-md)]',\n },\n // Unseen no longer tints the background — the read/new state is carried\n // by the leading-corner Gift indicator instead, matching the\n // notification / message cards.\n unseen: {\n true: 'ds:hover:bg-[color:var(--muted)]/40',\n false: 'ds:hover:bg-[color:var(--muted)]/40',\n },\n // Row chrome: flat (inside a bordered tray/panel) vs elevated (own card\n // on a rail). Mirrors AppointmentCard / NotificationCard so the Inbox\n // feed reads consistently with the other rail panels.\n surface: {\n flat: '',\n elevated:\n 'ds:[:where(&)]:border-[length:var(--surface-border-width,var(--border-width-sm))] ds:border-[color:var(--card-border)] ds:shadow-[var(--shadow-sm)]',\n },\n },\n defaultVariants: {\n density: 'tray',\n unseen: false,\n surface: 'flat',\n },\n },\n);\n\nconst thumbVariants = cva(\n [\n 'ds:shrink-0 ds:rounded-[var(--radius-sm)] ds:object-cover',\n // Tile backdrop so transparent / still-loading thumbnails keep a\n // visible square instead of collapsing into whitespace.\n 'ds:bg-[color:var(--muted)]',\n 'ds:forced-colors:border ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n density: {\n tray: 'ds:size-10',\n panel: 'ds:size-12',\n },\n },\n defaultVariants: {\n density: 'tray',\n },\n },\n);\n\nconst stretchedLinkClass = [\n 'ds:focus-visible:outline-none',\n \"ds:after:content-[''] ds:after:absolute ds:after:inset-0 ds:after:rounded-[var(--radius-sm)]\",\n 'ds:after:pointer-events-auto',\n 'ds:focus-visible:after:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:after:outline-solid',\n 'ds:focus-visible:after:outline-[color:var(--ring)]',\n 'ds:focus-visible:after:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:after:outline-[CanvasText]',\n].join(' ');\n\nexport interface ProductHubUpdateRowProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'onClick' | 'role' | 'title'\n> {\n /** The release to render. */\n item: ProductHubItem;\n /** `tray` — compact dropdown row. `panel` — roomier dashboard row. */\n density?: 'tray' | 'panel';\n /**\n * Row chrome. `'flat'` (default) — chrome-less row inside a bordered\n * tray/panel. `'elevated'` — own card chrome (border + `--shadow-sm`) for\n * rail feeds (e.g. the Inbox), matching the sibling notification/message\n * cards.\n */\n surface?: 'flat' | 'elevated';\n /** BCP-47 locale override for the date. */\n locale?: string;\n /** Analytics hook — navigation is owned by the row anchor. */\n onActivate?: (item: ProductHubItem) => void;\n /**\n * When supplied, renders a close affordance (revealed on row hover / focus)\n * that fires with this item — e.g. dismissing the update from an Inbox feed.\n */\n onDismiss?: (item: ProductHubItem) => void;\n}\n\n/**\n * @internal Shared row between ProductHubTray and ProductHubPanel.\n * Exported for the sibling panel only — import the trays, not this.\n */\nexport function ProductHubUpdateRow({\n item,\n density = 'tray',\n surface = 'flat',\n locale,\n onActivate,\n onDismiss,\n className,\n ...rest\n}: ProductHubUpdateRowProps) {\n const { t } = useTranslation('ui');\n const safeSrc = safeImageSrc(item.imageUrl);\n const hasSafeUrl = !!item.url && isSafeEntityUrl(item.url);\n const unseen = !!item.unseen;\n\n // Close insets track the row padding so it aligns with the title's first\n // line at either density.\n const closeInset =\n density === 'panel'\n ? 'ds:top-[var(--spacing-md)] ds:end-[var(--spacing-md)]'\n : 'ds:top-[var(--spacing-sm)] ds:end-[var(--spacing-sm)]';\n\n // Read after the title when the row gets focus / is traversed:\n // \"<title>, new, (opens in a new tab)\". The unseen dot itself is\n // decorative — state never relies on colour alone.\n const unseenHint = unseen ? (\n <span className=\"ds:sr-only\">\n {t('productHubTray.unseenLabel', ', new')}\n </span>\n ) : null;\n\n return (\n <div\n role=\"listitem\"\n data-component=\"product-hub-update\"\n data-update-id={item.id}\n data-unseen={unseen ? 'true' : 'false'}\n className={rowVariants({ density, unseen, surface, className })}\n {...rest}\n >\n <span className=\"ds:relative ds:shrink-0\">\n {safeSrc ? (\n <img\n src={safeSrc}\n alt=\"\"\n aria-hidden=\"true\"\n referrerPolicy=\"no-referrer\"\n loading=\"lazy\"\n className={thumbVariants({ density })}\n />\n ) : (\n <span\n aria-hidden=\"true\"\n className={`${thumbVariants({ density })} ds:inline-flex ds:items-center ds:justify-center ds:text-[color:var(--muted-foreground)] ds:[&>svg]:size-5`}\n >\n <Gift />\n </span>\n )}\n {/* Unseen \"new\" marker — a dot on the thumbnail corner (the read /\n unread indicator moved inline-start). Decorative; the title link\n carries the sr-only \"new\" hint for assistive tech. */}\n {unseen ? (\n <span\n aria-hidden=\"true\"\n data-testid=\"product-hub-unseen-dot\"\n className=\"ds:absolute ds:top-[calc(var(--spacing-xs)*-1)] ds:end-[calc(var(--spacing-xs)*-1)] ds:z-[1] ds:block ds:size-[calc(var(--spacing-sm)+var(--spacing-xs))] ds:rounded-[var(--radius-full)] ds:bg-[color:var(--primary)] ds:ring-2 ds:ring-[color:var(--card)] ds:forced-colors:bg-[Highlight]\"\n />\n ) : null}\n </span>\n\n <div className=\"ds:min-w-0 ds:flex-1 ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <span className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)] type-title-item ds:text-[color:var(--foreground)]\">\n {hasSafeUrl ? (\n // A real (non-display:contents) anchor so the row is reliably\n // keyboard-focusable; the ::after stretch keeps the whole row\n // clickable and carries the focus ring.\n <a\n href={item.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`${stretchedLinkClass} ds:min-w-0 ds:flex-1 ds:no-underline ds:text-[color:var(--foreground)]`}\n onClick={() => onActivate?.(item)}\n >\n <span className=\"ds:block ds:truncate ds:font-semibold\">\n {item.title}\n </span>\n {unseenHint}\n <span className=\"ds:sr-only\">\n {t('productHubTray.opensInNewTab', '(opens in a new tab)')}\n </span>\n </a>\n ) : (\n <>\n <span className=\"ds:min-w-0 ds:flex-1 ds:truncate ds:font-semibold\">\n {item.title}\n </span>\n {unseenHint}\n </>\n )}\n </span>\n\n {item.summary ? (\n <p className=\"ds:m-0 type-body-sm ds:text-[color:var(--muted-foreground)] ds:[overflow:hidden] ds:[display:-webkit-box] ds:[-webkit-box-orient:vertical] ds:[-webkit-line-clamp:2] ds:break-words\">\n {item.summary}\n </p>\n ) : null}\n\n {item.dateIso ? (\n <Timestamp\n value={item.dateIso}\n format=\"absolute\"\n locale={locale}\n className=\"ds:italic ds:text-[color:var(--muted-foreground)]\"\n />\n ) : null}\n </div>\n\n {/* Close — inline-end, hover/focus-revealed. Absolutely positioned so it\n claims no width at rest: the title fills the row and there's no empty\n gap when the row isn't hovered. */}\n {onDismiss ? (\n <span\n className={\n 'ds:absolute ds:z-[2] ds:opacity-0 ds:pointer-events-none ds:transition-opacity ds:motion-reduce:transition-none ds:group-hover:opacity-100 ds:group-hover:pointer-events-auto ds:group-focus-within:opacity-100 ds:group-focus-within:pointer-events-auto ' +\n closeInset\n }\n >\n <IconButton\n icon={<X />}\n intent=\"ghost\"\n size=\"sm\"\n aria-label={t('productHubTray.dismiss', 'Dismiss update')}\n onClick={() => onDismiss(item)}\n />\n </span>\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Shared loading / status helpers (also consumed by ProductHubPanel) */\n/* ------------------------------------------------------------------ */\n\n/** @internal Skeleton placeholder mirroring the row layout. */\nexport function UpdateSkeletonRow({\n density = 'tray',\n}: {\n density?: 'tray' | 'panel';\n}) {\n return (\n <div\n aria-hidden=\"true\"\n className={\n density === 'panel'\n ? 'ds:flex ds:items-start ds:gap-[var(--spacing-md)] ds:p-[var(--spacing-md)]'\n : 'ds:flex ds:items-start ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)]'\n }\n >\n <Skeleton\n variant=\"rounded\"\n width={density === 'panel' ? '3rem' : '2.5rem'}\n height={density === 'panel' ? '3rem' : '2.5rem'}\n />\n <div className=\"ds:flex-1 ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <Skeleton variant=\"text\" size=\"md\" width=\"60%\" />\n <Skeleton variant=\"text\" size=\"sm\" width=\"90%\" />\n <Skeleton variant=\"text\" size=\"sm\" width=\"30%\" />\n </div>\n </div>\n );\n}\n\n/** @internal Centered status container for error / consumer-slot states. */\nexport function UpdateStatusPanel({ children }: { children: ReactNode }) {\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"ds:flex ds:flex-col ds:items-center ds:justify-center ds:gap-[var(--spacing-xs)] ds:p-[var(--spacing-lg)] ds:text-center type-body-sm ds:text-[color:var(--muted-foreground)]\"\n >\n {children}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\nfunction formatBadgeCount(count: number, overflowLabel: string): string {\n return count > 99 ? overflowLabel : String(count);\n}\n\nfunction EmptyPanel() {\n const { t } = useTranslation('ui');\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"ds:flex ds:flex-col ds:items-center ds:justify-center ds:gap-[var(--spacing-xs)] ds:p-[var(--spacing-lg)] ds:text-center\"\n >\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-flex ds:items-center ds:justify-center ds:size-10 ds:rounded-[var(--radius-full)] ds:bg-[color:var(--muted)] ds:text-[color:var(--muted-foreground)] ds:[&>svg]:size-5\"\n >\n <Gift />\n </span>\n <p className=\"type-title-item ds:text-[color:var(--foreground)]\">\n {t('productHubTray.emptyTitle', 'No product updates yet')}\n </p>\n <p className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {t(\n 'productHubTray.emptyDescription',\n 'New releases and improvements will appear here.',\n )}\n </p>\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Root */\n/* ------------------------------------------------------------------ */\n\nexport const ProductHubTray = forwardRef<HTMLDivElement, ProductHubTrayProps>(\n (\n {\n id,\n items,\n hubUrl,\n loading = false,\n error,\n unseenCount,\n onOpenChange,\n onItemActivate,\n triggerLabel,\n maxVisible = 10,\n emptyState,\n defaultOpen = false,\n locale,\n align = 'end',\n side = 'bottom',\n size = 'md',\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n\n const [isOpenRaw, handleOpenChange] = useControllableState<boolean>({\n defaultValue: defaultOpen,\n onChange: onOpenChange,\n });\n const isOpen = isOpenRaw ?? false;\n\n const displayCount = unseenCount ?? items.filter((i) => i.unseen).length;\n const resolvedTriggerLabel =\n triggerLabel ??\n (displayCount > 0\n ? t('productHubTray.triggerLabel', {\n count: displayCount,\n defaultValue: \"What's new, {{count}} unseen updates\",\n })\n : t('productHubTray.triggerLabelNone', \"What's new\"));\n\n const badgeLabel = formatBadgeCount(\n displayCount,\n t('productHubTray.badgeCountOverflow', '99+'),\n );\n\n const visible = items.slice(0, Math.max(0, maxVisible));\n const showList = !error && !loading && visible.length > 0;\n const safeHubUrl = hubUrl && isSafeEntityUrl(hubUrl) ? hubUrl : undefined;\n\n /* Curated handle — refs keep the look-ups current without\n * re-memoising on every items update. */\n const itemsRef = useRef<ProductHubItem[]>(items);\n itemsRef.current = items;\n const unseenRef = useRef<number | undefined>(unseenCount);\n unseenRef.current = unseenCount;\n\n const handle = useMemo<ProductHubTrayHandle>(\n () => ({\n open: () => handleOpenChange(true),\n close: () => handleOpenChange(false),\n getUnseenCount: () =>\n unseenRef.current ?? itemsRef.current.filter((i) => i.unseen).length,\n }),\n [handleOpenChange],\n );\n\n const rootRef = useRef<HTMLDivElement>(null);\n useImperativeHandle(ref, () => rootRef.current as HTMLDivElement, []);\n useAgentRegistration(productHubTrayAgent, handle, id);\n\n let body: ReactNode;\n if (error) {\n body = <UpdateStatusPanel>{error}</UpdateStatusPanel>;\n } else if (loading) {\n body = (\n <>\n <UpdateSkeletonRow />\n <UpdateSkeletonRow />\n <UpdateSkeletonRow />\n </>\n );\n } else if (visible.length === 0) {\n body = emptyState ?? <EmptyPanel />;\n } else {\n body = visible.map((item) => (\n <ProductHubUpdateRow\n key={item.id}\n item={item}\n density=\"tray\"\n locale={locale}\n onActivate={onItemActivate}\n />\n ));\n }\n\n const exitOnTab = useNonModalTabExit(true, {\n getAnchor: findPopoverTrigger,\n onReturnToTrigger: () => handleOpenChange(false),\n });\n\n return (\n <div\n ref={rootRef}\n data-component=\"product-hub-tray\"\n data-component-id={id}\n className={[productHubTrayVariants({ size }), className]\n .filter(Boolean)\n .join(' ')}\n {...rest}\n >\n <RadixPopover.Root open={isOpen} onOpenChange={handleOpenChange}>\n <RadixPopover.Trigger asChild>\n <IconButton\n icon={<Gift />}\n intent=\"outline\"\n size={size === 'sm' ? 'sm' : 'md'}\n aria-label={resolvedTriggerLabel}\n aria-haspopup=\"dialog\"\n />\n </RadixPopover.Trigger>\n {displayCount > 0 ? (\n <span\n aria-hidden=\"true\"\n data-testid=\"product-hub-tray-badge\"\n className={badgeVariants()}\n >\n {badgeLabel}\n </span>\n ) : null}\n <RadixPopover.Portal>\n <RadixPopover.Content\n role=\"dialog\"\n onKeyDown={exitOnTab}\n aria-label={t('productHubTray.panelTitle', \"What's new\")}\n side={side}\n align={align}\n sideOffset={8}\n // Keeps Radix's collision-avoidance from flush-mounting the\n // panel against the viewport edge on narrow screens.\n collisionPadding={16}\n className={panelVariants({ size })}\n >\n <div className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)] ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:pb-[var(--spacing-xs)]\">\n <h3 className=\"ds:m-0 type-title-card ds:text-[color:var(--foreground)]\">\n {t('productHubTray.panelTitle', \"What's new\")}\n </h3>\n </div>\n <Separator />\n {/* The release list is the ONLY scroll region. `role=\"list\"`\n requires `listitem` children, so it is applied only when\n rows render (axe aria-required-children). Consumers\n override the height cap via the\n `--product-hub-tray-max-block-size` custom property. */}\n <ScrollArea\n orientation=\"vertical\"\n className=\"ds:flex-1 ds:sm:flex-none ds:sm:[max-block-size:var(--product-hub-tray-max-block-size,24rem)]\"\n >\n <div\n role={showList ? 'list' : undefined}\n data-max-visible={maxVisible}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:pt-[var(--spacing-xs)]\"\n >\n {body}\n </div>\n </ScrollArea>\n {safeHubUrl ? (\n <>\n <Separator />\n <div className=\"ds:flex ds:justify-center ds:pt-[var(--spacing-sm)] ds:pb-[var(--spacing-xs)]\">\n <Link href={safeHubUrl} external>\n {t('productHubTray.openHub', 'Open in Product Hub')}\n </Link>\n </div>\n </>\n ) : null}\n </RadixPopover.Content>\n </RadixPopover.Portal>\n </RadixPopover.Root>\n </div>\n );\n },\n);\n\nProductHubTray.displayName = 'ProductHubTray';\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — ProductHubPanel. */\n/* */\n/* Read-mostly dashboard surface: an agent can read the displayed */\n/* release ids + unseen flags (never titles / summaries / URLs) and */\n/* route a per-item activation through the curated handle. The adapter */\n/* never touches the DOM directly. */\n/* */\n/* NOTE: catalog discovery only picks up `<dirName>.agent.ts`, so this */\n/* sibling adapter is registered at runtime but not yet listed in */\n/* dist/agent-catalog.json (same situation as appointment-tray inside */\n/* the appointment-card directory). */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { ProductHubPanelHandle } from './product-hub-panel';\n\nexport const productHubPanelAgent: AgentAdapter<ProductHubPanelHandle> = {\n id: 'product-hub-panel',\n // selectItem activates one release row (fires the host hook) without\n // persisting a stored selection → `pick`, not `select_single`.\n capabilities: ['pick'],\n state: {\n items: {\n type: 'Array<{ id: string; unseen: boolean }>',\n descriptionKey: 'ui.agent.productHubPanel.state.items',\n description:\n 'Currently-displayed releases. Ids + unseen flag only — no content.',\n read: (handle) => handle.getItems(),\n },\n unseenCount: {\n type: 'number',\n descriptionKey: 'ui.agent.productHubPanel.state.unseenCount',\n description: 'Number of displayed releases still marked unseen.',\n read: (handle) => handle.getUnseenCount(),\n },\n },\n actions: {\n select_item: {\n safety: 'read',\n argsType: '{ id: string }',\n argsSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Stable release id (the data-update-id of the row).',\n },\n },\n required: ['id'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.productHubPanel.actions.selectItem',\n description:\n 'Activate the release with the given id (fires the host analytics hook).',\n examples: [\n { args: { id: 'rel-0680' }, note: 'Activate a specific release row.' },\n ],\n invoke: (handle, args: { id: string }) => {\n handle.selectItem(args.id);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'product-hub-panel',\n description: 'Marks the ProductHubPanel section.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific panel from the agent.',\n },\n item: {\n attr: 'data-update-id',\n description:\n 'Stable release id emitted on each rendered release row inside the panel.',\n },\n },\n};\n","import {\n forwardRef,\n useImperativeHandle,\n useMemo,\n useRef,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Gift } from 'lucide-react';\nimport { EmptyState } from '../empty-state/empty-state';\nimport { Link } from '../link';\nimport { Separator } from '../separator/separator';\nimport { isSafeEntityUrl } from '../_shared/is-safe-url';\nimport { useAgentRegistration } from '../../agent/registry';\nimport {\n ProductHubUpdateRow,\n UpdateSkeletonRow,\n UpdateStatusPanel,\n type ProductHubItem,\n} from './product-hub-tray';\nimport { productHubPanelAgent } from './product-hub-panel.agent';\n\n/* -------------------------------------------------------------------- */\n/* ProductHubPanel */\n/* */\n/* Dashboard-panel sibling of ProductHubTray: a titled, bordered card */\n/* (model: AgendaTray + the dashboard \"Recent notifications\" panel) */\n/* listing the same release rows at a roomier density — no popover. */\n/* The consumer fetches the data; loading / empty / error are props. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA */\n/* -------------------------------------------------------------------- */\n\nconst productHubPanelVariants = cva(\n [\n 'ds:flex ds:flex-col',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:[:where(&)]:border-[length:var(--surface-border-width,var(--border-width-sm))] ds:border-[color:var(--card-border)]',\n 'ds:bg-[color:var(--card)] ds:text-[color:var(--card-foreground)]',\n 'ds:overflow-hidden',\n 'ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n surface: {\n flat: '',\n elevated: 'ds:shadow-[var(--shadow-card)]',\n },\n },\n defaultVariants: {\n surface: 'elevated',\n },\n },\n);\n\n/* -------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------- */\n\n/**\n * Curated imperative handle for ProductHubPanel — read-only ids / counts\n * plus a select delegation. See `product-hub-panel.agent.ts`.\n */\nexport interface ProductHubPanelHandle {\n getItems: () => Array<{ id: string; unseen: boolean }>;\n getUnseenCount: () => number;\n selectItem: (id: string) => void;\n}\n\nexport interface ProductHubPanelProps\n extends\n Omit<HTMLAttributes<HTMLElement>, 'onClick' | 'children' | 'id'>,\n VariantProps<typeof productHubPanelVariants> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so\n * an agent / MCP UI bridge can address this specific panel.\n */\n id?: string;\n /** Releases rendered in the panel, newest first. */\n items: ProductHubItem[];\n /**\n * Product-hub landing URL. When set (and safe) the panel renders an\n * \"Open in Product Hub\" footer link that opens in a new tab.\n */\n hubUrl?: string;\n /** When true the panel shows skeleton placeholders. */\n loading?: boolean;\n /** Error-state slot — rendered instead of the list. */\n error?: ReactNode;\n /** Panel heading. Defaults to the localised \"What's new\". */\n title?: string;\n /** Optional sub-heading rendered under the title. */\n description?: string;\n /** Number of releases rendered before the rest are cut off. Default 5. */\n maxVisible?: number;\n /** Empty-state slot — replaces the built-in EmptyState. */\n emptyState?: ReactNode;\n /**\n * Analytics hook — fires when a row is activated. Navigation itself is\n * owned by the row anchor (new tab).\n */\n onItemActivate?: (item: ProductHubItem) => void;\n /** BCP-47 locale override for the per-row dates. */\n locale?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const ProductHubPanel = forwardRef<HTMLElement, ProductHubPanelProps>(\n (\n {\n id,\n items,\n hubUrl,\n loading = false,\n error,\n title,\n description,\n maxVisible = 5,\n emptyState,\n onItemActivate,\n locale,\n surface = 'elevated',\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const heading = title ?? t('productHubPanel.title', \"What's new\");\n\n const visible = items.slice(0, Math.max(0, maxVisible));\n const safeHubUrl = hubUrl && isSafeEntityUrl(hubUrl) ? hubUrl : undefined;\n\n let body: ReactNode;\n if (error) {\n body = <UpdateStatusPanel>{error}</UpdateStatusPanel>;\n } else if (loading) {\n body = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:p-[var(--spacing-sm)] ds:pt-0\">\n {[0, 1, 2].map((i) => (\n <UpdateSkeletonRow key={i} density=\"panel\" />\n ))}\n </div>\n );\n } else if (visible.length === 0) {\n body = emptyState ?? (\n <div className=\"ds:p-[var(--spacing-md)]\">\n <EmptyState\n variant=\"first-use\"\n size=\"sm\"\n title={t('productHubPanel.emptyTitle', 'No product updates yet')}\n description={t(\n 'productHubPanel.emptyDescription',\n 'New releases and improvements will appear here.',\n )}\n />\n </div>\n );\n } else {\n body = (\n <div\n role=\"list\"\n data-max-visible={maxVisible}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:p-[var(--spacing-sm)] ds:pt-0\"\n >\n {visible.map((item) => (\n <ProductHubUpdateRow\n key={item.id}\n item={item}\n density=\"panel\"\n locale={locale}\n onActivate={onItemActivate}\n />\n ))}\n </div>\n );\n }\n\n /* Curated imperative handle for agent integration. */\n const itemsRef = useRef<ProductHubItem[]>(items);\n itemsRef.current = items;\n\n const handle = useMemo<ProductHubPanelHandle>(\n () => ({\n getItems: () =>\n itemsRef.current.map((i) => ({ id: i.id, unseen: !!i.unseen })),\n getUnseenCount: () => itemsRef.current.filter((i) => i.unseen).length,\n selectItem: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onItemActivate?.(found);\n },\n }),\n [onItemActivate],\n );\n\n const innerRef = useRef<HTMLElement>(null);\n useImperativeHandle(ref, () => innerRef.current as HTMLElement, []);\n useAgentRegistration(productHubPanelAgent, handle, id);\n\n return (\n <section\n ref={innerRef}\n aria-label={heading}\n data-component=\"product-hub-panel\"\n data-component-id={id}\n className={productHubPanelVariants({ surface, className })}\n {...rest}\n >\n <header className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)] ds:p-[var(--spacing-md)] ds:pb-[var(--spacing-sm)]\">\n {/* h2 — visual peer of the dashboard's other titled regions.\n Heading ladder: h1 (page) → h2 (this panel) → row titles. */}\n <h2 className=\"ds:m-0 ds:flex ds:items-center ds:gap-[var(--spacing-xs)] ds:text-start type-title-section ds:text-[color:var(--foreground)]\">\n <Gift aria-hidden=\"true\" className=\"ds:size-5 ds:shrink-0\" />\n {heading}\n </h2>\n {description ? (\n <p className=\"ds:m-0 ds:text-start type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {description}\n </p>\n ) : null}\n </header>\n {body}\n {safeHubUrl ? (\n <>\n <Separator />\n <div className=\"ds:flex ds:justify-center ds:p-[var(--spacing-sm)]\">\n <Link href={safeHubUrl} external>\n {t('productHubPanel.openHub', 'Open in Product Hub')}\n </Link>\n </div>\n </>\n ) : null}\n </section>\n );\n },\n);\n\nProductHubPanel.displayName = 'ProductHubPanel';\n"],"names":["__iconNode","Gift","createLucideIcon","productHubTrayAgent","handle","productHubTrayVariants","cva","panelVariants","badgeVariants","rowVariants","thumbVariants","stretchedLinkClass","ProductHubUpdateRow","item","density","surface","locale","onActivate","onDismiss","className","rest","t","useTranslation","safeSrc","safeImageSrc","hasSafeUrl","isSafeEntityUrl","unseen","closeInset","unseenHint","jsx","jsxs","Fragment","Timestamp","IconButton","X","UpdateSkeletonRow","Skeleton","UpdateStatusPanel","children","formatBadgeCount","count","overflowLabel","EmptyPanel","ProductHubTray","forwardRef","id","items","hubUrl","loading","error","unseenCount","onOpenChange","onItemActivate","triggerLabel","maxVisible","emptyState","defaultOpen","align","side","size","ref","isOpenRaw","handleOpenChange","useControllableState","isOpen","displayCount","i","resolvedTriggerLabel","badgeLabel","visible","showList","safeHubUrl","itemsRef","useRef","unseenRef","useMemo","rootRef","useImperativeHandle","useAgentRegistration","body","exitOnTab","useNonModalTabExit","findPopoverTrigger","RadixPopover","Separator","ScrollArea","Link","productHubPanelAgent","args","productHubPanelVariants","ProductHubPanel","title","description","heading","EmptyState","targetId","found","innerRef"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAMA,KAAa;AAAA,EACjB,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAAA,EACzC,CAAC,QAAQ,EAAE,GAAG,6CAA6C,KAAK,SAAQ,CAAE;AAAA,EAC1E;AAAA,IACE;AAAA,IACA,EAAE,GAAG,yEAAyE,KAAK,SAAQ;AAAA,EAC/F;AAAA,EACE,CAAC,QAAQ,EAAE,GAAG,KAAK,GAAG,KAAK,OAAO,MAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,SAAQ,CAAE;AAC/E,GACMC,IAAOC,GAAiB,QAAQF,EAAU,GCLnCG,KAA0D;AAAA,EACrE,IAAI;AAAA,EACJ,cAAc,CAAC,QAAQ,OAAO;AAAA,EAC9B,OAAO;AAAA,IACL,aAAa;AAAA,MACX,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACC,MAAWA,EAAO,eAAA;AAAA,IAAe;AAAA,EAC1C;AAAA,EAEF,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACA,MAAW;AAClB,QAAAA,EAAO,KAAA;AAAA,MACT;AAAA,IAAA;AAAA,IAEF,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACA,MAAW;AAClB,QAAAA,EAAO,MAAA;AAAA,MACT;AAAA,IAAA;AAAA,EACF;AAAA,EAEF,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IAAA;AAAA,IAEf,YAAY;AAAA,MACV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,aACE;AAAA,IAAA;AAAA,IAEJ,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aACE;AAAA,IAAA;AAAA,EACJ;AAEJ,GCkEMC,KAAyBC;AAAA,EAC7B;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MAAA;AAAA,IACN;AAAA,IAEF,iBAAiB;AAAA,MACf,MAAM;AAAA,IAAA;AAAA,EACR;AAEJ,GAEMC,KAAgBD;AAAA,EACpB;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA;AAAA,IAGA;AAAA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MAAA;AAAA,IACN;AAAA,IAEF,iBAAiB;AAAA,MACf,MAAM;AAAA,IAAA;AAAA,EACR;AAEJ,GAEME,KAAgBF;AAAA,EACpB;AAAA;AAAA;AAAA,IAGE;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,GAAG;AACZ,GAOMG,KAAcH;AAAA,EAClB;AAAA;AAAA;AAAA,IAGE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA;AAAA;AAAA;AAAA,MAKT,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA;AAAA;AAAA;AAAA,MAKT,SAAS;AAAA,QACP,MAAM;AAAA,QACN,UACE;AAAA,MAAA;AAAA,IACJ;AAAA,IAEF,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,SAAS;AAAA,IAAA;AAAA,EACX;AAEJ,GAEMI,IAAgBJ;AAAA,EACpB;AAAA,IACE;AAAA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,IAEF,iBAAiB;AAAA,MACf,SAAS;AAAA,IAAA;AAAA,EACX;AAEJ,GAEMK,KAAqB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG;AAgCH,SAASC,EAAoB;AAAA,EAClC,MAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,SAAAC,IAAU;AAAA,EACV,QAAAC;AAAA,EACA,YAAAC;AAAA,EACA,WAAAC;AAAA,EACA,WAAAC;AAAA,EACA,GAAGC;AACL,GAA6B;AAC3B,QAAM,EAAE,GAAAC,EAAA,IAAMC,EAAe,IAAI,GAC3BC,IAAUC,GAAaX,EAAK,QAAQ,GACpCY,IAAa,CAAC,CAACZ,EAAK,OAAOa,EAAgBb,EAAK,GAAG,GACnDc,IAAS,CAAC,CAACd,EAAK,QAIhBe,IACJd,MAAY,UACR,0DACA,yDAKAe,IAAaF,IACjB,gBAAAG,EAAC,QAAA,EAAK,WAAU,cACb,UAAAT,EAAE,8BAA8B,OAAO,EAAA,CAC1C,IACE;AAEJ,SACE,gBAAAU;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,kBAAe;AAAA,MACf,kBAAgBlB,EAAK;AAAA,MACrB,eAAac,IAAS,SAAS;AAAA,MAC/B,WAAWlB,GAAY,EAAE,SAAAK,GAAS,QAAAa,GAAQ,SAAAZ,GAAS,WAAAI,GAAW;AAAA,MAC7D,GAAGC;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAW,EAAC,QAAA,EAAK,WAAU,2BACb,UAAA;AAAA,UAAAR,IACC,gBAAAO;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,KAAKP;AAAA,cACL,KAAI;AAAA,cACJ,eAAY;AAAA,cACZ,gBAAe;AAAA,cACf,SAAQ;AAAA,cACR,WAAWb,EAAc,EAAE,SAAAI,EAAA,CAAS;AAAA,YAAA;AAAA,UAAA,IAGtC,gBAAAgB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,eAAY;AAAA,cACZ,WAAW,GAAGpB,EAAc,EAAE,SAAAI,EAAA,CAAS,CAAC;AAAA,cAExC,4BAACb,GAAA,CAAA,CAAK;AAAA,YAAA;AAAA,UAAA;AAAA,UAMT0B,IACC,gBAAAG;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,eAAY;AAAA,cACZ,eAAY;AAAA,cACZ,WAAU;AAAA,YAAA;AAAA,UAAA,IAEV;AAAA,QAAA,GACN;AAAA,QAEA,gBAAAC,EAAC,OAAA,EAAI,WAAU,uEACb,UAAA;AAAA,UAAA,gBAAAD,EAAC,QAAA,EAAK,WAAU,wGACb,UAAAL;AAAA;AAAA;AAAA;AAAA,YAIC,gBAAAM;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAMlB,EAAK;AAAA,gBACX,QAAO;AAAA,gBACP,KAAI;AAAA,gBACJ,WAAW,GAAGF,EAAkB;AAAA,gBAChC,SAAS,MAAMM,KAAA,gBAAAA,EAAaJ;AAAA,gBAE5B,UAAA;AAAA,kBAAA,gBAAAiB,EAAC,QAAA,EAAK,WAAU,yCACb,UAAAjB,EAAK,OACR;AAAA,kBACCgB;AAAA,oCACA,QAAA,EAAK,WAAU,cACb,UAAAR,EAAE,gCAAgC,sBAAsB,EAAA,CAC3D;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,cAGF,gBAAAU,EAAAC,GAAA,EACE,UAAA;AAAA,YAAA,gBAAAF,EAAC,QAAA,EAAK,WAAU,qDACb,UAAAjB,EAAK,OACR;AAAA,YACCgB;AAAA,UAAA,EAAA,CACH,EAAA,CAEJ;AAAA,UAEChB,EAAK,UACJ,gBAAAiB,EAAC,KAAA,EAAE,WAAU,uLACV,UAAAjB,EAAK,SACR,IACE;AAAA,UAEHA,EAAK,UACJ,gBAAAiB;AAAA,YAACG;AAAA,YAAA;AAAA,cACC,OAAOpB,EAAK;AAAA,cACZ,QAAO;AAAA,cACP,QAAAG;AAAA,cACA,WAAU;AAAA,YAAA;AAAA,UAAA,IAEV;AAAA,QAAA,GACN;AAAA,QAKCE,IACC,gBAAAY;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WACE,+PACAF;AAAA,YAGF,UAAA,gBAAAE;AAAA,cAACI;AAAA,cAAA;AAAA,gBACC,wBAAOC,IAAA,EAAE;AAAA,gBACT,QAAO;AAAA,gBACP,MAAK;AAAA,gBACL,cAAYd,EAAE,0BAA0B,gBAAgB;AAAA,gBACxD,SAAS,MAAMH,EAAUL,CAAI;AAAA,cAAA;AAAA,YAAA;AAAA,UAC/B;AAAA,QAAA,IAEA;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV;AAOO,SAASuB,EAAkB;AAAA,EAChC,SAAAtB,IAAU;AACZ,GAEG;AACD,SACE,gBAAAiB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,eAAY;AAAA,MACZ,WACEjB,MAAY,UACR,+EACA;AAAA,MAGN,UAAA;AAAA,QAAA,gBAAAgB;AAAA,UAACO;AAAA,UAAA;AAAA,YACC,SAAQ;AAAA,YACR,OAAOvB,MAAY,UAAU,SAAS;AAAA,YACtC,QAAQA,MAAY,UAAU,SAAS;AAAA,UAAA;AAAA,QAAA;AAAA,QAEzC,gBAAAiB,EAAC,OAAA,EAAI,WAAU,4DACb,UAAA;AAAA,UAAA,gBAAAD,EAACO,KAAS,SAAQ,QAAO,MAAK,MAAK,OAAM,OAAM;AAAA,4BAC9CA,GAAA,EAAS,SAAQ,QAAO,MAAK,MAAK,OAAM,OAAM;AAAA,4BAC9CA,GAAA,EAAS,SAAQ,QAAO,MAAK,MAAK,OAAM,MAAA,CAAM;AAAA,QAAA,EAAA,CACjD;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAGO,SAASC,EAAkB,EAAE,UAAAC,KAAqC;AACvE,SACE,gBAAAT;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,aAAU;AAAA,MACV,WAAU;AAAA,MAET,UAAAS;AAAA,IAAA;AAAA,EAAA;AAGP;AAMA,SAASC,GAAiBC,GAAeC,GAA+B;AACtE,SAAOD,IAAQ,KAAKC,IAAgB,OAAOD,CAAK;AAClD;AAEA,SAASE,KAAa;AACpB,QAAM,EAAE,GAAAtB,EAAA,IAAMC,EAAe,IAAI;AACjC,SACE,gBAAAS;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,aAAU;AAAA,MACV,WAAU;AAAA,MAEV,UAAA;AAAA,QAAA,gBAAAD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,eAAY;AAAA,YACZ,WAAU;AAAA,YAEV,4BAAC7B,GAAA,CAAA,CAAK;AAAA,UAAA;AAAA,QAAA;AAAA,0BAEP,KAAA,EAAE,WAAU,qDACV,UAAAoB,EAAE,6BAA6B,wBAAwB,GAC1D;AAAA,QACA,gBAAAS,EAAC,KAAA,EAAE,WAAU,qDACV,UAAAT;AAAA,UACC;AAAA,UACA;AAAA,QAAA,EACF,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAMO,MAAMuB,KAAiBC;AAAA,EAC5B,CACE;AAAA,IACE,IAAAC;AAAA,IACA,OAAAC;AAAA,IACA,QAAAC;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,OAAAC;AAAA,IACA,aAAAC;AAAA,IACA,cAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,cAAAC;AAAA,IACA,YAAAC,IAAa;AAAA,IACb,YAAAC;AAAA,IACA,aAAAC,IAAc;AAAA,IACd,QAAAzC;AAAA,IACA,OAAA0C,IAAQ;AAAA,IACR,MAAAC,IAAO;AAAA,IACP,MAAAC,IAAO;AAAA,IACP,WAAAzC;AAAA,IACA,GAAGC;AAAA,EAAA,GAELyC,MACG;AACH,UAAM,EAAE,GAAAxC,EAAA,IAAMC,EAAe,IAAI,GAE3B,CAACwC,GAAWC,CAAgB,IAAIC,GAA8B;AAAA,MAClE,cAAcP;AAAA,MACd,UAAUL;AAAA,IAAA,CACX,GACKa,IAASH,KAAa,IAEtBI,IAAef,KAAeJ,EAAM,OAAO,CAACoB,MAAMA,EAAE,MAAM,EAAE,QAC5DC,IACJd,MACCY,IAAe,IACZ7C,EAAE,+BAA+B;AAAA,MAC/B,OAAO6C;AAAA,MACP,cAAc;AAAA,IAAA,CACf,IACD7C,EAAE,mCAAmC,YAAY,IAEjDgD,IAAa7B;AAAA,MACjB0B;AAAA,MACA7C,EAAE,qCAAqC,KAAK;AAAA,IAAA,GAGxCiD,IAAUvB,EAAM,MAAM,GAAG,KAAK,IAAI,GAAGQ,CAAU,CAAC,GAChDgB,KAAW,CAACrB,KAAS,CAACD,KAAWqB,EAAQ,SAAS,GAClDE,IAAaxB,KAAUtB,EAAgBsB,CAAM,IAAIA,IAAS,QAI1DyB,IAAWC,EAAyB3B,CAAK;AAC/C,IAAA0B,EAAS,UAAU1B;AACnB,UAAM4B,IAAYD,EAA2BvB,CAAW;AACxD,IAAAwB,EAAU,UAAUxB;AAEpB,UAAM/C,KAASwE;AAAA,MACb,OAAO;AAAA,QACL,MAAM,MAAMb,EAAiB,EAAI;AAAA,QACjC,OAAO,MAAMA,EAAiB,EAAK;AAAA,QACnC,gBAAgB,MACdY,EAAU,WAAWF,EAAS,QAAQ,OAAO,CAACN,MAAMA,EAAE,MAAM,EAAE;AAAA,MAAA;AAAA,MAElE,CAACJ,CAAgB;AAAA,IAAA,GAGbc,IAAUH,EAAuB,IAAI;AAC3C,IAAAI,EAAoBjB,GAAK,MAAMgB,EAAQ,SAA2B,CAAA,CAAE,GACpEE,EAAqB5E,IAAqBC,IAAQ0C,CAAE;AAEpD,QAAIkC;AACJ,IAAI9B,IACF8B,IAAO,gBAAAlD,EAACQ,KAAmB,UAAAY,EAAA,CAAM,IACxBD,IACT+B,IACE,gBAAAjD,EAAAC,GAAA,EACE,UAAA;AAAA,MAAA,gBAAAF,EAACM,GAAA,EAAkB;AAAA,wBAClBA,GAAA,EAAkB;AAAA,wBAClBA,GAAA,CAAA,CAAkB;AAAA,IAAA,GACrB,IAEOkC,EAAQ,WAAW,IAC5BU,IAAOxB,uBAAeb,IAAA,CAAA,CAAW,IAEjCqC,IAAOV,EAAQ,IAAI,CAACzD,MAClB,gBAAAiB;AAAA,MAAClB;AAAA,MAAA;AAAA,QAEC,MAAAC;AAAA,QACA,SAAQ;AAAA,QACR,QAAAG;AAAA,QACA,YAAYqC;AAAA,MAAA;AAAA,MAJPxC,EAAK;AAAA,IAAA,CAMb;AAGH,UAAMoE,KAAYC,GAAmB,IAAM;AAAA,MACzC,WAAWC;AAAA,MACX,mBAAmB,MAAMpB,EAAiB,EAAK;AAAA,IAAA,CAChD;AAED,WACE,gBAAAjC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK+C;AAAA,QACL,kBAAe;AAAA,QACf,qBAAmB/B;AAAA,QACnB,WAAW,CAACzC,GAAuB,EAAE,MAAAuD,GAAM,GAAGzC,CAAS,EACpD,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,QACV,GAAGC;AAAA,QAEJ,4BAACgE,EAAa,MAAb,EAAkB,MAAMnB,GAAQ,cAAcF,GAC7C,UAAA;AAAA,UAAA,gBAAAjC,EAACsD,EAAa,SAAb,EAAqB,SAAO,IAC3B,UAAA,gBAAAtD;AAAA,YAACI;AAAA,YAAA;AAAA,cACC,wBAAOjC,GAAA,EAAK;AAAA,cACZ,QAAO;AAAA,cACP,MAAM2D,MAAS,OAAO,OAAO;AAAA,cAC7B,cAAYQ;AAAA,cACZ,iBAAc;AAAA,YAAA;AAAA,UAAA,GAElB;AAAA,UACCF,IAAe,IACd,gBAAApC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,eAAY;AAAA,cACZ,eAAY;AAAA,cACZ,WAAWtB,GAAA;AAAA,cAEV,UAAA6D;AAAA,YAAA;AAAA,UAAA,IAED;AAAA,UACJ,gBAAAvC,EAACsD,EAAa,QAAb,EACC,UAAA,gBAAArD;AAAA,YAACqD,EAAa;AAAA,YAAb;AAAA,cACC,MAAK;AAAA,cACL,WAAWH;AAAA,cACX,cAAY5D,EAAE,6BAA6B,YAAY;AAAA,cACvD,MAAAsC;AAAA,cACA,OAAAD;AAAA,cACA,YAAY;AAAA,cAGZ,kBAAkB;AAAA,cAClB,WAAWnD,GAAc,EAAE,MAAAqD,GAAM;AAAA,cAEjC,UAAA;AAAA,gBAAA,gBAAA9B,EAAC,OAAA,EAAI,WAAU,uJACb,UAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,4DACX,UAAAT,EAAE,6BAA6B,YAAY,EAAA,CAC9C,GACF;AAAA,kCACCgE,GAAA,EAAU;AAAA,gBAMX,gBAAAvD;AAAA,kBAACwD;AAAA,kBAAA;AAAA,oBACC,aAAY;AAAA,oBACZ,WAAU;AAAA,oBAEV,UAAA,gBAAAxD;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,MAAMyC,KAAW,SAAS;AAAA,wBAC1B,oBAAkBhB;AAAA,wBAClB,WAAU;AAAA,wBAET,UAAAyB;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBACH;AAAA,gBAAA;AAAA,gBAEDR,IACC,gBAAAzC,EAAAC,GAAA,EACE,UAAA;AAAA,kBAAA,gBAAAF,EAACuD,GAAA,EAAU;AAAA,kBACX,gBAAAvD,EAAC,OAAA,EAAI,WAAU,iFACb,4BAACyD,GAAA,EAAK,MAAMf,GAAY,UAAQ,IAC7B,UAAAnD,EAAE,0BAA0B,qBAAqB,GACpD,EAAA,CACF;AAAA,gBAAA,EAAA,CACF,IACE;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA,EACN,CACF;AAAA,QAAA,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEAuB,GAAe,cAAc;ACvrBtB,MAAM4C,KAA4D;AAAA,EACvE,IAAI;AAAA;AAAA;AAAA,EAGJ,cAAc,CAAC,MAAM;AAAA,EACrB,OAAO;AAAA,IACL,OAAO;AAAA,MACL,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACpF,MAAWA,EAAO,SAAA;AAAA,IAAS;AAAA,IAEpC,aAAa;AAAA,MACX,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACA,MAAWA,EAAO,eAAA;AAAA,IAAe;AAAA,EAC1C;AAAA,EAEF,SAAS;AAAA,IACP,aAAa;AAAA,MACX,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY;AAAA,UACV,IAAI;AAAA,YACF,MAAM;AAAA,YACN,aAAa;AAAA,UAAA;AAAA,QACf;AAAA,QAEF,UAAU,CAAC,IAAI;AAAA,MAAA;AAAA,MAEjB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,UAAU;AAAA,QACR,EAAE,MAAM,EAAE,IAAI,WAAA,GAAc,MAAM,mCAAA;AAAA,MAAmC;AAAA,MAEvE,QAAQ,CAACA,GAAQqF,MAAyB;AACxC,QAAArF,EAAO,WAAWqF,EAAK,EAAE;AAAA,MAC3B;AAAA,IAAA;AAAA,EACF;AAAA,EAEF,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IAAA;AAAA,IAEf,YAAY;AAAA,MACV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,aACE;AAAA,IAAA;AAAA,IAEJ,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aACE;AAAA,IAAA;AAAA,EACJ;AAEJ,GC5CMC,KAA0BpF;AAAA,EAC9B;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,MAAM;AAAA,QACN,UAAU;AAAA,MAAA;AAAA,IACZ;AAAA,IAEF,iBAAiB;AAAA,MACf,SAAS;AAAA,IAAA;AAAA,EACX;AAEJ,GAyDaqF,KAAkB9C;AAAA,EAC7B,CACE;AAAA,IACE,IAAAC;AAAA,IACA,OAAAC;AAAA,IACA,QAAAC;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,OAAAC;AAAA,IACA,OAAA0C;AAAA,IACA,aAAAC;AAAA,IACA,YAAAtC,IAAa;AAAA,IACb,YAAAC;AAAA,IACA,gBAAAH;AAAA,IACA,QAAArC;AAAA,IACA,SAAAD,IAAU;AAAA,IACV,WAAAI;AAAA,IACA,GAAGC;AAAA,EAAA,GAELyC,MACG;AACH,UAAM,EAAE,GAAAxC,EAAA,IAAMC,EAAe,IAAI,GAC3BwE,IAAUF,KAASvE,EAAE,yBAAyB,YAAY,GAE1DiD,IAAUvB,EAAM,MAAM,GAAG,KAAK,IAAI,GAAGQ,CAAU,CAAC,GAChDiB,IAAaxB,KAAUtB,EAAgBsB,CAAM,IAAIA,IAAS;AAEhE,QAAIgC;AACJ,IAAI9B,IACF8B,IAAO,gBAAAlD,EAACQ,KAAmB,UAAAY,EAAA,CAAM,IACxBD,IACT+B,sBACG,OAAA,EAAI,WAAU,mFACZ,UAAA,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,CAACb,MACd,gBAAArC,EAACM,GAAA,EAA0B,SAAQ,QAAA,GAAX+B,CAAmB,CAC5C,GACH,IAEOG,EAAQ,WAAW,IAC5BU,IAAOxB,KACL,gBAAA1B,EAAC,OAAA,EAAI,WAAU,4BACb,UAAA,gBAAAA;AAAA,MAACiE;AAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,OAAO1E,EAAE,8BAA8B,wBAAwB;AAAA,QAC/D,aAAaA;AAAA,UACX;AAAA,UACA;AAAA,QAAA;AAAA,MACF;AAAA,IAAA,GAEJ,IAGF2D,IACE,gBAAAlD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,oBAAkByB;AAAA,QAClB,WAAU;AAAA,QAET,UAAAe,EAAQ,IAAI,CAACzD,MACZ,gBAAAiB;AAAA,UAAClB;AAAA,UAAA;AAAA,YAEC,MAAAC;AAAA,YACA,SAAQ;AAAA,YACR,QAAAG;AAAA,YACA,YAAYqC;AAAA,UAAA;AAAA,UAJPxC,EAAK;AAAA,QAAA,CAMb;AAAA,MAAA;AAAA,IAAA;AAMP,UAAM4D,IAAWC,EAAyB3B,CAAK;AAC/C,IAAA0B,EAAS,UAAU1B;AAEnB,UAAM3C,IAASwE;AAAA,MACb,OAAO;AAAA,QACL,UAAU,MACRH,EAAS,QAAQ,IAAI,CAACN,OAAO,EAAE,IAAIA,EAAE,IAAI,QAAQ,CAAC,CAACA,EAAE,SAAS;AAAA,QAChE,gBAAgB,MAAMM,EAAS,QAAQ,OAAO,CAACN,MAAMA,EAAE,MAAM,EAAE;AAAA,QAC/D,YAAY,CAAC6B,MAAqB;AAChC,gBAAMC,IAAQxB,EAAS,QAAQ,KAAK,CAACN,MAAMA,EAAE,OAAO6B,CAAQ;AAC5D,UAAIC,qBAAwBA;AAAA,QAC9B;AAAA,MAAA;AAAA,MAEF,CAAC5C,CAAc;AAAA,IAAA,GAGX6C,IAAWxB,EAAoB,IAAI;AACzC,WAAAI,EAAoBjB,GAAK,MAAMqC,EAAS,SAAwB,CAAA,CAAE,GAClEnB,EAAqBS,IAAsBpF,GAAQ0C,CAAE,GAGnD,gBAAAf;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKmE;AAAA,QACL,cAAYJ;AAAA,QACZ,kBAAe;AAAA,QACf,qBAAmBhD;AAAA,QACnB,WAAW4C,GAAwB,EAAE,SAAA3E,GAAS,WAAAI,GAAW;AAAA,QACxD,GAAGC;AAAA,QAEJ,UAAA;AAAA,UAAA,gBAAAW,EAAC,UAAA,EAAO,WAAU,sGAGhB,UAAA;AAAA,YAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,gIACZ,UAAA;AAAA,cAAA,gBAAAD,EAAC7B,GAAA,EAAK,eAAY,QAAO,WAAU,yBAAwB;AAAA,cAC1D6F;AAAA,YAAA,GACH;AAAA,YACCD,IACC,gBAAA/D,EAAC,KAAA,EAAE,WAAU,6EACV,aACH,IACE;AAAA,UAAA,GACN;AAAA,UACCkD;AAAA,UACAR,IACC,gBAAAzC,EAAAC,GAAA,EACE,UAAA;AAAA,YAAA,gBAAAF,EAACuD,GAAA,EAAU;AAAA,YACX,gBAAAvD,EAAC,OAAA,EAAI,WAAU,sDACb,4BAACyD,GAAA,EAAK,MAAMf,GAAY,UAAQ,IAC7B,UAAAnD,EAAE,2BAA2B,qBAAqB,GACrD,EAAA,CACF;AAAA,UAAA,EAAA,CACF,IACE;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AAEAsE,GAAgB,cAAc;","x_google_ignoreList":[0]}
|
|
@@ -2,7 +2,7 @@ import { jsx as e, jsxs as c, Fragment as h } from "react/jsx-runtime";
|
|
|
2
2
|
import { forwardRef as P, useMemo as C, useImperativeHandle as S } from "react";
|
|
3
3
|
import { c as D } from "./index-D2ZczOXr.js";
|
|
4
4
|
import { useTranslation as G } from "react-i18next";
|
|
5
|
-
import { L as f } from "./link-
|
|
5
|
+
import { L as f } from "./link-N5_YpLtm.js";
|
|
6
6
|
import { S as m } from "./separator-CYU_bGFn.js";
|
|
7
7
|
import { L as M } from "./logo-hIsyVE96.js";
|
|
8
8
|
import { A as O, b as Y, c as K, a as W } from "./accordion-Ch3xp0mX.js";
|
|
@@ -565,4 +565,4 @@ export {
|
|
|
565
565
|
Q as a,
|
|
566
566
|
q as c
|
|
567
567
|
};
|
|
568
|
-
//# sourceMappingURL=public-footer-
|
|
568
|
+
//# sourceMappingURL=public-footer-CXOrdAaS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-footer-ZWTEG1Rq.js","sources":["../../src/components/public-footer/legal-urls.ts","../../src/components/public-footer/socials.tsx","../../src/components/public-footer/public-footer.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* PublicFooter — legally-required URL composition. */\n/* */\n/* GDPR + Italian/German commercial law require Privacy, Terms-of-use, */\n/* entity name and VAT to be visible on every public AlfaDocs surface. */\n/* The kit owns the slug table so a privacy-policy URL change is a single */\n/* kit bump rather than three repo edits. */\n/* */\n/* For locales without an explicit canonical slug, we fall back to the */\n/* Italian slugs — alfadocs.com defaults to Italian and unlocalised pages */\n/* render the IT version. Marketing supplies updates over time. */\n/* -------------------------------------------------------------------- */\n\nexport const DEFAULT_MARKETING_BASE_URL = 'https://www.alfadocs.com';\n\nexport type LegalUrlKey = 'privacy' | 'terms' | 'contacts';\n\nexport type LegalSlugMap = Record<LegalUrlKey, string>;\n\n/** Per-locale slug override; missing locales fall back to the kit default. */\nexport type LegalUrlOverride = Record<string, string>;\n\nexport interface LegalUrlOverrides {\n privacy?: LegalUrlOverride;\n terms?: LegalUrlOverride;\n contacts?: LegalUrlOverride;\n}\n\n/* Italian default — also used as the fallback for any locale without an\n * explicit entry below. */\nconst ITALIAN_SLUGS: LegalSlugMap = {\n privacy: '/privacy-prenotazione-online',\n terms: '/it/condizioni-di-utilizzo',\n contacts: '/it/contattaci',\n};\n\n/* Canonical per-locale slug table. Explicit entries come from marketing;\n * everything else inherits ITALIAN_SLUGS via the resolver below. */\nconst SLUGS: Record<string, LegalSlugMap> = {\n it: ITALIAN_SLUGS,\n en: {\n privacy: '/en/privacy',\n terms: '/en/terms-of-use',\n contacts: '/en/contact-us',\n },\n de: {\n privacy: '/de/datenschutz',\n terms: '/de/nutzungsbedingungen',\n contacts: '/de/kontakt',\n },\n fr: {\n privacy: '/fr/confidentialite',\n terms: '/fr/conditions-utilisation',\n contacts: '/fr/contact',\n },\n es: {\n privacy: '/es/privacidad',\n terms: '/es/condiciones-uso',\n contacts: '/es/contacto',\n },\n};\n\nconst HTTPS_PREFIX = 'https://';\n\nfunction normaliseBaseUrl(input: string | undefined): string {\n if (!input) return DEFAULT_MARKETING_BASE_URL;\n if (!input.startsWith(HTTPS_PREFIX)) {\n if (import.meta.env.DEV) {\n // eslint-disable-next-line no-console\n console.warn(\n `[PublicFooter] marketingBaseUrl must start with \"https://\" — falling back to ${DEFAULT_MARKETING_BASE_URL}. Received: \"${input}\"`,\n );\n }\n return DEFAULT_MARKETING_BASE_URL;\n }\n // Strip trailing slash so composed URLs don't double up.\n return input.replace(/\\/+$/, '');\n}\n\nfunction pickSlug(\n locale: string,\n key: LegalUrlKey,\n overrides: LegalUrlOverrides | undefined,\n): string {\n const override = overrides?.[key]?.[locale];\n if (override) return override;\n const localeSlug = SLUGS[locale]?.[key];\n if (localeSlug) return localeSlug;\n return ITALIAN_SLUGS[key];\n}\n\n/** Resolved legal URLs for the active locale + baseUrl + overrides. */\nexport interface ResolvedLegalUrls {\n privacy: string;\n terms: string;\n contacts: string;\n}\n\nexport function composeLegalUrls(\n locale: string,\n marketingBaseUrl: string | undefined,\n overrides?: LegalUrlOverrides,\n): ResolvedLegalUrls {\n const base = normaliseBaseUrl(marketingBaseUrl);\n const lang = (locale || 'it').split('-')[0]; // strip region — 'pt-BR' → 'pt'\n return {\n privacy: `${base}${pickSlug(lang, 'privacy', overrides)}`,\n terms: `${base}${pickSlug(lang, 'terms', overrides)}`,\n contacts: `${base}${pickSlug(lang, 'contacts', overrides)}`,\n };\n}\n","/* -------------------------------------------------------------------- */\n/* PublicFooter — default social-network URLs + brand icon components. */\n/* */\n/* AlfaDocs's four canonical social profiles. Consumers can subset via */\n/* `socials={[...]}` or override individual `href` values. */\n/* */\n/* Icons are small inline SVG components (paths from simpleicons.org) */\n/* rendered with `currentColor` so they inherit the footer's */\n/* `--muted-foreground` ink. Lucide-react does not ship brand glyphs, and */\n/* pulling a separate brand-icon package for four logos is not worth the */\n/* bundle cost. */\n/* -------------------------------------------------------------------- */\n\nimport type { ComponentType, SVGProps } from 'react';\n\nexport const SOCIAL_NETWORKS = [\n 'linkedin',\n 'youtube',\n 'instagram',\n 'facebook',\n] as const;\n\nexport type SocialNetwork = (typeof SOCIAL_NETWORKS)[number];\n\nexport const DEFAULT_SOCIAL_URLS: Record<SocialNetwork, string> = {\n linkedin: 'https://www.linkedin.com/company/alfadocs',\n youtube: 'https://www.youtube.com/@alfadocs',\n instagram: 'https://www.instagram.com/alfadocs',\n facebook: 'https://www.facebook.com/alfadocs',\n};\n\ntype IconProps = SVGProps<SVGSVGElement>;\ntype SocialIcon = ComponentType<IconProps>;\n\nconst baseProps = {\n viewBox: '0 0 24 24',\n fill: 'currentColor',\n xmlns: 'http://www.w3.org/2000/svg',\n} as const;\n\nconst LinkedinIcon: SocialIcon = (props) => (\n <svg {...baseProps} {...props}>\n <path d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 0 1-2.063-2.065 2.063 2.063 0 1 1 2.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z\" />\n </svg>\n);\n\nconst YoutubeIcon: SocialIcon = (props) => (\n <svg {...baseProps} {...props}>\n <path d=\"M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z\" />\n </svg>\n);\n\nconst InstagramIcon: SocialIcon = (props) => (\n <svg {...baseProps} {...props}>\n <path d=\"M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 1 0 0 12.324 6.162 6.162 0 0 0 0-12.324zM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm6.406-11.845a1.44 1.44 0 1 0 0 2.881 1.44 1.44 0 0 0 0-2.881z\" />\n </svg>\n);\n\nconst FacebookIcon: SocialIcon = (props) => (\n <svg {...baseProps} {...props}>\n <path d=\"M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z\" />\n </svg>\n);\n\nexport const SOCIAL_ICONS: Record<SocialNetwork, SocialIcon> = {\n linkedin: LinkedinIcon,\n youtube: YoutubeIcon,\n instagram: InstagramIcon,\n facebook: FacebookIcon,\n};\n","import {\n forwardRef,\n useImperativeHandle,\n useMemo,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Link } from '../link';\nimport { Separator } from '../separator';\nimport { Logo } from '../logo';\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from '../accordion';\nimport {\n composeLegalUrls,\n type LegalUrlOverrides,\n type ResolvedLegalUrls,\n} from './legal-urls';\nimport {\n DEFAULT_SOCIAL_URLS,\n SOCIAL_ICONS,\n SOCIAL_NETWORKS,\n type SocialNetwork,\n} from './socials';\n\n/* ------------------------------------------------------------------ */\n/* Constants */\n/* ------------------------------------------------------------------ */\n\nconst ENTITY_NAME = 'AlfaDocs GmbH';\nconst ENTITY_VAT = 'P.IVA DE301955405';\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst rootVariants = cva(\n [\n 'ds:w-full',\n 'ds:text-[color:var(--muted-foreground)]',\n 'ds:text-[length:var(--font-size-sm)]',\n 'ds:bg-[var(--background)]',\n ].join(' '),\n {\n variants: {\n variant: {\n minimal: [\n 'ds:py-[var(--spacing-sm)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:border-block-start ds:border-[var(--border)]',\n ].join(' '),\n // 0.30.5: compact got a polish pass — bumped vertical padding to\n // `lg` (~24px) so the footer reads as a real landmark, not a\n // one-line afterthought, plus a stronger top border in\n // accessible mode (the default `--border` clears 3:1 in light /\n // dark; accessible bumps to a heavier weight).\n //\n // 0.31.2: forced-colors top-border fallback. Windows High\n // Contrast strips `--border` to whatever the system maps it\n // to — which is often invisible against `Canvas`. Pinning to\n // `CanvasText` keeps the landmark edge visible for users on\n // strict HC themes.\n compact: [\n 'ds:py-[var(--spacing-lg)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:border-block-start ds:border-[var(--border)]',\n // 2px in the accessible themes, none elsewhere (--accessible-on).\n 'ds:[border-block-start-width:calc(var(--border-width-md)*var(--accessible-on,0))]',\n 'ds:forced-colors:[border-block-start-color:CanvasText]',\n ].join(' '),\n full: [\n 'ds:py-[var(--spacing-xl)]',\n 'ds:ps-[var(--spacing-lg)] ds:pe-[var(--spacing-lg)]',\n 'ds:bg-[var(--muted)]',\n ].join(' '),\n },\n },\n defaultVariants: { variant: 'compact' },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------ */\n\nexport type PublicFooterVariant = NonNullable<\n VariantProps<typeof rootVariants>['variant']\n>;\n\nexport interface PublicFooterLink {\n href: string;\n label: string;\n /** When true, link opens in a new tab with the localised aria-label suffix. */\n external?: boolean;\n}\n\nexport interface PublicFooterLinkGroup {\n /** Stable key — used to look up the column heading via `t('ui.footer.group.<key>')`. */\n key: 'product' | 'resources' | 'company' | 'legal' | (string & {});\n links: PublicFooterLink[];\n}\n\nexport interface PublicFooterSocial {\n network: SocialNetwork;\n /** Override the kit's default URL. */\n href?: string;\n}\n\nexport interface PublicFooterProps {\n variant: PublicFooterVariant;\n /** Origin for legally-required URLs. Default: 'https://www.alfadocs.com'. */\n marketingBaseUrl?: string;\n /** Override individual legal-link slugs per locale. Rare. */\n legalUrlOverrides?: LegalUrlOverrides;\n /** `full` variant: consumer-supplied link columns. Legal column is always rendered. */\n linkGroups?: PublicFooterLinkGroup[];\n /** `full` variant: subset of social networks. Default: all four. Pass `[]` to hide the row. */\n socials?: PublicFooterSocial[];\n /** `full` variant: custom logo node. Default: kit's wordmark Logo. */\n logoSlot?: ReactNode;\n /** Extra surface-specific links — appended after the standard nav row in compact + full. Ignored by minimal. */\n extraNavSlot?: ReactNode;\n /** Trust badges (HIPAA, ISO). Rendered at the start of `minimal`'s row, or in the bottom strip of `full`. */\n trustBadgesSlot?: ReactNode;\n /**\n * @default false\n * Render the brand tagline (\"German technology, Italian design\") in\n * the bottom microcopy row of `compact` and `full` variants.\n *\n * 0.32.4: default flipped to `false`. The tagline was loud on\n * booking-website's deployed footer and didn't carry product\n * meaning for end-users; marketing surfaces can opt back in\n * explicitly with `showTagline`. The `footer.tagline` i18n key\n * stays available so the opt-in path still works.\n */\n showTagline?: boolean;\n /**\n * The line with the year, the company name and the VAT number. On by\n * default: a public page must carry it. Turn it off only on a screen\n * that sits inside the app, such as sign-in or registration, where the\n * privacy and terms links are all the footer needs.\n * @default true\n */\n showCopyright?: boolean;\n 'aria-label'?: string;\n id?: string;\n}\n\nexport interface PublicFooterHandle {\n getVariant: () => PublicFooterVariant;\n /** Resolved legal URLs for the current locale + marketingBaseUrl + overrides. */\n getLegalUrls: () => ResolvedLegalUrls;\n}\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\n/** Allowlist consumer-supplied URLs — public marketing surface, defence in depth. */\nconst SAFE_HREF_RE = /^(https?:\\/\\/|mailto:|tel:|\\/(?!\\/))/i;\nfunction safeHref(href: string): string {\n return SAFE_HREF_RE.test(href) ? href : '#';\n}\n\nfunction CopyrightLine({\n copyright,\n align = 'center',\n}: {\n copyright: string;\n align?: 'start' | 'center';\n}) {\n return (\n <p\n className={[\n 'ds:m-0 ds:text-[color:var(--muted-foreground)]',\n 'ds:text-[length:var(--font-size-sm)]',\n align === 'center' ? 'ds:text-center' : 'ds:text-start',\n ].join(' ')}\n >\n {copyright}\n </p>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* PublicFooter */\n/* ------------------------------------------------------------------ */\n\nexport const PublicFooter = forwardRef<PublicFooterHandle, PublicFooterProps>(\n function PublicFooter(\n {\n variant,\n marketingBaseUrl,\n legalUrlOverrides,\n linkGroups,\n socials,\n logoSlot,\n extraNavSlot,\n trustBadgesSlot,\n showTagline = false,\n showCopyright = true,\n id,\n 'aria-label': ariaLabel,\n },\n ref,\n ) {\n const { t, i18n } = useTranslation('ui');\n\n const legalUrls = useMemo(\n () =>\n composeLegalUrls(i18n.language, marketingBaseUrl, legalUrlOverrides),\n [i18n.language, marketingBaseUrl, legalUrlOverrides],\n );\n\n useImperativeHandle(\n ref,\n () => ({\n getVariant: () => variant,\n getLegalUrls: () => legalUrls,\n }),\n [variant, legalUrls],\n );\n\n const year = new Date().getFullYear();\n const copyright = showCopyright\n ? t('footer.copyright', {\n year,\n entity: ENTITY_NAME,\n vat: ENTITY_VAT,\n })\n : undefined;\n const tagline = showTagline ? t('footer.tagline') : undefined;\n const landmarkLabel = ariaLabel ?? t('footer.nav.label');\n\n const labels = {\n privacy: t('footer.nav.privacy'),\n terms: t('footer.nav.terms'),\n contacts: t('footer.nav.contacts'),\n };\n\n const resolvedSocials = useMemo<PublicFooterSocial[]>(() => {\n if (socials !== undefined) return socials;\n return SOCIAL_NETWORKS.map((network) => ({ network }));\n }, [socials]);\n\n return (\n <footer\n id={id}\n role=\"contentinfo\"\n aria-label={landmarkLabel}\n data-component=\"public-footer\"\n data-component-id={id}\n data-variant={variant}\n className={rootVariants({ variant })}\n >\n {variant === 'minimal' && (\n <MinimalBody\n legalUrls={legalUrls}\n labels={labels}\n copyright={copyright}\n trustBadgesSlot={trustBadgesSlot}\n />\n )}\n {variant === 'compact' && (\n <CompactBody\n legalUrls={legalUrls}\n labels={labels}\n copyright={copyright}\n tagline={tagline}\n socials={resolvedSocials}\n logoSlot={logoSlot}\n extraNavSlot={extraNavSlot}\n t={t}\n />\n )}\n {variant === 'full' && (\n <FullBody\n legalUrls={legalUrls}\n labels={labels}\n copyright={copyright}\n tagline={tagline}\n linkGroups={linkGroups}\n socials={resolvedSocials}\n logoSlot={logoSlot}\n extraNavSlot={extraNavSlot}\n trustBadgesSlot={trustBadgesSlot}\n t={t}\n />\n )}\n </footer>\n );\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Minimal */\n/* ------------------------------------------------------------------ */\n\n// The minimal row's links are one line of small text, 21px tall: under the\n// 24px WCAG 2.5.8 asks of a target. A transparent `::before` stretches the\n// hit area to 24px (--spacing-lg) in the block direction without moving or\n// resizing anything the eye sees, and to --min-target-size (48px) in the\n// accessible themes, through --accessible-target-floor. Once a link is as\n// tall as that the inset turns positive and the box sits inside the link,\n// which is harmless.\nconst MINIMAL_LINK_HIT_AREA =\n 'ds:relative ds:before:absolute ds:before:inset-x-0 ds:before:inset-y-[calc((var(--accessible-target-floor,var(--spacing-lg))-100%)/-2)] ds:before:content-[\"\"]';\n\nfunction MinimalBody({\n legalUrls,\n labels,\n copyright,\n trustBadgesSlot,\n}: {\n legalUrls: ResolvedLegalUrls;\n labels: { privacy: string; terms: string; contacts: string };\n copyright?: string;\n trustBadgesSlot?: ReactNode;\n}) {\n return (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-center ds:gap-x-[var(--spacing-sm)] ds:gap-y-[var(--spacing-sm)]\">\n {trustBadgesSlot && (\n <span\n data-slot=\"trust-badges\"\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)] ds:me-[var(--spacing-sm)]\"\n >\n {trustBadgesSlot}\n </span>\n )}\n <Link\n href={legalUrls.privacy}\n external\n externalIcon={false}\n intent=\"subtle\"\n className={MINIMAL_LINK_HIT_AREA}\n >\n {labels.privacy}\n </Link>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n <Link\n href={legalUrls.terms}\n external\n externalIcon={false}\n intent=\"subtle\"\n className={MINIMAL_LINK_HIT_AREA}\n >\n {labels.terms}\n </Link>\n {copyright ? (\n <>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n <span>{copyright}</span>\n </>\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Compact */\n/* ------------------------------------------------------------------ */\n\n// Shared social-icon row — used by Compact and Full. Renders an icon\n// per enabled network; the parent decides where to drop it.\nfunction SocialIconList({\n socials,\n t,\n size,\n}: {\n socials: PublicFooterSocial[];\n t: TFunction;\n size: 'sm' | 'md';\n}) {\n if (socials.length === 0) return null;\n const iconClass = size === 'sm' ? 'ds:size-4' : 'ds:size-5';\n return (\n <ul\n data-slot=\"socials\"\n className=\"ds:list-none ds:m-0 ds:p-0 ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n {socials.map((s) => {\n const Icon = SOCIAL_ICONS[s.network];\n const href = s.href ?? DEFAULT_SOCIAL_URLS[s.network];\n const label = t(`footer.social.aria.${s.network}`);\n return (\n <li key={s.network}>\n <Link\n href={safeHref(href)}\n external\n externalIcon={false}\n intent=\"subtle\"\n aria-label={label}\n className=\"ds:inline-flex ds:items-center ds:justify-center ds:min-w-[var(--min-target-size)] ds:min-h-[var(--min-target-size)]\"\n >\n <Icon\n aria-hidden=\"true\"\n className={iconClass}\n focusable=\"false\"\n />\n </Link>\n </li>\n );\n })}\n </ul>\n );\n}\n\nfunction CompactBody({\n legalUrls,\n labels,\n copyright,\n tagline,\n socials,\n logoSlot,\n extraNavSlot,\n t,\n}: {\n legalUrls: ResolvedLegalUrls;\n labels: { privacy: string; terms: string; contacts: string };\n copyright?: string;\n tagline?: string;\n socials: PublicFooterSocial[];\n logoSlot?: ReactNode;\n extraNavSlot?: ReactNode;\n t: TFunction;\n}) {\n // 0.30.5: compact polish — defaults to a social-icon row + (small,\n // muted) wordmark at the start of the link row. Consumers who want\n // the lean treatment can opt out via `socials={[]}` (kills the row)\n // and `logoSlot={<></>}` (kills the wordmark). The lean fallback is\n // still a useful surface for embedded widgets (the booking aside).\n return (\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-md)]\">\n {socials.length > 0 ? (\n <SocialIconList socials={socials} t={t} size=\"sm\" />\n ) : null}\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-center ds:gap-x-[var(--spacing-sm)] ds:gap-y-[var(--spacing-sm)]\">\n {logoSlot !== undefined ? (\n logoSlot !== null && logoSlot !== false && logoSlot !== '' ? (\n <>\n <span\n data-slot=\"compact-logo\"\n className=\"ds:inline-flex ds:items-center ds:opacity-70\"\n >\n {logoSlot}\n </span>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n </>\n ) : null\n ) : (\n // No consumer override — render the kit's default small\n // wordmark, muted so it reads as marker not headline.\n <>\n <span\n data-slot=\"compact-logo\"\n className=\"ds:inline-flex ds:items-center ds:opacity-70\"\n >\n <Logo variant=\"wordmark\" tone=\"auto\" aria-label=\"Alfadocs\" />\n </span>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n </>\n )}\n <Link\n href={legalUrls.privacy}\n external\n externalIcon={false}\n intent=\"subtle\"\n >\n {labels.privacy}\n </Link>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n <Link\n href={legalUrls.terms}\n external\n externalIcon={false}\n intent=\"subtle\"\n >\n {labels.terms}\n </Link>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n <Link\n href={legalUrls.contacts}\n external\n externalIcon={false}\n intent=\"subtle\"\n >\n {labels.contacts}\n </Link>\n {extraNavSlot && (\n <>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n <span data-slot=\"extra-nav\">{extraNavSlot}</span>\n </>\n )}\n </div>\n {copyright ? <CopyrightLine copyright={copyright} /> : null}\n {tagline ? (\n <p\n data-slot=\"tagline\"\n className=\"ds:m-0 ds:text-center ds:text-[color:var(--muted-foreground)] ds:text-[length:var(--font-size-xs)] ds:italic\"\n >\n {tagline}\n </p>\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Full */\n/* ------------------------------------------------------------------ */\n\ntype TFunction = ReturnType<typeof useTranslation>['t'];\n\nfunction buildLegalColumn(\n legalUrls: ResolvedLegalUrls,\n labels: { privacy: string; terms: string; contacts: string },\n): PublicFooterLinkGroup {\n return {\n key: 'legal',\n links: [\n { href: legalUrls.privacy, label: labels.privacy, external: true },\n { href: legalUrls.terms, label: labels.terms, external: true },\n { href: legalUrls.contacts, label: labels.contacts, external: true },\n ],\n };\n}\n\nfunction FullBody({\n legalUrls,\n labels,\n copyright,\n tagline,\n linkGroups,\n socials,\n logoSlot,\n extraNavSlot,\n trustBadgesSlot,\n t,\n}: {\n legalUrls: ResolvedLegalUrls;\n labels: { privacy: string; terms: string; contacts: string };\n copyright?: string;\n tagline?: string;\n linkGroups?: PublicFooterLinkGroup[];\n socials: PublicFooterSocial[];\n logoSlot?: ReactNode;\n extraNavSlot?: ReactNode;\n trustBadgesSlot?: ReactNode;\n t: TFunction;\n}) {\n // The kit-built Legal column is always appended — Privacy / Terms /\n // Contacts must render in every variant per the legal brief.\n const columns: PublicFooterLinkGroup[] = [\n ...(linkGroups ?? []),\n buildLegalColumn(legalUrls, labels),\n ];\n\n const brand = (\n <div\n data-slot=\"brand\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n <div className=\"ds:inline-flex\">\n {logoSlot ?? (\n <Logo variant=\"wordmark\" tone=\"auto\" aria-label=\"Alfadocs\" />\n )}\n </div>\n <SocialIconList socials={socials} t={t} size=\"md\" />\n </div>\n );\n\n return (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xl)]\">\n {/* Top: brand block on inline-start + link columns to inline-end */}\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xl)] ds:lg:flex-row ds:lg:items-start ds:lg:gap-[var(--spacing-xl)]\">\n <div className=\"ds:lg:w-[15rem] ds:lg:shrink-0\">{brand}</div>\n\n <div className=\"ds:flex-1 ds:min-w-0\">\n {/* md+ — grid of columns */}\n <div\n className=\"ds:hidden ds:md:grid ds:md:grid-cols-2 ds:lg:grid-cols-4 ds:gap-[var(--spacing-lg)]\"\n data-slot=\"link-columns-grid\"\n data-columns={columns.length}\n >\n <FullColumnsGrid columns={columns} t={t} />\n </div>\n\n {/* below md — accordion */}\n <div className=\"ds:md:hidden\" data-slot=\"link-columns-accordion\">\n <Accordion type=\"multiple\">\n {columns.map((group, i) => (\n <AccordionItem\n key={`${i}-${group.key}`}\n value={`${i}-${group.key}`}\n >\n <AccordionTrigger>\n {t(`footer.group.${group.key}`, {\n defaultValue: group.key,\n })}\n </AccordionTrigger>\n <AccordionContent>\n <ul className=\"ds:list-none ds:m-0 ds:p-0 ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {group.links.map((link) => (\n <li key={`${group.key}-${link.href}-${link.label}`}>\n <Link\n href={safeHref(link.href)}\n external={link.external}\n externalIcon={false}\n intent=\"subtle\"\n >\n {link.label}\n </Link>\n </li>\n ))}\n </ul>\n </AccordionContent>\n </AccordionItem>\n ))}\n </Accordion>\n </div>\n </div>\n </div>\n\n <Separator orientation=\"horizontal\" />\n\n {/* Bottom strip: copyright inline-start, mini legal links inline-end\n on the same row. Stacks under sm. */}\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:sm:flex-row ds:sm:items-center ds:sm:justify-between\">\n {copyright ? (\n <CopyrightLine copyright={copyright} align=\"start\" />\n ) : null}\n <div\n data-slot=\"bottom-legal\"\n className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)] ds:sm:justify-end\"\n >\n <Link\n href={legalUrls.privacy}\n external\n externalIcon={false}\n intent=\"subtle\"\n >\n {labels.privacy}\n </Link>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n <Link\n href={legalUrls.terms}\n external\n externalIcon={false}\n intent=\"subtle\"\n >\n {labels.terms}\n </Link>\n {(trustBadgesSlot || extraNavSlot) && (\n <>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n {trustBadgesSlot && (\n <span\n data-slot=\"trust-badges\"\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\"\n >\n {trustBadgesSlot}\n </span>\n )}\n {extraNavSlot && (\n <span\n data-slot=\"extra-nav\"\n className=\"ds:inline-flex ds:items-center\"\n >\n {extraNavSlot}\n </span>\n )}\n </>\n )}\n </div>\n </div>\n\n {tagline ? (\n <p\n data-slot=\"tagline\"\n className=\"ds:m-0 ds:text-center ds:text-[color:var(--muted-foreground)] ds:text-[length:var(--font-size-xs)] ds:italic\"\n >\n {tagline}\n </p>\n ) : null}\n </div>\n );\n}\n\nfunction FullColumnsGrid({\n columns,\n t,\n}: {\n columns: PublicFooterLinkGroup[];\n t: TFunction;\n}) {\n return (\n <>\n {columns.map((group, i) => (\n <section\n key={`${i}-${group.key}`}\n aria-labelledby={`public-footer-group-${i}-${group.key}`}\n >\n {/* h3 so the footer's column headings don't collide with the host\n page's section h2 outline. */}\n <h3\n id={`public-footer-group-${i}-${group.key}`}\n className=\"ds:m-0 ds:mb-[var(--spacing-sm)] ds:text-[color:var(--foreground)] ds:text-[length:var(--font-size-sm)] ds:font-medium\"\n >\n {t(`footer.group.${group.key}`, { defaultValue: group.key })}\n </h3>\n <ul className=\"ds:list-none ds:m-0 ds:p-0 ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {group.links.map((link) => (\n <li key={`${group.key}-${link.href}-${link.label}`}>\n <Link\n href={safeHref(link.href)}\n external={link.external}\n externalIcon={false}\n intent=\"subtle\"\n >\n {link.label}\n </Link>\n </li>\n ))}\n </ul>\n </section>\n ))}\n </>\n );\n}\n\nPublicFooter.displayName = 'PublicFooter';\n"],"names":["DEFAULT_MARKETING_BASE_URL","ITALIAN_SLUGS","SLUGS","HTTPS_PREFIX","normaliseBaseUrl","input","pickSlug","locale","key","overrides","override","_a","localeSlug","_b","composeLegalUrls","marketingBaseUrl","base","lang","SOCIAL_NETWORKS","DEFAULT_SOCIAL_URLS","baseProps","LinkedinIcon","props","jsx","YoutubeIcon","InstagramIcon","FacebookIcon","SOCIAL_ICONS","ENTITY_NAME","ENTITY_VAT","rootVariants","cva","SAFE_HREF_RE","safeHref","href","CopyrightLine","copyright","align","PublicFooter","forwardRef","variant","legalUrlOverrides","linkGroups","socials","logoSlot","extraNavSlot","trustBadgesSlot","showTagline","showCopyright","id","ariaLabel","ref","t","i18n","useTranslation","legalUrls","useMemo","useImperativeHandle","year","tagline","landmarkLabel","labels","resolvedSocials","network","jsxs","MinimalBody","CompactBody","FullBody","MINIMAL_LINK_HIT_AREA","Link","Separator","Fragment","SocialIconList","size","iconClass","s","Icon","label","Logo","buildLegalColumn","columns","FullColumnsGrid","Accordion","group","i","AccordionItem","AccordionTrigger","AccordionContent","link"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"public-footer-CXOrdAaS.js","sources":["../../src/components/public-footer/legal-urls.ts","../../src/components/public-footer/socials.tsx","../../src/components/public-footer/public-footer.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* PublicFooter — legally-required URL composition. */\n/* */\n/* GDPR + Italian/German commercial law require Privacy, Terms-of-use, */\n/* entity name and VAT to be visible on every public AlfaDocs surface. */\n/* The kit owns the slug table so a privacy-policy URL change is a single */\n/* kit bump rather than three repo edits. */\n/* */\n/* For locales without an explicit canonical slug, we fall back to the */\n/* Italian slugs — alfadocs.com defaults to Italian and unlocalised pages */\n/* render the IT version. Marketing supplies updates over time. */\n/* -------------------------------------------------------------------- */\n\nexport const DEFAULT_MARKETING_BASE_URL = 'https://www.alfadocs.com';\n\nexport type LegalUrlKey = 'privacy' | 'terms' | 'contacts';\n\nexport type LegalSlugMap = Record<LegalUrlKey, string>;\n\n/** Per-locale slug override; missing locales fall back to the kit default. */\nexport type LegalUrlOverride = Record<string, string>;\n\nexport interface LegalUrlOverrides {\n privacy?: LegalUrlOverride;\n terms?: LegalUrlOverride;\n contacts?: LegalUrlOverride;\n}\n\n/* Italian default — also used as the fallback for any locale without an\n * explicit entry below. */\nconst ITALIAN_SLUGS: LegalSlugMap = {\n privacy: '/privacy-prenotazione-online',\n terms: '/it/condizioni-di-utilizzo',\n contacts: '/it/contattaci',\n};\n\n/* Canonical per-locale slug table. Explicit entries come from marketing;\n * everything else inherits ITALIAN_SLUGS via the resolver below. */\nconst SLUGS: Record<string, LegalSlugMap> = {\n it: ITALIAN_SLUGS,\n en: {\n privacy: '/en/privacy',\n terms: '/en/terms-of-use',\n contacts: '/en/contact-us',\n },\n de: {\n privacy: '/de/datenschutz',\n terms: '/de/nutzungsbedingungen',\n contacts: '/de/kontakt',\n },\n fr: {\n privacy: '/fr/confidentialite',\n terms: '/fr/conditions-utilisation',\n contacts: '/fr/contact',\n },\n es: {\n privacy: '/es/privacidad',\n terms: '/es/condiciones-uso',\n contacts: '/es/contacto',\n },\n};\n\nconst HTTPS_PREFIX = 'https://';\n\nfunction normaliseBaseUrl(input: string | undefined): string {\n if (!input) return DEFAULT_MARKETING_BASE_URL;\n if (!input.startsWith(HTTPS_PREFIX)) {\n if (import.meta.env.DEV) {\n // eslint-disable-next-line no-console\n console.warn(\n `[PublicFooter] marketingBaseUrl must start with \"https://\" — falling back to ${DEFAULT_MARKETING_BASE_URL}. Received: \"${input}\"`,\n );\n }\n return DEFAULT_MARKETING_BASE_URL;\n }\n // Strip trailing slash so composed URLs don't double up.\n return input.replace(/\\/+$/, '');\n}\n\nfunction pickSlug(\n locale: string,\n key: LegalUrlKey,\n overrides: LegalUrlOverrides | undefined,\n): string {\n const override = overrides?.[key]?.[locale];\n if (override) return override;\n const localeSlug = SLUGS[locale]?.[key];\n if (localeSlug) return localeSlug;\n return ITALIAN_SLUGS[key];\n}\n\n/** Resolved legal URLs for the active locale + baseUrl + overrides. */\nexport interface ResolvedLegalUrls {\n privacy: string;\n terms: string;\n contacts: string;\n}\n\nexport function composeLegalUrls(\n locale: string,\n marketingBaseUrl: string | undefined,\n overrides?: LegalUrlOverrides,\n): ResolvedLegalUrls {\n const base = normaliseBaseUrl(marketingBaseUrl);\n const lang = (locale || 'it').split('-')[0]; // strip region — 'pt-BR' → 'pt'\n return {\n privacy: `${base}${pickSlug(lang, 'privacy', overrides)}`,\n terms: `${base}${pickSlug(lang, 'terms', overrides)}`,\n contacts: `${base}${pickSlug(lang, 'contacts', overrides)}`,\n };\n}\n","/* -------------------------------------------------------------------- */\n/* PublicFooter — default social-network URLs + brand icon components. */\n/* */\n/* AlfaDocs's four canonical social profiles. Consumers can subset via */\n/* `socials={[...]}` or override individual `href` values. */\n/* */\n/* Icons are small inline SVG components (paths from simpleicons.org) */\n/* rendered with `currentColor` so they inherit the footer's */\n/* `--muted-foreground` ink. Lucide-react does not ship brand glyphs, and */\n/* pulling a separate brand-icon package for four logos is not worth the */\n/* bundle cost. */\n/* -------------------------------------------------------------------- */\n\nimport type { ComponentType, SVGProps } from 'react';\n\nexport const SOCIAL_NETWORKS = [\n 'linkedin',\n 'youtube',\n 'instagram',\n 'facebook',\n] as const;\n\nexport type SocialNetwork = (typeof SOCIAL_NETWORKS)[number];\n\nexport const DEFAULT_SOCIAL_URLS: Record<SocialNetwork, string> = {\n linkedin: 'https://www.linkedin.com/company/alfadocs',\n youtube: 'https://www.youtube.com/@alfadocs',\n instagram: 'https://www.instagram.com/alfadocs',\n facebook: 'https://www.facebook.com/alfadocs',\n};\n\ntype IconProps = SVGProps<SVGSVGElement>;\ntype SocialIcon = ComponentType<IconProps>;\n\nconst baseProps = {\n viewBox: '0 0 24 24',\n fill: 'currentColor',\n xmlns: 'http://www.w3.org/2000/svg',\n} as const;\n\nconst LinkedinIcon: SocialIcon = (props) => (\n <svg {...baseProps} {...props}>\n <path d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 0 1-2.063-2.065 2.063 2.063 0 1 1 2.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z\" />\n </svg>\n);\n\nconst YoutubeIcon: SocialIcon = (props) => (\n <svg {...baseProps} {...props}>\n <path d=\"M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z\" />\n </svg>\n);\n\nconst InstagramIcon: SocialIcon = (props) => (\n <svg {...baseProps} {...props}>\n <path d=\"M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 1 0 0 12.324 6.162 6.162 0 0 0 0-12.324zM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm6.406-11.845a1.44 1.44 0 1 0 0 2.881 1.44 1.44 0 0 0 0-2.881z\" />\n </svg>\n);\n\nconst FacebookIcon: SocialIcon = (props) => (\n <svg {...baseProps} {...props}>\n <path d=\"M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z\" />\n </svg>\n);\n\nexport const SOCIAL_ICONS: Record<SocialNetwork, SocialIcon> = {\n linkedin: LinkedinIcon,\n youtube: YoutubeIcon,\n instagram: InstagramIcon,\n facebook: FacebookIcon,\n};\n","import {\n forwardRef,\n useImperativeHandle,\n useMemo,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Link } from '../link';\nimport { Separator } from '../separator';\nimport { Logo } from '../logo';\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from '../accordion';\nimport {\n composeLegalUrls,\n type LegalUrlOverrides,\n type ResolvedLegalUrls,\n} from './legal-urls';\nimport {\n DEFAULT_SOCIAL_URLS,\n SOCIAL_ICONS,\n SOCIAL_NETWORKS,\n type SocialNetwork,\n} from './socials';\n\n/* ------------------------------------------------------------------ */\n/* Constants */\n/* ------------------------------------------------------------------ */\n\nconst ENTITY_NAME = 'AlfaDocs GmbH';\nconst ENTITY_VAT = 'P.IVA DE301955405';\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst rootVariants = cva(\n [\n 'ds:w-full',\n 'ds:text-[color:var(--muted-foreground)]',\n 'ds:text-[length:var(--font-size-sm)]',\n 'ds:bg-[var(--background)]',\n ].join(' '),\n {\n variants: {\n variant: {\n minimal: [\n 'ds:py-[var(--spacing-sm)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:border-block-start ds:border-[var(--border)]',\n ].join(' '),\n // 0.30.5: compact got a polish pass — bumped vertical padding to\n // `lg` (~24px) so the footer reads as a real landmark, not a\n // one-line afterthought, plus a stronger top border in\n // accessible mode (the default `--border` clears 3:1 in light /\n // dark; accessible bumps to a heavier weight).\n //\n // 0.31.2: forced-colors top-border fallback. Windows High\n // Contrast strips `--border` to whatever the system maps it\n // to — which is often invisible against `Canvas`. Pinning to\n // `CanvasText` keeps the landmark edge visible for users on\n // strict HC themes.\n compact: [\n 'ds:py-[var(--spacing-lg)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:border-block-start ds:border-[var(--border)]',\n // 2px in the accessible themes, none elsewhere (--accessible-on).\n 'ds:[border-block-start-width:calc(var(--border-width-md)*var(--accessible-on,0))]',\n 'ds:forced-colors:[border-block-start-color:CanvasText]',\n ].join(' '),\n full: [\n 'ds:py-[var(--spacing-xl)]',\n 'ds:ps-[var(--spacing-lg)] ds:pe-[var(--spacing-lg)]',\n 'ds:bg-[var(--muted)]',\n ].join(' '),\n },\n },\n defaultVariants: { variant: 'compact' },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------ */\n\nexport type PublicFooterVariant = NonNullable<\n VariantProps<typeof rootVariants>['variant']\n>;\n\nexport interface PublicFooterLink {\n href: string;\n label: string;\n /** When true, link opens in a new tab with the localised aria-label suffix. */\n external?: boolean;\n}\n\nexport interface PublicFooterLinkGroup {\n /** Stable key — used to look up the column heading via `t('ui.footer.group.<key>')`. */\n key: 'product' | 'resources' | 'company' | 'legal' | (string & {});\n links: PublicFooterLink[];\n}\n\nexport interface PublicFooterSocial {\n network: SocialNetwork;\n /** Override the kit's default URL. */\n href?: string;\n}\n\nexport interface PublicFooterProps {\n variant: PublicFooterVariant;\n /** Origin for legally-required URLs. Default: 'https://www.alfadocs.com'. */\n marketingBaseUrl?: string;\n /** Override individual legal-link slugs per locale. Rare. */\n legalUrlOverrides?: LegalUrlOverrides;\n /** `full` variant: consumer-supplied link columns. Legal column is always rendered. */\n linkGroups?: PublicFooterLinkGroup[];\n /** `full` variant: subset of social networks. Default: all four. Pass `[]` to hide the row. */\n socials?: PublicFooterSocial[];\n /** `full` variant: custom logo node. Default: kit's wordmark Logo. */\n logoSlot?: ReactNode;\n /** Extra surface-specific links — appended after the standard nav row in compact + full. Ignored by minimal. */\n extraNavSlot?: ReactNode;\n /** Trust badges (HIPAA, ISO). Rendered at the start of `minimal`'s row, or in the bottom strip of `full`. */\n trustBadgesSlot?: ReactNode;\n /**\n * @default false\n * Render the brand tagline (\"German technology, Italian design\") in\n * the bottom microcopy row of `compact` and `full` variants.\n *\n * 0.32.4: default flipped to `false`. The tagline was loud on\n * booking-website's deployed footer and didn't carry product\n * meaning for end-users; marketing surfaces can opt back in\n * explicitly with `showTagline`. The `footer.tagline` i18n key\n * stays available so the opt-in path still works.\n */\n showTagline?: boolean;\n /**\n * The line with the year, the company name and the VAT number. On by\n * default: a public page must carry it. Turn it off only on a screen\n * that sits inside the app, such as sign-in or registration, where the\n * privacy and terms links are all the footer needs.\n * @default true\n */\n showCopyright?: boolean;\n 'aria-label'?: string;\n id?: string;\n}\n\nexport interface PublicFooterHandle {\n getVariant: () => PublicFooterVariant;\n /** Resolved legal URLs for the current locale + marketingBaseUrl + overrides. */\n getLegalUrls: () => ResolvedLegalUrls;\n}\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\n/** Allowlist consumer-supplied URLs — public marketing surface, defence in depth. */\nconst SAFE_HREF_RE = /^(https?:\\/\\/|mailto:|tel:|\\/(?!\\/))/i;\nfunction safeHref(href: string): string {\n return SAFE_HREF_RE.test(href) ? href : '#';\n}\n\nfunction CopyrightLine({\n copyright,\n align = 'center',\n}: {\n copyright: string;\n align?: 'start' | 'center';\n}) {\n return (\n <p\n className={[\n 'ds:m-0 ds:text-[color:var(--muted-foreground)]',\n 'ds:text-[length:var(--font-size-sm)]',\n align === 'center' ? 'ds:text-center' : 'ds:text-start',\n ].join(' ')}\n >\n {copyright}\n </p>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* PublicFooter */\n/* ------------------------------------------------------------------ */\n\nexport const PublicFooter = forwardRef<PublicFooterHandle, PublicFooterProps>(\n function PublicFooter(\n {\n variant,\n marketingBaseUrl,\n legalUrlOverrides,\n linkGroups,\n socials,\n logoSlot,\n extraNavSlot,\n trustBadgesSlot,\n showTagline = false,\n showCopyright = true,\n id,\n 'aria-label': ariaLabel,\n },\n ref,\n ) {\n const { t, i18n } = useTranslation('ui');\n\n const legalUrls = useMemo(\n () =>\n composeLegalUrls(i18n.language, marketingBaseUrl, legalUrlOverrides),\n [i18n.language, marketingBaseUrl, legalUrlOverrides],\n );\n\n useImperativeHandle(\n ref,\n () => ({\n getVariant: () => variant,\n getLegalUrls: () => legalUrls,\n }),\n [variant, legalUrls],\n );\n\n const year = new Date().getFullYear();\n const copyright = showCopyright\n ? t('footer.copyright', {\n year,\n entity: ENTITY_NAME,\n vat: ENTITY_VAT,\n })\n : undefined;\n const tagline = showTagline ? t('footer.tagline') : undefined;\n const landmarkLabel = ariaLabel ?? t('footer.nav.label');\n\n const labels = {\n privacy: t('footer.nav.privacy'),\n terms: t('footer.nav.terms'),\n contacts: t('footer.nav.contacts'),\n };\n\n const resolvedSocials = useMemo<PublicFooterSocial[]>(() => {\n if (socials !== undefined) return socials;\n return SOCIAL_NETWORKS.map((network) => ({ network }));\n }, [socials]);\n\n return (\n <footer\n id={id}\n role=\"contentinfo\"\n aria-label={landmarkLabel}\n data-component=\"public-footer\"\n data-component-id={id}\n data-variant={variant}\n className={rootVariants({ variant })}\n >\n {variant === 'minimal' && (\n <MinimalBody\n legalUrls={legalUrls}\n labels={labels}\n copyright={copyright}\n trustBadgesSlot={trustBadgesSlot}\n />\n )}\n {variant === 'compact' && (\n <CompactBody\n legalUrls={legalUrls}\n labels={labels}\n copyright={copyright}\n tagline={tagline}\n socials={resolvedSocials}\n logoSlot={logoSlot}\n extraNavSlot={extraNavSlot}\n t={t}\n />\n )}\n {variant === 'full' && (\n <FullBody\n legalUrls={legalUrls}\n labels={labels}\n copyright={copyright}\n tagline={tagline}\n linkGroups={linkGroups}\n socials={resolvedSocials}\n logoSlot={logoSlot}\n extraNavSlot={extraNavSlot}\n trustBadgesSlot={trustBadgesSlot}\n t={t}\n />\n )}\n </footer>\n );\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Minimal */\n/* ------------------------------------------------------------------ */\n\n// The minimal row's links are one line of small text, 21px tall: under the\n// 24px WCAG 2.5.8 asks of a target. A transparent `::before` stretches the\n// hit area to 24px (--spacing-lg) in the block direction without moving or\n// resizing anything the eye sees, and to --min-target-size (48px) in the\n// accessible themes, through --accessible-target-floor. Once a link is as\n// tall as that the inset turns positive and the box sits inside the link,\n// which is harmless.\nconst MINIMAL_LINK_HIT_AREA =\n 'ds:relative ds:before:absolute ds:before:inset-x-0 ds:before:inset-y-[calc((var(--accessible-target-floor,var(--spacing-lg))-100%)/-2)] ds:before:content-[\"\"]';\n\nfunction MinimalBody({\n legalUrls,\n labels,\n copyright,\n trustBadgesSlot,\n}: {\n legalUrls: ResolvedLegalUrls;\n labels: { privacy: string; terms: string; contacts: string };\n copyright?: string;\n trustBadgesSlot?: ReactNode;\n}) {\n return (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-center ds:gap-x-[var(--spacing-sm)] ds:gap-y-[var(--spacing-sm)]\">\n {trustBadgesSlot && (\n <span\n data-slot=\"trust-badges\"\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)] ds:me-[var(--spacing-sm)]\"\n >\n {trustBadgesSlot}\n </span>\n )}\n <Link\n href={legalUrls.privacy}\n external\n externalIcon={false}\n intent=\"subtle\"\n className={MINIMAL_LINK_HIT_AREA}\n >\n {labels.privacy}\n </Link>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n <Link\n href={legalUrls.terms}\n external\n externalIcon={false}\n intent=\"subtle\"\n className={MINIMAL_LINK_HIT_AREA}\n >\n {labels.terms}\n </Link>\n {copyright ? (\n <>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n <span>{copyright}</span>\n </>\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Compact */\n/* ------------------------------------------------------------------ */\n\n// Shared social-icon row — used by Compact and Full. Renders an icon\n// per enabled network; the parent decides where to drop it.\nfunction SocialIconList({\n socials,\n t,\n size,\n}: {\n socials: PublicFooterSocial[];\n t: TFunction;\n size: 'sm' | 'md';\n}) {\n if (socials.length === 0) return null;\n const iconClass = size === 'sm' ? 'ds:size-4' : 'ds:size-5';\n return (\n <ul\n data-slot=\"socials\"\n className=\"ds:list-none ds:m-0 ds:p-0 ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n {socials.map((s) => {\n const Icon = SOCIAL_ICONS[s.network];\n const href = s.href ?? DEFAULT_SOCIAL_URLS[s.network];\n const label = t(`footer.social.aria.${s.network}`);\n return (\n <li key={s.network}>\n <Link\n href={safeHref(href)}\n external\n externalIcon={false}\n intent=\"subtle\"\n aria-label={label}\n className=\"ds:inline-flex ds:items-center ds:justify-center ds:min-w-[var(--min-target-size)] ds:min-h-[var(--min-target-size)]\"\n >\n <Icon\n aria-hidden=\"true\"\n className={iconClass}\n focusable=\"false\"\n />\n </Link>\n </li>\n );\n })}\n </ul>\n );\n}\n\nfunction CompactBody({\n legalUrls,\n labels,\n copyright,\n tagline,\n socials,\n logoSlot,\n extraNavSlot,\n t,\n}: {\n legalUrls: ResolvedLegalUrls;\n labels: { privacy: string; terms: string; contacts: string };\n copyright?: string;\n tagline?: string;\n socials: PublicFooterSocial[];\n logoSlot?: ReactNode;\n extraNavSlot?: ReactNode;\n t: TFunction;\n}) {\n // 0.30.5: compact polish — defaults to a social-icon row + (small,\n // muted) wordmark at the start of the link row. Consumers who want\n // the lean treatment can opt out via `socials={[]}` (kills the row)\n // and `logoSlot={<></>}` (kills the wordmark). The lean fallback is\n // still a useful surface for embedded widgets (the booking aside).\n return (\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-md)]\">\n {socials.length > 0 ? (\n <SocialIconList socials={socials} t={t} size=\"sm\" />\n ) : null}\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-center ds:gap-x-[var(--spacing-sm)] ds:gap-y-[var(--spacing-sm)]\">\n {logoSlot !== undefined ? (\n logoSlot !== null && logoSlot !== false && logoSlot !== '' ? (\n <>\n <span\n data-slot=\"compact-logo\"\n className=\"ds:inline-flex ds:items-center ds:opacity-70\"\n >\n {logoSlot}\n </span>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n </>\n ) : null\n ) : (\n // No consumer override — render the kit's default small\n // wordmark, muted so it reads as marker not headline.\n <>\n <span\n data-slot=\"compact-logo\"\n className=\"ds:inline-flex ds:items-center ds:opacity-70\"\n >\n <Logo variant=\"wordmark\" tone=\"auto\" aria-label=\"Alfadocs\" />\n </span>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n </>\n )}\n <Link\n href={legalUrls.privacy}\n external\n externalIcon={false}\n intent=\"subtle\"\n >\n {labels.privacy}\n </Link>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n <Link\n href={legalUrls.terms}\n external\n externalIcon={false}\n intent=\"subtle\"\n >\n {labels.terms}\n </Link>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n <Link\n href={legalUrls.contacts}\n external\n externalIcon={false}\n intent=\"subtle\"\n >\n {labels.contacts}\n </Link>\n {extraNavSlot && (\n <>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n <span data-slot=\"extra-nav\">{extraNavSlot}</span>\n </>\n )}\n </div>\n {copyright ? <CopyrightLine copyright={copyright} /> : null}\n {tagline ? (\n <p\n data-slot=\"tagline\"\n className=\"ds:m-0 ds:text-center ds:text-[color:var(--muted-foreground)] ds:text-[length:var(--font-size-xs)] ds:italic\"\n >\n {tagline}\n </p>\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Full */\n/* ------------------------------------------------------------------ */\n\ntype TFunction = ReturnType<typeof useTranslation>['t'];\n\nfunction buildLegalColumn(\n legalUrls: ResolvedLegalUrls,\n labels: { privacy: string; terms: string; contacts: string },\n): PublicFooterLinkGroup {\n return {\n key: 'legal',\n links: [\n { href: legalUrls.privacy, label: labels.privacy, external: true },\n { href: legalUrls.terms, label: labels.terms, external: true },\n { href: legalUrls.contacts, label: labels.contacts, external: true },\n ],\n };\n}\n\nfunction FullBody({\n legalUrls,\n labels,\n copyright,\n tagline,\n linkGroups,\n socials,\n logoSlot,\n extraNavSlot,\n trustBadgesSlot,\n t,\n}: {\n legalUrls: ResolvedLegalUrls;\n labels: { privacy: string; terms: string; contacts: string };\n copyright?: string;\n tagline?: string;\n linkGroups?: PublicFooterLinkGroup[];\n socials: PublicFooterSocial[];\n logoSlot?: ReactNode;\n extraNavSlot?: ReactNode;\n trustBadgesSlot?: ReactNode;\n t: TFunction;\n}) {\n // The kit-built Legal column is always appended — Privacy / Terms /\n // Contacts must render in every variant per the legal brief.\n const columns: PublicFooterLinkGroup[] = [\n ...(linkGroups ?? []),\n buildLegalColumn(legalUrls, labels),\n ];\n\n const brand = (\n <div\n data-slot=\"brand\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n <div className=\"ds:inline-flex\">\n {logoSlot ?? (\n <Logo variant=\"wordmark\" tone=\"auto\" aria-label=\"Alfadocs\" />\n )}\n </div>\n <SocialIconList socials={socials} t={t} size=\"md\" />\n </div>\n );\n\n return (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xl)]\">\n {/* Top: brand block on inline-start + link columns to inline-end */}\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xl)] ds:lg:flex-row ds:lg:items-start ds:lg:gap-[var(--spacing-xl)]\">\n <div className=\"ds:lg:w-[15rem] ds:lg:shrink-0\">{brand}</div>\n\n <div className=\"ds:flex-1 ds:min-w-0\">\n {/* md+ — grid of columns */}\n <div\n className=\"ds:hidden ds:md:grid ds:md:grid-cols-2 ds:lg:grid-cols-4 ds:gap-[var(--spacing-lg)]\"\n data-slot=\"link-columns-grid\"\n data-columns={columns.length}\n >\n <FullColumnsGrid columns={columns} t={t} />\n </div>\n\n {/* below md — accordion */}\n <div className=\"ds:md:hidden\" data-slot=\"link-columns-accordion\">\n <Accordion type=\"multiple\">\n {columns.map((group, i) => (\n <AccordionItem\n key={`${i}-${group.key}`}\n value={`${i}-${group.key}`}\n >\n <AccordionTrigger>\n {t(`footer.group.${group.key}`, {\n defaultValue: group.key,\n })}\n </AccordionTrigger>\n <AccordionContent>\n <ul className=\"ds:list-none ds:m-0 ds:p-0 ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {group.links.map((link) => (\n <li key={`${group.key}-${link.href}-${link.label}`}>\n <Link\n href={safeHref(link.href)}\n external={link.external}\n externalIcon={false}\n intent=\"subtle\"\n >\n {link.label}\n </Link>\n </li>\n ))}\n </ul>\n </AccordionContent>\n </AccordionItem>\n ))}\n </Accordion>\n </div>\n </div>\n </div>\n\n <Separator orientation=\"horizontal\" />\n\n {/* Bottom strip: copyright inline-start, mini legal links inline-end\n on the same row. Stacks under sm. */}\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:sm:flex-row ds:sm:items-center ds:sm:justify-between\">\n {copyright ? (\n <CopyrightLine copyright={copyright} align=\"start\" />\n ) : null}\n <div\n data-slot=\"bottom-legal\"\n className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)] ds:sm:justify-end\"\n >\n <Link\n href={legalUrls.privacy}\n external\n externalIcon={false}\n intent=\"subtle\"\n >\n {labels.privacy}\n </Link>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n <Link\n href={legalUrls.terms}\n external\n externalIcon={false}\n intent=\"subtle\"\n >\n {labels.terms}\n </Link>\n {(trustBadgesSlot || extraNavSlot) && (\n <>\n <Separator orientation=\"vertical\" className=\"ds:h-4\" />\n {trustBadgesSlot && (\n <span\n data-slot=\"trust-badges\"\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\"\n >\n {trustBadgesSlot}\n </span>\n )}\n {extraNavSlot && (\n <span\n data-slot=\"extra-nav\"\n className=\"ds:inline-flex ds:items-center\"\n >\n {extraNavSlot}\n </span>\n )}\n </>\n )}\n </div>\n </div>\n\n {tagline ? (\n <p\n data-slot=\"tagline\"\n className=\"ds:m-0 ds:text-center ds:text-[color:var(--muted-foreground)] ds:text-[length:var(--font-size-xs)] ds:italic\"\n >\n {tagline}\n </p>\n ) : null}\n </div>\n );\n}\n\nfunction FullColumnsGrid({\n columns,\n t,\n}: {\n columns: PublicFooterLinkGroup[];\n t: TFunction;\n}) {\n return (\n <>\n {columns.map((group, i) => (\n <section\n key={`${i}-${group.key}`}\n aria-labelledby={`public-footer-group-${i}-${group.key}`}\n >\n {/* h3 so the footer's column headings don't collide with the host\n page's section h2 outline. */}\n <h3\n id={`public-footer-group-${i}-${group.key}`}\n className=\"ds:m-0 ds:mb-[var(--spacing-sm)] ds:text-[color:var(--foreground)] ds:text-[length:var(--font-size-sm)] ds:font-medium\"\n >\n {t(`footer.group.${group.key}`, { defaultValue: group.key })}\n </h3>\n <ul className=\"ds:list-none ds:m-0 ds:p-0 ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {group.links.map((link) => (\n <li key={`${group.key}-${link.href}-${link.label}`}>\n <Link\n href={safeHref(link.href)}\n external={link.external}\n externalIcon={false}\n intent=\"subtle\"\n >\n {link.label}\n </Link>\n </li>\n ))}\n </ul>\n </section>\n ))}\n </>\n );\n}\n\nPublicFooter.displayName = 'PublicFooter';\n"],"names":["DEFAULT_MARKETING_BASE_URL","ITALIAN_SLUGS","SLUGS","HTTPS_PREFIX","normaliseBaseUrl","input","pickSlug","locale","key","overrides","override","_a","localeSlug","_b","composeLegalUrls","marketingBaseUrl","base","lang","SOCIAL_NETWORKS","DEFAULT_SOCIAL_URLS","baseProps","LinkedinIcon","props","jsx","YoutubeIcon","InstagramIcon","FacebookIcon","SOCIAL_ICONS","ENTITY_NAME","ENTITY_VAT","rootVariants","cva","SAFE_HREF_RE","safeHref","href","CopyrightLine","copyright","align","PublicFooter","forwardRef","variant","legalUrlOverrides","linkGroups","socials","logoSlot","extraNavSlot","trustBadgesSlot","showTagline","showCopyright","id","ariaLabel","ref","t","i18n","useTranslation","legalUrls","useMemo","useImperativeHandle","year","tagline","landmarkLabel","labels","resolvedSocials","network","jsxs","MinimalBody","CompactBody","FullBody","MINIMAL_LINK_HIT_AREA","Link","Separator","Fragment","SocialIconList","size","iconClass","s","Icon","label","Logo","buildLegalColumn","columns","FullColumnsGrid","Accordion","group","i","AccordionItem","AccordionTrigger","AccordionContent","link"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { jsxs as d, jsx as e, Fragment as v } from "react/jsx-runtime";
|
|
|
2
2
|
import { forwardRef as y } from "react";
|
|
3
3
|
import { c as H } from "./index-D2ZczOXr.js";
|
|
4
4
|
import { A as S } from "./app-frame-DUPEwu4E.js";
|
|
5
|
-
import { P as x } from "./public-footer-
|
|
5
|
+
import { P as x } from "./public-footer-CXOrdAaS.js";
|
|
6
6
|
import { useTranslation as b } from "react-i18next";
|
|
7
7
|
import { B as u } from "./button-D-MQxsA_.js";
|
|
8
8
|
import { H as N, g as O, f as F, a as z, d as B } from "./header-_TppWBpK.js";
|
|
@@ -168,4 +168,4 @@ export {
|
|
|
168
168
|
V as S,
|
|
169
169
|
w as a
|
|
170
170
|
};
|
|
171
|
-
//# sourceMappingURL=signed-out-frame-
|
|
171
|
+
//# sourceMappingURL=signed-out-frame-Rg_GVDnl.js.map
|