@alfadocs/ui-kit-debug 1.3.0 → 1.3.3
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/{ai-consent-banner-DKgFfSzc.js → ai-consent-banner-BUKKPDTg.js} +2 -2
- package/dist/_chunks/{ai-consent-banner-DKgFfSzc.js.map → ai-consent-banner-BUKKPDTg.js.map} +1 -1
- package/dist/_chunks/{alert-DS22ha1n.js → alert-CiJT540z.js} +2 -2
- package/dist/_chunks/{alert-DS22ha1n.js.map → alert-CiJT540z.js.map} +1 -1
- package/dist/_chunks/{anamnesis-i18n-DGRdwc0i.js → anamnesis-i18n-B9twItQc.js} +1547 -1526
- package/dist/_chunks/anamnesis-i18n-B9twItQc.js.map +1 -0
- package/dist/_chunks/{audio-recorder-sRsGS-0V.js → audio-recorder-BSuKNrmd.js} +2 -2
- package/dist/_chunks/{audio-recorder-sRsGS-0V.js.map → audio-recorder-BSuKNrmd.js.map} +1 -1
- package/dist/_chunks/{booking-D8fCzcUd.js → booking-BxFV0hT5.js} +2 -2
- package/dist/_chunks/{booking-D8fCzcUd.js.map → booking-BxFV0hT5.js.map} +1 -1
- package/dist/_chunks/{care-plan-card-DjjVnBYz.js → care-plan-card-1G_f4I5s.js} +2 -2
- package/dist/_chunks/{care-plan-card-DjjVnBYz.js.map → care-plan-card-1G_f4I5s.js.map} +1 -1
- package/dist/_chunks/{care-plan-entry-card-BVhpvd-P.js → care-plan-entry-card-DmBsffHS.js} +2 -2
- package/dist/_chunks/{care-plan-entry-card-BVhpvd-P.js.map → care-plan-entry-card-DmBsffHS.js.map} +1 -1
- package/dist/_chunks/{collapsible-CGL9ontS.js → collapsible-CTjxzGuF.js} +26 -29
- package/dist/_chunks/collapsible-CTjxzGuF.js.map +1 -0
- package/dist/_chunks/{document-preview-DAczwybt.js → document-preview-D3gg4MXB.js} +2 -2
- package/dist/_chunks/{document-preview-DAczwybt.js.map → document-preview-D3gg4MXB.js.map} +1 -1
- package/dist/_chunks/{document-scanner-BRYIc3A-.js → document-scanner-D8ASqxif.js} +2 -2
- package/dist/_chunks/{document-scanner-BRYIc3A-.js.map → document-scanner-D8ASqxif.js.map} +1 -1
- package/dist/_chunks/{entity-summary-BS6n7Iah.js → entity-summary-C6lL3seQ.js} +2 -2
- package/dist/_chunks/{entity-summary-BS6n7Iah.js.map → entity-summary-C6lL3seQ.js.map} +1 -1
- package/dist/_chunks/{freemium-paywall-DsT7MaLd.js → freemium-paywall-C_Ue6wxU.js} +2 -2
- package/dist/_chunks/{freemium-paywall-DsT7MaLd.js.map → freemium-paywall-C_Ue6wxU.js.map} +1 -1
- package/dist/_chunks/{marketplace-app-shell-DQC9Gpm0.js → marketplace-app-shell-DwcFMxzp.js} +2 -2
- package/dist/_chunks/{marketplace-app-shell-DQC9Gpm0.js.map → marketplace-app-shell-DwcFMxzp.js.map} +1 -1
- package/dist/_chunks/{patient-details-l7pnsUq9.js → patient-details-BAUg0FWs.js} +2 -2
- package/dist/_chunks/{patient-details-l7pnsUq9.js.map → patient-details-BAUg0FWs.js.map} +1 -1
- package/dist/_chunks/{patient-search-H54Utav2.js → patient-search-yG0UaCpQ.js} +2 -2
- package/dist/_chunks/{patient-search-H54Utav2.js.map → patient-search-yG0UaCpQ.js.map} +1 -1
- package/dist/_chunks/{payment-automation-upsell-C4LIw1iQ.js → payment-automation-upsell-D_x880pr.js} +2 -2
- package/dist/_chunks/{payment-automation-upsell-C4LIw1iQ.js.map → payment-automation-upsell-D_x880pr.js.map} +1 -1
- package/dist/_chunks/{payment-form-CyKT20xZ.js → payment-form-h-BZ8onk.js} +2 -2
- package/dist/_chunks/{payment-form-CyKT20xZ.js.map → payment-form-h-BZ8onk.js.map} +1 -1
- package/dist/_chunks/{pdf-viewer-DHg8SfUI.js → pdf-viewer-Ddx-T053.js} +2 -2
- package/dist/_chunks/{pdf-viewer-DHg8SfUI.js.map → pdf-viewer-Ddx-T053.js.map} +1 -1
- package/dist/_chunks/{practice-results-qvJRkvLn.js → practice-results-B-HPc13W.js} +2 -2
- package/dist/_chunks/{practice-results-qvJRkvLn.js.map → practice-results-B-HPc13W.js.map} +1 -1
- package/dist/_chunks/{reviews-panel-BfUJhx3m.js → reviews-panel-tZlWiUBl.js} +2 -2
- package/dist/_chunks/{reviews-panel-BfUJhx3m.js.map → reviews-panel-tZlWiUBl.js.map} +1 -1
- package/dist/_chunks/{sign-document-D70TEUw9.js → sign-document-CW_ByDUh.js} +2 -2
- package/dist/_chunks/{sign-document-D70TEUw9.js.map → sign-document-CW_ByDUh.js.map} +1 -1
- package/dist/_chunks/{signature-request-BlNCXpRN.js → signature-request-DZEFtbER.js} +2 -2
- package/dist/_chunks/{signature-request-BlNCXpRN.js.map → signature-request-DZEFtbER.js.map} +1 -1
- package/dist/_chunks/{warning-stack-IVf0oxh2.js → warning-stack-BtjmJChC.js} +2 -2
- package/dist/_chunks/{warning-stack-IVf0oxh2.js.map → warning-stack-BtjmJChC.js.map} +1 -1
- package/dist/_chunks/{workflow-map-ByyBYj6Y.js → workflow-map-BVMeVHkV.js} +2 -2
- package/dist/_chunks/{workflow-map-ByyBYj6Y.js.map → workflow-map-BVMeVHkV.js.map} +1 -1
- package/dist/agent-catalog.json +1 -1
- package/dist/components/ai-consent-banner/index.js +1 -1
- package/dist/components/alert/index.js +1 -1
- package/dist/components/audio-recorder/index.js +1 -1
- package/dist/components/booking/index.js +1 -1
- package/dist/components/care-plan-card/index.js +1 -1
- package/dist/components/care-plan-entry-card/index.js +1 -1
- package/dist/components/collapsible/collapsible.d.ts.map +1 -1
- package/dist/components/collapsible/index.js +1 -1
- package/dist/components/document-preview/index.js +1 -1
- package/dist/components/document-scanner/index.js +1 -1
- package/dist/components/entity-summary/index.js +1 -1
- package/dist/components/freemium-paywall/index.js +1 -1
- package/dist/components/patient-details/index.js +1 -1
- package/dist/components/patient-search/index.js +1 -1
- package/dist/components/payment-form/index.js +1 -1
- package/dist/components/pdf-viewer/index.js +1 -1
- package/dist/components/practice-results/index.js +1 -1
- package/dist/components/reviews-panel/index.js +1 -1
- package/dist/components/sign-document/index.js +1 -1
- package/dist/components/warning-stack/index.js +1 -1
- package/dist/components/workflow/index.js +1 -1
- package/dist/index.js +24 -24
- package/dist/patterns/anamnesis/anamnesis-compile.d.ts +6 -1
- package/dist/patterns/anamnesis/anamnesis-compile.d.ts.map +1 -1
- package/dist/patterns/anamnesis/anamnesis-intake.d.ts +11 -2
- package/dist/patterns/anamnesis/anamnesis-intake.d.ts.map +1 -1
- package/dist/patterns/anamnesis/anamnesis.d.ts +13 -1
- package/dist/patterns/anamnesis/anamnesis.d.ts.map +1 -1
- package/dist/patterns/anamnesis/index.d.ts +2 -0
- package/dist/patterns/anamnesis/index.d.ts.map +1 -1
- package/dist/patterns/anamnesis/index.js +1 -1
- package/dist/patterns/marketplace-app-shell/index.js +1 -1
- package/dist/patterns/payment-automation-upsell/index.js +1 -1
- package/dist/patterns/signature-request/index.js +1 -1
- package/dist/tokens.css +1 -1
- package/package.json +1 -1
- package/dist/_chunks/anamnesis-i18n-DGRdwc0i.js.map +0 -1
- package/dist/_chunks/collapsible-CGL9ontS.js.map +0 -1
|
@@ -2,7 +2,7 @@ import { jsxs as r, jsx as n } from "react/jsx-runtime";
|
|
|
2
2
|
import { forwardRef as N, useState as k, useRef as q, useMemo as I } from "react";
|
|
3
3
|
import { c as L } from "./index-D2ZczOXr.js";
|
|
4
4
|
import { useTranslation as R } from "react-i18next";
|
|
5
|
-
import { A as d } from "./alert-
|
|
5
|
+
import { A as d } from "./alert-CiJT540z.js";
|
|
6
6
|
import { B as w } from "./badge-DCOqV9mI.js";
|
|
7
7
|
import { B as T } from "./button-CPGiR_bH.js";
|
|
8
8
|
import { C as V } from "./checkbox-BuZ1u__2.js";
|
|
@@ -167,4 +167,4 @@ export {
|
|
|
167
167
|
P as A,
|
|
168
168
|
K as a
|
|
169
169
|
};
|
|
170
|
-
//# sourceMappingURL=ai-consent-banner-
|
|
170
|
+
//# sourceMappingURL=ai-consent-banner-BUKKPDTg.js.map
|
package/dist/_chunks/{ai-consent-banner-DKgFfSzc.js.map → ai-consent-banner-BUKKPDTg.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-consent-banner-DKgFfSzc.js","sources":["../../src/components/ai-consent-banner/ai-consent-banner.agent.ts","../../src/components/ai-consent-banner/ai-consent-banner.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — AiConsentBanner. */\n/* */\n/* Read-only structural surface: the current consent state and whether */\n/* the grant affordance is armed. Identifiers / structural state ONLY — */\n/* never the grantee's name or any PHI. The real consent gate lives */\n/* server-side; this adapter does not expose a grant action so an agent */\n/* cannot consent on a user's behalf. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { AiConsentBannerHandle } from './ai-consent-banner';\n\nexport const aiConsentBannerAgent: AgentAdapter<AiConsentBannerHandle> = {\n id: 'ai-consent-banner',\n capabilities: [],\n state: {\n consentState: {\n type: \"'granted' | 'required' | 'pending'\",\n descriptionKey: 'ui.agent.aiConsentBanner.state.consentState',\n description:\n 'Current consent state. Structural only — never the grantee identity.',\n read: (handle) => handle.getState(),\n },\n armed: {\n type: 'boolean',\n descriptionKey: 'ui.agent.aiConsentBanner.state.armed',\n description:\n 'Whether the consent confirmation checkbox is ticked (required state only).',\n read: (handle) => handle.isArmed(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'ai-consent-banner',\n description: 'Marks the AiConsentBanner root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific banner from the agent.',\n },\n },\n};\n","import {\n forwardRef,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Alert } from '../alert/alert';\nimport { Badge } from '../badge/badge';\nimport { Button } from '../button/button';\nimport { Checkbox } from '../checkbox/checkbox';\nimport { Spinner } from '../spinner/spinner';\nimport { Timestamp } from '../timestamp/timestamp';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { aiConsentBannerAgent } from './ai-consent-banner.agent';\n\n/* -------------------------------------------------------------------- */\n/* AiConsentBanner */\n/* */\n/* Presentational AI-consent gate surfaced above an AI-assisted surface */\n/* (e.g. Alfascribe consultation transcription). The SERVER owns the */\n/* real gate — this component only reflects the consent record and lets */\n/* the operator initiate a grant; it never enforces access itself. */\n/* */\n/* Three states drive the Alert variant + body: */\n/* - granted → success Alert with a Badge + when/who it was granted. */\n/* - required → info Alert with a Checkbox-gated Grant Button. */\n/* - pending → info Alert in a disabled, Spinner-busy state while the */\n/* server persists the grant. */\n/* */\n/* All visible text flows through useTranslation('ui') against the */\n/* `aiConsentBanner.*` namespace. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA — root */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n state: {\n granted: '',\n required: '',\n pending: '',\n },\n },\n defaultVariants: {\n state: 'required',\n },\n});\n\n/* -------------------------------------------------------------------- */\n/* State derivation */\n/* -------------------------------------------------------------------- */\n\nexport type AiConsentState = NonNullable<\n VariantProps<typeof rootVariants>['state']\n>;\n\n/** Pending wins over granted/required so the busy state is never masked. */\nfunction deriveState(granted: boolean, pending: boolean): AiConsentState {\n if (pending) return 'pending';\n return granted ? 'granted' : 'required';\n}\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/** Agent-readiness curated handle. Exposes the structural consent state only. */\nexport interface AiConsentBannerHandle {\n /** Current derived state: 'granted' | 'required' | 'pending'. */\n getState: () => AiConsentState;\n /** Whether the Grant affordance is currently armed (checkbox ticked). */\n isArmed: () => boolean;\n}\n\nexport interface AiConsentBannerProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children' | 'role'\n> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so an\n * agent / MCP UI bridge can address this specific banner. Mirrored to the\n * real DOM `id`.\n */\n id?: string;\n /** Whether consent has already been granted. Server-sourced. */\n granted: boolean;\n /**\n * When consent was granted — ISO-8601 string, ms-epoch, or Date. Rendered\n * via `Timestamp` in the granted state.\n */\n grantedAt?: string | number | Date;\n /** Who granted consent (operator display name / role). Granted state only. */\n grantedBy?: string;\n /**\n * Whether the current user is allowed to grant consent. When `false`, the\n * required-state Grant affordance is hidden and a not-allowed note shows.\n * Default `true`.\n */\n canGrant?: boolean;\n /** The grant is being persisted server-side — shows the busy Spinner state. */\n pending?: boolean;\n /** Fired when the operator confirms the consent grant. */\n onGrantConsent?: () => void;\n /** Override the region's accessible name. */\n 'aria-label'?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const AiConsentBanner = forwardRef<HTMLDivElement, AiConsentBannerProps>(\n (\n {\n id,\n granted,\n grantedAt,\n grantedBy,\n canGrant = true,\n pending = false,\n onGrantConsent,\n 'aria-label': ariaLabel,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const state = deriveState(granted, pending);\n\n // Local arm switch — the required state gates the Grant Button behind an\n // explicit \"I understand\" checkbox so consent is never one mis-click away.\n const [armed, setArmed] = useState(false);\n\n const armedRef = useRef(armed);\n armedRef.current = armed;\n\n const handle = useMemo<AiConsentBannerHandle>(\n () => ({\n getState: () => deriveState(granted, pending),\n isArmed: () => armedRef.current,\n }),\n [granted, pending],\n );\n useAgentRegistration(aiConsentBannerAgent, handle, id);\n\n const resolvedAriaLabel =\n ariaLabel ?? t('aiConsentBanner.regionLabel', 'AI assistance consent');\n\n // Alert variant per state: granted → success, required/pending → info.\n const alertVariant = state === 'granted' ? 'success' : 'info';\n\n let body: React.ReactNode;\n if (state === 'granted') {\n body = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Badge variant=\"success\">\n {t('aiConsentBanner.badge.granted', 'Consent granted')}\n </Badge>\n {grantedAt !== undefined ? (\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.grantedAtPrefix', 'Granted')}{' '}\n <Timestamp value={grantedAt} format=\"relative\" shape=\"inline\" />\n </span>\n ) : null}\n </div>\n {grantedBy ? (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.grantedBy', {\n name: grantedBy,\n defaultValue: 'By {{name}}',\n })}\n </p>\n ) : null}\n </div>\n );\n } else if (state === 'pending') {\n body = (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Spinner\n variant=\"pulse\"\n size=\"sm\"\n label={t('aiConsentBanner.pendingLabel', 'Saving consent…')}\n />\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.pendingLabel', 'Saving consent…')}\n </span>\n </div>\n );\n } else {\n // required\n body = canGrant ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n <Checkbox\n checked={armed}\n onCheckedChange={(next) => setArmed(next === true)}\n label={t(\n 'aiConsentBanner.confirmLabel',\n 'I confirm consent has been obtained for AI assistance.',\n )}\n />\n <Alert.Action>\n <Button\n intent=\"primary\"\n size=\"sm\"\n disabled={!armed}\n onClick={onGrantConsent}\n >\n {t('aiConsentBanner.grantButton', 'Grant consent')}\n </Button>\n </Alert.Action>\n </div>\n ) : (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {t(\n 'aiConsentBanner.notAllowed',\n 'You do not have permission to grant AI assistance consent.',\n )}\n </p>\n );\n }\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={resolvedAriaLabel}\n aria-busy={state === 'pending' ? true : undefined}\n data-component=\"ai-consent-banner\"\n data-component-id={id}\n data-state={state}\n id={id}\n className={rootVariants({ state, className })}\n {...rest}\n >\n <Alert\n variant={alertVariant}\n icon={state === 'pending' ? null : undefined}\n >\n <Alert.Title>\n {t('aiConsentBanner.title', 'AI assistance consent')}\n </Alert.Title>\n <Alert.Description>\n {state === 'granted'\n ? t(\n 'aiConsentBanner.description.granted',\n 'AI assistance is enabled for this record.',\n )\n : t(\n 'aiConsentBanner.description.required',\n 'AI assistance requires recorded consent before it can run.',\n )}\n </Alert.Description>\n {body}\n </Alert>\n </div>\n );\n },\n);\n\nAiConsentBanner.displayName = 'AiConsentBanner';\n"],"names":["aiConsentBannerAgent","handle","rootVariants","cva","deriveState","granted","pending","AiConsentBanner","forwardRef","id","grantedAt","grantedBy","canGrant","onGrantConsent","ariaLabel","className","rest","ref","t","useTranslation","state","armed","setArmed","useState","armedRef","useRef","useMemo","useAgentRegistration","resolvedAriaLabel","alertVariant","body","jsxs","jsx","Badge","Timestamp","Spinner","Checkbox","next","Alert","Button"],"mappings":";;;;;;;;;;;AAaO,MAAMA,IAA4D;AAAA,EACvE,IAAI;AAAA,EACJ,cAAc,CAAA;AAAA,EACd,OAAO;AAAA,IACL,cAAc;AAAA,MACZ,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACC,MAAWA,EAAO,SAAA;AAAA,IAAS;AAAA,IAEpC,OAAO;AAAA,MACL,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACA,MAAWA,EAAO,QAAA;AAAA,IAAQ;AAAA,EACnC;AAAA,EAEF,SAAS,CAAA;AAAA,EACT,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,EACJ;AAEJ,GCNMC,IAAeC,EAAI,+CAA+C;AAAA,EACtE,UAAU;AAAA,IACR,OAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,MACV,SAAS;AAAA,IAAA;AAAA,EACX;AAAA,EAEF,iBAAiB;AAAA,IACf,OAAO;AAAA,EAAA;AAEX,CAAC;AAWD,SAASC,EAAYC,GAAkBC,GAAkC;AACvE,SAAIA,IAAgB,YACbD,IAAU,YAAY;AAC/B;AAmDO,MAAME,IAAkBC;AAAA,EAC7B,CACE;AAAA,IACE,IAAAC;AAAA,IACA,SAAAJ;AAAA,IACA,WAAAK;AAAA,IACA,WAAAC;AAAA,IACA,UAAAC,IAAW;AAAA,IACX,SAAAN,IAAU;AAAA,IACV,gBAAAO;AAAA,IACA,cAAcC;AAAA,IACd,WAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAM,EAAE,GAAAC,EAAA,IAAMC,EAAA,GACRC,IAAQhB,EAAYC,GAASC,CAAO,GAIpC,CAACe,GAAOC,CAAQ,IAAIC,EAAS,EAAK,GAElCC,IAAWC,EAAOJ,CAAK;AAC7B,IAAAG,EAAS,UAAUH;AAEnB,UAAMpB,IAASyB;AAAA,MACb,OAAO;AAAA,QACL,UAAU,MAAMtB,EAAYC,GAASC,CAAO;AAAA,QAC5C,SAAS,MAAMkB,EAAS;AAAA,MAAA;AAAA,MAE1B,CAACnB,GAASC,CAAO;AAAA,IAAA;AAEnB,IAAAqB,EAAqB3B,GAAsBC,GAAQQ,CAAE;AAErD,UAAMmB,IACJd,KAAaI,EAAE,+BAA+B,uBAAuB,GAGjEW,IAAeT,MAAU,YAAY,YAAY;AAEvD,QAAIU;AACJ,WAAIV,MAAU,YACZU,IACE,gBAAAC,EAAC,OAAA,EAAI,WAAU,kDACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,mEACb,UAAA;AAAA,QAAA,gBAAAC,EAACC,KAAM,SAAQ,WACZ,UAAAf,EAAE,iCAAiC,iBAAiB,GACvD;AAAA,QACCR,MAAc,SACb,gBAAAqB,EAAC,QAAA,EAAK,WAAU,wDACb,UAAA;AAAA,UAAAb,EAAE,mCAAmC,SAAS;AAAA,UAAG;AAAA,4BACjDgB,GAAA,EAAU,OAAOxB,GAAW,QAAO,YAAW,OAAM,SAAA,CAAS;AAAA,QAAA,EAAA,CAChE,IACE;AAAA,MAAA,GACN;AAAA,MACCC,IACC,gBAAAqB,EAAC,KAAA,EAAE,WAAU,+DACV,YAAE,6BAA6B;AAAA,QAC9B,MAAMrB;AAAA,QACN,cAAc;AAAA,MAAA,CACf,GACH,IACE;AAAA,IAAA,GACN,IAEOS,MAAU,YACnBU,IACE,gBAAAC,EAAC,OAAA,EAAI,WAAU,sDACb,UAAA;AAAA,MAAA,gBAAAC;AAAA,QAACG;AAAA,QAAA;AAAA,UACC,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,OAAOjB,EAAE,gCAAgC,iBAAiB;AAAA,QAAA;AAAA,MAAA;AAAA,wBAE3D,QAAA,EAAK,WAAU,wDACb,UAAAA,EAAE,gCAAgC,iBAAiB,EAAA,CACtD;AAAA,IAAA,GACF,IAIFY,IAAOlB,IACL,gBAAAmB,EAAC,OAAA,EAAI,WAAU,kDACb,UAAA;AAAA,MAAA,gBAAAC;AAAA,QAACI;AAAA,QAAA;AAAA,UACC,SAASf;AAAA,UACT,iBAAiB,CAACgB,MAASf,EAASe,MAAS,EAAI;AAAA,UACjD,OAAOnB;AAAA,YACL;AAAA,YACA;AAAA,UAAA;AAAA,QACF;AAAA,MAAA;AAAA,MAEF,gBAAAc,EAACM,EAAM,QAAN,EACC,UAAA,gBAAAN;AAAA,QAACO;AAAA,QAAA;AAAA,UACC,QAAO;AAAA,UACP,MAAK;AAAA,UACL,UAAU,CAAClB;AAAA,UACX,SAASR;AAAA,UAER,UAAAK,EAAE,+BAA+B,eAAe;AAAA,QAAA;AAAA,MAAA,EACnD,CACF;AAAA,IAAA,EAAA,CACF,IAEA,gBAAAc,EAAC,KAAA,EAAE,WAAU,+DACV,UAAAd;AAAA,MACC;AAAA,MACA;AAAA,IAAA,GAEJ,GAKF,gBAAAc;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAf;AAAA,QACA,MAAK;AAAA,QACL,cAAYW;AAAA,QACZ,aAAWR,MAAU,YAAY,KAAO;AAAA,QACxC,kBAAe;AAAA,QACf,qBAAmBX;AAAA,QACnB,cAAYW;AAAA,QACZ,IAAAX;AAAA,QACA,WAAWP,EAAa,EAAE,OAAAkB,GAAO,WAAAL,GAAW;AAAA,QAC3C,GAAGC;AAAA,QAEJ,UAAA,gBAAAe;AAAA,UAACO;AAAA,UAAA;AAAA,YACC,SAAST;AAAA,YACT,MAAMT,MAAU,YAAY,OAAO;AAAA,YAEnC,UAAA;AAAA,cAAA,gBAAAY,EAACM,EAAM,OAAN,EACE,UAAApB,EAAE,yBAAyB,uBAAuB,GACrD;AAAA,cACA,gBAAAc,EAACM,EAAM,aAAN,EACE,gBAAU,YACPpB;AAAA,gBACE;AAAA,gBACA;AAAA,cAAA,IAEFA;AAAA,gBACE;AAAA,gBACA;AAAA,cAAA,GAER;AAAA,cACCY;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MACH;AAAA,IAAA;AAAA,EAGN;AACF;AAEAvB,EAAgB,cAAc;"}
|
|
1
|
+
{"version":3,"file":"ai-consent-banner-BUKKPDTg.js","sources":["../../src/components/ai-consent-banner/ai-consent-banner.agent.ts","../../src/components/ai-consent-banner/ai-consent-banner.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — AiConsentBanner. */\n/* */\n/* Read-only structural surface: the current consent state and whether */\n/* the grant affordance is armed. Identifiers / structural state ONLY — */\n/* never the grantee's name or any PHI. The real consent gate lives */\n/* server-side; this adapter does not expose a grant action so an agent */\n/* cannot consent on a user's behalf. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { AiConsentBannerHandle } from './ai-consent-banner';\n\nexport const aiConsentBannerAgent: AgentAdapter<AiConsentBannerHandle> = {\n id: 'ai-consent-banner',\n capabilities: [],\n state: {\n consentState: {\n type: \"'granted' | 'required' | 'pending'\",\n descriptionKey: 'ui.agent.aiConsentBanner.state.consentState',\n description:\n 'Current consent state. Structural only — never the grantee identity.',\n read: (handle) => handle.getState(),\n },\n armed: {\n type: 'boolean',\n descriptionKey: 'ui.agent.aiConsentBanner.state.armed',\n description:\n 'Whether the consent confirmation checkbox is ticked (required state only).',\n read: (handle) => handle.isArmed(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'ai-consent-banner',\n description: 'Marks the AiConsentBanner root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific banner from the agent.',\n },\n },\n};\n","import {\n forwardRef,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Alert } from '../alert/alert';\nimport { Badge } from '../badge/badge';\nimport { Button } from '../button/button';\nimport { Checkbox } from '../checkbox/checkbox';\nimport { Spinner } from '../spinner/spinner';\nimport { Timestamp } from '../timestamp/timestamp';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { aiConsentBannerAgent } from './ai-consent-banner.agent';\n\n/* -------------------------------------------------------------------- */\n/* AiConsentBanner */\n/* */\n/* Presentational AI-consent gate surfaced above an AI-assisted surface */\n/* (e.g. Alfascribe consultation transcription). The SERVER owns the */\n/* real gate — this component only reflects the consent record and lets */\n/* the operator initiate a grant; it never enforces access itself. */\n/* */\n/* Three states drive the Alert variant + body: */\n/* - granted → success Alert with a Badge + when/who it was granted. */\n/* - required → info Alert with a Checkbox-gated Grant Button. */\n/* - pending → info Alert in a disabled, Spinner-busy state while the */\n/* server persists the grant. */\n/* */\n/* All visible text flows through useTranslation('ui') against the */\n/* `aiConsentBanner.*` namespace. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA — root */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n state: {\n granted: '',\n required: '',\n pending: '',\n },\n },\n defaultVariants: {\n state: 'required',\n },\n});\n\n/* -------------------------------------------------------------------- */\n/* State derivation */\n/* -------------------------------------------------------------------- */\n\nexport type AiConsentState = NonNullable<\n VariantProps<typeof rootVariants>['state']\n>;\n\n/** Pending wins over granted/required so the busy state is never masked. */\nfunction deriveState(granted: boolean, pending: boolean): AiConsentState {\n if (pending) return 'pending';\n return granted ? 'granted' : 'required';\n}\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/** Agent-readiness curated handle. Exposes the structural consent state only. */\nexport interface AiConsentBannerHandle {\n /** Current derived state: 'granted' | 'required' | 'pending'. */\n getState: () => AiConsentState;\n /** Whether the Grant affordance is currently armed (checkbox ticked). */\n isArmed: () => boolean;\n}\n\nexport interface AiConsentBannerProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children' | 'role'\n> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so an\n * agent / MCP UI bridge can address this specific banner. Mirrored to the\n * real DOM `id`.\n */\n id?: string;\n /** Whether consent has already been granted. Server-sourced. */\n granted: boolean;\n /**\n * When consent was granted — ISO-8601 string, ms-epoch, or Date. Rendered\n * via `Timestamp` in the granted state.\n */\n grantedAt?: string | number | Date;\n /** Who granted consent (operator display name / role). Granted state only. */\n grantedBy?: string;\n /**\n * Whether the current user is allowed to grant consent. When `false`, the\n * required-state Grant affordance is hidden and a not-allowed note shows.\n * Default `true`.\n */\n canGrant?: boolean;\n /** The grant is being persisted server-side — shows the busy Spinner state. */\n pending?: boolean;\n /** Fired when the operator confirms the consent grant. */\n onGrantConsent?: () => void;\n /** Override the region's accessible name. */\n 'aria-label'?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const AiConsentBanner = forwardRef<HTMLDivElement, AiConsentBannerProps>(\n (\n {\n id,\n granted,\n grantedAt,\n grantedBy,\n canGrant = true,\n pending = false,\n onGrantConsent,\n 'aria-label': ariaLabel,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const state = deriveState(granted, pending);\n\n // Local arm switch — the required state gates the Grant Button behind an\n // explicit \"I understand\" checkbox so consent is never one mis-click away.\n const [armed, setArmed] = useState(false);\n\n const armedRef = useRef(armed);\n armedRef.current = armed;\n\n const handle = useMemo<AiConsentBannerHandle>(\n () => ({\n getState: () => deriveState(granted, pending),\n isArmed: () => armedRef.current,\n }),\n [granted, pending],\n );\n useAgentRegistration(aiConsentBannerAgent, handle, id);\n\n const resolvedAriaLabel =\n ariaLabel ?? t('aiConsentBanner.regionLabel', 'AI assistance consent');\n\n // Alert variant per state: granted → success, required/pending → info.\n const alertVariant = state === 'granted' ? 'success' : 'info';\n\n let body: React.ReactNode;\n if (state === 'granted') {\n body = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Badge variant=\"success\">\n {t('aiConsentBanner.badge.granted', 'Consent granted')}\n </Badge>\n {grantedAt !== undefined ? (\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.grantedAtPrefix', 'Granted')}{' '}\n <Timestamp value={grantedAt} format=\"relative\" shape=\"inline\" />\n </span>\n ) : null}\n </div>\n {grantedBy ? (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.grantedBy', {\n name: grantedBy,\n defaultValue: 'By {{name}}',\n })}\n </p>\n ) : null}\n </div>\n );\n } else if (state === 'pending') {\n body = (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Spinner\n variant=\"pulse\"\n size=\"sm\"\n label={t('aiConsentBanner.pendingLabel', 'Saving consent…')}\n />\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.pendingLabel', 'Saving consent…')}\n </span>\n </div>\n );\n } else {\n // required\n body = canGrant ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n <Checkbox\n checked={armed}\n onCheckedChange={(next) => setArmed(next === true)}\n label={t(\n 'aiConsentBanner.confirmLabel',\n 'I confirm consent has been obtained for AI assistance.',\n )}\n />\n <Alert.Action>\n <Button\n intent=\"primary\"\n size=\"sm\"\n disabled={!armed}\n onClick={onGrantConsent}\n >\n {t('aiConsentBanner.grantButton', 'Grant consent')}\n </Button>\n </Alert.Action>\n </div>\n ) : (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {t(\n 'aiConsentBanner.notAllowed',\n 'You do not have permission to grant AI assistance consent.',\n )}\n </p>\n );\n }\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={resolvedAriaLabel}\n aria-busy={state === 'pending' ? true : undefined}\n data-component=\"ai-consent-banner\"\n data-component-id={id}\n data-state={state}\n id={id}\n className={rootVariants({ state, className })}\n {...rest}\n >\n <Alert\n variant={alertVariant}\n icon={state === 'pending' ? null : undefined}\n >\n <Alert.Title>\n {t('aiConsentBanner.title', 'AI assistance consent')}\n </Alert.Title>\n <Alert.Description>\n {state === 'granted'\n ? t(\n 'aiConsentBanner.description.granted',\n 'AI assistance is enabled for this record.',\n )\n : t(\n 'aiConsentBanner.description.required',\n 'AI assistance requires recorded consent before it can run.',\n )}\n </Alert.Description>\n {body}\n </Alert>\n </div>\n );\n },\n);\n\nAiConsentBanner.displayName = 'AiConsentBanner';\n"],"names":["aiConsentBannerAgent","handle","rootVariants","cva","deriveState","granted","pending","AiConsentBanner","forwardRef","id","grantedAt","grantedBy","canGrant","onGrantConsent","ariaLabel","className","rest","ref","t","useTranslation","state","armed","setArmed","useState","armedRef","useRef","useMemo","useAgentRegistration","resolvedAriaLabel","alertVariant","body","jsxs","jsx","Badge","Timestamp","Spinner","Checkbox","next","Alert","Button"],"mappings":"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"}
|
|
@@ -222,7 +222,7 @@ const z = p(
|
|
|
222
222
|
{
|
|
223
223
|
ref: s,
|
|
224
224
|
className: [
|
|
225
|
-
"ds:mt-[var(--spacing-
|
|
225
|
+
"ds:mt-[var(--spacing-md)] ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]",
|
|
226
226
|
n
|
|
227
227
|
].filter(Boolean).join(" "),
|
|
228
228
|
...d
|
|
@@ -316,4 +316,4 @@ const Ne = Object.assign(B, {
|
|
|
316
316
|
export {
|
|
317
317
|
Ne as A
|
|
318
318
|
};
|
|
319
|
-
//# sourceMappingURL=alert-
|
|
319
|
+
//# sourceMappingURL=alert-CiJT540z.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alert-DS22ha1n.js","sources":["../../node_modules/lucide-react/dist/esm/icons/circle-arrow-up.mjs","../../src/components/alert/alert.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 [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m16 12-4-4-4 4\", key: \"177agl\" }],\n [\"path\", { d: \"M12 16V8\", key: \"1sbj14\" }]\n];\nconst CircleArrowUp = createLucideIcon(\"circle-arrow-up\", __iconNode);\n\nexport { __iconNode, CircleArrowUp as default };\n//# sourceMappingURL=circle-arrow-up.mjs.map\n","import {\n Children,\n createContext,\n forwardRef,\n isValidElement,\n useCallback,\n useContext,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n type MutableRefObject,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport {\n CircleAlert,\n CircleArrowUp,\n CircleCheck,\n Info,\n TriangleAlert,\n X,\n} from 'lucide-react';\nimport { useControllableState } from '../../hooks/use-controllable-state';\nimport { useClampOverflow } from '../../hooks/use-clamp-overflow';\nimport { Tooltip } from '../tooltip';\n\n/* ------------------------------------------------------------------ */\n/* Clamp context — opt-in compact mode propagated from the root Alert */\n/* to its Title / Description so a consumer enables it with one prop. */\n/* ------------------------------------------------------------------ */\n\nconst AlertClampContext = createContext(false);\n\n/** Inline \"Read more / Read less\" disclosure. Tinted with `text-current` so it\n * inherits the alert variant's foreground rather than the link palette. */\nconst DISCLOSURE_BUTTON_CLASSES = [\n // Full-opacity `text-current` so it matches the body text's contrast (an\n // `opacity` dim would drop the variant-tinted text below AA). Underline\n // carries the affordance instead. No `--min-target-size` floor: this is an\n // inline text disclosure sitting in the flow of the body copy, which is\n // exempt from WCAG 2.5.8 target-size the same way an inline link is.\n 'ds:mt-[var(--spacing-2xs)] ds:inline-flex ds:items-center ds:self-start',\n 'ds:text-[length:var(--font-size-xs)] ds:font-semibold',\n 'ds:underline ds:underline-offset-2 ds:text-current ds:hover:no-underline',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n].join(' ');\n\nconst alertVariants = cva(\n [\n // Default `items-center` keeps the icon + dismiss optically aligned\n // with a single-line description. The `data-[has-title=true]`\n // selector flips to `items-start` when an `<Alert.Title>` is\n // present so the icon anchors to the heading's top instead of\n // floating against the centre of the title+description block.\n // For multi-line descriptions without a title, `items-center` still\n // looks right at 2–3 lines and matches Toast / Notification.\n 'ds:flex ds:items-center ds:data-[has-title=true]:items-start ds:gap-[var(--spacing-md)]',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:border ds:border-[length:var(--border-width-sm)]',\n 'ds:p-[var(--spacing-md)]',\n 'ds:break-words',\n ].join(' '),\n {\n variants: {\n // Each variant paints `<Button intent=\"tonal\">` descendants via a\n // child selector — the button carries `data-intent=\"tonal\"`, the\n // Alert applies the matching tint (`*-foreground` for bg + the\n // surface `--background` for fg). Descendant selectors sidestep\n // custom-property inheritance and are rock-solid across themes.\n variant: {\n info: [\n 'ds:border-[color:var(--info)]',\n 'ds:bg-[color-mix(in_srgb,var(--info)_10%,transparent)]',\n 'ds:text-[var(--info-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--info-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n success: [\n 'ds:border-[color:var(--success)]',\n 'ds:bg-[color-mix(in_srgb,var(--success)_10%,transparent)]',\n 'ds:text-[var(--success-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--success-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n warning: [\n 'ds:border-[color:var(--warning)]',\n 'ds:bg-[color-mix(in_srgb,var(--warning)_10%,transparent)]',\n 'ds:text-[var(--warning-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--warning-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n error: [\n 'ds:border-[color:var(--error)]',\n 'ds:bg-[color-mix(in_srgb,var(--error)_10%,transparent)]',\n 'ds:text-[var(--error-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--error-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n // Sales / marketing upsell — accent magenta via the --promo\n // semantic pair so marketing pushes (product hub → warning\n // stack) read as offers, not operational warnings. Surface is\n // the same subtle accent gradient as SidebarUpgradeChip (it\n // flattens in the accessible themes and follows Canvas in\n // forced-colors), keeping the two upsell affordances kin.\n promo: [\n 'ds:border-[color:var(--promo)]',\n 'ds:bg-[image:var(--gradient-surface-subtle-accent)]',\n 'ds:text-[var(--promo-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--promo-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n },\n },\n defaultVariants: {\n variant: 'info',\n },\n },\n);\n\n// Icon stays `mt-0.5` only when an `<Alert.Title>` is present — that\n// offset compensates for the title's cap-height vs. line-box origin so\n// the glyph aligns with the heading's caps. Without a title, the\n// container uses `items-center` and the offset would push the icon\n// 2px off the optical axis.\nconst ICON_BASE = 'ds:shrink-0 ds:size-5';\nconst ICON_WITH_TITLE = `${ICON_BASE} ds:mt-0.5`;\n\nconst CLOSE_BUTTON_CLASSES = [\n // Default (no title): the alert root uses `items-center` and the\n // button centres in the cross-axis. A centred 16×16 glyph inside a\n // 44×44 button aligns optically with a single-line description.\n // With a title: the root flips to `items-start` so the button's top\n // edge aligns with the title row top. A centred glyph would then\n // land ~11 px below the title's optical centre (button height is\n // --min-target-size, much taller than the title's line-height). The\n // `[data-has-title=true]` variant below flips the button to\n // `items-start` and adds a block-start padding that pulls the glyph\n // up onto the title row — same cap-height compensation idea as the\n // leading icon's `mt-0.5`.\n 'ds:ms-auto ds:shrink-0 ds:inline-flex ds:items-center ds:justify-center',\n 'ds:[[data-has-title=true]_&]:items-start',\n 'ds:[[data-has-title=true]_&]:pt-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:min-h-[var(--min-target-size)] ds:min-w-[var(--min-target-size)]',\n 'ds:-mt-[var(--spacing-xs)] ds:-me-[var(--spacing-xs)]',\n 'ds:text-current ds:opacity-70',\n 'ds:hover:opacity-100',\n 'ds:transition-opacity ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n].join(' ');\n\n// `role` / `live` here are only the *default* announcement for each tint.\n// The `announce` prop overrides both — visual severity and announcement\n// urgency are independent (a warning-tinted static notice must not interrupt).\nconst VARIANT_CONFIG = {\n info: { icon: <Info aria-hidden=\"true\" />, role: 'status', live: 'polite' },\n success: {\n icon: <CircleCheck aria-hidden=\"true\" />,\n role: 'status',\n live: 'polite',\n },\n warning: {\n icon: <TriangleAlert aria-hidden=\"true\" />,\n role: 'alert',\n live: 'assertive',\n },\n error: {\n icon: <CircleAlert aria-hidden=\"true\" />,\n role: 'alert',\n live: 'assertive',\n },\n // Promotions never interrupt — same polite semantics as info.\n promo: {\n icon: <CircleArrowUp aria-hidden=\"true\" />,\n role: 'status',\n live: 'polite',\n },\n} as const;\n\n// `off` emits neither role nor aria-live: a permanently-mounted notice is\n// read in document order and is not a live region at all.\nconst ANNOUNCE_CONFIG = {\n off: { role: undefined, live: undefined },\n polite: { role: 'status', live: 'polite' },\n assertive: { role: 'alert', live: 'assertive' },\n} as const;\n\ninterface AlertTitleProps extends HTMLAttributes<HTMLHeadingElement> {\n as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span';\n}\n\nconst AlertTitle = forwardRef<HTMLHeadingElement, AlertTitleProps>(\n ({ as: Tag = 'h5', className, children, ...props }, ref) => {\n const clamp = useContext(AlertClampContext);\n const { ref: clampRef, isOverflowing } =\n useClampOverflow<HTMLHeadingElement>(clamp);\n const setRefs = useCallback(\n (node: HTMLHeadingElement | null) => {\n (clampRef as MutableRefObject<HTMLHeadingElement | null>).current =\n node;\n if (typeof ref === 'function') ref(node);\n else if (ref)\n (ref as MutableRefObject<HTMLHeadingElement | null>).current = node;\n },\n [ref, clampRef],\n );\n\n // The full title stays in the DOM (line-clamp only clips it visually), so\n // screen readers always read it whole. The tooltip is a sighted-user\n // affordance, shown only when the title is actually cut — and only for\n // string titles, since the Tooltip label must be plain text.\n const tooltipReady = clamp && isOverflowing && typeof children === 'string';\n\n const heading = (\n <Tag\n ref={setRefs}\n // Focusable only when truncated, so keyboard users can surface the\n // tooltip too (otherwise it would be mouse/hover-only).\n tabIndex={tooltipReady ? 0 : undefined}\n className={[\n 'type-title-item',\n clamp ? 'ds:line-clamp-2' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n >\n {children}\n </Tag>\n );\n\n return tooltipReady ? (\n <Tooltip label={children as string}>{heading}</Tooltip>\n ) : (\n heading\n );\n },\n);\nAlertTitle.displayName = 'Alert.Title';\n\nconst AlertDescription = forwardRef<\n HTMLParagraphElement,\n HTMLAttributes<HTMLParagraphElement>\n>(({ className, children, ...props }, ref) => {\n const clamp = useContext(AlertClampContext);\n const { t } = useTranslation();\n const bodyId = useId();\n const [expanded, setExpanded] = useState(false);\n // Only measure while clamped — once expanded there's nothing to clip.\n const { ref: clampRef, isOverflowing } =\n useClampOverflow<HTMLParagraphElement>(clamp && !expanded);\n const setRefs = useCallback(\n (node: HTMLParagraphElement | null) => {\n (clampRef as MutableRefObject<HTMLParagraphElement | null>).current =\n node;\n if (typeof ref === 'function') ref(node);\n else if (ref)\n (ref as MutableRefObject<HTMLParagraphElement | null>).current = node;\n },\n [ref, clampRef],\n );\n // Show the toggle once the body has overflowed; keep it while expanded so\n // the user can collapse again.\n const showToggle = clamp && (isOverflowing || expanded);\n\n return (\n <>\n <p\n ref={setRefs}\n id={clamp ? bodyId : undefined}\n // `mt` is gated on the root's `data-has-title=\"true\"` attribute so\n // the margin only paints when there's a Title above the\n // Description to separate from. Without this gate, a Description\n // rendered alone sits a few pixels below the icon + dismiss ×\n // optical centre — visible on the AlfaDocs marketing privacy\n // generator before HTP-4860's follow-up fix.\n className={[\n 'ds:[[data-has-title=true]_&]:mt-[var(--spacing-xs)] type-body-sm',\n clamp && !expanded ? 'ds:line-clamp-2' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n >\n {children}\n </p>\n {showToggle ? (\n <button\n type=\"button\"\n aria-expanded={expanded}\n aria-controls={bodyId}\n onClick={() => setExpanded((prev) => !prev)}\n className={DISCLOSURE_BUTTON_CLASSES}\n >\n {expanded\n ? t('feedback.alert.readLess', 'Read less')\n : t('feedback.alert.readMore', 'Read more')}\n </button>\n ) : null}\n </>\n );\n});\nAlertDescription.displayName = 'Alert.Description';\n\nconst AlertAction = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={[\n 'ds:mt-[var(--spacing-sm)] ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n />\n ),\n);\nAlertAction.displayName = 'Alert.Action';\n\n/** How urgently the alert is announced — independent of the visual `variant`.\n *\n * - `off` — not a live region. No `role`, no `aria-live`. Correct for a\n * static notice that is present from mount (a read-only banner, a summary\n * of missing answers on a form the user is still typing into).\n * - `polite` — `role=\"status\"` + `aria-live=\"polite\"`. Queued behind the\n * current utterance. The right default for anything that appears in\n * response to a user action but is not an emergency.\n * - `assertive` — `role=\"alert\"` + `aria-live=\"assertive\"`. Interrupts the\n * screen reader immediately. Reserve for content the user cannot miss.\n */\nexport type AlertAnnounce = 'off' | 'polite' | 'assertive';\n\nexport interface AlertProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'role'>,\n VariantProps<typeof alertVariants> {\n variant?: 'info' | 'success' | 'warning' | 'error' | 'promo';\n dismissible?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n icon?: ReactNode;\n /** Announcement urgency — sets `role` **and** `aria-live` together, so the\n * tint (`variant`) and the interruption are chosen independently. Defaults\n * to the variant's historical mapping: `info` / `success` / `promo` →\n * `polite`, `warning` / `error` → `assertive`. Wins over `live`. */\n announce?: AlertAnnounce;\n /** @deprecated Use `announce`. Sets `aria-live` only and leaves `role`\n * variant-derived, which can pair `role=\"alert\"` with `aria-live=\"polite\"`.\n * Kept for the consumers already shipping it. */\n live?: 'assertive' | 'polite' | 'off';\n /** Compact mode: clamps `Alert.Title` to 2 lines (with a tooltip when the\n * title is truncated) and `Alert.Description` to 2 lines (with a \"Read more\"\n * toggle). Opt-in — leave off for standalone alerts whose full message must\n * always be visible. */\n clamp?: boolean;\n}\n\nexport type { AlertTitleProps };\n\nconst AlertRoot = forwardRef<HTMLDivElement, AlertProps>(\n (\n {\n variant = 'info',\n dismissible = false,\n open: controlledOpen,\n onOpenChange,\n icon,\n announce,\n live,\n clamp = false,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const [isOpenRaw, setOpen] = useControllableState<boolean>({\n value: controlledOpen,\n defaultValue: true,\n onChange: onOpenChange,\n });\n const isOpen = isOpenRaw ?? true;\n const [isClosing, setIsClosing] = useState(false);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const animationDurationMs = useCallback((): number => {\n if (typeof window === 'undefined') return 200;\n const raw = window\n .getComputedStyle(document.documentElement)\n .getPropertyValue('--animation-duration');\n if (!raw) return 200;\n const trimmed = raw.trim();\n const n = parseFloat(trimmed);\n if (!Number.isFinite(n)) return 200;\n return trimmed.endsWith('ms') ? n : n * 1000;\n }, []);\n\n if (!isOpen) return null;\n\n const config = VARIANT_CONFIG[variant];\n const effectiveIcon = icon !== undefined ? icon : config.icon;\n\n // `announce` owns role + aria-live together. Without it we keep the\n // shipped behaviour exactly: role from the variant, aria-live from the\n // legacy `live` prop or the variant default.\n const announcement = announce\n ? ANNOUNCE_CONFIG[announce]\n : { role: config.role, live: live ?? config.live };\n\n // Detect an `<Alert.Title>` anywhere in the immediate children so\n // the root can flip its cross-axis alignment. Nested wrappers\n // around a Title aren't supported — keep the API as flat as the\n // existing `Alert.Title` / `Alert.Description` convention.\n const hasTitle = Children.toArray(children).some(\n (child) => isValidElement(child) && child.type === AlertTitle,\n );\n\n const handleDismiss = () => {\n if (isClosing) return;\n setIsClosing(true);\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n closeTimerRef.current = setTimeout(() => {\n setIsClosing(false);\n setOpen(false);\n }, animationDurationMs());\n };\n\n return (\n <div\n ref={ref}\n role={announcement.role}\n aria-live={announcement.live}\n data-component=\"alert\"\n data-has-title={hasTitle ? 'true' : 'false'}\n data-state={isClosing ? 'closing' : 'open'}\n className={[\n alertVariants({ variant, className }),\n // Entry: fade + slide-down on mount. Exit: fade + slide-up + slight\n // scale when dismissed. Driven by `tw-animate-css`. Respects\n // `prefers-reduced-motion` via `motion-safe:` and zeroes under the\n // accessible theme (`--animation-duration: 0ms`).\n 'ds:motion-safe:animate-in ds:motion-safe:fade-in-0 ds:motion-safe:slide-in-from-top-2',\n 'ds:motion-safe:data-[state=closing]:animate-out ds:motion-safe:data-[state=closing]:fade-out-0',\n 'ds:motion-safe:data-[state=closing]:slide-out-to-top-2 ds:motion-safe:data-[state=closing]:zoom-out-95',\n // Pin the exit's end-state until React unmounts. Without\n // `fill-mode-forwards` the element snaps back to opacity:1 for one\n // paint frame after the animation ends.\n 'ds:motion-safe:data-[state=closing]:fill-mode-forwards',\n 'ds:motion-safe:duration-[var(--animation-duration)]',\n ].join(' ')}\n {...props}\n >\n {effectiveIcon ? (\n <span className={hasTitle ? ICON_WITH_TITLE : ICON_BASE}>\n {effectiveIcon}\n </span>\n ) : null}\n\n <div className=\"ds:flex-1 ds:min-w-0\">\n <AlertClampContext.Provider value={clamp}>\n {children}\n </AlertClampContext.Provider>\n </div>\n\n {dismissible ? (\n <button\n type=\"button\"\n aria-label={t('common.close', 'Close')}\n onClick={handleDismiss}\n // Stable hook for containers (WarningStack) that hand focus to\n // a neighbouring dismiss control after this one unmounts.\n data-alert-dismiss=\"\"\n className={CLOSE_BUTTON_CLASSES}\n >\n <X aria-hidden=\"true\" className=\"ds:size-4\" />\n </button>\n ) : null}\n </div>\n );\n },\n);\n\nAlertRoot.displayName = 'Alert';\n\nexport const Alert = Object.assign(AlertRoot, {\n Title: AlertTitle,\n Description: AlertDescription,\n Action: AlertAction,\n});\n"],"names":["__iconNode","CircleArrowUp","createLucideIcon","AlertClampContext","createContext","DISCLOSURE_BUTTON_CLASSES","alertVariants","cva","ICON_BASE","ICON_WITH_TITLE","CLOSE_BUTTON_CLASSES","VARIANT_CONFIG","jsx","Info","CircleCheck","TriangleAlert","CircleAlert","ANNOUNCE_CONFIG","AlertTitle","forwardRef","Tag","className","children","props","ref","clamp","useContext","clampRef","isOverflowing","useClampOverflow","setRefs","useCallback","node","tooltipReady","heading","Tooltip","AlertDescription","t","useTranslation","bodyId","useId","expanded","setExpanded","useState","showToggle","jsxs","Fragment","prev","AlertAction","AlertRoot","variant","dismissible","controlledOpen","onOpenChange","icon","announce","live","isOpenRaw","setOpen","useControllableState","isOpen","isClosing","setIsClosing","closeTimerRef","useRef","animationDurationMs","raw","trimmed","n","config","effectiveIcon","announcement","hasTitle","Children","child","isValidElement","handleDismiss","X","Alert"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"alert-CiJT540z.js","sources":["../../node_modules/lucide-react/dist/esm/icons/circle-arrow-up.mjs","../../src/components/alert/alert.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 [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m16 12-4-4-4 4\", key: \"177agl\" }],\n [\"path\", { d: \"M12 16V8\", key: \"1sbj14\" }]\n];\nconst CircleArrowUp = createLucideIcon(\"circle-arrow-up\", __iconNode);\n\nexport { __iconNode, CircleArrowUp as default };\n//# sourceMappingURL=circle-arrow-up.mjs.map\n","import {\n Children,\n createContext,\n forwardRef,\n isValidElement,\n useCallback,\n useContext,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n type MutableRefObject,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport {\n CircleAlert,\n CircleArrowUp,\n CircleCheck,\n Info,\n TriangleAlert,\n X,\n} from 'lucide-react';\nimport { useControllableState } from '../../hooks/use-controllable-state';\nimport { useClampOverflow } from '../../hooks/use-clamp-overflow';\nimport { Tooltip } from '../tooltip';\n\n/* ------------------------------------------------------------------ */\n/* Clamp context — opt-in compact mode propagated from the root Alert */\n/* to its Title / Description so a consumer enables it with one prop. */\n/* ------------------------------------------------------------------ */\n\nconst AlertClampContext = createContext(false);\n\n/** Inline \"Read more / Read less\" disclosure. Tinted with `text-current` so it\n * inherits the alert variant's foreground rather than the link palette. */\nconst DISCLOSURE_BUTTON_CLASSES = [\n // Full-opacity `text-current` so it matches the body text's contrast (an\n // `opacity` dim would drop the variant-tinted text below AA). Underline\n // carries the affordance instead. No `--min-target-size` floor: this is an\n // inline text disclosure sitting in the flow of the body copy, which is\n // exempt from WCAG 2.5.8 target-size the same way an inline link is.\n 'ds:mt-[var(--spacing-2xs)] ds:inline-flex ds:items-center ds:self-start',\n 'ds:text-[length:var(--font-size-xs)] ds:font-semibold',\n 'ds:underline ds:underline-offset-2 ds:text-current ds:hover:no-underline',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n].join(' ');\n\nconst alertVariants = cva(\n [\n // Default `items-center` keeps the icon + dismiss optically aligned\n // with a single-line description. The `data-[has-title=true]`\n // selector flips to `items-start` when an `<Alert.Title>` is\n // present so the icon anchors to the heading's top instead of\n // floating against the centre of the title+description block.\n // For multi-line descriptions without a title, `items-center` still\n // looks right at 2–3 lines and matches Toast / Notification.\n 'ds:flex ds:items-center ds:data-[has-title=true]:items-start ds:gap-[var(--spacing-md)]',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:border ds:border-[length:var(--border-width-sm)]',\n 'ds:p-[var(--spacing-md)]',\n 'ds:break-words',\n ].join(' '),\n {\n variants: {\n // Each variant paints `<Button intent=\"tonal\">` descendants via a\n // child selector — the button carries `data-intent=\"tonal\"`, the\n // Alert applies the matching tint (`*-foreground` for bg + the\n // surface `--background` for fg). Descendant selectors sidestep\n // custom-property inheritance and are rock-solid across themes.\n variant: {\n info: [\n 'ds:border-[color:var(--info)]',\n 'ds:bg-[color-mix(in_srgb,var(--info)_10%,transparent)]',\n 'ds:text-[var(--info-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--info-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n success: [\n 'ds:border-[color:var(--success)]',\n 'ds:bg-[color-mix(in_srgb,var(--success)_10%,transparent)]',\n 'ds:text-[var(--success-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--success-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n warning: [\n 'ds:border-[color:var(--warning)]',\n 'ds:bg-[color-mix(in_srgb,var(--warning)_10%,transparent)]',\n 'ds:text-[var(--warning-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--warning-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n error: [\n 'ds:border-[color:var(--error)]',\n 'ds:bg-[color-mix(in_srgb,var(--error)_10%,transparent)]',\n 'ds:text-[var(--error-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--error-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n // Sales / marketing upsell — accent magenta via the --promo\n // semantic pair so marketing pushes (product hub → warning\n // stack) read as offers, not operational warnings. Surface is\n // the same subtle accent gradient as SidebarUpgradeChip (it\n // flattens in the accessible themes and follows Canvas in\n // forced-colors), keeping the two upsell affordances kin.\n promo: [\n 'ds:border-[color:var(--promo)]',\n 'ds:bg-[image:var(--gradient-surface-subtle-accent)]',\n 'ds:text-[var(--promo-foreground)]',\n 'ds:[&_[data-intent=tonal]]:bg-[color:var(--promo-foreground)]',\n 'ds:[&_[data-intent=tonal]]:text-[color:var(--background)]',\n ].join(' '),\n },\n },\n defaultVariants: {\n variant: 'info',\n },\n },\n);\n\n// Icon stays `mt-0.5` only when an `<Alert.Title>` is present — that\n// offset compensates for the title's cap-height vs. line-box origin so\n// the glyph aligns with the heading's caps. Without a title, the\n// container uses `items-center` and the offset would push the icon\n// 2px off the optical axis.\nconst ICON_BASE = 'ds:shrink-0 ds:size-5';\nconst ICON_WITH_TITLE = `${ICON_BASE} ds:mt-0.5`;\n\nconst CLOSE_BUTTON_CLASSES = [\n // Default (no title): the alert root uses `items-center` and the\n // button centres in the cross-axis. A centred 16×16 glyph inside a\n // 44×44 button aligns optically with a single-line description.\n // With a title: the root flips to `items-start` so the button's top\n // edge aligns with the title row top. A centred glyph would then\n // land ~11 px below the title's optical centre (button height is\n // --min-target-size, much taller than the title's line-height). The\n // `[data-has-title=true]` variant below flips the button to\n // `items-start` and adds a block-start padding that pulls the glyph\n // up onto the title row — same cap-height compensation idea as the\n // leading icon's `mt-0.5`.\n 'ds:ms-auto ds:shrink-0 ds:inline-flex ds:items-center ds:justify-center',\n 'ds:[[data-has-title=true]_&]:items-start',\n 'ds:[[data-has-title=true]_&]:pt-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:min-h-[var(--min-target-size)] ds:min-w-[var(--min-target-size)]',\n 'ds:-mt-[var(--spacing-xs)] ds:-me-[var(--spacing-xs)]',\n 'ds:text-current ds:opacity-70',\n 'ds:hover:opacity-100',\n 'ds:transition-opacity ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n].join(' ');\n\n// `role` / `live` here are only the *default* announcement for each tint.\n// The `announce` prop overrides both — visual severity and announcement\n// urgency are independent (a warning-tinted static notice must not interrupt).\nconst VARIANT_CONFIG = {\n info: { icon: <Info aria-hidden=\"true\" />, role: 'status', live: 'polite' },\n success: {\n icon: <CircleCheck aria-hidden=\"true\" />,\n role: 'status',\n live: 'polite',\n },\n warning: {\n icon: <TriangleAlert aria-hidden=\"true\" />,\n role: 'alert',\n live: 'assertive',\n },\n error: {\n icon: <CircleAlert aria-hidden=\"true\" />,\n role: 'alert',\n live: 'assertive',\n },\n // Promotions never interrupt — same polite semantics as info.\n promo: {\n icon: <CircleArrowUp aria-hidden=\"true\" />,\n role: 'status',\n live: 'polite',\n },\n} as const;\n\n// `off` emits neither role nor aria-live: a permanently-mounted notice is\n// read in document order and is not a live region at all.\nconst ANNOUNCE_CONFIG = {\n off: { role: undefined, live: undefined },\n polite: { role: 'status', live: 'polite' },\n assertive: { role: 'alert', live: 'assertive' },\n} as const;\n\ninterface AlertTitleProps extends HTMLAttributes<HTMLHeadingElement> {\n as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span';\n}\n\nconst AlertTitle = forwardRef<HTMLHeadingElement, AlertTitleProps>(\n ({ as: Tag = 'h5', className, children, ...props }, ref) => {\n const clamp = useContext(AlertClampContext);\n const { ref: clampRef, isOverflowing } =\n useClampOverflow<HTMLHeadingElement>(clamp);\n const setRefs = useCallback(\n (node: HTMLHeadingElement | null) => {\n (clampRef as MutableRefObject<HTMLHeadingElement | null>).current =\n node;\n if (typeof ref === 'function') ref(node);\n else if (ref)\n (ref as MutableRefObject<HTMLHeadingElement | null>).current = node;\n },\n [ref, clampRef],\n );\n\n // The full title stays in the DOM (line-clamp only clips it visually), so\n // screen readers always read it whole. The tooltip is a sighted-user\n // affordance, shown only when the title is actually cut — and only for\n // string titles, since the Tooltip label must be plain text.\n const tooltipReady = clamp && isOverflowing && typeof children === 'string';\n\n const heading = (\n <Tag\n ref={setRefs}\n // Focusable only when truncated, so keyboard users can surface the\n // tooltip too (otherwise it would be mouse/hover-only).\n tabIndex={tooltipReady ? 0 : undefined}\n className={[\n 'type-title-item',\n clamp ? 'ds:line-clamp-2' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n >\n {children}\n </Tag>\n );\n\n return tooltipReady ? (\n <Tooltip label={children as string}>{heading}</Tooltip>\n ) : (\n heading\n );\n },\n);\nAlertTitle.displayName = 'Alert.Title';\n\nconst AlertDescription = forwardRef<\n HTMLParagraphElement,\n HTMLAttributes<HTMLParagraphElement>\n>(({ className, children, ...props }, ref) => {\n const clamp = useContext(AlertClampContext);\n const { t } = useTranslation();\n const bodyId = useId();\n const [expanded, setExpanded] = useState(false);\n // Only measure while clamped — once expanded there's nothing to clip.\n const { ref: clampRef, isOverflowing } =\n useClampOverflow<HTMLParagraphElement>(clamp && !expanded);\n const setRefs = useCallback(\n (node: HTMLParagraphElement | null) => {\n (clampRef as MutableRefObject<HTMLParagraphElement | null>).current =\n node;\n if (typeof ref === 'function') ref(node);\n else if (ref)\n (ref as MutableRefObject<HTMLParagraphElement | null>).current = node;\n },\n [ref, clampRef],\n );\n // Show the toggle once the body has overflowed; keep it while expanded so\n // the user can collapse again.\n const showToggle = clamp && (isOverflowing || expanded);\n\n return (\n <>\n <p\n ref={setRefs}\n id={clamp ? bodyId : undefined}\n // `mt` is gated on the root's `data-has-title=\"true\"` attribute so\n // the margin only paints when there's a Title above the\n // Description to separate from. Without this gate, a Description\n // rendered alone sits a few pixels below the icon + dismiss ×\n // optical centre — visible on the AlfaDocs marketing privacy\n // generator before HTP-4860's follow-up fix.\n className={[\n 'ds:[[data-has-title=true]_&]:mt-[var(--spacing-xs)] type-body-sm',\n clamp && !expanded ? 'ds:line-clamp-2' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n >\n {children}\n </p>\n {showToggle ? (\n <button\n type=\"button\"\n aria-expanded={expanded}\n aria-controls={bodyId}\n onClick={() => setExpanded((prev) => !prev)}\n className={DISCLOSURE_BUTTON_CLASSES}\n >\n {expanded\n ? t('feedback.alert.readLess', 'Read less')\n : t('feedback.alert.readMore', 'Read more')}\n </button>\n ) : null}\n </>\n );\n});\nAlertDescription.displayName = 'Alert.Description';\n\nconst AlertAction = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={[\n 'ds:mt-[var(--spacing-md)] ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n />\n ),\n);\nAlertAction.displayName = 'Alert.Action';\n\n/** How urgently the alert is announced — independent of the visual `variant`.\n *\n * - `off` — not a live region. No `role`, no `aria-live`. Correct for a\n * static notice that is present from mount (a read-only banner, a summary\n * of missing answers on a form the user is still typing into).\n * - `polite` — `role=\"status\"` + `aria-live=\"polite\"`. Queued behind the\n * current utterance. The right default for anything that appears in\n * response to a user action but is not an emergency.\n * - `assertive` — `role=\"alert\"` + `aria-live=\"assertive\"`. Interrupts the\n * screen reader immediately. Reserve for content the user cannot miss.\n */\nexport type AlertAnnounce = 'off' | 'polite' | 'assertive';\n\nexport interface AlertProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'role'>,\n VariantProps<typeof alertVariants> {\n variant?: 'info' | 'success' | 'warning' | 'error' | 'promo';\n dismissible?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n icon?: ReactNode;\n /** Announcement urgency — sets `role` **and** `aria-live` together, so the\n * tint (`variant`) and the interruption are chosen independently. Defaults\n * to the variant's historical mapping: `info` / `success` / `promo` →\n * `polite`, `warning` / `error` → `assertive`. Wins over `live`. */\n announce?: AlertAnnounce;\n /** @deprecated Use `announce`. Sets `aria-live` only and leaves `role`\n * variant-derived, which can pair `role=\"alert\"` with `aria-live=\"polite\"`.\n * Kept for the consumers already shipping it. */\n live?: 'assertive' | 'polite' | 'off';\n /** Compact mode: clamps `Alert.Title` to 2 lines (with a tooltip when the\n * title is truncated) and `Alert.Description` to 2 lines (with a \"Read more\"\n * toggle). Opt-in — leave off for standalone alerts whose full message must\n * always be visible. */\n clamp?: boolean;\n}\n\nexport type { AlertTitleProps };\n\nconst AlertRoot = forwardRef<HTMLDivElement, AlertProps>(\n (\n {\n variant = 'info',\n dismissible = false,\n open: controlledOpen,\n onOpenChange,\n icon,\n announce,\n live,\n clamp = false,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const [isOpenRaw, setOpen] = useControllableState<boolean>({\n value: controlledOpen,\n defaultValue: true,\n onChange: onOpenChange,\n });\n const isOpen = isOpenRaw ?? true;\n const [isClosing, setIsClosing] = useState(false);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const animationDurationMs = useCallback((): number => {\n if (typeof window === 'undefined') return 200;\n const raw = window\n .getComputedStyle(document.documentElement)\n .getPropertyValue('--animation-duration');\n if (!raw) return 200;\n const trimmed = raw.trim();\n const n = parseFloat(trimmed);\n if (!Number.isFinite(n)) return 200;\n return trimmed.endsWith('ms') ? n : n * 1000;\n }, []);\n\n if (!isOpen) return null;\n\n const config = VARIANT_CONFIG[variant];\n const effectiveIcon = icon !== undefined ? icon : config.icon;\n\n // `announce` owns role + aria-live together. Without it we keep the\n // shipped behaviour exactly: role from the variant, aria-live from the\n // legacy `live` prop or the variant default.\n const announcement = announce\n ? ANNOUNCE_CONFIG[announce]\n : { role: config.role, live: live ?? config.live };\n\n // Detect an `<Alert.Title>` anywhere in the immediate children so\n // the root can flip its cross-axis alignment. Nested wrappers\n // around a Title aren't supported — keep the API as flat as the\n // existing `Alert.Title` / `Alert.Description` convention.\n const hasTitle = Children.toArray(children).some(\n (child) => isValidElement(child) && child.type === AlertTitle,\n );\n\n const handleDismiss = () => {\n if (isClosing) return;\n setIsClosing(true);\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n closeTimerRef.current = setTimeout(() => {\n setIsClosing(false);\n setOpen(false);\n }, animationDurationMs());\n };\n\n return (\n <div\n ref={ref}\n role={announcement.role}\n aria-live={announcement.live}\n data-component=\"alert\"\n data-has-title={hasTitle ? 'true' : 'false'}\n data-state={isClosing ? 'closing' : 'open'}\n className={[\n alertVariants({ variant, className }),\n // Entry: fade + slide-down on mount. Exit: fade + slide-up + slight\n // scale when dismissed. Driven by `tw-animate-css`. Respects\n // `prefers-reduced-motion` via `motion-safe:` and zeroes under the\n // accessible theme (`--animation-duration: 0ms`).\n 'ds:motion-safe:animate-in ds:motion-safe:fade-in-0 ds:motion-safe:slide-in-from-top-2',\n 'ds:motion-safe:data-[state=closing]:animate-out ds:motion-safe:data-[state=closing]:fade-out-0',\n 'ds:motion-safe:data-[state=closing]:slide-out-to-top-2 ds:motion-safe:data-[state=closing]:zoom-out-95',\n // Pin the exit's end-state until React unmounts. Without\n // `fill-mode-forwards` the element snaps back to opacity:1 for one\n // paint frame after the animation ends.\n 'ds:motion-safe:data-[state=closing]:fill-mode-forwards',\n 'ds:motion-safe:duration-[var(--animation-duration)]',\n ].join(' ')}\n {...props}\n >\n {effectiveIcon ? (\n <span className={hasTitle ? ICON_WITH_TITLE : ICON_BASE}>\n {effectiveIcon}\n </span>\n ) : null}\n\n <div className=\"ds:flex-1 ds:min-w-0\">\n <AlertClampContext.Provider value={clamp}>\n {children}\n </AlertClampContext.Provider>\n </div>\n\n {dismissible ? (\n <button\n type=\"button\"\n aria-label={t('common.close', 'Close')}\n onClick={handleDismiss}\n // Stable hook for containers (WarningStack) that hand focus to\n // a neighbouring dismiss control after this one unmounts.\n data-alert-dismiss=\"\"\n className={CLOSE_BUTTON_CLASSES}\n >\n <X aria-hidden=\"true\" className=\"ds:size-4\" />\n </button>\n ) : null}\n </div>\n );\n },\n);\n\nAlertRoot.displayName = 'Alert';\n\nexport const Alert = Object.assign(AlertRoot, {\n Title: AlertTitle,\n Description: AlertDescription,\n Action: AlertAction,\n});\n"],"names":["__iconNode","CircleArrowUp","createLucideIcon","AlertClampContext","createContext","DISCLOSURE_BUTTON_CLASSES","alertVariants","cva","ICON_BASE","ICON_WITH_TITLE","CLOSE_BUTTON_CLASSES","VARIANT_CONFIG","jsx","Info","CircleCheck","TriangleAlert","CircleAlert","ANNOUNCE_CONFIG","AlertTitle","forwardRef","Tag","className","children","props","ref","clamp","useContext","clampRef","isOverflowing","useClampOverflow","setRefs","useCallback","node","tooltipReady","heading","Tooltip","AlertDescription","t","useTranslation","bodyId","useId","expanded","setExpanded","useState","showToggle","jsxs","Fragment","prev","AlertAction","AlertRoot","variant","dismissible","controlledOpen","onOpenChange","icon","announce","live","isOpenRaw","setOpen","useControllableState","isOpen","isClosing","setIsClosing","closeTimerRef","useRef","animationDurationMs","raw","trimmed","n","config","effectiveIcon","announcement","hasTitle","Children","child","isValidElement","handleDismiss","X","Alert"],"mappings":"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","x_google_ignoreList":[0]}
|