@alfadocs/ui-kit-debug 0.84.0 → 0.85.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/actions-cell-renderer-DaL80uqL.js.map +1 -1
- package/dist/_chunks/{ai-consent-banner-DUhr1yNj.js → ai-consent-banner-BXD7W6FI.js} +2 -2
- package/dist/_chunks/{ai-consent-banner-DUhr1yNj.js.map → ai-consent-banner-BXD7W6FI.js.map} +1 -1
- package/dist/_chunks/{alert-KJbsPYkI.js → alert-Cxaqd-QO.js} +12 -12
- package/dist/_chunks/alert-Cxaqd-QO.js.map +1 -0
- package/dist/_chunks/anamnesis-card-CJ5MNbkc.js.map +1 -1
- package/dist/_chunks/{audio-recorder-Cc3KuL9y.js → audio-recorder-BjnB7V8n.js} +2 -2
- package/dist/_chunks/{audio-recorder-Cc3KuL9y.js.map → audio-recorder-BjnB7V8n.js.map} +1 -1
- package/dist/_chunks/{booking-CLmeXtGv.js → booking-BvCu2XWY.js} +2 -2
- package/dist/_chunks/{booking-CLmeXtGv.js.map → booking-BvCu2XWY.js.map} +1 -1
- package/dist/_chunks/breadcrumb-agut0PwN.js.map +1 -1
- package/dist/_chunks/calendar-event-card-C6qGtywL.js.map +1 -1
- package/dist/_chunks/chat-input-QpHxBEnN.js.map +1 -1
- package/dist/_chunks/chat-message-CdjWqZjo.js.map +1 -1
- package/dist/_chunks/checkbox-group-CfqMv57d.js.map +1 -1
- package/dist/_chunks/dependent-selector-DyFpdzZV.js.map +1 -1
- package/dist/_chunks/{document-preview-nwfulDEs.js → document-preview-DXl9migE.js} +2 -2
- package/dist/_chunks/{document-preview-nwfulDEs.js.map → document-preview-DXl9migE.js.map} +1 -1
- package/dist/_chunks/{document-scanner-B6h1Ir56.js → document-scanner-cS_ispQs.js} +3 -3
- package/dist/_chunks/document-scanner-cS_ispQs.js.map +1 -0
- package/dist/_chunks/editable-currency-cell-renderer-Dus_sBvX.js.map +1 -1
- package/dist/_chunks/email-input-Dpe63k0K.js.map +1 -1
- package/dist/_chunks/{entity-summary--vP698Jn.js → entity-summary-BILN4wEG.js} +2 -2
- package/dist/_chunks/{entity-summary--vP698Jn.js.map → entity-summary-BILN4wEG.js.map} +1 -1
- package/dist/_chunks/{field-value-DHG6gEKS.js → field-value-BRVbZJej.js} +133 -144
- package/dist/_chunks/field-value-BRVbZJej.js.map +1 -0
- package/dist/_chunks/{file-manager-DLJlinIO.js → file-manager-B9LZzT5E.js} +129 -129
- package/dist/_chunks/file-manager-B9LZzT5E.js.map +1 -0
- package/dist/_chunks/{file-upload-DENvuhfs.js → file-upload-CwxdqkMK.js} +134 -146
- package/dist/_chunks/file-upload-CwxdqkMK.js.map +1 -0
- package/dist/_chunks/finished-terminal-C0_mefrf.js.map +1 -1
- package/dist/_chunks/fiscal-code-input-QP9gkyDE.js.map +1 -1
- package/dist/_chunks/form-field-M5UpX65Z.js.map +1 -1
- package/dist/_chunks/{freemium-paywall-CmV642PA.js → freemium-paywall-Dr2342_S.js} +2 -2
- package/dist/_chunks/{freemium-paywall-CmV642PA.js.map → freemium-paywall-Dr2342_S.js.map} +1 -1
- package/dist/_chunks/iban-input-DXIA8Ln_.js.map +1 -1
- package/dist/_chunks/{marketplace-app-shell-Br2yebEK.js → marketplace-app-shell-Chcj4q4z.js} +2 -2
- package/dist/_chunks/{marketplace-app-shell-Br2yebEK.js.map → marketplace-app-shell-Chcj4q4z.js.map} +1 -1
- package/dist/_chunks/message-square-Bye4ATvx.js +20 -0
- package/dist/_chunks/message-square-Bye4ATvx.js.map +1 -0
- package/dist/_chunks/{notes-panel-Cvdp818a.js → notes-panel-BLjlYBt-.js} +2 -2
- package/dist/_chunks/{notes-panel-Cvdp818a.js.map → notes-panel-BLjlYBt-.js.map} +1 -1
- package/dist/_chunks/pagination-EkD5SiCK.js.map +1 -1
- package/dist/_chunks/{patient-details-COvYWp2e.js → patient-details-B9LCdyWW.js} +2 -2
- package/dist/_chunks/{patient-details-COvYWp2e.js.map → patient-details-B9LCdyWW.js.map} +1 -1
- package/dist/_chunks/{patient-search-BaUJ_Y-N.js → patient-search-vtRTSdf6.js} +2 -2
- package/dist/_chunks/{patient-search-BaUJ_Y-N.js.map → patient-search-vtRTSdf6.js.map} +1 -1
- package/dist/_chunks/{patient-summary-card-D6kgdTNn.js → patient-summary-card-vn1H4xWj.js} +2 -2
- package/dist/_chunks/patient-summary-card-vn1H4xWj.js.map +1 -0
- package/dist/_chunks/{patient-table-BHzmUbzu.js → patient-table-B6AKMTm3.js} +182 -196
- package/dist/_chunks/patient-table-B6AKMTm3.js.map +1 -0
- package/dist/_chunks/{payment-form-DL9xk9BA.js → payment-form-BoGxEmGn.js} +2 -2
- package/dist/_chunks/{payment-form-DL9xk9BA.js.map → payment-form-BoGxEmGn.js.map} +1 -1
- package/dist/_chunks/{payment-request-card-d-RmzsUd.js → payment-request-card-CygO1anM.js} +72 -70
- package/dist/_chunks/payment-request-card-CygO1anM.js.map +1 -0
- package/dist/_chunks/{pdf-viewer-DF3VMaPo.js → pdf-viewer-CcOuR2wj.js} +2 -2
- package/dist/_chunks/{pdf-viewer-DF3VMaPo.js.map → pdf-viewer-CcOuR2wj.js.map} +1 -1
- package/dist/_chunks/postal-code-input-BznBxVxf.js.map +1 -1
- package/dist/_chunks/{practice-results-BCr7jMt1.js → practice-results-yKbwIxqa.js} +2 -2
- package/dist/_chunks/{practice-results-BCr7jMt1.js.map → practice-results-yKbwIxqa.js.map} +1 -1
- package/dist/_chunks/radio-group-CI-6SmSw.js.map +1 -1
- package/dist/_chunks/{radiograph-panel.agent-CxF9pVxd.js → radiograph-panel.agent-M9XD4ze4.js} +2 -2
- package/dist/_chunks/{radiograph-panel.agent-CxF9pVxd.js.map → radiograph-panel.agent-M9XD4ze4.js.map} +1 -1
- package/dist/_chunks/{rich-text-editor-CCWjNkbx.js → rich-text-editor-RRkBN_WB.js} +2 -2
- package/dist/_chunks/rich-text-editor-RRkBN_WB.js.map +1 -0
- package/dist/_chunks/select-BW5ecXlX.js.map +1 -1
- package/dist/_chunks/{session-countdown-C8AsE072.js → session-countdown-Bc70VXN1.js} +58 -48
- package/dist/_chunks/session-countdown-Bc70VXN1.js.map +1 -0
- package/dist/_chunks/{sign-document-Bfk0WpWV.js → sign-document-DI561d1C.js} +2 -2
- package/dist/_chunks/sign-document-DI561d1C.js.map +1 -0
- package/dist/_chunks/{signature-request-CEOrCDyk.js → signature-request-D_6jgDZd.js} +60 -77
- package/dist/_chunks/signature-request-D_6jgDZd.js.map +1 -0
- package/dist/_chunks/task-card-BUgK6yZT.js.map +1 -1
- package/dist/_chunks/{task-tray-Br3vc0O1.js → task-tray-CLIqIXUZ.js} +58 -70
- package/dist/_chunks/task-tray-CLIqIXUZ.js.map +1 -0
- package/dist/_chunks/tasks-panel-CjGAhIN8.js.map +1 -1
- package/dist/_chunks/timeline-r-8IUoBS.js.map +1 -1
- package/dist/_chunks/{toast.agent-uV8CeAy6.js → toast.agent-Iw2jWdce.js} +2 -2
- package/dist/_chunks/{toast.agent-uV8CeAy6.js.map → toast.agent-Iw2jWdce.js.map} +1 -1
- package/dist/_chunks/tooth-scheme-BzJ6rcte.js.map +1 -1
- package/dist/_chunks/use-password-requirements-Bwtqx1qN.js.map +1 -1
- package/dist/_chunks/{warning-stack-BlG_Ujy3.js → warning-stack-CAHQ0xxS.js} +2 -2
- package/dist/_chunks/{warning-stack-BlG_Ujy3.js.map → warning-stack-CAHQ0xxS.js.map} +1 -1
- package/dist/_chunks/{workflow-map-C643Q43h.js → workflow-map-SIfAhmWz.js} +2 -2
- package/dist/_chunks/workflow-map-SIfAhmWz.js.map +1 -0
- 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/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/file-manager/index.js +1 -1
- package/dist/components/file-upload/file-upload.d.ts.map +1 -1
- package/dist/components/file-upload/index.js +1 -1
- package/dist/components/freemium-paywall/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-search/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/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/radiograph-panel/index.js +1 -1
- package/dist/components/rich-text-editor/index.js +1 -1
- package/dist/components/select/select.d.ts +8 -5
- package/dist/components/select/select.d.ts.map +1 -1
- package/dist/components/session-countdown/index.js +1 -1
- package/dist/components/sign-document/index.js +1 -1
- package/dist/components/task-card/task-card.d.ts.map +1 -1
- package/dist/components/task-tray/index.js +1 -1
- package/dist/components/toast/index.js +1 -1
- package/dist/components/tooth-scheme/tooth-scheme.d.ts.map +1 -1
- package/dist/components/warning-stack/index.js +1 -1
- package/dist/components/workflow/index.js +1 -1
- package/dist/index.js +434 -445
- package/dist/index.js.map +1 -1
- package/dist/patterns/marketplace-app-shell/index.js +1 -1
- package/dist/patterns/signature-request/index.js +1 -1
- package/dist/tokens.css +1 -1
- package/package.json +5 -3
- package/dist/_chunks/alert-KJbsPYkI.js.map +0 -1
- package/dist/_chunks/circle-x-W8Enq3i4.js +0 -16
- package/dist/_chunks/circle-x-W8Enq3i4.js.map +0 -1
- package/dist/_chunks/document-scanner-B6h1Ir56.js.map +0 -1
- package/dist/_chunks/field-value-DHG6gEKS.js.map +0 -1
- package/dist/_chunks/file-manager-DLJlinIO.js.map +0 -1
- package/dist/_chunks/file-upload-DENvuhfs.js.map +0 -1
- package/dist/_chunks/patient-summary-card-D6kgdTNn.js.map +0 -1
- package/dist/_chunks/patient-table-BHzmUbzu.js.map +0 -1
- package/dist/_chunks/payment-request-card-d-RmzsUd.js.map +0 -1
- package/dist/_chunks/rich-text-editor-CCWjNkbx.js.map +0 -1
- package/dist/_chunks/session-countdown-C8AsE072.js.map +0 -1
- package/dist/_chunks/sign-document-Bfk0WpWV.js.map +0 -1
- package/dist/_chunks/signature-request-CEOrCDyk.js.map +0 -1
- package/dist/_chunks/task-tray-Br3vc0O1.js.map +0 -1
- package/dist/_chunks/workflow-map-C643Q43h.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-scanner-cS_ispQs.js","sources":["../../src/components/document-scanner/document-scanner.agent.ts","../../src/components/document-scanner/document-scanner.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — DocumentScanner. */\n/* */\n/* State exposes only structural lifecycle info — never the captured */\n/* image bytes (PHI). Actions drive the camera + capture flow. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { DocumentScannerHandle } from './document-scanner';\n\nexport const documentScannerAgent: AgentAdapter<DocumentScannerHandle> = {\n id: 'document-scanner',\n capabilities: ['capture', 'submit'],\n state: {\n hasCapture: {\n type: 'boolean',\n descriptionKey: 'documentScanner.agent.state.hasCapture',\n description: 'True when a captured or uploaded image is available.',\n read: (handle) => handle.hasCapture(),\n },\n phase: {\n type: 'string',\n descriptionKey: 'documentScanner.agent.state.phase',\n description:\n \"Lifecycle phase: 'idle' | 'requesting' | 'streaming' | 'captured' | 'error'.\",\n read: (handle) => handle.getPhase(),\n },\n },\n actions: {\n start_camera: {\n safety: 'write',\n idempotent: true,\n descriptionKey: 'documentScanner.agent.actions.startCamera',\n description: 'Request camera permission and begin the live viewfinder.',\n errors: [\n 'permission-denied',\n 'no-camera',\n 'not-readable',\n 'insecure-context',\n ],\n invoke: (handle) => handle.startCamera(),\n },\n capture: {\n safety: 'write',\n descriptionKey: 'documentScanner.agent.actions.capture',\n description: 'Freeze the current viewfinder frame as a captured image.',\n errors: ['capture-failed'],\n invoke: (handle) => handle.capture(),\n },\n submit: {\n safety: 'write',\n descriptionKey: 'documentScanner.agent.actions.confirm',\n description: 'Confirm the current capture, emitting it via onConfirm.',\n invoke: (handle) => {\n handle.confirm();\n },\n },\n retake: {\n safety: 'destructive',\n descriptionKey: 'documentScanner.agent.actions.retake',\n description:\n 'Discard the current capture and return to the capture path.',\n invoke: (handle) => {\n handle.retake();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'document-scanner',\n description: 'Marks the DocumentScanner wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* DocumentScanner — patient check-in ID-document capture. */\n/* */\n/* - Native MediaDevices: a live <video autoplay playsinline muted> */\n/* viewfinder via getUserMedia({ video: { facingMode } }), an */\n/* offscreen <canvas> for the freeze-frame / crop draw, and an <img> */\n/* for the captured preview. No third-party dependency for capture. */\n/* - Upload fallback: the existing kit FileUpload (variant='button') */\n/* handles accept / maxSize / reject and is ALWAYS reachable — even */\n/* on a hard camera error it is the recovery path (per HTP-5113). */\n/* - Lifecycle: the camera starts only on an explicit user gesture and */\n/* every MediaStreamTrack is stopped on unmount, on capture, on */\n/* error, on Escape, and on document visibilitychange→hidden so the */\n/* camera LED is released (privacy + battery). Mirrors */\n/* audio-recorder's teardown pattern. */\n/* - Confirm payload: { dataUrl, blob, source, width, height, mimeType, */\n/* byteSize, capturedAt (ISO-8601), sha256 }. sha256 is the */\n/* SubtleCrypto digest of the encoded bytes — tamper-evident for */\n/* audit, matching signature-capture. Document-only: no selfie, no */\n/* liveness, no OCR / MRZ / auto-crop (out of scope, would need a */\n/* separate 08-third-party dependency). */\n/* - Security: no fetch / XHR / localStorage / sessionStorage / globals */\n/* in this file — the captured ID document is PHI and the consumer */\n/* owns persistence + the \"already on file → skip\" decision. */\n/* ------------------------------------------------------------------ */\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Camera, RotateCcw, Check, LoaderCircle } from 'lucide-react';\nimport { Button } from '../button';\nimport { Alert } from '../alert';\nimport { FileUpload, type FileUploadRejection } from '../file-upload';\nimport { useControllableState } from '../../hooks/use-controllable-state';\nimport { useAgentRegistration } from '../../agent';\nimport { documentScannerAgent } from './document-scanner.agent';\n\n/* ------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------ */\n\nexport type DocumentScannerSource = 'camera' | 'upload';\n\nexport interface DocumentCapture {\n /** Data URL of the captured / uploaded image (encoded to `mimeType`). */\n dataUrl: string;\n /** Encoded bytes as a Blob — the consumer persists this. */\n blob: Blob;\n /** Where the image came from. */\n source: DocumentScannerSource;\n /** Intrinsic pixel width of the encoded image. */\n width: number;\n /** Intrinsic pixel height of the encoded image. */\n height: number;\n /** MIME of the encoded image. */\n mimeType: string;\n /** Encoded byte size. */\n byteSize: number;\n /** ISO-8601 UTC timestamp for when the capture was confirmed. */\n capturedAt: string;\n /** Hex-encoded SHA-256 digest of the encoded bytes. */\n sha256: string;\n}\n\nexport type DocumentScannerErrorKind =\n | 'permission-denied'\n | 'no-camera'\n | 'not-readable'\n | 'insecure-context'\n | 'capture-failed'\n | 'file-invalid-type'\n | 'file-too-large';\n\nexport interface DocumentScannerError {\n kind: DocumentScannerErrorKind;\n}\n\nexport type DocumentType = 'tessera-sanitaria' | 'cie' | 'id-card' | 'generic';\n\nexport type DocumentScannerPhase =\n | 'idle'\n | 'requesting'\n | 'streaming'\n | 'captured'\n | 'error';\n\n/** Curated imperative handle for agent / external automation. */\nexport interface DocumentScannerHandle {\n /** True when a captured or uploaded image is held. */\n hasCapture: () => boolean;\n /** Current lifecycle phase. */\n getPhase: () => DocumentScannerPhase;\n /** Request the camera and begin the viewfinder. */\n startCamera: () => Promise<void> | void;\n /** Freeze the current viewfinder frame. */\n capture: () => Promise<void> | void;\n /** Confirm the current capture, firing `onConfirm`. */\n confirm: () => void;\n /** Discard the current capture and return to the capture path. */\n retake: () => void;\n}\n\nexport interface DocumentScannerProps {\n /** Opaque instance id — emitted as `data-component-id` for the agent registry. */\n id?: string;\n /** Controlled captured-image value. When defined the component is controlled. */\n value?: DocumentCapture | null;\n /** Initial captured image for uncontrolled use; seeds the `captured` preview. */\n defaultValue?: DocumentCapture | null;\n /** Fired when the user confirms a captured or uploaded image. */\n onConfirm?: (capture: DocumentCapture) => void;\n /** Fired when the user discards the current capture to retake / re-upload. */\n onRetake?: () => void;\n /** Fired on a permission / hardware / decode failure (telemetry). */\n onError?: (error: DocumentScannerError) => void;\n /** Drives the overlay frame aspect ratio + the translated hint copy. */\n documentType?: DocumentType;\n /** Camera-vs-upload strategy. `auto` falls back to upload on camera failure. */\n captureMode?: 'auto' | 'camera-only' | 'upload-only';\n /** react-dropzone accept map for the upload fallback. */\n accept?: Record<string, string[]>;\n /** Max upload byte size. Defaults to 10MB. */\n maxSize?: number;\n /** Camera to request. Defaults to the rear (`environment`) camera. */\n facingMode?: 'environment' | 'user';\n /** MIME of the encoded capture. */\n outputType?: 'image/jpeg' | 'image/webp' | 'image/png';\n /** 0..1 quality for lossy `outputType`. Ignored for image/png. */\n outputQuality?: number;\n /** Crop the confirmed image to the overlay frame rect. */\n cropToFrame?: boolean;\n /** Disable all controls and skip the camera request. */\n disabled?: boolean;\n /** Accessible label for the component's group region. */\n ariaLabel?: string;\n /** Extra classes merged onto the outermost wrapper. */\n className?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst rootVariants = cva(\n [\n 'ds:flex ds:flex-col ds:gap-[var(--spacing-md)]',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--card-border)]',\n 'ds:shadow-[var(--shadow-card)] ds:[.theme-accessible_&]:border-2',\n 'ds:bg-[var(--background)] ds:text-[var(--foreground)]',\n 'ds:p-[var(--spacing-md)]',\n 'ds:aria-disabled:opacity-[var(--opacity-50)] ds:aria-disabled:cursor-not-allowed',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:[max-inline-size:20rem]',\n md: 'ds:[max-inline-size:28rem]',\n lg: 'ds:[max-inline-size:36rem]',\n },\n },\n defaultVariants: { size: 'md' },\n },\n);\n\n// The viewport is a positioned, neutral surface that holds the <video> /\n// <img> and the (absolutely-positioned, aria-hidden) frame overlay. The\n// document aspect ratio drives the box shape so the frame matches the card.\nconst viewportVariants = cva(\n [\n 'ds:relative ds:block ds:inline-size-full ds:overflow-hidden',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:bg-[var(--muted)]',\n ].join(' '),\n {\n variants: {\n // ID-1 cards (Tessera Sanitaria / CIE / id-card) are ~1.586:1; the\n // generic frame is a slightly squarer neutral card.\n frame: {\n 'tessera-sanitaria': 'ds:aspect-[1.586/1]',\n cie: 'ds:aspect-[1.586/1]',\n 'id-card': 'ds:aspect-[1.586/1]',\n generic: 'ds:aspect-[1.4/1]',\n },\n },\n defaultVariants: { frame: 'tessera-sanitaria' },\n },\n);\n\nconst mediaVariants = cva(\n [\n 'ds:absolute ds:inset-0 ds:block',\n 'ds:inline-size-full ds:block-size-full',\n 'ds:object-cover',\n ].join(' '),\n);\n\n// The alignment frame sits over arbitrary live video. It is a\n// high-contrast neutral stroke (var(--background) = white on light /\n// near-black on dark) backed by a tokenised scrim — NEVER the magenta\n// accent (fails AA over an unknown image). Decorative → aria-hidden.\nconst frameOverlayVariants = cva(\n [\n 'ds:pointer-events-none ds:absolute',\n 'ds:inset-[12%]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:border-2 ds:border-[color:var(--background)]',\n 'ds:shadow-[0_0_0_100vmax_color-mix(in_srgb,var(--foreground)_45%,transparent)]',\n ].join(' '),\n);\n\nconst cornerVariants = cva(\n [\n 'ds:pointer-events-none ds:absolute ds:size-6',\n 'ds:border-[color:var(--background)]',\n ].join(' '),\n);\n\nconst controlBarVariants = cva(\n [\n // Phone: actions stack full-width; sm+: a wrapping row.\n 'ds:flex ds:flex-col ds:items-stretch ds:gap-[var(--spacing-sm)]',\n 'ds:sm:flex-row ds:sm:flex-wrap ds:sm:items-center',\n ].join(' '),\n);\n\nconst hintVariants = cva(\n ['type-body-sm ds:text-center', 'ds:text-[var(--muted-foreground)]'].join(\n ' ',\n ),\n);\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\nfunction toHex(bytes: Uint8Array): string {\n let out = '';\n for (let i = 0; i < bytes.length; i += 1) {\n out += bytes[i].toString(16).padStart(2, '0');\n }\n return out;\n}\n\nasync function sha256Hex(buffer: ArrayBuffer): Promise<string> {\n const g = globalThis as { crypto?: Crypto };\n if (g.crypto?.subtle) {\n // Copy into a fresh ArrayBuffer so the BufferSource is never a\n // SharedArrayBuffer (SubtleCrypto's narrowing rejects the latter).\n const copy = new Uint8Array(buffer.byteLength);\n copy.set(new Uint8Array(buffer));\n const digest = await g.crypto.subtle.digest('SHA-256', copy.buffer);\n return toHex(new Uint8Array(digest));\n }\n // No subtle crypto (older test env) — return empty so the rest of the\n // payload is still usable. Tests stub crypto.subtle.\n return '';\n}\n\n/** Map a getUserMedia rejection (a DOMException) to our error kind. */\nfunction classifyMediaError(err: unknown): DocumentScannerErrorKind {\n const name = err instanceof Error ? err.name : '';\n if (name === 'NotAllowedError' || name === 'SecurityError') {\n return 'permission-denied';\n }\n if (name === 'NotFoundError' || name === 'OverconstrainedError') {\n return 'no-camera';\n }\n if (name === 'NotReadableError' || name === 'AbortError') {\n return 'not-readable';\n }\n return 'capture-failed';\n}\n\n/** True when getUserMedia is actually reachable (HTTPS / localhost + API). */\nfunction mediaDevicesAvailable(): boolean {\n return (\n typeof navigator !== 'undefined' &&\n typeof navigator.mediaDevices !== 'undefined' &&\n typeof navigator.mediaDevices.getUserMedia === 'function'\n );\n}\n\nconst HINT_KEY: Record<DocumentType, string> = {\n 'tessera-sanitaria': 'documentScanner.hint.tesseraSanitaria',\n cie: 'documentScanner.hint.cie',\n 'id-card': 'documentScanner.hint.idCard',\n generic: 'documentScanner.hint.generic',\n};\n\nconst ERROR_KEY: Record<DocumentScannerErrorKind, string> = {\n 'permission-denied': 'documentScanner.error.permissionDenied',\n 'no-camera': 'documentScanner.error.noCamera',\n 'not-readable': 'documentScanner.error.notReadable',\n 'insecure-context': 'documentScanner.error.insecureContext',\n 'capture-failed': 'documentScanner.error.captureFailed',\n 'file-invalid-type': 'documentScanner.error.fileInvalidType',\n 'file-too-large': 'documentScanner.error.fileTooLarge',\n};\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\ntype SizeVariant = NonNullable<VariantProps<typeof rootVariants>['size']>;\n\ninterface DocumentScannerInternalProps extends DocumentScannerProps {\n /** Visual size variant (exposed via Controls). */\n size?: SizeVariant;\n}\n\nexport const DocumentScanner = forwardRef<\n DocumentScannerHandle,\n DocumentScannerInternalProps\n>(\n (\n {\n id,\n value,\n defaultValue = null,\n onConfirm,\n onRetake,\n onError,\n documentType = 'tessera-sanitaria',\n captureMode = 'auto',\n accept = {\n 'image/jpeg': ['.jpg', '.jpeg'],\n 'image/png': ['.png'],\n 'image/webp': ['.webp'],\n },\n maxSize = 10 * 1024 * 1024,\n facingMode = 'environment',\n outputType = 'image/jpeg',\n outputQuality = 0.92,\n cropToFrame = true,\n disabled = false,\n size = 'md',\n ariaLabel,\n className,\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const rawId = useId();\n const hintId = `ds-${rawId.replace(/[^a-zA-Z0-9-_]/g, '')}-hint`;\n\n // Controlled / uncontrolled captured value. `value` defined → controlled.\n const [capture, setCapture] = useControllableState<DocumentCapture | null>({\n value,\n defaultValue,\n });\n\n // Whether the captured value was seeded by `defaultValue` (already on\n // file) — drives the \"Already on file\" badge + Retake-only chrome.\n const seededRef = useRef<boolean>(defaultValue != null || value != null);\n\n const [phase, setPhase] = useState<DocumentScannerPhase>(\n defaultValue != null || value != null ? 'captured' : 'idle',\n );\n const [errorKind, setErrorKind] = useState<DocumentScannerErrorKind | null>(\n null,\n );\n const [streamReady, setStreamReady] = useState(false);\n // True while an uploaded image is being decoded (distinct from the\n // camera-permission `requesting` so the live region announces the right\n // \"Processing image\" copy).\n const [decoding, setDecoding] = useState(false);\n\n const videoRef = useRef<HTMLVideoElement>(null);\n const viewportRef = useRef<HTMLDivElement>(null);\n const streamRef = useRef<MediaStream | null>(null);\n const unmountedRef = useRef(false);\n\n const confirmBtnRef = useRef<HTMLButtonElement>(null);\n const shutterBtnRef = useRef<HTMLButtonElement>(null);\n const useCameraBtnRef = useRef<HTMLButtonElement>(null);\n const recoveryRef = useRef<HTMLButtonElement>(null);\n\n // Latest callbacks via refs so the async media path never closes over\n // a stale prop.\n const onErrorRef = useRef(onError);\n const onConfirmRef = useRef(onConfirm);\n const onRetakeRef = useRef(onRetake);\n useEffect(() => {\n onErrorRef.current = onError;\n onConfirmRef.current = onConfirm;\n onRetakeRef.current = onRetake;\n }, [onError, onConfirm, onRetake]);\n\n const isControlled = value !== undefined;\n const isUploadOnly = captureMode === 'upload-only';\n\n /* ---- Stream teardown — the single most important privacy path ---- */\n const stopStream = useCallback(() => {\n const held = streamRef.current;\n if (held) {\n held.getTracks().forEach((track) => track.stop());\n }\n streamRef.current = null;\n const video = videoRef.current;\n if (video) {\n // Detach so the element releases its reference to the (now-stopped)\n // stream and the browser drops the camera indicator.\n video.srcObject = null;\n }\n setStreamReady(false);\n }, []);\n\n const reportError = useCallback((kind: DocumentScannerErrorKind) => {\n setErrorKind(kind);\n setPhase('error');\n onErrorRef.current?.({ kind });\n }, []);\n\n /* ---- Start the camera — user gesture only, never auto on mount ---- */\n const startCamera = useCallback(async () => {\n if (disabled || isUploadOnly) return;\n if (!mediaDevicesAvailable()) {\n // No mediaDevices → insecure context (non-HTTPS) or unsupported.\n reportError('insecure-context');\n return;\n }\n setErrorKind(null);\n setPhase('requesting');\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n video: { facingMode },\n audio: false,\n });\n // Guard against an unmount between the permission prompt and\n // resolution — otherwise the freshly-acquired track leaks and the\n // camera LED stays live.\n if (unmountedRef.current) {\n stream.getTracks().forEach((track) => track.stop());\n return;\n }\n streamRef.current = stream;\n const video = videoRef.current;\n if (video) {\n try {\n video.srcObject = stream;\n } catch {\n // Some environments reject a non-native MediaStream on\n // srcObject; the stream is still held + torn down correctly.\n }\n // iOS Safari needs an explicit play() after attaching.\n const playResult = video.play?.();\n if (playResult && typeof playResult.catch === 'function') {\n playResult.catch(() => {\n /* autoplay can reject silently in some browsers; the\n loadedmetadata handler still enables the shutter */\n });\n }\n }\n setPhase('streaming');\n } catch (err: unknown) {\n stopStream();\n reportError(classifyMediaError(err));\n }\n }, [disabled, isUploadOnly, facingMode, stopStream, reportError]);\n\n /* ---- Shutter enablement: gate on the video actually playing ---- */\n const handleVideoReady = useCallback(() => {\n const video = videoRef.current;\n if (!video) return;\n // HAVE_CURRENT_DATA (2) means at least one frame is decodable.\n if (video.readyState >= 2) {\n setStreamReady(true);\n }\n }, []);\n\n /* ---- Poll readiness on entering streaming ---- */\n // The loadedmetadata / canplay events can fire before React attaches the\n // listeners (the metadata may already be decoded by the time the stream\n // is swapped onto the element). A short poll closes that race so the\n // shutter reliably enables.\n useEffect(() => {\n if (phase !== 'streaming') return undefined;\n handleVideoReady();\n const interval = window.setInterval(handleVideoReady, 100);\n const stopAfter = window.setTimeout(\n () => window.clearInterval(interval),\n 4000,\n );\n return () => {\n window.clearInterval(interval);\n window.clearTimeout(stopAfter);\n };\n }, [phase, handleVideoReady]);\n\n /* ---- Capture: freeze the current frame onto a canvas ---- */\n const capturePhoto = useCallback(async () => {\n const video = videoRef.current;\n if (!video || video.readyState < 2) {\n reportError('capture-failed');\n return;\n }\n const vw = video.videoWidth || video.clientWidth;\n const vh = video.videoHeight || video.clientHeight;\n if (vw === 0 || vh === 0) {\n reportError('capture-failed');\n return;\n }\n\n // Crop region in source-video pixel space. The overlay frame is\n // inset 12% on each edge of the viewport; mirror that onto the\n // source so the cropped image is the document, not the whole frame.\n let sx = 0;\n let sy = 0;\n let sw = vw;\n let sh = vh;\n if (cropToFrame) {\n const insetX = vw * 0.12;\n const insetY = vh * 0.12;\n sx = insetX;\n sy = insetY;\n sw = vw - insetX * 2;\n sh = vh - insetY * 2;\n }\n\n const canvas = document.createElement('canvas');\n canvas.width = Math.max(1, Math.round(sw));\n canvas.height = Math.max(1, Math.round(sh));\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n reportError('capture-failed');\n return;\n }\n try {\n ctx.drawImage(video, sx, sy, sw, sh, 0, 0, canvas.width, canvas.height);\n } catch {\n // A video element with no decoded frame throws InvalidStateError in\n // some browsers — surface it as a capture failure rather than crash.\n reportError('capture-failed');\n return;\n }\n\n // Release the camera as soon as the frame is frozen — we no longer\n // need the live stream and the LED should go dark immediately.\n stopStream();\n\n const blob = await new Promise<Blob | null>((resolve) => {\n if (typeof canvas.toBlob === 'function') {\n canvas.toBlob(\n (b) => resolve(b),\n outputType,\n outputType === 'image/png' ? undefined : outputQuality,\n );\n } else {\n resolve(null);\n }\n });\n if (!blob) {\n reportError('capture-failed');\n return;\n }\n const dataUrl = canvas.toDataURL(\n outputType,\n outputType === 'image/png' ? undefined : outputQuality,\n );\n const arrayBuffer = await blob.arrayBuffer();\n const sha256 = await sha256Hex(arrayBuffer);\n\n seededRef.current = false;\n const next: DocumentCapture = {\n dataUrl,\n blob,\n source: 'camera',\n width: canvas.width,\n height: canvas.height,\n mimeType: outputType,\n byteSize: blob.size,\n capturedAt: new Date().toISOString(),\n sha256,\n };\n setCapture(next);\n setPhase('captured');\n }, [\n cropToFrame,\n outputType,\n outputQuality,\n stopStream,\n reportError,\n setCapture,\n ]);\n\n /* ---- Upload fallback → decode an image File into a capture ---- */\n const handleUploadDrop = useCallback(\n async (accepted: File[]) => {\n const file = accepted[0];\n if (!file) return;\n setDecoding(true);\n try {\n const objectUrl = URL.createObjectURL(file);\n const dimensions = await new Promise<{ w: number; h: number }>(\n (resolve, reject) => {\n const img = new Image();\n img.onload = () =>\n resolve({ w: img.naturalWidth, h: img.naturalHeight });\n img.onerror = () => reject(new Error('decode-failed'));\n img.src = objectUrl;\n },\n ).finally(() => {\n // The object URL is only needed to read intrinsic dimensions;\n // the persisted payload carries a data URL instead.\n URL.revokeObjectURL(objectUrl);\n });\n\n const dataUrl = await new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(String(reader.result));\n reader.onerror = () => reject(new Error('read-failed'));\n reader.readAsDataURL(file);\n });\n\n const arrayBuffer = await file.arrayBuffer();\n const sha256 = await sha256Hex(arrayBuffer);\n\n seededRef.current = false;\n setErrorKind(null);\n setCapture({\n dataUrl,\n blob: file,\n source: 'upload',\n width: dimensions.w,\n height: dimensions.h,\n mimeType: file.type || outputType,\n byteSize: file.size,\n capturedAt: new Date().toISOString(),\n sha256,\n });\n setPhase('captured');\n } catch {\n reportError('capture-failed');\n } finally {\n setDecoding(false);\n }\n },\n [outputType, reportError, setCapture],\n );\n\n const handleUploadReject = useCallback(\n (rejections: FileUploadRejection[]) => {\n // FileUpload's reason enum is wider than our two error kinds. The\n // dropzone is locked to a single image (maxFiles:1, multiple:false),\n // so 'too-many-files' / 'file-too-small' are unreachable here; both\n // size/type problems fold into the matching inline message and\n // default to invalid-type for anything else.\n const reason = rejections[0]?.reason;\n const kind: DocumentScannerErrorKind =\n reason === 'file-too-large' ? 'file-too-large' : 'file-invalid-type';\n reportError(kind);\n },\n [reportError],\n );\n\n /* ---- Confirm / Retake ---- */\n const confirm = useCallback(() => {\n if (!capture) return;\n onConfirmRef.current?.(capture);\n }, [capture]);\n\n // Set when a user-initiated transition back to idle should move focus to\n // the Use-camera button (Retake). Distinguishes retake-to-idle from the\n // initial idle mount, so focus is never stolen on first paint.\n const focusUseCameraRef = useRef(false);\n\n const retake = useCallback(() => {\n // Controlled mode: retake is advisory only. The consumer owns `value`,\n // so we must NOT clear the capture, flip seededRef, or force a local\n // phase — doing so would race the controlled-value sync effect (which\n // re-asserts `captured` while value is still set), dropping the\n // \"already on file\" badge and surfacing a stray Confirm for an\n // already-persisted image. Emit onRetake and let the value drive phase.\n if (isControlled) {\n onRetakeRef.current?.();\n return;\n }\n seededRef.current = false;\n focusUseCameraRef.current = true;\n setCapture(null);\n setErrorKind(null);\n setDecoding(false);\n setPhase('idle');\n onRetakeRef.current?.();\n }, [isControlled, setCapture]);\n\n /* ---- Focus management on phase transitions ---- */\n useEffect(() => {\n if (phase === 'captured' && !seededRef.current) {\n // Land the keyboard / SR user on the next logical action.\n confirmBtnRef.current?.focus();\n } else if (phase === 'error') {\n recoveryRef.current?.focus();\n } else if (phase === 'idle' && focusUseCameraRef.current) {\n // After a Retake, return focus to the capture entry point. Never on\n // the initial idle mount (the flag is only set by retake()).\n focusUseCameraRef.current = false;\n useCameraBtnRef.current?.focus();\n }\n }, [phase]);\n\n /* ---- Escape from streaming returns to idle and stops the stream ---- */\n useEffect(() => {\n if (phase !== 'streaming') return undefined;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n stopStream();\n setPhase('idle');\n }\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [phase, stopStream]);\n\n /* ---- Release the camera when the tab is hidden ---- */\n useEffect(() => {\n const onVisibility = () => {\n if (document.visibilityState === 'hidden' && streamRef.current) {\n stopStream();\n setPhase('idle');\n }\n };\n document.addEventListener('visibilitychange', onVisibility);\n return () =>\n document.removeEventListener('visibilitychange', onVisibility);\n }, [stopStream]);\n\n /* ---- Unmount cleanup: release the camera if still held ---- */\n useEffect(() => {\n return () => {\n unmountedRef.current = true;\n const held = streamRef.current;\n if (held) held.getTracks().forEach((track) => track.stop());\n streamRef.current = null;\n };\n }, []);\n\n /* ---- Sync controlled value → phase ---- */\n useEffect(() => {\n if (!isControlled) return;\n if (value != null) {\n setPhase('captured');\n } else if (phase === 'captured') {\n setPhase('idle');\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value, isControlled]);\n\n /* ---- Imperative handle + agent registration ---- */\n const agentHandle = useMemo<DocumentScannerHandle>(\n () => ({\n hasCapture: () => capture != null,\n getPhase: () => phase,\n startCamera: () => startCamera(),\n capture: () => capturePhoto(),\n confirm: () => confirm(),\n retake: () => retake(),\n }),\n [capture, phase, startCamera, capturePhoto, confirm, retake],\n );\n useImperativeHandle(ref, () => agentHandle, [agentHandle]);\n useAgentRegistration(documentScannerAgent, agentHandle, id);\n\n /* ---- Derived strings ---- */\n const regionLabel = ariaLabel ?? t('documentScanner.regionLabel');\n const hintText = t(HINT_KEY[documentType]);\n const maxSizeMb = Math.round(maxSize / (1024 * 1024));\n\n const statusText = (() => {\n if (decoding) return t('documentScanner.state.uploading');\n switch (phase) {\n case 'idle':\n return t('documentScanner.state.idle');\n case 'requesting':\n return t('documentScanner.state.requesting');\n case 'streaming':\n return t('documentScanner.state.streaming');\n case 'captured':\n return t('documentScanner.state.captured');\n case 'error':\n return errorKind\n ? t(ERROR_KEY[errorKind], { maxSizeMb })\n : t('documentScanner.error.captureFailed');\n }\n })();\n\n // A camera retry only makes sense for a hardware/permission failure —\n // not for upload-side rejections or an insecure (non-HTTPS) context.\n const canRetryCamera =\n !isUploadOnly &&\n errorKind !== 'file-invalid-type' &&\n errorKind !== 'file-too-large' &&\n errorKind !== 'insecure-context';\n\n // The upload affordance is always reachable: shown in idle/error for\n // auto + camera-only, primary in upload-only, and the recovery path on\n // any hard camera error.\n const showUploadFallback =\n !disabled &&\n (captureMode === 'auto' ||\n captureMode === 'upload-only' ||\n phase === 'error');\n\n const uploadAffordance = (\n <FileUpload\n variant=\"button\"\n accept={accept}\n maxSize={maxSize}\n multiple={false}\n maxFiles={1}\n disabled={disabled}\n showPreview={false}\n onDrop={(acceptedFiles) => {\n void handleUploadDrop(acceptedFiles);\n }}\n onReject={handleUploadReject}\n />\n );\n\n /* ---- Render ---- */\n const showViewport =\n phase === 'idle' ||\n phase === 'requesting' ||\n phase === 'streaming' ||\n phase === 'error';\n\n return (\n <div\n role=\"group\"\n aria-label={regionLabel}\n aria-disabled={disabled || undefined}\n className={[rootVariants({ size }), className]\n .filter(Boolean)\n .join(' ')}\n data-component=\"document-scanner\"\n data-component-id={id}\n data-phase={phase}\n >\n {/* Polite live region — announces every phase change to SR users. */}\n <span\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n className=\"ds:sr-only\"\n data-testid=\"document-scanner-live\"\n >\n {statusText}\n </span>\n\n {phase === 'captured' && capture ? (\n /* ---- Captured preview ---- */\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <div className={viewportVariants({ frame: documentType })}>\n <img\n src={capture.dataUrl}\n alt={t('documentScanner.previewAlt')}\n className={mediaVariants()}\n data-testid=\"document-scanner-preview\"\n />\n {seededRef.current ? (\n <span className=\"ds:absolute ds:top-[var(--spacing-sm)] ds:start-[var(--spacing-sm)] ds:rounded-[var(--radius-full)] ds:border ds:border-[color:color-mix(in_srgb,var(--foreground)_15%,transparent)] ds:bg-[var(--primary)] ds:text-[var(--primary-foreground)] ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:py-[var(--spacing-2xs)] type-meta\">\n {t('documentScanner.onFileBadge')}\n </span>\n ) : null}\n </div>\n <div className={controlBarVariants()}>\n <Button\n intent=\"secondary\"\n size=\"md\"\n // Button's md variant is h-10 (40px) with no min-target\n // compensation — pin to --min-target-size (44/48px) to clear\n // WCAG 2.5.5, matching SignatureCapture's action buttons.\n className=\"ds:[min-block-size:var(--min-target-size)] ds:[min-inline-size:var(--min-target-size)]\"\n startIcon={<RotateCcw aria-hidden=\"true\" />}\n onClick={retake}\n disabled={disabled}\n >\n {t('documentScanner.retake')}\n </Button>\n {/* Seeded \"already on file\" images need no Confirm — they are\n already persisted; the only action is Retake. */}\n {seededRef.current ? null : (\n <Button\n ref={confirmBtnRef}\n intent=\"primary\"\n size=\"md\"\n className=\"ds:[min-block-size:var(--min-target-size)] ds:[min-inline-size:var(--min-target-size)]\"\n startIcon={<Check aria-hidden=\"true\" />}\n onClick={confirm}\n disabled={disabled || capture == null}\n >\n {t('documentScanner.confirm')}\n </Button>\n )}\n </div>\n </div>\n ) : null}\n\n {showViewport ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n {/* Viewport — only meaningful while streaming/requesting; in\n idle/error it is a neutral placeholder behind the controls. */}\n {!isUploadOnly && phase !== 'error' ? (\n <div\n ref={viewportRef}\n className={viewportVariants({ frame: documentType })}\n aria-busy={phase === 'requesting' || undefined}\n >\n <video\n ref={videoRef}\n autoPlay\n playsInline\n muted\n aria-label={t('documentScanner.videoLabel')}\n className={mediaVariants()}\n onLoadedMetadata={handleVideoReady}\n onCanPlay={handleVideoReady}\n data-testid=\"document-scanner-video\"\n />\n {phase === 'requesting' ? (\n <div className=\"ds:absolute ds:inset-0 ds:flex ds:items-center ds:justify-center ds:bg-[color-mix(in_srgb,var(--foreground)_20%,transparent)]\">\n <LoaderCircle\n aria-hidden=\"true\"\n className=\"ds:size-8 ds:animate-spin ds:text-[var(--background)] ds:motion-reduce:animate-none\"\n />\n </div>\n ) : null}\n {/* Decorative alignment frame + corner guides. */}\n <div\n aria-hidden=\"true\"\n className={frameOverlayVariants()}\n data-testid=\"document-scanner-frame\"\n >\n <span\n className={[\n cornerVariants(),\n 'ds:top-0 ds:start-0 ds:border-t-2 ds:border-s-2 ds:rounded-ss-[var(--radius-sm)]',\n ].join(' ')}\n />\n <span\n className={[\n cornerVariants(),\n 'ds:top-0 ds:end-0 ds:border-t-2 ds:border-e-2 ds:rounded-se-[var(--radius-sm)]',\n ].join(' ')}\n />\n <span\n className={[\n cornerVariants(),\n 'ds:bottom-0 ds:start-0 ds:border-b-2 ds:border-s-2 ds:rounded-es-[var(--radius-sm)]',\n ].join(' ')}\n />\n <span\n className={[\n cornerVariants(),\n 'ds:bottom-0 ds:end-0 ds:border-b-2 ds:border-e-2 ds:rounded-ee-[var(--radius-sm)]',\n ].join(' ')}\n />\n </div>\n </div>\n ) : null}\n\n {phase === 'streaming' ? (\n <p id={hintId} className={hintVariants()}>\n {hintText}\n </p>\n ) : null}\n\n {/* Error block — Alert pattern with the upload recovery path. */}\n {phase === 'error' && errorKind ? (\n <Alert variant=\"error\" live=\"assertive\">\n <Alert.Description>\n {t(ERROR_KEY[errorKind], { maxSizeMb })}\n </Alert.Description>\n <Alert.Action>\n {/* The camera-retry button is the focus target on a\n hardware/permission error; for upload-side or\n insecure-context errors there is nothing to retry and\n the upload affordance is the recovery path. */}\n {canRetryCamera ? (\n <Button\n ref={recoveryRef}\n intent=\"secondary\"\n size=\"sm\"\n onClick={() => {\n void startCamera();\n }}\n disabled={disabled}\n >\n {t('documentScanner.retry')}\n </Button>\n ) : null}\n {showUploadFallback ? uploadAffordance : null}\n </Alert.Action>\n </Alert>\n ) : null}\n\n {/* Primary control bar (no hard error). */}\n {phase !== 'error' ? (\n <div className={controlBarVariants()}>\n {phase === 'streaming' ? (\n <Button\n ref={shutterBtnRef}\n intent=\"primary\"\n size=\"lg\"\n startIcon={<Camera aria-hidden=\"true\" />}\n onClick={() => {\n void capturePhoto();\n }}\n disabled={disabled || !streamReady}\n aria-describedby={hintId}\n aria-label={t('documentScanner.capture')}\n >\n {t('documentScanner.capture')}\n </Button>\n ) : null}\n\n {(phase === 'idle' || phase === 'requesting') &&\n !isUploadOnly ? (\n <Button\n ref={useCameraBtnRef}\n intent=\"primary\"\n size=\"md\"\n className=\"ds:[min-block-size:var(--min-target-size)] ds:[min-inline-size:var(--min-target-size)]\"\n loading={phase === 'requesting'}\n startIcon={<Camera aria-hidden=\"true\" />}\n onClick={() => {\n void startCamera();\n }}\n disabled={disabled}\n >\n {t('documentScanner.useCamera')}\n </Button>\n ) : null}\n\n {decoding ? (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] type-body-sm ds:text-[var(--muted-foreground)]\">\n <LoaderCircle\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:animate-spin ds:motion-reduce:animate-none\"\n />\n {t('documentScanner.state.uploading')}\n </span>\n ) : showUploadFallback && phase !== 'streaming' ? (\n uploadAffordance\n ) : null}\n\n {/* In streaming, upload stays reachable as a low-emphasis\n fallback below the shutter. */}\n {phase === 'streaming' && captureMode !== 'camera-only'\n ? uploadAffordance\n : null}\n </div>\n ) : null}\n </div>\n ) : null}\n </div>\n );\n },\n);\n\nDocumentScanner.displayName = 'DocumentScanner';\n\nexport {\n rootVariants as documentScannerRootVariants,\n viewportVariants as documentScannerViewportVariants,\n};\n"],"names":["documentScannerAgent","handle","rootVariants","cva","viewportVariants","mediaVariants","frameOverlayVariants","cornerVariants","controlBarVariants","hintVariants","toHex","bytes","out","i","sha256Hex","buffer","g","_a","copy","digest","classifyMediaError","err","name","mediaDevicesAvailable","HINT_KEY","ERROR_KEY","DocumentScanner","forwardRef","id","value","defaultValue","onConfirm","onRetake","onError","documentType","captureMode","accept","maxSize","facingMode","outputType","outputQuality","cropToFrame","disabled","size","ariaLabel","className","ref","t","useTranslation","hintId","useId","capture","setCapture","useControllableState","seededRef","useRef","phase","setPhase","useState","errorKind","setErrorKind","streamReady","setStreamReady","decoding","setDecoding","videoRef","viewportRef","streamRef","unmountedRef","confirmBtnRef","shutterBtnRef","useCameraBtnRef","recoveryRef","onErrorRef","onConfirmRef","onRetakeRef","useEffect","isControlled","isUploadOnly","stopStream","useCallback","held","track","video","reportError","kind","startCamera","stream","playResult","handleVideoReady","interval","stopAfter","capturePhoto","vw","vh","sx","sy","sw","sh","insetX","insetY","canvas","ctx","blob","resolve","b","dataUrl","arrayBuffer","sha256","next","handleUploadDrop","accepted","file","objectUrl","dimensions","reject","img","reader","handleUploadReject","rejections","confirm","focusUseCameraRef","retake","_b","_c","onKeyDown","event","onVisibility","agentHandle","useMemo","useImperativeHandle","useAgentRegistration","regionLabel","hintText","maxSizeMb","statusText","canRetryCamera","showUploadFallback","uploadAffordance","jsx","FileUpload","acceptedFiles","showViewport","jsxs","Button","RotateCcw","Check","LoaderCircle","Alert","Camera"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editable-currency-cell-renderer-Dus_sBvX.js","sources":["../../node_modules/lucide-react/dist/esm/icons/arrow-down.mjs","../../node_modules/lucide-react/dist/esm/icons/arrow-up.mjs","../../src/components/data-table/hooks/use-total-row.ts","../../src/components/data-table/cell-renderers/tooth-cell-renderer.tsx","../../src/components/data-table/cell-renderers/reorder-cell-renderer.tsx","../../src/components/data-table/cell-renderers/toggle-cell-renderer.tsx","../../src/components/data-table/cell-renderers/color-dot-cell-renderer.tsx","../../src/components/data-table/cell-renderers/balance-cell-renderer.tsx","../../src/components/data-table/cell-renderers/editable-text-cell-renderer.tsx","../../src/components/data-table/cell-renderers/editable-currency-cell-renderer.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 5v14\", key: \"s699le\" }],\n [\"path\", { d: \"m19 12-7 7-7-7\", key: \"1idqje\" }]\n];\nconst ArrowDown = createLucideIcon(\"arrow-down\", __iconNode);\n\nexport { __iconNode, ArrowDown as default };\n//# sourceMappingURL=arrow-down.mjs.map\n","/**\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: \"m5 12 7-7 7 7\", key: \"hav0vg\" }],\n [\"path\", { d: \"M12 19V5\", key: \"x0mq9r\" }]\n];\nconst ArrowUp = createLucideIcon(\"arrow-up\", __iconNode);\n\nexport { __iconNode, ArrowUp as default };\n//# sourceMappingURL=arrow-up.mjs.map\n","import { useMemo } from 'react';\n\n/**\n * Compute a pinned total row from a dataset and a list of numeric fields.\n *\n * The returned object is structurally a `TData` with non-summed fields left\n * `undefined` — plug it into `pinnedBottomRowData={[totalRow]}`. Cell renderers\n * in the non-summed columns receive `undefined`, so they should render nothing\n * (all of the DS cell renderers short-circuit on `null`/`undefined`).\n *\n * Pass an optional `labelField` + `labelValue` to show a static caption such\n * as \"Total\" in the first column of the pinned row.\n */\nexport function useTotalRow<TData>(\n rowData: TData[] | undefined,\n sumFields: Array<keyof TData & string>,\n options?: {\n labelField?: keyof TData & string;\n labelValue?: string;\n },\n): TData {\n return useMemo(() => {\n const row: Record<string, unknown> = {};\n\n for (const field of sumFields) {\n let total = 0;\n for (const r of rowData ?? []) {\n const raw = (r as Record<string, unknown>)[field];\n const n = typeof raw === 'number' ? raw : Number(raw);\n if (Number.isFinite(n)) total += n;\n }\n row[field] = total;\n }\n\n if (options?.labelField && options.labelValue !== undefined) {\n row[options.labelField] = options.labelValue;\n }\n\n return row as TData;\n }, [rowData, sumFields, options?.labelField, options?.labelValue]);\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Tag } from '../../tag/tag';\n\n// Tooth glyph — lucide ships no dental icon, so this is a small inline tooth\n// (a crown narrowing to two roots) tinted with `currentColor`, so it inherits\n// the Tag's text colour. Decorative; the FDI numbers are the accessible label.\nfunction ToothIcon() {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.75}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className=\"ds:size-3.5\"\n >\n <path d=\"M12 5.5c-1.074 -1.426 -2.45 -2.2 -4 -2c-2.5 .323 -3.7 2.5 -3.5 5c.1 1.5 .5 3 .5 4.5c0 1.5 .5 3.5 1 5c.3 .9 .5 2 1.5 2s1.3 -1.5 1.5 -2.5c.2 -1 .5 -2 1.5 -2s1.3 1 1.5 2c.2 1 .5 2.5 1.5 2.5s1.2 -1.1 1.5 -2c.5 -1.5 1 -3.5 1 -5c0 -1.5 .4 -3 .5 -4.5c.2 -2.5 -1 -4.677 -3.5 -5c-1.55 -.2 -2.926 .574 -4 2z\" />\n </svg>\n );\n}\n\nexport interface ToothCellRendererParams {\n /** Max inline size of the chip before its label truncates (with a tooltip). */\n maxInlineSize?: string;\n}\n\n/**\n * Renders an array of tooth ids (FDI notation) as a single outlined Tag — the\n * teeth comma-separated and prefixed with a tooth glyph, so dentition reads at\n * a glance instead of as bare numbers.\n */\nexport function ToothCellRenderer(\n props: CustomCellRendererProps<unknown, string[]> & ToothCellRendererParams,\n) {\n const { value, maxInlineSize = '8rem' } = props;\n if (!Array.isArray(value) || value.length === 0) return null;\n\n return (\n <Tag\n label={value.join(', ')}\n size=\"sm\"\n fill=\"outline\"\n leading={<ToothIcon />}\n maxInlineSize={maxInlineSize}\n />\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\nimport { ArrowUp, ArrowDown } from 'lucide-react';\nimport { IconButton } from '../../button/icon-button';\nimport { IconButtonGroup } from '../../icon-button-group';\n\n/**\n * Keyboard-accessible row-reorder cell. AG Grid's native row dragging is\n * mouse/touch only; this renderer adds move-up / move-down buttons so the order\n * is reachable by keyboard too (the missing accessible half of the\n * \"drag-sortable column\" primitive). The consumer owns `rowData` order and\n * reorders it in `onMove` — the same controlled contract as the editable cells.\n */\nexport interface ReorderCellRendererParams<TData = unknown> {\n /** Move the row one step in the given direction (consumer reorders rowData). */\n onMove: (data: TData, direction: 'up' | 'down') => void;\n /** Accessible name for the move-up button (defaults to a kit string). */\n moveUpLabel?: string;\n /** Accessible name for the move-down button (defaults to a kit string). */\n moveDownLabel?: string;\n /** Button intent (default `ghost`). */\n intent?: 'ghost' | 'outline';\n /** Render the two buttons as a connected `IconButtonGroup` (default true). */\n group?: boolean;\n /**\n * Disable move-up on the first displayed row and move-down on the last\n * (default true). Turn off when the grid is filtered/sorted and the ends are\n * not meaningful.\n */\n disableAtEnds?: boolean;\n}\n\n/**\n * Pixel width a reorder column needs for the two `sm` IconButtons (32px each)\n * plus the data-table cell's inline padding so the controls never clip. Mirrors\n * {@link actionsColumnWidth}.\n */\nexport function reorderColumnWidth(): number {\n const SM_BUTTON = 32;\n const CELL_INSET = 26;\n return SM_BUTTON * 2 + CELL_INSET;\n}\n\nexport function ReorderCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & ReorderCellRendererParams<TData>,\n) {\n const {\n data,\n node,\n api,\n onMove,\n moveUpLabel,\n moveDownLabel,\n intent = 'ghost',\n group = true,\n disableAtEnds = true,\n } = props;\n const { t } = useTranslation();\n if (!data) return null;\n\n const rowIndex = node.rowIndex ?? -1;\n const lastIndex = api.getDisplayedRowCount() - 1;\n const atFirst = disableAtEnds && rowIndex <= 0;\n const atLast = disableAtEnds && rowIndex >= lastIndex;\n\n const upLabel = moveUpLabel ?? t('dataTable.moveUp', 'Move up');\n const downLabel = moveDownLabel ?? t('dataTable.moveDown', 'Move down');\n\n // An ARRAY of IconButtons (not a Fragment): IconButtonGroup inspects its\n // direct children and rejects anything that isn't a DS IconButton.\n const buttons = [\n <IconButton\n key=\"up\"\n size=\"sm\"\n intent={intent}\n icon={<ArrowUp aria-hidden className=\"ds:size-4\" />}\n tooltip={upLabel}\n aria-label={upLabel}\n disabled={atFirst}\n onClick={(event) => {\n event.stopPropagation();\n onMove(data, 'up');\n }}\n />,\n <IconButton\n key=\"down\"\n size=\"sm\"\n intent={intent}\n icon={<ArrowDown aria-hidden className=\"ds:size-4\" />}\n tooltip={downLabel}\n aria-label={downLabel}\n disabled={atLast}\n onClick={(event) => {\n event.stopPropagation();\n onMove(data, 'down');\n }}\n />,\n ];\n\n return group ? (\n <IconButtonGroup\n aria-label={t('dataTable.reorder', 'Reorder row')}\n size=\"sm\"\n >\n {buttons}\n </IconButtonGroup>\n ) : (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n {buttons}\n </span>\n );\n}\n","import { useState, type ReactNode } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { CheckSquare, Square } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\n\nexport interface ToggleCellRendererParams<TData = unknown> {\n /**\n * Fires with the row and the new target value. May return a `Promise` —\n * if it rejects, the consumer is expected to revert the underlying value\n * and flash the row with `data-table-row-error` (return that row class\n * from `getRowClass`). Use `onError` below to be notified inside this\n * renderer.\n */\n onToggle: (data: TData, newValue: boolean) => void | Promise<void>;\n /**\n * Optional reject hook. Fires when the `onToggle` promise rejects, with\n * the row and the error. The button auto-disables during the in-flight\n * promise and re-enables on either settle.\n */\n onError?: (data: TData, error: unknown) => void;\n /** Icon shown when the current value is truthy. */\n trueIcon?: ReactNode;\n /** Icon shown when the current value is falsy. */\n falseIcon?: ReactNode;\n /** Extra classes applied to the \"on\" icon — defaults to success token. */\n trueClass?: string;\n /** Extra classes applied to the \"off\" icon. */\n falseClass?: string;\n /** Accessible label. Falls back to the default on/off announcements. */\n label?: string;\n}\n\nexport function ToggleCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData, boolean> &\n ToggleCellRendererParams<TData>,\n) {\n const {\n value,\n data,\n onToggle,\n onError,\n trueIcon,\n falseIcon,\n trueClass = 'ds:text-[color:var(--success)]',\n falseClass = 'ds:text-[color:var(--muted-foreground)]',\n label,\n } = props;\n const { t } = useTranslation();\n const [pending, setPending] = useState(false);\n if (!data) return null;\n\n const isOn = Boolean(value);\n const icon = isOn\n ? (trueIcon ?? <CheckSquare aria-hidden className=\"ds:size-4\" />)\n : (falseIcon ?? <Square aria-hidden className=\"ds:size-4\" />);\n const stateClass = isOn ? trueClass : falseClass;\n const resolvedLabel =\n label ?? (isOn ? t('inputs.switch.on') : t('inputs.switch.off'));\n\n async function handleClick(event: React.MouseEvent) {\n event.stopPropagation();\n if (pending || !data) return;\n const next = !isOn;\n const result = onToggle(data, next);\n if (result && typeof (result as Promise<void>).then === 'function') {\n setPending(true);\n try {\n await result;\n } catch (err) {\n onError?.(data, err);\n } finally {\n setPending(false);\n }\n }\n }\n\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={isOn}\n aria-busy={pending}\n aria-label={resolvedLabel}\n disabled={pending}\n onClick={handleClick}\n className={[\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:min-h-[var(--min-target-size)] ds:min-w-[var(--min-target-size)]',\n 'ds:appearance-none ds:bg-transparent ds:p-[var(--spacing-xs)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:disabled:opacity-50',\n stateClass,\n ].join(' ')}\n >\n {icon}\n </button>\n );\n}\n","import { useRef } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useIsomorphicLayoutEffect } from '../../../hooks/use-isomorphic-layout-effect';\n\nexport interface ColorDotCellRendererParams {\n /** Field name on the row whose value holds the hex color. */\n colorField: string;\n /** Visual size of the dot. */\n size?: 'sm' | 'md' | 'lg';\n /** Optional label shown next to the dot. */\n labelField?: string;\n}\n\nconst SIZE_CLASS: Record<\n NonNullable<ColorDotCellRendererParams['size']>,\n string\n> = {\n sm: 'ds:size-[var(--icon-size-sm)]',\n md: 'ds:size-[var(--icon-size-md)]',\n lg: 'ds:size-[var(--icon-size-lg)]',\n};\n\nfunction readField(row: unknown, field: string): string | undefined {\n if (!row || typeof row !== 'object') return undefined;\n const value = (row as Record<string, unknown>)[field];\n return typeof value === 'string' ? value : undefined;\n}\n\n// Only accept trusted CSS color forms. Anything outside this allow-list\n// (including smuggled `url()` or extra declarations) is dropped so the\n// CSS custom-property writer can't be used to inject styles.\nconst HEX_RE = /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;\nconst RGB_RE = /^rgba?\\(\\s*[\\d.\\s,%/]+\\)$/i;\nconst HSL_RE = /^hsla?\\(\\s*[\\d.\\s,%/]+\\)$/i;\nconst CSS_VAR_RE = /^var\\(--[a-z0-9-]+(?:,\\s*[^)]+)?\\)$/i;\n\nfunction sanitizeColor(raw: string | undefined): string | undefined {\n if (!raw) return undefined;\n const v = raw.trim();\n if (\n HEX_RE.test(v) ||\n RGB_RE.test(v) ||\n HSL_RE.test(v) ||\n CSS_VAR_RE.test(v)\n ) {\n return v;\n }\n return undefined;\n}\n\nexport function ColorDotCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & ColorDotCellRendererParams,\n) {\n const { data, colorField, size = 'md', labelField } = props;\n const dotRef = useRef<HTMLSpanElement | null>(null);\n const rawColor = data ? readField(data, colorField) : undefined;\n const color = sanitizeColor(rawColor);\n const label = data && labelField ? readField(data, labelField) : undefined;\n\n // Apply the dynamic color via a CSS custom property on the element.\n // Keeps hex/rgb literals out of JSX (constraint #2 and #4). The data\n // itself drives the color — constraints only forbid hardcoded colors\n // in component source, not in consumer row data.\n useIsomorphicLayoutEffect(() => {\n const el = dotRef.current;\n if (!el) return;\n if (color) {\n el.style.setProperty('--data-table-dot-color', color);\n } else {\n el.style.removeProperty('--data-table-dot-color');\n }\n }, [color]);\n\n if (!color) return null;\n\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <span\n ref={dotRef}\n aria-hidden=\"true\"\n className={[\n 'ds:inline-block ds:shrink-0 ds:rounded-[var(--radius-full)]',\n 'ds:bg-[var(--data-table-dot-color)]',\n 'ds:border ds:border-[color:var(--border)]',\n SIZE_CLASS[size],\n ].join(' ')}\n />\n {label ? <span>{label}</span> : null}\n </span>\n );\n}\n","import type { ColDef } from 'ag-grid-community';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\n\nexport interface BalanceLine {\n /** User-visible label for this line. */\n label: string;\n /** Field name on the row whose numeric value is rendered. */\n valueField: string;\n /** `'currency'` renders via Intl, `'percent'` appends `%`, `'number'` raw. Default `'number'`. */\n format?: 'currency' | 'percent' | 'number';\n}\n\nexport interface BalanceCellRendererParams {\n lines: BalanceLine[];\n /** ISO 4217 code, used by `currency`-formatted lines. Default `'EUR'`. */\n currency?: string;\n /** Apply destructive color to negative values. */\n highlightNegative?: boolean;\n}\n\nfunction readNumber(row: unknown, field: string): number | null {\n if (!row || typeof row !== 'object') return null;\n const raw = (row as Record<string, unknown>)[field];\n const n = typeof raw === 'number' ? raw : Number(raw);\n return Number.isFinite(n) ? n : null;\n}\n\n/**\n * Renders a compact set of label / value pairs inside a single AG Grid cell.\n *\n * Layout is **horizontal** with middle-dot separators so the cell fits\n * inside the default AG Grid row height without spilling into the row\n * below. Use the SALDI / Listini patterns (Totale · Incassato · Da Incassare)\n * as the canonical example.\n *\n * If a consumer's content wraps (long localized labels, narrow columns)\n * they can opt into row auto-growth by spreading\n * {@link balanceCellRendererColDefDefaults} onto the column definition.\n */\nexport function BalanceCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & BalanceCellRendererParams,\n) {\n const { data, lines, currency = 'EUR', highlightNegative } = props;\n const { i18n } = useTranslation();\n if (!data) return null;\n\n const locale = i18n.language || 'en';\n\n const formatLine = (\n line: BalanceLine,\n ): { label: string; formatted: string; negative: boolean } | null => {\n const n = readNumber(data, line.valueField);\n if (n === null) return null;\n\n let formatted: string;\n switch (line.format ?? 'number') {\n case 'currency':\n formatted = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n }).format(n);\n break;\n case 'percent':\n formatted = new Intl.NumberFormat(locale, {\n style: 'percent',\n maximumFractionDigits: 1,\n }).format(n / 100);\n break;\n default:\n formatted = new Intl.NumberFormat(locale).format(n);\n }\n\n return {\n label: line.label,\n formatted,\n negative: Boolean(highlightNegative) && n < 0,\n };\n };\n\n const rendered = lines\n .map(formatLine)\n .filter(\n (x): x is { label: string; formatted: string; negative: boolean } =>\n x !== null,\n );\n if (rendered.length === 0) return null;\n\n return (\n <div\n className={[\n 'ds:flex',\n 'ds:flex-wrap',\n 'ds:items-center',\n 'ds:gap-x-[var(--spacing-sm)]',\n 'ds:gap-y-0',\n 'type-meta',\n 'ds:leading-tight',\n ].join(' ')}\n >\n {rendered.map((item, idx) => (\n <span\n key={`${item.label}-${idx}`}\n className=\"ds:inline-flex ds:items-baseline ds:gap-x-[var(--spacing-xs)]\"\n >\n {idx > 0 ? (\n <span\n aria-hidden=\"true\"\n className=\"ds:me-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\"\n >\n ·\n </span>\n ) : null}\n <span className=\"ds:text-[color:var(--muted-foreground)]\">\n {item.label}\n </span>\n <span\n className={[\n 'ds:tabular-nums',\n 'ds:font-medium',\n item.negative ? 'ds:text-[color:var(--destructive)]' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {item.formatted}\n </span>\n </span>\n ))}\n </div>\n );\n}\n\n/**\n * Column-definition defaults consumers can spread onto a `ColDef` when they\n * want the renderer's wrapped / multi-line behaviour to grow the row.\n *\n * The default compact horizontal layout is engineered to fit the standard\n * AG Grid row height, so this opt-in is only needed when a long label set\n * wraps across two or more lines and the consumer would rather grow the\n * row than wrap silently.\n *\n * AG Grid does NOT auto-grow row height to fit a tall cell unless\n * `autoHeight` and `wrapText` are set on the colDef itself — a cell\n * renderer can't impose that from inside.\n *\n * @example\n * ```ts\n * {\n * headerName: 'Saldi',\n * cellRenderer: BalanceCellRenderer,\n * cellRendererParams: { lines, currency: 'EUR' },\n * ...balanceCellRendererColDefDefaults,\n * }\n * ```\n */\nexport const balanceCellRendererColDefDefaults: Readonly<\n Pick<ColDef, 'autoHeight' | 'wrapText'>\n> = {\n autoHeight: true,\n wrapText: true,\n};\n","import { useEffect, useRef, useState } from 'react';\nimport type { CustomCellEditorProps } from 'ag-grid-react';\nimport {\n INPUT_SURFACE_CHROME,\n INPUT_SURFACE_HEIGHT,\n INPUT_SURFACE_PADDING_X,\n INPUT_SURFACE_TEXT,\n} from '../../_shared/input-surface';\n\n/**\n * Inline text editor that visually matches `<TextInput size=\"sm\">`. Use as\n * `cellEditor` on a colDef with `editable: true`. The cell renderer (default\n * or custom) takes over again once editing stops.\n *\n * AG Grid commits on Enter or Tab or blur; cancels on Escape. The consumer\n * receives the committed value via `onCellValueChanged`.\n */\nexport function EditableTextCellRenderer<TData = unknown>(\n props: CustomCellEditorProps<TData, string>,\n) {\n const { initialValue, onValueChange, stopEditing, column } = props;\n const [value, setValue] = useState<string>(initialValue ?? '');\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Focus + select on mount so typing replaces the current value.\n useEffect(() => {\n const el = inputRef.current;\n if (!el) return;\n el.focus();\n el.select();\n }, []);\n\n // The current value is pushed to AG Grid via `onValueChange` on every\n // keystroke — AG Grid commits the most recent value when editing stops.\n // No `useGridCellEditor` hook needed for that contract.\n\n // Thread the column header into the input's accessible name so screen\n // readers announce \"Edit text, {column}\" instead of an unlabelled input.\n // AG Grid doesn't auto-wire the column header to cell editors.\n const headerName =\n (column?.getColDef?.()?.headerName as string | undefined) ?? undefined;\n\n return (\n <input\n ref={inputRef}\n type=\"text\"\n value={value}\n aria-label={headerName}\n onChange={(e) => {\n const next = e.target.value;\n setValue(next);\n onValueChange(next);\n }}\n onKeyDown={(e) => {\n // Escape cancels, Enter/Tab commit — AG Grid handles both, but we\n // explicitly stop editing on Enter so the consumer sees the commit\n // immediately rather than waiting for the next focus blur.\n if (e.key === 'Enter') {\n e.preventDefault();\n stopEditing();\n }\n }}\n className={[\n 'ds:block ds:w-full ds:appearance-none',\n // Input surface chrome: rounded border + bg + focus halo.\n INPUT_SURFACE_CHROME,\n // Use the `md` height (`--min-target-size`) so the input\n // auto-lifts to 48px under `.theme-accessible` to satisfy\n // WCAG 2.5.5 target size.\n INPUT_SURFACE_HEIGHT.md,\n INPUT_SURFACE_TEXT.sm,\n INPUT_SURFACE_PADDING_X.sm,\n ].join(' ')}\n />\n );\n}\n","import { useEffect, useRef, useState } from 'react';\nimport type { CustomCellEditorProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\nimport {\n INPUT_SURFACE_CHROME,\n INPUT_SURFACE_HEIGHT,\n INPUT_SURFACE_PADDING_X,\n INPUT_SURFACE_TEXT,\n} from '../../_shared/input-surface';\n\nexport interface EditableCurrencyCellEditorParams {\n /** ISO 4217 currency code (e.g. `EUR`, `USD`). Defaults to `EUR`. */\n currency?: string;\n /** Decimal places allowed in the editor. Defaults to 2 (cents precision). */\n decimals?: number;\n /** Minimum allowed value — values below this are clamped on commit. */\n min?: number;\n /** Maximum allowed value — values above this are clamped on commit. */\n max?: number;\n}\n\n/**\n * Inline numeric editor that visually matches `<TextInput size=\"sm\">`. Use as\n * `cellEditor` on a colDef with `editable: true`. The display formatting is\n * still the renderer's job — once editing stops, the cell hands back to\n * `CurrencyCellRenderer` (or whichever renderer the colDef declares).\n *\n * Stores a Number, not a string, so consumers receive `row.amount = 12.5`\n * not `\"12.5\"`. Strips locale separators on each change so commas/dots in\n * any language convert to a clean numeric value.\n */\nexport function EditableCurrencyCellRenderer<TData = unknown>(\n props: CustomCellEditorProps<TData, number> &\n EditableCurrencyCellEditorParams,\n) {\n const {\n initialValue,\n onValueChange,\n stopEditing,\n column,\n decimals = 2,\n min,\n max,\n } = props;\n const { i18n } = useTranslation();\n const inputRef = useRef<HTMLInputElement | null>(null);\n // Thread the column header into the input's accessible name — see\n // editable-text-cell-renderer.tsx for the rationale.\n const headerName =\n (column?.getColDef?.()?.headerName as string | undefined) ?? undefined;\n\n // Local string state so the user can type intermediate values like \"12.\"\n // before the trailing zero arrives. We commit a Number to AG Grid on each\n // change for consumers that watch row state live; the final commit fires\n // when editing stops.\n const [draft, setDraft] = useState<string>(() => {\n if (initialValue == null || Number.isNaN(initialValue)) return '';\n return String(initialValue);\n });\n\n useEffect(() => {\n const el = inputRef.current;\n if (!el) return;\n el.focus();\n el.select();\n }, []);\n\n function parseDraft(input: string): number | null {\n if (input.trim().length === 0) return null;\n // Accept either the user's locale decimal separator or a `.`. Strip\n // grouping characters (locale thousands separators, plus spaces).\n const lang = i18n.language || 'en';\n const partsFmt = new Intl.NumberFormat(lang).formatToParts(12345.6);\n const groupChar = partsFmt.find((p) => p.type === 'group')?.value ?? '';\n const decimalChar =\n partsFmt.find((p) => p.type === 'decimal')?.value ?? '.';\n const cleaned = input\n .replace(new RegExp(`\\\\${groupChar}`, 'g'), '')\n .replace(decimalChar, '.')\n .replace(/[^\\d.-]/g, '');\n const n = Number(cleaned);\n return Number.isFinite(n) ? n : null;\n }\n\n function commit(input: string) {\n const parsed = parseDraft(input);\n if (parsed == null) {\n onValueChange(null);\n return;\n }\n // Clamp first, then round to the declared precision so we never\n // persist floating-point dust from string parsing.\n let clamped = parsed;\n if (typeof min === 'number') clamped = Math.max(min, clamped);\n if (typeof max === 'number') clamped = Math.min(max, clamped);\n const factor = 10 ** decimals;\n onValueChange(Math.round(clamped * factor) / factor);\n }\n\n return (\n <input\n ref={inputRef}\n type=\"text\"\n // Inputmode hints mobile keyboards to show the decimal pad instead\n // of the full keyboard. type=\"number\" would also work but spinners\n // and locale parsing are inconsistent across browsers.\n inputMode=\"decimal\"\n value={draft}\n aria-label={headerName}\n onChange={(e) => {\n const next = e.target.value;\n setDraft(next);\n commit(next);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n stopEditing();\n }\n // Escape — AG Grid cancels by default; the editor doesn't need\n // explicit handling beyond what AG Grid wires automatically.\n }}\n className={[\n 'ds:block ds:w-full ds:appearance-none ds:text-end ds:tabular-nums',\n INPUT_SURFACE_CHROME,\n // Use `md` height — see editable-text-cell-renderer for rationale.\n INPUT_SURFACE_HEIGHT.md,\n INPUT_SURFACE_TEXT.sm,\n INPUT_SURFACE_PADDING_X.sm,\n ].join(' ')}\n />\n );\n}\n"],"names":["__iconNode","ArrowDown","createLucideIcon","ArrowUp","useTotalRow","rowData","sumFields","options","useMemo","row","field","total","r","raw","n","ToothIcon","jsx","ToothCellRenderer","props","value","maxInlineSize","Tag","reorderColumnWidth","ReorderCellRenderer","data","node","api","onMove","moveUpLabel","moveDownLabel","intent","group","disableAtEnds","t","useTranslation","rowIndex","lastIndex","atFirst","atLast","upLabel","downLabel","buttons","IconButton","event","IconButtonGroup","ToggleCellRenderer","onToggle","onError","trueIcon","falseIcon","trueClass","falseClass","label","pending","setPending","useState","isOn","icon","CheckSquare","Square","stateClass","resolvedLabel","handleClick","result","err","SIZE_CLASS","readField","HEX_RE","RGB_RE","HSL_RE","CSS_VAR_RE","sanitizeColor","v","ColorDotCellRenderer","colorField","size","labelField","dotRef","useRef","rawColor","color","useIsomorphicLayoutEffect","el","jsxs","readNumber","BalanceCellRenderer","lines","currency","highlightNegative","i18n","locale","formatLine","line","formatted","rendered","x","item","idx","EditableTextCellRenderer","initialValue","onValueChange","stopEditing","column","setValue","inputRef","useEffect","headerName","_b","_a","e","next","INPUT_SURFACE_CHROME","INPUT_SURFACE_HEIGHT","INPUT_SURFACE_TEXT","INPUT_SURFACE_PADDING_X","EditableCurrencyCellRenderer","decimals","min","max","draft","setDraft","parseDraft","input","lang","partsFmt","groupChar","p","decimalChar","cleaned","commit","parsed","clamped","factor"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
1
|
+
{"version":3,"file":"editable-currency-cell-renderer-Dus_sBvX.js","sources":["../../node_modules/lucide-react/dist/esm/icons/arrow-down.mjs","../../node_modules/lucide-react/dist/esm/icons/arrow-up.mjs","../../src/components/data-table/hooks/use-total-row.ts","../../src/components/data-table/cell-renderers/tooth-cell-renderer.tsx","../../src/components/data-table/cell-renderers/reorder-cell-renderer.tsx","../../src/components/data-table/cell-renderers/toggle-cell-renderer.tsx","../../src/components/data-table/cell-renderers/color-dot-cell-renderer.tsx","../../src/components/data-table/cell-renderers/balance-cell-renderer.tsx","../../src/components/data-table/cell-renderers/editable-text-cell-renderer.tsx","../../src/components/data-table/cell-renderers/editable-currency-cell-renderer.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 5v14\", key: \"s699le\" }],\n [\"path\", { d: \"m19 12-7 7-7-7\", key: \"1idqje\" }]\n];\nconst ArrowDown = createLucideIcon(\"arrow-down\", __iconNode);\n\nexport { __iconNode, ArrowDown as default };\n//# sourceMappingURL=arrow-down.mjs.map\n","/**\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: \"m5 12 7-7 7 7\", key: \"hav0vg\" }],\n [\"path\", { d: \"M12 19V5\", key: \"x0mq9r\" }]\n];\nconst ArrowUp = createLucideIcon(\"arrow-up\", __iconNode);\n\nexport { __iconNode, ArrowUp as default };\n//# sourceMappingURL=arrow-up.mjs.map\n","import { useMemo } from 'react';\n\n/**\n * Compute a pinned total row from a dataset and a list of numeric fields.\n *\n * The returned object is structurally a `TData` with non-summed fields left\n * `undefined` — plug it into `pinnedBottomRowData={[totalRow]}`. Cell renderers\n * in the non-summed columns receive `undefined`, so they should render nothing\n * (all of the DS cell renderers short-circuit on `null`/`undefined`).\n *\n * Pass an optional `labelField` + `labelValue` to show a static caption such\n * as \"Total\" in the first column of the pinned row.\n */\nexport function useTotalRow<TData>(\n rowData: TData[] | undefined,\n sumFields: Array<keyof TData & string>,\n options?: {\n labelField?: keyof TData & string;\n labelValue?: string;\n },\n): TData {\n return useMemo(() => {\n const row: Record<string, unknown> = {};\n\n for (const field of sumFields) {\n let total = 0;\n for (const r of rowData ?? []) {\n const raw = (r as Record<string, unknown>)[field];\n const n = typeof raw === 'number' ? raw : Number(raw);\n if (Number.isFinite(n)) total += n;\n }\n row[field] = total;\n }\n\n if (options?.labelField && options.labelValue !== undefined) {\n row[options.labelField] = options.labelValue;\n }\n\n return row as TData;\n }, [rowData, sumFields, options?.labelField, options?.labelValue]);\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Tag } from '../../tag/tag';\n\n// Tooth glyph — lucide ships no dental icon, so this is a small inline tooth\n// (a crown narrowing to two roots) tinted with `currentColor`, so it inherits\n// the Tag's text colour. Decorative; the FDI numbers are the accessible label.\nfunction ToothIcon() {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.75}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className=\"ds:size-3.5\"\n >\n <path d=\"M12 5.5c-1.074 -1.426 -2.45 -2.2 -4 -2c-2.5 .323 -3.7 2.5 -3.5 5c.1 1.5 .5 3 .5 4.5c0 1.5 .5 3.5 1 5c.3 .9 .5 2 1.5 2s1.3 -1.5 1.5 -2.5c.2 -1 .5 -2 1.5 -2s1.3 1 1.5 2c.2 1 .5 2.5 1.5 2.5s1.2 -1.1 1.5 -2c.5 -1.5 1 -3.5 1 -5c0 -1.5 .4 -3 .5 -4.5c.2 -2.5 -1 -4.677 -3.5 -5c-1.55 -.2 -2.926 .574 -4 2z\" />\n </svg>\n );\n}\n\nexport interface ToothCellRendererParams {\n /** Max inline size of the chip before its label truncates (with a tooltip). */\n maxInlineSize?: string;\n}\n\n/**\n * Renders an array of tooth ids (FDI notation) as a single outlined Tag — the\n * teeth comma-separated and prefixed with a tooth glyph, so dentition reads at\n * a glance instead of as bare numbers.\n */\nexport function ToothCellRenderer(\n props: CustomCellRendererProps<unknown, string[]> & ToothCellRendererParams,\n) {\n const { value, maxInlineSize = '8rem' } = props;\n if (!Array.isArray(value) || value.length === 0) return null;\n\n return (\n <Tag\n label={value.join(', ')}\n size=\"sm\"\n fill=\"outline\"\n leading={<ToothIcon />}\n maxInlineSize={maxInlineSize}\n />\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\nimport { ArrowUp, ArrowDown } from 'lucide-react';\nimport { IconButton } from '../../button/icon-button';\nimport { IconButtonGroup } from '../../icon-button-group';\n\n/**\n * Keyboard-accessible row-reorder cell. AG Grid's native row dragging is\n * mouse/touch only; this renderer adds move-up / move-down buttons so the order\n * is reachable by keyboard too (the missing accessible half of the\n * \"drag-sortable column\" primitive). The consumer owns `rowData` order and\n * reorders it in `onMove` — the same controlled contract as the editable cells.\n */\nexport interface ReorderCellRendererParams<TData = unknown> {\n /** Move the row one step in the given direction (consumer reorders rowData). */\n onMove: (data: TData, direction: 'up' | 'down') => void;\n /** Accessible name for the move-up button (defaults to a kit string). */\n moveUpLabel?: string;\n /** Accessible name for the move-down button (defaults to a kit string). */\n moveDownLabel?: string;\n /** Button intent (default `ghost`). */\n intent?: 'ghost' | 'outline';\n /** Render the two buttons as a connected `IconButtonGroup` (default true). */\n group?: boolean;\n /**\n * Disable move-up on the first displayed row and move-down on the last\n * (default true). Turn off when the grid is filtered/sorted and the ends are\n * not meaningful.\n */\n disableAtEnds?: boolean;\n}\n\n/**\n * Pixel width a reorder column needs for the two `sm` IconButtons (32px each)\n * plus the data-table cell's inline padding so the controls never clip. Mirrors\n * {@link actionsColumnWidth}.\n */\nexport function reorderColumnWidth(): number {\n const SM_BUTTON = 32;\n const CELL_INSET = 26;\n return SM_BUTTON * 2 + CELL_INSET;\n}\n\nexport function ReorderCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & ReorderCellRendererParams<TData>,\n) {\n const {\n data,\n node,\n api,\n onMove,\n moveUpLabel,\n moveDownLabel,\n intent = 'ghost',\n group = true,\n disableAtEnds = true,\n } = props;\n const { t } = useTranslation();\n if (!data) return null;\n\n const rowIndex = node.rowIndex ?? -1;\n const lastIndex = api.getDisplayedRowCount() - 1;\n const atFirst = disableAtEnds && rowIndex <= 0;\n const atLast = disableAtEnds && rowIndex >= lastIndex;\n\n const upLabel = moveUpLabel ?? t('dataTable.moveUp', 'Move up');\n const downLabel = moveDownLabel ?? t('dataTable.moveDown', 'Move down');\n\n // An ARRAY of IconButtons (not a Fragment): IconButtonGroup inspects its\n // direct children and rejects anything that isn't a DS IconButton.\n const buttons = [\n <IconButton\n key=\"up\"\n size=\"sm\"\n intent={intent}\n icon={<ArrowUp aria-hidden className=\"ds:size-4\" />}\n tooltip={upLabel}\n aria-label={upLabel}\n disabled={atFirst}\n onClick={(event) => {\n event.stopPropagation();\n onMove(data, 'up');\n }}\n />,\n <IconButton\n key=\"down\"\n size=\"sm\"\n intent={intent}\n icon={<ArrowDown aria-hidden className=\"ds:size-4\" />}\n tooltip={downLabel}\n aria-label={downLabel}\n disabled={atLast}\n onClick={(event) => {\n event.stopPropagation();\n onMove(data, 'down');\n }}\n />,\n ];\n\n return group ? (\n <IconButtonGroup\n aria-label={t('dataTable.reorder', 'Reorder row')}\n size=\"sm\"\n >\n {buttons}\n </IconButtonGroup>\n ) : (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n {buttons}\n </span>\n );\n}\n","import { useState, type ReactNode } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { SquareCheckBig, Square } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\n\nexport interface ToggleCellRendererParams<TData = unknown> {\n /**\n * Fires with the row and the new target value. May return a `Promise` —\n * if it rejects, the consumer is expected to revert the underlying value\n * and flash the row with `data-table-row-error` (return that row class\n * from `getRowClass`). Use `onError` below to be notified inside this\n * renderer.\n */\n onToggle: (data: TData, newValue: boolean) => void | Promise<void>;\n /**\n * Optional reject hook. Fires when the `onToggle` promise rejects, with\n * the row and the error. The button auto-disables during the in-flight\n * promise and re-enables on either settle.\n */\n onError?: (data: TData, error: unknown) => void;\n /** Icon shown when the current value is truthy. */\n trueIcon?: ReactNode;\n /** Icon shown when the current value is falsy. */\n falseIcon?: ReactNode;\n /** Extra classes applied to the \"on\" icon — defaults to success token. */\n trueClass?: string;\n /** Extra classes applied to the \"off\" icon. */\n falseClass?: string;\n /** Accessible label. Falls back to the default on/off announcements. */\n label?: string;\n}\n\nexport function ToggleCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData, boolean> &\n ToggleCellRendererParams<TData>,\n) {\n const {\n value,\n data,\n onToggle,\n onError,\n trueIcon,\n falseIcon,\n trueClass = 'ds:text-[color:var(--success)]',\n falseClass = 'ds:text-[color:var(--muted-foreground)]',\n label,\n } = props;\n const { t } = useTranslation();\n const [pending, setPending] = useState(false);\n if (!data) return null;\n\n const isOn = Boolean(value);\n const icon = isOn\n ? (trueIcon ?? <SquareCheckBig aria-hidden className=\"ds:size-4\" />)\n : (falseIcon ?? <Square aria-hidden className=\"ds:size-4\" />);\n const stateClass = isOn ? trueClass : falseClass;\n const resolvedLabel =\n label ?? (isOn ? t('inputs.switch.on') : t('inputs.switch.off'));\n\n async function handleClick(event: React.MouseEvent) {\n event.stopPropagation();\n if (pending || !data) return;\n const next = !isOn;\n const result = onToggle(data, next);\n if (result && typeof (result as Promise<void>).then === 'function') {\n setPending(true);\n try {\n await result;\n } catch (err) {\n onError?.(data, err);\n } finally {\n setPending(false);\n }\n }\n }\n\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={isOn}\n aria-busy={pending}\n aria-label={resolvedLabel}\n disabled={pending}\n onClick={handleClick}\n className={[\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:min-h-[var(--min-target-size)] ds:min-w-[var(--min-target-size)]',\n 'ds:appearance-none ds:bg-transparent ds:p-[var(--spacing-xs)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:disabled:opacity-50',\n stateClass,\n ].join(' ')}\n >\n {icon}\n </button>\n );\n}\n","import { useRef } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useIsomorphicLayoutEffect } from '../../../hooks/use-isomorphic-layout-effect';\n\nexport interface ColorDotCellRendererParams {\n /** Field name on the row whose value holds the hex color. */\n colorField: string;\n /** Visual size of the dot. */\n size?: 'sm' | 'md' | 'lg';\n /** Optional label shown next to the dot. */\n labelField?: string;\n}\n\nconst SIZE_CLASS: Record<\n NonNullable<ColorDotCellRendererParams['size']>,\n string\n> = {\n sm: 'ds:size-[var(--icon-size-sm)]',\n md: 'ds:size-[var(--icon-size-md)]',\n lg: 'ds:size-[var(--icon-size-lg)]',\n};\n\nfunction readField(row: unknown, field: string): string | undefined {\n if (!row || typeof row !== 'object') return undefined;\n const value = (row as Record<string, unknown>)[field];\n return typeof value === 'string' ? value : undefined;\n}\n\n// Only accept trusted CSS color forms. Anything outside this allow-list\n// (including smuggled `url()` or extra declarations) is dropped so the\n// CSS custom-property writer can't be used to inject styles.\nconst HEX_RE = /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;\nconst RGB_RE = /^rgba?\\(\\s*[\\d.\\s,%/]+\\)$/i;\nconst HSL_RE = /^hsla?\\(\\s*[\\d.\\s,%/]+\\)$/i;\nconst CSS_VAR_RE = /^var\\(--[a-z0-9-]+(?:,\\s*[^)]+)?\\)$/i;\n\nfunction sanitizeColor(raw: string | undefined): string | undefined {\n if (!raw) return undefined;\n const v = raw.trim();\n if (\n HEX_RE.test(v) ||\n RGB_RE.test(v) ||\n HSL_RE.test(v) ||\n CSS_VAR_RE.test(v)\n ) {\n return v;\n }\n return undefined;\n}\n\nexport function ColorDotCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & ColorDotCellRendererParams,\n) {\n const { data, colorField, size = 'md', labelField } = props;\n const dotRef = useRef<HTMLSpanElement | null>(null);\n const rawColor = data ? readField(data, colorField) : undefined;\n const color = sanitizeColor(rawColor);\n const label = data && labelField ? readField(data, labelField) : undefined;\n\n // Apply the dynamic color via a CSS custom property on the element.\n // Keeps hex/rgb literals out of JSX (constraint #2 and #4). The data\n // itself drives the color — constraints only forbid hardcoded colors\n // in component source, not in consumer row data.\n useIsomorphicLayoutEffect(() => {\n const el = dotRef.current;\n if (!el) return;\n if (color) {\n el.style.setProperty('--data-table-dot-color', color);\n } else {\n el.style.removeProperty('--data-table-dot-color');\n }\n }, [color]);\n\n if (!color) return null;\n\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <span\n ref={dotRef}\n aria-hidden=\"true\"\n className={[\n 'ds:inline-block ds:shrink-0 ds:rounded-[var(--radius-full)]',\n 'ds:bg-[var(--data-table-dot-color)]',\n 'ds:border ds:border-[color:var(--border)]',\n SIZE_CLASS[size],\n ].join(' ')}\n />\n {label ? <span>{label}</span> : null}\n </span>\n );\n}\n","import type { ColDef } from 'ag-grid-community';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\n\nexport interface BalanceLine {\n /** User-visible label for this line. */\n label: string;\n /** Field name on the row whose numeric value is rendered. */\n valueField: string;\n /** `'currency'` renders via Intl, `'percent'` appends `%`, `'number'` raw. Default `'number'`. */\n format?: 'currency' | 'percent' | 'number';\n}\n\nexport interface BalanceCellRendererParams {\n lines: BalanceLine[];\n /** ISO 4217 code, used by `currency`-formatted lines. Default `'EUR'`. */\n currency?: string;\n /** Apply destructive color to negative values. */\n highlightNegative?: boolean;\n}\n\nfunction readNumber(row: unknown, field: string): number | null {\n if (!row || typeof row !== 'object') return null;\n const raw = (row as Record<string, unknown>)[field];\n const n = typeof raw === 'number' ? raw : Number(raw);\n return Number.isFinite(n) ? n : null;\n}\n\n/**\n * Renders a compact set of label / value pairs inside a single AG Grid cell.\n *\n * Layout is **horizontal** with middle-dot separators so the cell fits\n * inside the default AG Grid row height without spilling into the row\n * below. Use the SALDI / Listini patterns (Totale · Incassato · Da Incassare)\n * as the canonical example.\n *\n * If a consumer's content wraps (long localized labels, narrow columns)\n * they can opt into row auto-growth by spreading\n * {@link balanceCellRendererColDefDefaults} onto the column definition.\n */\nexport function BalanceCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & BalanceCellRendererParams,\n) {\n const { data, lines, currency = 'EUR', highlightNegative } = props;\n const { i18n } = useTranslation();\n if (!data) return null;\n\n const locale = i18n.language || 'en';\n\n const formatLine = (\n line: BalanceLine,\n ): { label: string; formatted: string; negative: boolean } | null => {\n const n = readNumber(data, line.valueField);\n if (n === null) return null;\n\n let formatted: string;\n switch (line.format ?? 'number') {\n case 'currency':\n formatted = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n }).format(n);\n break;\n case 'percent':\n formatted = new Intl.NumberFormat(locale, {\n style: 'percent',\n maximumFractionDigits: 1,\n }).format(n / 100);\n break;\n default:\n formatted = new Intl.NumberFormat(locale).format(n);\n }\n\n return {\n label: line.label,\n formatted,\n negative: Boolean(highlightNegative) && n < 0,\n };\n };\n\n const rendered = lines\n .map(formatLine)\n .filter(\n (x): x is { label: string; formatted: string; negative: boolean } =>\n x !== null,\n );\n if (rendered.length === 0) return null;\n\n return (\n <div\n className={[\n 'ds:flex',\n 'ds:flex-wrap',\n 'ds:items-center',\n 'ds:gap-x-[var(--spacing-sm)]',\n 'ds:gap-y-0',\n 'type-meta',\n 'ds:leading-tight',\n ].join(' ')}\n >\n {rendered.map((item, idx) => (\n <span\n key={`${item.label}-${idx}`}\n className=\"ds:inline-flex ds:items-baseline ds:gap-x-[var(--spacing-xs)]\"\n >\n {idx > 0 ? (\n <span\n aria-hidden=\"true\"\n className=\"ds:me-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\"\n >\n ·\n </span>\n ) : null}\n <span className=\"ds:text-[color:var(--muted-foreground)]\">\n {item.label}\n </span>\n <span\n className={[\n 'ds:tabular-nums',\n 'ds:font-medium',\n item.negative ? 'ds:text-[color:var(--destructive)]' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {item.formatted}\n </span>\n </span>\n ))}\n </div>\n );\n}\n\n/**\n * Column-definition defaults consumers can spread onto a `ColDef` when they\n * want the renderer's wrapped / multi-line behaviour to grow the row.\n *\n * The default compact horizontal layout is engineered to fit the standard\n * AG Grid row height, so this opt-in is only needed when a long label set\n * wraps across two or more lines and the consumer would rather grow the\n * row than wrap silently.\n *\n * AG Grid does NOT auto-grow row height to fit a tall cell unless\n * `autoHeight` and `wrapText` are set on the colDef itself — a cell\n * renderer can't impose that from inside.\n *\n * @example\n * ```ts\n * {\n * headerName: 'Saldi',\n * cellRenderer: BalanceCellRenderer,\n * cellRendererParams: { lines, currency: 'EUR' },\n * ...balanceCellRendererColDefDefaults,\n * }\n * ```\n */\nexport const balanceCellRendererColDefDefaults: Readonly<\n Pick<ColDef, 'autoHeight' | 'wrapText'>\n> = {\n autoHeight: true,\n wrapText: true,\n};\n","import { useEffect, useRef, useState } from 'react';\nimport type { CustomCellEditorProps } from 'ag-grid-react';\nimport {\n INPUT_SURFACE_CHROME,\n INPUT_SURFACE_HEIGHT,\n INPUT_SURFACE_PADDING_X,\n INPUT_SURFACE_TEXT,\n} from '../../_shared/input-surface';\n\n/**\n * Inline text editor that visually matches `<TextInput size=\"sm\">`. Use as\n * `cellEditor` on a colDef with `editable: true`. The cell renderer (default\n * or custom) takes over again once editing stops.\n *\n * AG Grid commits on Enter or Tab or blur; cancels on Escape. The consumer\n * receives the committed value via `onCellValueChanged`.\n */\nexport function EditableTextCellRenderer<TData = unknown>(\n props: CustomCellEditorProps<TData, string>,\n) {\n const { initialValue, onValueChange, stopEditing, column } = props;\n const [value, setValue] = useState<string>(initialValue ?? '');\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Focus + select on mount so typing replaces the current value.\n useEffect(() => {\n const el = inputRef.current;\n if (!el) return;\n el.focus();\n el.select();\n }, []);\n\n // The current value is pushed to AG Grid via `onValueChange` on every\n // keystroke — AG Grid commits the most recent value when editing stops.\n // No `useGridCellEditor` hook needed for that contract.\n\n // Thread the column header into the input's accessible name so screen\n // readers announce \"Edit text, {column}\" instead of an unlabelled input.\n // AG Grid doesn't auto-wire the column header to cell editors.\n const headerName =\n (column?.getColDef?.()?.headerName as string | undefined) ?? undefined;\n\n return (\n <input\n ref={inputRef}\n type=\"text\"\n value={value}\n aria-label={headerName}\n onChange={(e) => {\n const next = e.target.value;\n setValue(next);\n onValueChange(next);\n }}\n onKeyDown={(e) => {\n // Escape cancels, Enter/Tab commit — AG Grid handles both, but we\n // explicitly stop editing on Enter so the consumer sees the commit\n // immediately rather than waiting for the next focus blur.\n if (e.key === 'Enter') {\n e.preventDefault();\n stopEditing();\n }\n }}\n className={[\n 'ds:block ds:w-full ds:appearance-none',\n // Input surface chrome: rounded border + bg + focus halo.\n INPUT_SURFACE_CHROME,\n // Use the `md` height (`--min-target-size`) so the input\n // auto-lifts to 48px under `.theme-accessible` to satisfy\n // WCAG 2.5.5 target size.\n INPUT_SURFACE_HEIGHT.md,\n INPUT_SURFACE_TEXT.sm,\n INPUT_SURFACE_PADDING_X.sm,\n ].join(' ')}\n />\n );\n}\n","import { useEffect, useRef, useState } from 'react';\nimport type { CustomCellEditorProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\nimport {\n INPUT_SURFACE_CHROME,\n INPUT_SURFACE_HEIGHT,\n INPUT_SURFACE_PADDING_X,\n INPUT_SURFACE_TEXT,\n} from '../../_shared/input-surface';\n\nexport interface EditableCurrencyCellEditorParams {\n /** ISO 4217 currency code (e.g. `EUR`, `USD`). Defaults to `EUR`. */\n currency?: string;\n /** Decimal places allowed in the editor. Defaults to 2 (cents precision). */\n decimals?: number;\n /** Minimum allowed value — values below this are clamped on commit. */\n min?: number;\n /** Maximum allowed value — values above this are clamped on commit. */\n max?: number;\n}\n\n/**\n * Inline numeric editor that visually matches `<TextInput size=\"sm\">`. Use as\n * `cellEditor` on a colDef with `editable: true`. The display formatting is\n * still the renderer's job — once editing stops, the cell hands back to\n * `CurrencyCellRenderer` (or whichever renderer the colDef declares).\n *\n * Stores a Number, not a string, so consumers receive `row.amount = 12.5`\n * not `\"12.5\"`. Strips locale separators on each change so commas/dots in\n * any language convert to a clean numeric value.\n */\nexport function EditableCurrencyCellRenderer<TData = unknown>(\n props: CustomCellEditorProps<TData, number> &\n EditableCurrencyCellEditorParams,\n) {\n const {\n initialValue,\n onValueChange,\n stopEditing,\n column,\n decimals = 2,\n min,\n max,\n } = props;\n const { i18n } = useTranslation();\n const inputRef = useRef<HTMLInputElement | null>(null);\n // Thread the column header into the input's accessible name — see\n // editable-text-cell-renderer.tsx for the rationale.\n const headerName =\n (column?.getColDef?.()?.headerName as string | undefined) ?? undefined;\n\n // Local string state so the user can type intermediate values like \"12.\"\n // before the trailing zero arrives. We commit a Number to AG Grid on each\n // change for consumers that watch row state live; the final commit fires\n // when editing stops.\n const [draft, setDraft] = useState<string>(() => {\n if (initialValue == null || Number.isNaN(initialValue)) return '';\n return String(initialValue);\n });\n\n useEffect(() => {\n const el = inputRef.current;\n if (!el) return;\n el.focus();\n el.select();\n }, []);\n\n function parseDraft(input: string): number | null {\n if (input.trim().length === 0) return null;\n // Accept either the user's locale decimal separator or a `.`. Strip\n // grouping characters (locale thousands separators, plus spaces).\n const lang = i18n.language || 'en';\n const partsFmt = new Intl.NumberFormat(lang).formatToParts(12345.6);\n const groupChar = partsFmt.find((p) => p.type === 'group')?.value ?? '';\n const decimalChar =\n partsFmt.find((p) => p.type === 'decimal')?.value ?? '.';\n const cleaned = input\n .replace(new RegExp(`\\\\${groupChar}`, 'g'), '')\n .replace(decimalChar, '.')\n .replace(/[^\\d.-]/g, '');\n const n = Number(cleaned);\n return Number.isFinite(n) ? n : null;\n }\n\n function commit(input: string) {\n const parsed = parseDraft(input);\n if (parsed == null) {\n onValueChange(null);\n return;\n }\n // Clamp first, then round to the declared precision so we never\n // persist floating-point dust from string parsing.\n let clamped = parsed;\n if (typeof min === 'number') clamped = Math.max(min, clamped);\n if (typeof max === 'number') clamped = Math.min(max, clamped);\n const factor = 10 ** decimals;\n onValueChange(Math.round(clamped * factor) / factor);\n }\n\n return (\n <input\n ref={inputRef}\n type=\"text\"\n // Inputmode hints mobile keyboards to show the decimal pad instead\n // of the full keyboard. type=\"number\" would also work but spinners\n // and locale parsing are inconsistent across browsers.\n inputMode=\"decimal\"\n value={draft}\n aria-label={headerName}\n onChange={(e) => {\n const next = e.target.value;\n setDraft(next);\n commit(next);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n stopEditing();\n }\n // Escape — AG Grid cancels by default; the editor doesn't need\n // explicit handling beyond what AG Grid wires automatically.\n }}\n className={[\n 'ds:block ds:w-full ds:appearance-none ds:text-end ds:tabular-nums',\n INPUT_SURFACE_CHROME,\n // Use `md` height — see editable-text-cell-renderer for rationale.\n INPUT_SURFACE_HEIGHT.md,\n INPUT_SURFACE_TEXT.sm,\n INPUT_SURFACE_PADDING_X.sm,\n ].join(' ')}\n />\n );\n}\n"],"names":["__iconNode","ArrowDown","createLucideIcon","ArrowUp","useTotalRow","rowData","sumFields","options","useMemo","row","field","total","r","raw","n","ToothIcon","jsx","ToothCellRenderer","props","value","maxInlineSize","Tag","reorderColumnWidth","ReorderCellRenderer","data","node","api","onMove","moveUpLabel","moveDownLabel","intent","group","disableAtEnds","t","useTranslation","rowIndex","lastIndex","atFirst","atLast","upLabel","downLabel","buttons","IconButton","event","IconButtonGroup","ToggleCellRenderer","onToggle","onError","trueIcon","falseIcon","trueClass","falseClass","label","pending","setPending","useState","isOn","icon","SquareCheckBig","Square","stateClass","resolvedLabel","handleClick","result","err","SIZE_CLASS","readField","HEX_RE","RGB_RE","HSL_RE","CSS_VAR_RE","sanitizeColor","v","ColorDotCellRenderer","colorField","size","labelField","dotRef","useRef","rawColor","color","useIsomorphicLayoutEffect","el","jsxs","readNumber","BalanceCellRenderer","lines","currency","highlightNegative","i18n","locale","formatLine","line","formatted","rendered","x","item","idx","EditableTextCellRenderer","initialValue","onValueChange","stopEditing","column","setValue","inputRef","useEffect","headerName","_b","_a","e","next","INPUT_SURFACE_CHROME","INPUT_SURFACE_HEIGHT","INPUT_SURFACE_TEXT","INPUT_SURFACE_PADDING_X","EditableCurrencyCellRenderer","decimals","min","max","draft","setDraft","parseDraft","input","lang","partsFmt","groupChar","p","decimalChar","cleaned","commit","parsed","clamped","factor"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email-input-Dpe63k0K.js","sources":["../../node_modules/validator/lib/util/assertString.js","../../node_modules/validator/lib/util/checkHost.js","../../node_modules/validator/lib/isByteLength.js","../../node_modules/validator/lib/util/merge.js","../../node_modules/validator/lib/isFQDN.js","../../node_modules/validator/lib/isIP.js","../../node_modules/validator/lib/isEmail.js","../../src/components/email-input/email-input.agent.ts","../../src/components/email-input/email-input.tsx"],"sourcesContent":["\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = assertString;\nfunction assertString(input) {\n if (input === undefined || input === null) throw new TypeError(\"Expected a string but received a \".concat(input));\n if (input.constructor.name !== 'String') throw new TypeError(\"Expected a string but received a \".concat(input.constructor.name));\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = checkHost;\nfunction isRegExp(obj) {\n return Object.prototype.toString.call(obj) === '[object RegExp]';\n}\nfunction checkHost(host, matches) {\n for (var i = 0; i < matches.length; i++) {\n var match = matches[i];\n if (host === match || isRegExp(match) && match.test(host)) {\n return true;\n }\n }\n return false;\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = isByteLength;\nvar _assertString = _interopRequireDefault(require(\"./util/assertString\"));\nfunction _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\n/* eslint-disable prefer-rest-params */\nfunction isByteLength(str, options) {\n (0, _assertString.default)(str);\n var min;\n var max;\n if (_typeof(options) === 'object') {\n min = options.min || 0;\n max = options.max;\n } else {\n // backwards compatibility: isByteLength(str, min [, max])\n min = arguments[1];\n max = arguments[2];\n }\n var len = encodeURI(str).split(/%..|./).length - 1;\n return len >= min && (typeof max === 'undefined' || len <= max);\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = merge;\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction merge() {\n var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n var defaults = arguments.length > 1 ? arguments[1] : undefined;\n if (_typeof(obj) !== 'object' || obj === null) {\n obj = {};\n }\n for (var key in defaults) {\n if (typeof obj[key] === 'undefined') {\n obj[key] = defaults[key];\n }\n }\n return obj;\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = isFQDN;\nvar _assertString = _interopRequireDefault(require(\"./util/assertString\"));\nvar _merge = _interopRequireDefault(require(\"./util/merge\"));\nfunction _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }\nvar default_fqdn_options = {\n require_tld: true,\n allow_underscores: false,\n allow_trailing_dot: false,\n allow_numeric_tld: false,\n allow_wildcard: false,\n ignore_max_length: false\n};\nfunction isFQDN(str, options) {\n (0, _assertString.default)(str);\n options = (0, _merge.default)(options, default_fqdn_options);\n\n /* Remove the optional trailing dot before checking validity */\n if (options.allow_trailing_dot && str[str.length - 1] === '.') {\n str = str.substring(0, str.length - 1);\n }\n\n /* Remove the optional wildcard before checking validity */\n if (options.allow_wildcard === true && str.indexOf('*.') === 0) {\n str = str.substring(2);\n }\n var parts = str.split('.');\n var tld = parts[parts.length - 1];\n if (options.require_tld) {\n // disallow fqdns without tld\n if (parts.length < 2) {\n return false;\n }\n if (!options.allow_numeric_tld && !/^([a-z\\u00A1-\\u00A8\\u00AA-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]{2,}|xn[a-z0-9-]{2,})$/i.test(tld)) {\n return false;\n }\n\n // disallow spaces\n if (/\\s/.test(tld)) {\n return false;\n }\n }\n\n // reject numeric TLDs\n if (!options.allow_numeric_tld && /^\\d+$/.test(tld)) {\n return false;\n }\n return parts.every(function (part) {\n if (part.length > 63 && !options.ignore_max_length) {\n return false;\n }\n if (!/^[a-z_\\u00a1-\\uffff0-9-]+$/i.test(part)) {\n return false;\n }\n\n // disallow full-width chars\n if (/[\\uff01-\\uff5e]/.test(part)) {\n return false;\n }\n\n // disallow parts starting or ending with hyphen\n if (/^-|-$/.test(part)) {\n return false;\n }\n if (!options.allow_underscores && /_/.test(part)) {\n return false;\n }\n return true;\n });\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = isIP;\nvar _assertString = _interopRequireDefault(require(\"./util/assertString\"));\nfunction _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\n/**\n11.3. Examples\n\n The following addresses\n\n fe80::1234 (on the 1st link of the node)\n ff02::5678 (on the 5th link of the node)\n ff08::9abc (on the 10th organization of the node)\n\n would be represented as follows:\n\n fe80::1234%1\n ff02::5678%5\n ff08::9abc%10\n\n (Here we assume a natural translation from a zone index to the\n <zone_id> part, where the Nth zone of any scope is translated into\n \"N\".)\n\n If we use interface names as <zone_id>, those addresses could also be\n represented as follows:\n\n fe80::1234%ne0\n ff02::5678%pvc1.3\n ff08::9abc%interface10\n\n where the interface \"ne0\" belongs to the 1st link, \"pvc1.3\" belongs\n to the 5th link, and \"interface10\" belongs to the 10th organization.\n * * */\nvar IPv4SegmentFormat = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';\nvar IPv4AddressFormat = \"(\".concat(IPv4SegmentFormat, \"[.]){3}\").concat(IPv4SegmentFormat);\nvar IPv4AddressRegExp = new RegExp(\"^\".concat(IPv4AddressFormat, \"$\"));\nvar IPv6SegmentFormat = '(?:[0-9a-fA-F]{1,4})';\nvar IPv6AddressRegExp = new RegExp('^(' + \"(?:\".concat(IPv6SegmentFormat, \":){7}(?:\").concat(IPv6SegmentFormat, \"|:)|\") + \"(?:\".concat(IPv6SegmentFormat, \":){6}(?:\").concat(IPv4AddressFormat, \"|:\").concat(IPv6SegmentFormat, \"|:)|\") + \"(?:\".concat(IPv6SegmentFormat, \":){5}(?::\").concat(IPv4AddressFormat, \"|(:\").concat(IPv6SegmentFormat, \"){1,2}|:)|\") + \"(?:\".concat(IPv6SegmentFormat, \":){4}(?:(:\").concat(IPv6SegmentFormat, \"){0,1}:\").concat(IPv4AddressFormat, \"|(:\").concat(IPv6SegmentFormat, \"){1,3}|:)|\") + \"(?:\".concat(IPv6SegmentFormat, \":){3}(?:(:\").concat(IPv6SegmentFormat, \"){0,2}:\").concat(IPv4AddressFormat, \"|(:\").concat(IPv6SegmentFormat, \"){1,4}|:)|\") + \"(?:\".concat(IPv6SegmentFormat, \":){2}(?:(:\").concat(IPv6SegmentFormat, \"){0,3}:\").concat(IPv4AddressFormat, \"|(:\").concat(IPv6SegmentFormat, \"){1,5}|:)|\") + \"(?:\".concat(IPv6SegmentFormat, \":){1}(?:(:\").concat(IPv6SegmentFormat, \"){0,4}:\").concat(IPv4AddressFormat, \"|(:\").concat(IPv6SegmentFormat, \"){1,6}|:)|\") + \"(?::((?::\".concat(IPv6SegmentFormat, \"){0,5}:\").concat(IPv4AddressFormat, \"|(?::\").concat(IPv6SegmentFormat, \"){1,7}|:))\") + ')(%[0-9a-zA-Z.]{1,})?$');\nfunction isIP(ipAddress) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n (0, _assertString.default)(ipAddress);\n\n // accessing 'arguments' for backwards compatibility: isIP(ipAddress [, version])\n // eslint-disable-next-line prefer-rest-params\n var version = (_typeof(options) === 'object' ? options.version : arguments[1]) || '';\n if (!version) {\n return isIP(ipAddress, {\n version: 4\n }) || isIP(ipAddress, {\n version: 6\n });\n }\n if (version.toString() === '4') {\n return IPv4AddressRegExp.test(ipAddress);\n }\n if (version.toString() === '6') {\n return IPv6AddressRegExp.test(ipAddress);\n }\n return false;\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = isEmail;\nvar _assertString = _interopRequireDefault(require(\"./util/assertString\"));\nvar _checkHost = _interopRequireDefault(require(\"./util/checkHost\"));\nvar _isByteLength = _interopRequireDefault(require(\"./isByteLength\"));\nvar _isFQDN = _interopRequireDefault(require(\"./isFQDN\"));\nvar _isIP = _interopRequireDefault(require(\"./isIP\"));\nvar _merge = _interopRequireDefault(require(\"./util/merge\"));\nfunction _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }\nvar default_email_options = {\n allow_display_name: false,\n allow_underscores: false,\n require_display_name: false,\n allow_utf8_local_part: true,\n require_tld: true,\n blacklisted_chars: '',\n ignore_max_length: false,\n host_blacklist: [],\n host_whitelist: []\n};\n\n/* eslint-disable max-len */\n/* eslint-disable no-control-regex */\nvar splitNameAddress = /^([^\\x00-\\x1F\\x7F-\\x9F\\cX]+)</i;\nvar emailUserPart = /^[a-z\\d!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]+$/i;\nvar gmailUserPart = /^[a-z\\d]+$/;\nvar quotedEmailUser = /^([\\s\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f\\x21\\x23-\\x5b\\x5d-\\x7e]|(\\\\[\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]))*$/i;\nvar emailUserUtf8Part = /^[a-z\\d!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~\\u00A1-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]+$/i;\nvar quotedEmailUserUtf8 = /^([\\s\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f\\x21\\x23-\\x5b\\x5d-\\x7e\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]|(\\\\[\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))*$/i;\nvar defaultMaxEmailLength = 254;\n/* eslint-enable max-len */\n/* eslint-enable no-control-regex */\n\n/**\n * Validate display name according to the RFC2822: https://tools.ietf.org/html/rfc2822#appendix-A.1.2\n * @param {String} display_name\n */\nfunction validateDisplayName(display_name) {\n var display_name_without_quotes = display_name.replace(/^\"(.+)\"$/, '$1');\n // display name with only spaces is not valid\n if (!display_name_without_quotes.trim()) {\n return false;\n }\n\n // check whether display name contains illegal character\n var contains_illegal = /[\\.\";<>]/.test(display_name_without_quotes);\n if (contains_illegal) {\n // if contains illegal characters,\n // must to be enclosed in double-quotes, otherwise it's not a valid display name\n if (display_name_without_quotes === display_name) {\n return false;\n }\n\n // the quotes in display name must start with character symbol \\\n var all_start_with_back_slash = display_name_without_quotes.split('\"').length === display_name_without_quotes.split('\\\\\"').length;\n if (!all_start_with_back_slash) {\n return false;\n }\n }\n return true;\n}\nfunction isEmail(str, options) {\n (0, _assertString.default)(str);\n options = (0, _merge.default)(options, default_email_options);\n if (options.require_display_name || options.allow_display_name) {\n var display_email = str.match(splitNameAddress);\n if (display_email) {\n var display_name = display_email[1];\n\n // Remove display name and angle brackets to get email address\n // Can be done in the regex but will introduce a ReDOS (See #1597 for more info)\n str = str.replace(display_name, '').replace(/(^<|>$)/g, '');\n\n // sometimes need to trim the last space to get the display name\n // because there may be a space between display name and email address\n // eg. myname <address@gmail.com>\n // the display name is `myname` instead of `myname `, so need to trim the last space\n if (display_name.endsWith(' ')) {\n display_name = display_name.slice(0, -1);\n }\n if (!validateDisplayName(display_name)) {\n return false;\n }\n } else if (options.require_display_name) {\n return false;\n }\n }\n if (!options.ignore_max_length && str.length > defaultMaxEmailLength) {\n return false;\n }\n var parts = str.split('@');\n var domain = parts.pop();\n var lower_domain = domain.toLowerCase();\n if (options.host_blacklist.length > 0 && (0, _checkHost.default)(lower_domain, options.host_blacklist)) {\n return false;\n }\n if (options.host_whitelist.length > 0 && !(0, _checkHost.default)(lower_domain, options.host_whitelist)) {\n return false;\n }\n var user = parts.join('@');\n if (options.domain_specific_validation && (lower_domain === 'gmail.com' || lower_domain === 'googlemail.com')) {\n /*\n Previously we removed dots for gmail addresses before validating.\n This was removed because it allows `multiple..dots@gmail.com`\n to be reported as valid, but it is not.\n Gmail only normalizes single dots, removing them from here is pointless,\n should be done in normalizeEmail\n */\n user = user.toLowerCase();\n\n // Removing sub-address from username before gmail validation\n var username = user.split('+')[0];\n\n // Dots are not included in gmail length restriction\n if (!(0, _isByteLength.default)(username.replace(/\\./g, ''), {\n min: 6,\n max: 30\n })) {\n return false;\n }\n var _user_parts = username.split('.');\n for (var i = 0; i < _user_parts.length; i++) {\n if (!gmailUserPart.test(_user_parts[i])) {\n return false;\n }\n }\n }\n if (options.ignore_max_length === false && (!(0, _isByteLength.default)(user, {\n max: 64\n }) || !(0, _isByteLength.default)(domain, {\n max: 254\n }))) {\n return false;\n }\n if (!(0, _isFQDN.default)(domain, {\n require_tld: options.require_tld,\n ignore_max_length: options.ignore_max_length,\n allow_underscores: options.allow_underscores\n })) {\n if (!options.allow_ip_domain) {\n return false;\n }\n if (!(0, _isIP.default)(domain)) {\n if (!domain.startsWith('[') || !domain.endsWith(']')) {\n return false;\n }\n var noBracketdomain = domain.slice(1, -1);\n if (noBracketdomain.length === 0 || !(0, _isIP.default)(noBracketdomain)) {\n return false;\n }\n }\n }\n if (options.blacklisted_chars) {\n if (user.search(new RegExp(\"[\".concat(options.blacklisted_chars, \"]+\"), 'g')) !== -1) return false;\n }\n if (user[0] === '\"' && user[user.length - 1] === '\"') {\n user = user.slice(1, user.length - 1);\n return options.allow_utf8_local_part ? quotedEmailUserUtf8.test(user) : quotedEmailUser.test(user);\n }\n var pattern = options.allow_utf8_local_part ? emailUserUtf8Part : emailUserPart;\n var user_parts = user.split('.');\n for (var _i = 0; _i < user_parts.length; _i++) {\n if (!pattern.test(user_parts[_i])) {\n return false;\n }\n }\n return true;\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","/* -------------------------------------------------------------------- */\n/* Agent adapter — EmailInput. */\n/* */\n/* Presentational specialisation of TextInput — no actions of its own. */\n/* The handle re-exposes the underlying input's value-setter so agents */\n/* can drive the field through the normal TextInput contract without */\n/* needing to know it's wrapped. See `src/docs/26-agent-readiness.mdx` */\n/* for the contract. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\n\n/**\n * Curated agent handle for EmailInput. State stays scoped to the visible\n * value + the kit-derived validity flag; never PHI (per PRS §Security).\n */\nexport interface EmailInputHandle {\n /** Returns the current input value. */\n getValue: () => string;\n /** Returns whether the current value parses as a valid email (non-empty + RFC). */\n isValid: () => boolean;\n}\n\nexport const emailInputAgent: AgentAdapter<EmailInputHandle> = {\n id: 'email-input',\n capabilities: [],\n state: {\n value: {\n type: 'string',\n descriptionKey: 'ui.agent.emailInput.state.value',\n description: 'The current email address typed into the field.',\n read: (handle) => handle.getValue(),\n },\n isValid: {\n type: 'boolean',\n descriptionKey: 'ui.agent.emailInput.state.isValid',\n description:\n 'True when the value is non-empty AND parses as a valid email per RFC 5322.',\n read: (handle) => handle.isValid(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'email-input',\n description:\n 'Marks the EmailInput wrapper. The inline error element carries `role=\"alert\"` when validation fails.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop, when provided.',\n },\n },\n};\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type FocusEvent,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { AlertCircle } from 'lucide-react';\n// Tree-shaken import — pulling `validator/lib/isEmail` instead of the\n// barrel keeps the bundle to ~3 KB. `import { isEmail } from 'validator'`\n// drags in ~50 KB of unused validators.\nimport isEmail from 'validator/lib/isEmail';\nimport { TextInput, type TextInputProps } from '../text-input';\nimport { useFormField } from '../form-field/form-field-context';\nimport { composeRefs } from '../_shared/compose-refs';\nimport { useAgentRegistration } from '../../agent';\nimport { emailInputAgent, type EmailInputHandle } from './email-input.agent';\n\n/* ------------------------------------------------------------------ */\n/* Public API */\n/* */\n/* `type`, `autoComplete`, `inputMode`, and `tone` are baked in — the */\n/* component decides those itself. `tone` is computed from the */\n/* validation state so consumers can never wedge it into an inconsistent*/\n/* visual signal. */\n/* ------------------------------------------------------------------ */\n\nexport interface EmailInputProps extends Omit<\n TextInputProps,\n 'type' | 'autoComplete' | 'inputMode' | 'tone'\n> {\n /**\n * Override the \"Invalid email\" error message. Pass `null` to suppress\n * the built-in message entirely (e.g. when wrapping the input in a\n * `FormField` and surfacing the error through its `error` prop). When\n * omitted, the translated default `t('inputs.email.invalid')` is used.\n */\n errorMessage?: ReactNode | null;\n /**\n * Called whenever the validation state flips. `valid` is `true` when\n * the value is non-empty AND parses as a valid email, `false`\n * otherwise. The callback fires on every blur AND on every change\n * after the first blur — never before the user has had a chance to\n * type something.\n */\n onValidityChange?: (valid: boolean) => void;\n /**\n * Skip the built-in validation entirely. The input behaves like a\n * plain `<TextInput type=\"email\">` — useful when the consumer is\n * wiring `FormField`'s `invalid` prop themselves, or running their\n * own schema validation (zod, react-hook-form). Default: `false`.\n */\n disableBuiltInValidation?: boolean;\n}\n\n/* ------------------------------------------------------------------ */\n/* Validation engine */\n/* */\n/* Pure helper — empty values are NOT flagged (let `required` handle */\n/* empty separately). Whitespace-only values fall through to validator */\n/* which rejects them as malformed. */\n/* ------------------------------------------------------------------ */\n\nfunction checkValidity(value: string): boolean {\n if (value.length === 0) return true;\n return isEmail(value);\n}\n\nexport const EmailInput = forwardRef<HTMLInputElement, EmailInputProps>(\n (\n {\n errorMessage,\n onValidityChange,\n disableBuiltInValidation = false,\n value,\n defaultValue,\n onChange,\n onBlur,\n id,\n 'aria-describedby': consumerDescribedBy,\n 'aria-invalid': consumerAriaInvalid,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const ctx = useFormField();\n\n const innerRef = useRef<HTMLInputElement | null>(null);\n const composedRef = composeRefs(ref, innerRef);\n\n const reactErrorId = useId();\n // Use FormField's errorId when a FormField wraps us, otherwise fall back\n // to a local id so aria-describedby can wire the inline error element.\n const errorElementId = ctx.errorId || reactErrorId;\n\n const isControlled = value !== undefined;\n\n // Seed once from controlled `value` or `defaultValue` so we can\n // validate an already-populated field at mount (e.g. server-side\n // rehydration). Recomputing on prop changes would defeat the React\n // \"defaultValue is initial only\" contract — we read it once via the\n // lazy initialiser and let `currentValue` track every change after.\n const [internalValue, setInternalValue] = useState<string>(() => {\n if (typeof value === 'string') return value;\n if (typeof defaultValue === 'string') return defaultValue;\n return '';\n });\n const currentValue = isControlled ? String(value) : internalValue;\n\n // `touched` flips to `true` on first blur, or immediately if the\n // field is seeded with a non-empty value (consumer is asking us to\n // validate something they already collected).\n const [touched, setTouched] = useState<boolean>(\n () => currentValue.length > 0,\n );\n\n const computedValid = useMemo(\n () => checkValidity(currentValue),\n [currentValue],\n );\n\n // Surface the error only when the field has been touched AND the\n // value is non-empty AND the value fails RFC. Empty is always\n // \"not yet invalid\" — `required` covers the empty case separately.\n const shouldShowError =\n !disableBuiltInValidation &&\n touched &&\n currentValue.length > 0 &&\n !computedValid;\n\n // Notify consumers on every validity flip after the first blur.\n // Empty before first blur is reported as `true` so consumers don't\n // light up a \"valid\" indicator prematurely — we only fire after\n // touched so the first emission reflects user intent.\n const lastValidRef = useRef<boolean | null>(null);\n useEffect(() => {\n if (!touched) return;\n // Empty value after touch -> `valid` is `false` because the user\n // emptied a field they were editing. This mirrors the spec note\n // that empty is reported as `false` in `onValidityChange`.\n const nextValid = currentValue.length > 0 && computedValid;\n if (lastValidRef.current !== nextValid) {\n lastValidRef.current = nextValid;\n onValidityChange?.(nextValid);\n }\n }, [touched, currentValue, computedValid, onValidityChange]);\n\n const handleChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) {\n setInternalValue(event.target.value);\n }\n onChange?.(event);\n },\n [isControlled, onChange],\n );\n\n const handleBlur = useCallback(\n (event: FocusEvent<HTMLInputElement>) => {\n setTouched(true);\n onBlur?.(event);\n },\n [onBlur],\n );\n\n /* ------------------------------------------------------------------ */\n /* Agent adapter */\n /* ------------------------------------------------------------------ */\n\n // Stable handle — both `getValue` and `isValid` read the live DOM\n // node, so the closure captures no React state. Empty dep array\n // keeps the agent registry from churning on every keystroke.\n const agentHandle = useMemo<EmailInputHandle>(\n () => ({\n getValue: () => innerRef.current?.value ?? '',\n isValid: () => {\n const v = innerRef.current?.value ?? '';\n return v.length > 0 && isEmail(v);\n },\n }),\n [],\n );\n useAgentRegistration(emailInputAgent, agentHandle, id);\n\n /* ------------------------------------------------------------------ */\n /* aria-describedby composition */\n /* */\n /* The inline error needs to be reachable via `aria-describedby`. We */\n /* merge any consumer-supplied id with our own error id when the */\n /* validation error is visible. If a FormField wraps us, its */\n /* `describedBy` already includes the FormField error id — we only add */\n /* our own when the kit is rendering the inline error. */\n /* ------------------------------------------------------------------ */\n\n const showInlineError = shouldShowError && errorMessage !== null;\n const contextDescribedBy = ctx.describedBy || undefined;\n const describedBy = useMemo(() => {\n const parts = [\n consumerDescribedBy,\n contextDescribedBy,\n showInlineError ? errorElementId : null,\n ].filter(Boolean) as string[];\n return parts.length > 0 ? parts.join(' ') : undefined;\n }, [\n consumerDescribedBy,\n contextDescribedBy,\n showInlineError,\n errorElementId,\n ]);\n\n // When we're showing our inline error AND no FormField is already\n // signalling invalid through context, surface the error tone +\n // aria-invalid via the underlying TextInput.\n const effectiveTone = shouldShowError ? 'error' : 'default';\n // A wrapping consumer may assert invalidity for a BUSINESS reason while the\n // format is fine (e.g. \"already in use\") — honour it on the a11y attribute\n // so it's announced. Visual `tone` stays self-governed (format-only).\n const consumerInvalid =\n consumerAriaInvalid === true || consumerAriaInvalid === 'true';\n const effectiveAriaInvalid =\n shouldShowError || ctx.invalid || consumerInvalid || undefined;\n\n const resolvedErrorMessage =\n errorMessage !== undefined\n ? errorMessage\n : t('inputs.email.invalid', 'Invalid email');\n\n return (\n <div\n data-component=\"email-input\"\n data-component-id={id}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n <TextInput\n {...rest}\n ref={composedRef}\n id={id}\n type=\"email\"\n inputMode=\"email\"\n autoComplete=\"email\"\n tone={effectiveTone}\n value={isControlled ? currentValue : undefined}\n defaultValue={!isControlled ? defaultValue : undefined}\n onChange={handleChange}\n onBlur={handleBlur}\n aria-invalid={effectiveAriaInvalid}\n aria-describedby={describedBy}\n />\n {showInlineError ? (\n <p\n id={errorElementId}\n role=\"alert\"\n data-slot=\"email-input-error\"\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] type-body-sm ds:text-destructive\"\n >\n <AlertCircle aria-hidden=\"true\" className=\"ds:size-4 ds:shrink-0\" />\n <span>{resolvedErrorMessage}</span>\n </p>\n ) : null}\n </div>\n );\n },\n);\n\nEmailInput.displayName = 'EmailInput';\n"],"names":["exports","assertString","input","module","checkHost","isRegExp","obj","host","matches","i","match","isByteLength","_assertString","_interopRequireDefault","e","_typeof","o","str","options","min","max","len","merge","defaults","key","isFQDN","_merge","default_fqdn_options","parts","tld","part","isIP","IPv4SegmentFormat","IPv4AddressFormat","IPv4AddressRegExp","IPv6SegmentFormat","IPv6AddressRegExp","ipAddress","version","isEmail","_checkHost","_isByteLength","_isFQDN","_isIP","default_email_options","splitNameAddress","emailUserPart","gmailUserPart","quotedEmailUser","emailUserUtf8Part","quotedEmailUserUtf8","defaultMaxEmailLength","validateDisplayName","display_name","display_name_without_quotes","contains_illegal","all_start_with_back_slash","display_email","domain","lower_domain","user","username","_user_parts","noBracketdomain","pattern","user_parts","_i","emailInputAgent","handle","checkValidity","value","EmailInput","forwardRef","errorMessage","onValidityChange","disableBuiltInValidation","defaultValue","onChange","onBlur","id","consumerDescribedBy","consumerAriaInvalid","rest","ref","t","useTranslation","ctx","useFormField","innerRef","useRef","composedRef","composeRefs","reactErrorId","useId","errorElementId","isControlled","internalValue","setInternalValue","useState","currentValue","touched","setTouched","computedValid","useMemo","shouldShowError","lastValidRef","useEffect","nextValid","handleChange","useCallback","event","handleBlur","agentHandle","_a","v","useAgentRegistration","showInlineError","contextDescribedBy","describedBy","effectiveTone","consumerInvalid","effectiveAriaInvalid","resolvedErrorMessage","jsxs","jsx","TextInput","AlertCircle"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6]}
|
|
1
|
+
{"version":3,"file":"email-input-Dpe63k0K.js","sources":["../../node_modules/validator/lib/util/assertString.js","../../node_modules/validator/lib/util/checkHost.js","../../node_modules/validator/lib/isByteLength.js","../../node_modules/validator/lib/util/merge.js","../../node_modules/validator/lib/isFQDN.js","../../node_modules/validator/lib/isIP.js","../../node_modules/validator/lib/isEmail.js","../../src/components/email-input/email-input.agent.ts","../../src/components/email-input/email-input.tsx"],"sourcesContent":["\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = assertString;\nfunction assertString(input) {\n if (input === undefined || input === null) throw new TypeError(\"Expected a string but received a \".concat(input));\n if (input.constructor.name !== 'String') throw new TypeError(\"Expected a string but received a \".concat(input.constructor.name));\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = checkHost;\nfunction isRegExp(obj) {\n return Object.prototype.toString.call(obj) === '[object RegExp]';\n}\nfunction checkHost(host, matches) {\n for (var i = 0; i < matches.length; i++) {\n var match = matches[i];\n if (host === match || isRegExp(match) && match.test(host)) {\n return true;\n }\n }\n return false;\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = isByteLength;\nvar _assertString = _interopRequireDefault(require(\"./util/assertString\"));\nfunction _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\n/* eslint-disable prefer-rest-params */\nfunction isByteLength(str, options) {\n (0, _assertString.default)(str);\n var min;\n var max;\n if (_typeof(options) === 'object') {\n min = options.min || 0;\n max = options.max;\n } else {\n // backwards compatibility: isByteLength(str, min [, max])\n min = arguments[1];\n max = arguments[2];\n }\n var len = encodeURI(str).split(/%..|./).length - 1;\n return len >= min && (typeof max === 'undefined' || len <= max);\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = merge;\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction merge() {\n var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n var defaults = arguments.length > 1 ? arguments[1] : undefined;\n if (_typeof(obj) !== 'object' || obj === null) {\n obj = {};\n }\n for (var key in defaults) {\n if (typeof obj[key] === 'undefined') {\n obj[key] = defaults[key];\n }\n }\n return obj;\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = isFQDN;\nvar _assertString = _interopRequireDefault(require(\"./util/assertString\"));\nvar _merge = _interopRequireDefault(require(\"./util/merge\"));\nfunction _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }\nvar default_fqdn_options = {\n require_tld: true,\n allow_underscores: false,\n allow_trailing_dot: false,\n allow_numeric_tld: false,\n allow_wildcard: false,\n ignore_max_length: false\n};\nfunction isFQDN(str, options) {\n (0, _assertString.default)(str);\n options = (0, _merge.default)(options, default_fqdn_options);\n\n /* Remove the optional trailing dot before checking validity */\n if (options.allow_trailing_dot && str[str.length - 1] === '.') {\n str = str.substring(0, str.length - 1);\n }\n\n /* Remove the optional wildcard before checking validity */\n if (options.allow_wildcard === true && str.indexOf('*.') === 0) {\n str = str.substring(2);\n }\n var parts = str.split('.');\n var tld = parts[parts.length - 1];\n if (options.require_tld) {\n // disallow fqdns without tld\n if (parts.length < 2) {\n return false;\n }\n if (!options.allow_numeric_tld && !/^([a-z\\u00A1-\\u00A8\\u00AA-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]{2,}|xn[a-z0-9-]{2,})$/i.test(tld)) {\n return false;\n }\n\n // disallow spaces\n if (/\\s/.test(tld)) {\n return false;\n }\n }\n\n // reject numeric TLDs\n if (!options.allow_numeric_tld && /^\\d+$/.test(tld)) {\n return false;\n }\n return parts.every(function (part) {\n if (part.length > 63 && !options.ignore_max_length) {\n return false;\n }\n if (!/^[a-z_\\u00a1-\\uffff0-9-]+$/i.test(part)) {\n return false;\n }\n\n // disallow full-width chars\n if (/[\\uff01-\\uff5e]/.test(part)) {\n return false;\n }\n\n // disallow parts starting or ending with hyphen\n if (/^-|-$/.test(part)) {\n return false;\n }\n if (!options.allow_underscores && /_/.test(part)) {\n return false;\n }\n return true;\n });\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = isIP;\nvar _assertString = _interopRequireDefault(require(\"./util/assertString\"));\nfunction _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\n/**\n11.3. Examples\n\n The following addresses\n\n fe80::1234 (on the 1st link of the node)\n ff02::5678 (on the 5th link of the node)\n ff08::9abc (on the 10th organization of the node)\n\n would be represented as follows:\n\n fe80::1234%1\n ff02::5678%5\n ff08::9abc%10\n\n (Here we assume a natural translation from a zone index to the\n <zone_id> part, where the Nth zone of any scope is translated into\n \"N\".)\n\n If we use interface names as <zone_id>, those addresses could also be\n represented as follows:\n\n fe80::1234%ne0\n ff02::5678%pvc1.3\n ff08::9abc%interface10\n\n where the interface \"ne0\" belongs to the 1st link, \"pvc1.3\" belongs\n to the 5th link, and \"interface10\" belongs to the 10th organization.\n * * */\nvar IPv4SegmentFormat = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';\nvar IPv4AddressFormat = \"(\".concat(IPv4SegmentFormat, \"[.]){3}\").concat(IPv4SegmentFormat);\nvar IPv4AddressRegExp = new RegExp(\"^\".concat(IPv4AddressFormat, \"$\"));\nvar IPv6SegmentFormat = '(?:[0-9a-fA-F]{1,4})';\nvar IPv6AddressRegExp = new RegExp('^(' + \"(?:\".concat(IPv6SegmentFormat, \":){7}(?:\").concat(IPv6SegmentFormat, \"|:)|\") + \"(?:\".concat(IPv6SegmentFormat, \":){6}(?:\").concat(IPv4AddressFormat, \"|:\").concat(IPv6SegmentFormat, \"|:)|\") + \"(?:\".concat(IPv6SegmentFormat, \":){5}(?::\").concat(IPv4AddressFormat, \"|(:\").concat(IPv6SegmentFormat, \"){1,2}|:)|\") + \"(?:\".concat(IPv6SegmentFormat, \":){4}(?:(:\").concat(IPv6SegmentFormat, \"){0,1}:\").concat(IPv4AddressFormat, \"|(:\").concat(IPv6SegmentFormat, \"){1,3}|:)|\") + \"(?:\".concat(IPv6SegmentFormat, \":){3}(?:(:\").concat(IPv6SegmentFormat, \"){0,2}:\").concat(IPv4AddressFormat, \"|(:\").concat(IPv6SegmentFormat, \"){1,4}|:)|\") + \"(?:\".concat(IPv6SegmentFormat, \":){2}(?:(:\").concat(IPv6SegmentFormat, \"){0,3}:\").concat(IPv4AddressFormat, \"|(:\").concat(IPv6SegmentFormat, \"){1,5}|:)|\") + \"(?:\".concat(IPv6SegmentFormat, \":){1}(?:(:\").concat(IPv6SegmentFormat, \"){0,4}:\").concat(IPv4AddressFormat, \"|(:\").concat(IPv6SegmentFormat, \"){1,6}|:)|\") + \"(?::((?::\".concat(IPv6SegmentFormat, \"){0,5}:\").concat(IPv4AddressFormat, \"|(?::\").concat(IPv6SegmentFormat, \"){1,7}|:))\") + ')(%[0-9a-zA-Z.]{1,})?$');\nfunction isIP(ipAddress) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n (0, _assertString.default)(ipAddress);\n\n // accessing 'arguments' for backwards compatibility: isIP(ipAddress [, version])\n // eslint-disable-next-line prefer-rest-params\n var version = (_typeof(options) === 'object' ? options.version : arguments[1]) || '';\n if (!version) {\n return isIP(ipAddress, {\n version: 4\n }) || isIP(ipAddress, {\n version: 6\n });\n }\n if (version.toString() === '4') {\n return IPv4AddressRegExp.test(ipAddress);\n }\n if (version.toString() === '6') {\n return IPv6AddressRegExp.test(ipAddress);\n }\n return false;\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = isEmail;\nvar _assertString = _interopRequireDefault(require(\"./util/assertString\"));\nvar _checkHost = _interopRequireDefault(require(\"./util/checkHost\"));\nvar _isByteLength = _interopRequireDefault(require(\"./isByteLength\"));\nvar _isFQDN = _interopRequireDefault(require(\"./isFQDN\"));\nvar _isIP = _interopRequireDefault(require(\"./isIP\"));\nvar _merge = _interopRequireDefault(require(\"./util/merge\"));\nfunction _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }\nvar default_email_options = {\n allow_display_name: false,\n allow_underscores: false,\n require_display_name: false,\n allow_utf8_local_part: true,\n require_tld: true,\n blacklisted_chars: '',\n ignore_max_length: false,\n host_blacklist: [],\n host_whitelist: []\n};\n\n/* eslint-disable max-len */\n/* eslint-disable no-control-regex */\nvar splitNameAddress = /^([^\\x00-\\x1F\\x7F-\\x9F\\cX]+)</i;\nvar emailUserPart = /^[a-z\\d!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]+$/i;\nvar gmailUserPart = /^[a-z\\d]+$/;\nvar quotedEmailUser = /^([\\s\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f\\x21\\x23-\\x5b\\x5d-\\x7e]|(\\\\[\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]))*$/i;\nvar emailUserUtf8Part = /^[a-z\\d!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~\\u00A1-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]+$/i;\nvar quotedEmailUserUtf8 = /^([\\s\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f\\x21\\x23-\\x5b\\x5d-\\x7e\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]|(\\\\[\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))*$/i;\nvar defaultMaxEmailLength = 254;\n/* eslint-enable max-len */\n/* eslint-enable no-control-regex */\n\n/**\n * Validate display name according to the RFC2822: https://tools.ietf.org/html/rfc2822#appendix-A.1.2\n * @param {String} display_name\n */\nfunction validateDisplayName(display_name) {\n var display_name_without_quotes = display_name.replace(/^\"(.+)\"$/, '$1');\n // display name with only spaces is not valid\n if (!display_name_without_quotes.trim()) {\n return false;\n }\n\n // check whether display name contains illegal character\n var contains_illegal = /[\\.\";<>]/.test(display_name_without_quotes);\n if (contains_illegal) {\n // if contains illegal characters,\n // must to be enclosed in double-quotes, otherwise it's not a valid display name\n if (display_name_without_quotes === display_name) {\n return false;\n }\n\n // the quotes in display name must start with character symbol \\\n var all_start_with_back_slash = display_name_without_quotes.split('\"').length === display_name_without_quotes.split('\\\\\"').length;\n if (!all_start_with_back_slash) {\n return false;\n }\n }\n return true;\n}\nfunction isEmail(str, options) {\n (0, _assertString.default)(str);\n options = (0, _merge.default)(options, default_email_options);\n if (options.require_display_name || options.allow_display_name) {\n var display_email = str.match(splitNameAddress);\n if (display_email) {\n var display_name = display_email[1];\n\n // Remove display name and angle brackets to get email address\n // Can be done in the regex but will introduce a ReDOS (See #1597 for more info)\n str = str.replace(display_name, '').replace(/(^<|>$)/g, '');\n\n // sometimes need to trim the last space to get the display name\n // because there may be a space between display name and email address\n // eg. myname <address@gmail.com>\n // the display name is `myname` instead of `myname `, so need to trim the last space\n if (display_name.endsWith(' ')) {\n display_name = display_name.slice(0, -1);\n }\n if (!validateDisplayName(display_name)) {\n return false;\n }\n } else if (options.require_display_name) {\n return false;\n }\n }\n if (!options.ignore_max_length && str.length > defaultMaxEmailLength) {\n return false;\n }\n var parts = str.split('@');\n var domain = parts.pop();\n var lower_domain = domain.toLowerCase();\n if (options.host_blacklist.length > 0 && (0, _checkHost.default)(lower_domain, options.host_blacklist)) {\n return false;\n }\n if (options.host_whitelist.length > 0 && !(0, _checkHost.default)(lower_domain, options.host_whitelist)) {\n return false;\n }\n var user = parts.join('@');\n if (options.domain_specific_validation && (lower_domain === 'gmail.com' || lower_domain === 'googlemail.com')) {\n /*\n Previously we removed dots for gmail addresses before validating.\n This was removed because it allows `multiple..dots@gmail.com`\n to be reported as valid, but it is not.\n Gmail only normalizes single dots, removing them from here is pointless,\n should be done in normalizeEmail\n */\n user = user.toLowerCase();\n\n // Removing sub-address from username before gmail validation\n var username = user.split('+')[0];\n\n // Dots are not included in gmail length restriction\n if (!(0, _isByteLength.default)(username.replace(/\\./g, ''), {\n min: 6,\n max: 30\n })) {\n return false;\n }\n var _user_parts = username.split('.');\n for (var i = 0; i < _user_parts.length; i++) {\n if (!gmailUserPart.test(_user_parts[i])) {\n return false;\n }\n }\n }\n if (options.ignore_max_length === false && (!(0, _isByteLength.default)(user, {\n max: 64\n }) || !(0, _isByteLength.default)(domain, {\n max: 254\n }))) {\n return false;\n }\n if (!(0, _isFQDN.default)(domain, {\n require_tld: options.require_tld,\n ignore_max_length: options.ignore_max_length,\n allow_underscores: options.allow_underscores\n })) {\n if (!options.allow_ip_domain) {\n return false;\n }\n if (!(0, _isIP.default)(domain)) {\n if (!domain.startsWith('[') || !domain.endsWith(']')) {\n return false;\n }\n var noBracketdomain = domain.slice(1, -1);\n if (noBracketdomain.length === 0 || !(0, _isIP.default)(noBracketdomain)) {\n return false;\n }\n }\n }\n if (options.blacklisted_chars) {\n if (user.search(new RegExp(\"[\".concat(options.blacklisted_chars, \"]+\"), 'g')) !== -1) return false;\n }\n if (user[0] === '\"' && user[user.length - 1] === '\"') {\n user = user.slice(1, user.length - 1);\n return options.allow_utf8_local_part ? quotedEmailUserUtf8.test(user) : quotedEmailUser.test(user);\n }\n var pattern = options.allow_utf8_local_part ? emailUserUtf8Part : emailUserPart;\n var user_parts = user.split('.');\n for (var _i = 0; _i < user_parts.length; _i++) {\n if (!pattern.test(user_parts[_i])) {\n return false;\n }\n }\n return true;\n}\nmodule.exports = exports.default;\nmodule.exports.default = exports.default;","/* -------------------------------------------------------------------- */\n/* Agent adapter — EmailInput. */\n/* */\n/* Presentational specialisation of TextInput — no actions of its own. */\n/* The handle re-exposes the underlying input's value-setter so agents */\n/* can drive the field through the normal TextInput contract without */\n/* needing to know it's wrapped. See `src/docs/26-agent-readiness.mdx` */\n/* for the contract. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\n\n/**\n * Curated agent handle for EmailInput. State stays scoped to the visible\n * value + the kit-derived validity flag; never PHI (per PRS §Security).\n */\nexport interface EmailInputHandle {\n /** Returns the current input value. */\n getValue: () => string;\n /** Returns whether the current value parses as a valid email (non-empty + RFC). */\n isValid: () => boolean;\n}\n\nexport const emailInputAgent: AgentAdapter<EmailInputHandle> = {\n id: 'email-input',\n capabilities: [],\n state: {\n value: {\n type: 'string',\n descriptionKey: 'ui.agent.emailInput.state.value',\n description: 'The current email address typed into the field.',\n read: (handle) => handle.getValue(),\n },\n isValid: {\n type: 'boolean',\n descriptionKey: 'ui.agent.emailInput.state.isValid',\n description:\n 'True when the value is non-empty AND parses as a valid email per RFC 5322.',\n read: (handle) => handle.isValid(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'email-input',\n description:\n 'Marks the EmailInput wrapper. The inline error element carries `role=\"alert\"` when validation fails.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop, when provided.',\n },\n },\n};\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type FocusEvent,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { CircleAlert } from 'lucide-react';\n// Tree-shaken import — pulling `validator/lib/isEmail` instead of the\n// barrel keeps the bundle to ~3 KB. `import { isEmail } from 'validator'`\n// drags in ~50 KB of unused validators.\nimport isEmail from 'validator/lib/isEmail';\nimport { TextInput, type TextInputProps } from '../text-input';\nimport { useFormField } from '../form-field/form-field-context';\nimport { composeRefs } from '../_shared/compose-refs';\nimport { useAgentRegistration } from '../../agent';\nimport { emailInputAgent, type EmailInputHandle } from './email-input.agent';\n\n/* ------------------------------------------------------------------ */\n/* Public API */\n/* */\n/* `type`, `autoComplete`, `inputMode`, and `tone` are baked in — the */\n/* component decides those itself. `tone` is computed from the */\n/* validation state so consumers can never wedge it into an inconsistent*/\n/* visual signal. */\n/* ------------------------------------------------------------------ */\n\nexport interface EmailInputProps extends Omit<\n TextInputProps,\n 'type' | 'autoComplete' | 'inputMode' | 'tone'\n> {\n /**\n * Override the \"Invalid email\" error message. Pass `null` to suppress\n * the built-in message entirely (e.g. when wrapping the input in a\n * `FormField` and surfacing the error through its `error` prop). When\n * omitted, the translated default `t('inputs.email.invalid')` is used.\n */\n errorMessage?: ReactNode | null;\n /**\n * Called whenever the validation state flips. `valid` is `true` when\n * the value is non-empty AND parses as a valid email, `false`\n * otherwise. The callback fires on every blur AND on every change\n * after the first blur — never before the user has had a chance to\n * type something.\n */\n onValidityChange?: (valid: boolean) => void;\n /**\n * Skip the built-in validation entirely. The input behaves like a\n * plain `<TextInput type=\"email\">` — useful when the consumer is\n * wiring `FormField`'s `invalid` prop themselves, or running their\n * own schema validation (zod, react-hook-form). Default: `false`.\n */\n disableBuiltInValidation?: boolean;\n}\n\n/* ------------------------------------------------------------------ */\n/* Validation engine */\n/* */\n/* Pure helper — empty values are NOT flagged (let `required` handle */\n/* empty separately). Whitespace-only values fall through to validator */\n/* which rejects them as malformed. */\n/* ------------------------------------------------------------------ */\n\nfunction checkValidity(value: string): boolean {\n if (value.length === 0) return true;\n return isEmail(value);\n}\n\nexport const EmailInput = forwardRef<HTMLInputElement, EmailInputProps>(\n (\n {\n errorMessage,\n onValidityChange,\n disableBuiltInValidation = false,\n value,\n defaultValue,\n onChange,\n onBlur,\n id,\n 'aria-describedby': consumerDescribedBy,\n 'aria-invalid': consumerAriaInvalid,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const ctx = useFormField();\n\n const innerRef = useRef<HTMLInputElement | null>(null);\n const composedRef = composeRefs(ref, innerRef);\n\n const reactErrorId = useId();\n // Use FormField's errorId when a FormField wraps us, otherwise fall back\n // to a local id so aria-describedby can wire the inline error element.\n const errorElementId = ctx.errorId || reactErrorId;\n\n const isControlled = value !== undefined;\n\n // Seed once from controlled `value` or `defaultValue` so we can\n // validate an already-populated field at mount (e.g. server-side\n // rehydration). Recomputing on prop changes would defeat the React\n // \"defaultValue is initial only\" contract — we read it once via the\n // lazy initialiser and let `currentValue` track every change after.\n const [internalValue, setInternalValue] = useState<string>(() => {\n if (typeof value === 'string') return value;\n if (typeof defaultValue === 'string') return defaultValue;\n return '';\n });\n const currentValue = isControlled ? String(value) : internalValue;\n\n // `touched` flips to `true` on first blur, or immediately if the\n // field is seeded with a non-empty value (consumer is asking us to\n // validate something they already collected).\n const [touched, setTouched] = useState<boolean>(\n () => currentValue.length > 0,\n );\n\n const computedValid = useMemo(\n () => checkValidity(currentValue),\n [currentValue],\n );\n\n // Surface the error only when the field has been touched AND the\n // value is non-empty AND the value fails RFC. Empty is always\n // \"not yet invalid\" — `required` covers the empty case separately.\n const shouldShowError =\n !disableBuiltInValidation &&\n touched &&\n currentValue.length > 0 &&\n !computedValid;\n\n // Notify consumers on every validity flip after the first blur.\n // Empty before first blur is reported as `true` so consumers don't\n // light up a \"valid\" indicator prematurely — we only fire after\n // touched so the first emission reflects user intent.\n const lastValidRef = useRef<boolean | null>(null);\n useEffect(() => {\n if (!touched) return;\n // Empty value after touch -> `valid` is `false` because the user\n // emptied a field they were editing. This mirrors the spec note\n // that empty is reported as `false` in `onValidityChange`.\n const nextValid = currentValue.length > 0 && computedValid;\n if (lastValidRef.current !== nextValid) {\n lastValidRef.current = nextValid;\n onValidityChange?.(nextValid);\n }\n }, [touched, currentValue, computedValid, onValidityChange]);\n\n const handleChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) {\n setInternalValue(event.target.value);\n }\n onChange?.(event);\n },\n [isControlled, onChange],\n );\n\n const handleBlur = useCallback(\n (event: FocusEvent<HTMLInputElement>) => {\n setTouched(true);\n onBlur?.(event);\n },\n [onBlur],\n );\n\n /* ------------------------------------------------------------------ */\n /* Agent adapter */\n /* ------------------------------------------------------------------ */\n\n // Stable handle — both `getValue` and `isValid` read the live DOM\n // node, so the closure captures no React state. Empty dep array\n // keeps the agent registry from churning on every keystroke.\n const agentHandle = useMemo<EmailInputHandle>(\n () => ({\n getValue: () => innerRef.current?.value ?? '',\n isValid: () => {\n const v = innerRef.current?.value ?? '';\n return v.length > 0 && isEmail(v);\n },\n }),\n [],\n );\n useAgentRegistration(emailInputAgent, agentHandle, id);\n\n /* ------------------------------------------------------------------ */\n /* aria-describedby composition */\n /* */\n /* The inline error needs to be reachable via `aria-describedby`. We */\n /* merge any consumer-supplied id with our own error id when the */\n /* validation error is visible. If a FormField wraps us, its */\n /* `describedBy` already includes the FormField error id — we only add */\n /* our own when the kit is rendering the inline error. */\n /* ------------------------------------------------------------------ */\n\n const showInlineError = shouldShowError && errorMessage !== null;\n const contextDescribedBy = ctx.describedBy || undefined;\n const describedBy = useMemo(() => {\n const parts = [\n consumerDescribedBy,\n contextDescribedBy,\n showInlineError ? errorElementId : null,\n ].filter(Boolean) as string[];\n return parts.length > 0 ? parts.join(' ') : undefined;\n }, [\n consumerDescribedBy,\n contextDescribedBy,\n showInlineError,\n errorElementId,\n ]);\n\n // When we're showing our inline error AND no FormField is already\n // signalling invalid through context, surface the error tone +\n // aria-invalid via the underlying TextInput.\n const effectiveTone = shouldShowError ? 'error' : 'default';\n // A wrapping consumer may assert invalidity for a BUSINESS reason while the\n // format is fine (e.g. \"already in use\") — honour it on the a11y attribute\n // so it's announced. Visual `tone` stays self-governed (format-only).\n const consumerInvalid =\n consumerAriaInvalid === true || consumerAriaInvalid === 'true';\n const effectiveAriaInvalid =\n shouldShowError || ctx.invalid || consumerInvalid || undefined;\n\n const resolvedErrorMessage =\n errorMessage !== undefined\n ? errorMessage\n : t('inputs.email.invalid', 'Invalid email');\n\n return (\n <div\n data-component=\"email-input\"\n data-component-id={id}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n <TextInput\n {...rest}\n ref={composedRef}\n id={id}\n type=\"email\"\n inputMode=\"email\"\n autoComplete=\"email\"\n tone={effectiveTone}\n value={isControlled ? currentValue : undefined}\n defaultValue={!isControlled ? defaultValue : undefined}\n onChange={handleChange}\n onBlur={handleBlur}\n aria-invalid={effectiveAriaInvalid}\n aria-describedby={describedBy}\n />\n {showInlineError ? (\n <p\n id={errorElementId}\n role=\"alert\"\n data-slot=\"email-input-error\"\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] type-body-sm ds:text-destructive\"\n >\n <CircleAlert aria-hidden=\"true\" className=\"ds:size-4 ds:shrink-0\" />\n <span>{resolvedErrorMessage}</span>\n </p>\n ) : null}\n </div>\n );\n },\n);\n\nEmailInput.displayName = 'EmailInput';\n"],"names":["exports","assertString","input","module","checkHost","isRegExp","obj","host","matches","i","match","isByteLength","_assertString","_interopRequireDefault","e","_typeof","o","str","options","min","max","len","merge","defaults","key","isFQDN","_merge","default_fqdn_options","parts","tld","part","isIP","IPv4SegmentFormat","IPv4AddressFormat","IPv4AddressRegExp","IPv6SegmentFormat","IPv6AddressRegExp","ipAddress","version","isEmail","_checkHost","_isByteLength","_isFQDN","_isIP","default_email_options","splitNameAddress","emailUserPart","gmailUserPart","quotedEmailUser","emailUserUtf8Part","quotedEmailUserUtf8","defaultMaxEmailLength","validateDisplayName","display_name","display_name_without_quotes","contains_illegal","all_start_with_back_slash","display_email","domain","lower_domain","user","username","_user_parts","noBracketdomain","pattern","user_parts","_i","emailInputAgent","handle","checkValidity","value","EmailInput","forwardRef","errorMessage","onValidityChange","disableBuiltInValidation","defaultValue","onChange","onBlur","id","consumerDescribedBy","consumerAriaInvalid","rest","ref","t","useTranslation","ctx","useFormField","innerRef","useRef","composedRef","composeRefs","reactErrorId","useId","errorElementId","isControlled","internalValue","setInternalValue","useState","currentValue","touched","setTouched","computedValid","useMemo","shouldShowError","lastValidRef","useEffect","nextValid","handleChange","useCallback","event","handleBlur","agentHandle","_a","v","useAgentRegistration","showInlineError","contextDescribedBy","describedBy","effectiveTone","consumerInvalid","effectiveAriaInvalid","resolvedErrorMessage","jsxs","jsx","TextInput","CircleAlert"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6]}
|