@alfadocs/ui-kit-debug 0.84.1 → 0.86.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/info-tip-Bxk3w6UM.js +166 -0
- package/dist/_chunks/info-tip-Bxk3w6UM.js.map +1 -0
- 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/{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/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 +45 -1
- package/dist/agent-i18n/en.json +9 -0
- 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/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/info-tip/index.d.ts +4 -0
- package/dist/components/info-tip/index.d.ts.map +1 -0
- package/dist/components/info-tip/index.js +6 -0
- package/dist/components/info-tip/index.js.map +1 -0
- package/dist/components/info-tip/info-tip.agent.d.ts +4 -0
- package/dist/components/info-tip/info-tip.agent.d.ts.map +1 -0
- package/dist/components/info-tip/info-tip.d.ts +42 -0
- package/dist/components/info-tip/info-tip.d.ts.map +1 -0
- 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/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/warning-stack/index.js +1 -1
- package/dist/components/workflow/index.js +1 -1
- package/dist/i18n/locales/ar.d.ts +3 -0
- package/dist/i18n/locales/ar.d.ts.map +1 -1
- package/dist/i18n/locales/ar.js +3 -0
- package/dist/i18n/locales/ar.js.map +1 -1
- package/dist/i18n/locales/de.d.ts +3 -0
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/de.js +3 -0
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/el.d.ts +3 -0
- package/dist/i18n/locales/el.d.ts.map +1 -1
- package/dist/i18n/locales/el.js +3 -0
- package/dist/i18n/locales/el.js.map +1 -1
- package/dist/i18n/locales/en.d.ts +3 -0
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +3 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +3 -0
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/es.js +3 -0
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +3 -0
- package/dist/i18n/locales/fr.d.ts.map +1 -1
- package/dist/i18n/locales/fr.js +3 -0
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hi.d.ts +3 -0
- package/dist/i18n/locales/hi.d.ts.map +1 -1
- package/dist/i18n/locales/hi.js +3 -0
- package/dist/i18n/locales/hi.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +3 -0
- package/dist/i18n/locales/it.d.ts.map +1 -1
- package/dist/i18n/locales/it.js +3 -0
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/ja.d.ts +3 -0
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/ja.js +3 -0
- package/dist/i18n/locales/ja.js.map +1 -1
- package/dist/i18n/locales/nl.d.ts +3 -0
- package/dist/i18n/locales/nl.d.ts.map +1 -1
- package/dist/i18n/locales/nl.js +3 -0
- package/dist/i18n/locales/nl.js.map +1 -1
- package/dist/i18n/locales/pl.d.ts +3 -0
- package/dist/i18n/locales/pl.d.ts.map +1 -1
- package/dist/i18n/locales/pl.js +3 -0
- package/dist/i18n/locales/pl.js.map +1 -1
- package/dist/i18n/locales/pt.d.ts +3 -0
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/pt.js +3 -0
- package/dist/i18n/locales/pt.js.map +1 -1
- package/dist/i18n/locales/ro.d.ts +3 -0
- package/dist/i18n/locales/ro.d.ts.map +1 -1
- package/dist/i18n/locales/ro.js +3 -0
- package/dist/i18n/locales/ro.js.map +1 -1
- package/dist/i18n/locales/ru.d.ts +3 -0
- package/dist/i18n/locales/ru.d.ts.map +1 -1
- package/dist/i18n/locales/ru.js +3 -0
- package/dist/i18n/locales/ru.js.map +1 -1
- package/dist/i18n/locales/sq.d.ts +3 -0
- package/dist/i18n/locales/sq.d.ts.map +1 -1
- package/dist/i18n/locales/sq.js +3 -0
- package/dist/i18n/locales/sq.js.map +1 -1
- package/dist/i18n/locales/sv.d.ts +3 -0
- package/dist/i18n/locales/sv.d.ts.map +1 -1
- package/dist/i18n/locales/sv.js +3 -0
- package/dist/i18n/locales/sv.js.map +1 -1
- package/dist/i18n/locales/tr.d.ts +3 -0
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/locales/tr.js +3 -0
- package/dist/i18n/locales/tr.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +3 -0
- package/dist/i18n/locales/zh.d.ts.map +1 -1
- package/dist/i18n/locales/zh.js +3 -0
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/index.js +715 -723
- package/dist/index.js.map +1 -1
- package/dist/locales/ar.json +3 -0
- package/dist/locales/de.json +3 -0
- package/dist/locales/el.json +3 -0
- package/dist/locales/en.json +3 -0
- package/dist/locales/es.json +3 -0
- package/dist/locales/fr.json +3 -0
- package/dist/locales/hi.json +3 -0
- package/dist/locales/it.json +3 -0
- package/dist/locales/ja.json +3 -0
- package/dist/locales/nl.json +3 -0
- package/dist/locales/pl.json +3 -0
- package/dist/locales/pt.json +3 -0
- package/dist/locales/ro.json +3 -0
- package/dist/locales/ru.json +3 -0
- package/dist/locales/sq.json +3 -0
- package/dist/locales/sv.json +3 -0
- package/dist/locales/tr.json +3 -0
- package/dist/locales/zh.json +3 -0
- 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 +9 -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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"freemium-paywall-CmV642PA.js","sources":["../../src/components/freemium-paywall/freemium-paywall.agent.ts","../../src/components/freemium-paywall/freemium-paywall.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — FreemiumPaywall. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { FreemiumPaywallHandle } from './freemium-paywall';\n\nexport const freemiumPaywallAgent: AgentAdapter<FreemiumPaywallHandle> = {\n id: 'freemium-paywall',\n capabilities: ['submit', 'dismiss'],\n state: {\n isOpen: {\n type: 'boolean',\n descriptionKey: 'ui.agent.freemiumPaywall.state.isOpen',\n description: 'True when the paywall dialog is open.',\n read: (handle) => handle.isOpen(),\n },\n selectedPlanId: {\n type: 'string | null',\n descriptionKey: 'ui.agent.freemiumPaywall.state.selectedPlanId',\n description: 'Opaque id of the currently-selected plan.',\n read: (handle) => handle.getSelectedPlanId(),\n },\n },\n actions: {\n upgrade: {\n safety: 'write',\n // Backs the `submit` capability: commits the current plan selection\n // to the host's upgrade flow (checkout / billing).\n openWorld: true,\n descriptionKey: 'ui.agent.freemiumPaywall.actions.upgrade',\n description: 'Fire onUpgrade with the currently-selected plan id.',\n errors: ['No plan selected — upgrade is a no-op until a plan is chosen.'],\n invoke: (handle) => {\n handle.upgrade();\n },\n },\n dismiss: {\n safety: 'destructive',\n // Backs the `dismiss` capability.\n descriptionKey: 'ui.agent.freemiumPaywall.actions.dismiss',\n description:\n 'Dismiss the paywall via the Not Now action. Irreversible from the same UI.',\n invoke: (handle) => {\n handle.dismiss();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'freemium-paywall',\n description: 'Marks the FreemiumPaywall dialog content.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","import {\n forwardRef,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n type ReactNode,\n} from 'react';\nimport * as RadixAlertDialog from '@radix-ui/react-alert-dialog';\nimport * as RadixRadioGroup from '@radix-ui/react-radio-group';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { useControllableState } from '../../hooks/use-controllable-state';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { freemiumPaywallAgent } from './freemium-paywall.agent';\nimport { AlertTriangle, Check } from 'lucide-react';\nimport { Button } from '../button';\nimport { Progress } from '../progress';\nimport { formatPaymentAmount } from '../payment-form';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport interface FreemiumPlan {\n id: string;\n /** Translation key for the plan name (e.g. `app.paywall.plans.pro`). */\n nameKey: string;\n /** Amount in minor units (cents, centesimi). */\n priceAmount: number;\n /** ISO 4217 currency code. */\n currency: string;\n /** Translation key for the cadence suffix (e.g. `app.paywall.period.month`). */\n perKey?: string;\n /** Per-line feature translation keys. */\n featuresKeys?: string[];\n}\n\nconst contentVariants = cva(\n [\n 'ds:fixed ds:z-[var(--z-modal)] ds:overflow-auto',\n 'ds:bg-[color:var(--popover)] ds:text-[color:var(--popover-foreground)]',\n 'ds:border ds:border-border ds:shadow-[var(--shadow-lg)]',\n // forced-colors: keep the dialog boundary visible under Windows High\n // Contrast, where `var(--border)` may collapse to system colours.\n 'ds:forced-colors:border-[CanvasText]',\n 'ds:focus:outline-none',\n ].join(' '),\n {\n variants: {\n layout: {\n centered:\n 'ds:start-1/2 ds:top-1/2 ds:-translate-x-1/2 ds:-translate-y-1/2 ds:rtl:translate-x-1/2 ds:rounded-[var(--radius-md)] ds:max-w-[var(--dialog-width-xl)] ds:w-[calc(100vw-2rem)] ds:max-h-[90vh]',\n sheet:\n // `inset-x-0` compiles to logical `inset-inline`; the\n // `inset-inline-0` spelling compiled to nothing.\n 'ds:inset-x-0 ds:bottom-0 ds:w-full ds:max-h-[90vh] ds:rounded-t-[var(--radius-md)]',\n },\n density: {\n compact:\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:pt-[var(--spacing-md)] ds:pb-[var(--spacing-md)]',\n full: 'ds:ps-[var(--spacing-lg)] ds:pe-[var(--spacing-lg)] ds:pt-[var(--spacing-lg)] ds:pb-[var(--spacing-lg)]',\n },\n },\n defaultVariants: { layout: 'centered', density: 'full' },\n },\n);\n\n/** Curated imperative handle for agent / external automation. */\nexport interface FreemiumPaywallHandle {\n isOpen: () => boolean;\n getSelectedPlanId: () => string | null;\n upgrade: () => void;\n dismiss: () => void;\n}\n\nexport interface FreemiumPaywallProps extends VariantProps<\n typeof contentVariants\n> {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n plans: FreemiumPlan[];\n /** Currently-selected plan id (controlled) or default. */\n selectedPlanId?: string;\n defaultSelectedPlanId?: string;\n onSelectedPlanChange?: (id: string) => void;\n /** Usage indicator values — omit the object to hide the bar. */\n usage?: { used: number; limit: number };\n /** Fires on upgrade. */\n onUpgrade: (planId: string) => void;\n /** Fires when the user dismisses via Not Now. */\n onCancel?: () => void;\n /** Title override; defaults to t('paywall.title'). */\n title?: ReactNode;\n /** Description override; defaults to t('paywall.description'). */\n description?: ReactNode;\n /**\n * Stable instance id. Emitted on the dialog content as\n * `data-component-id` and used as the agent-registry instance key so\n * a host can address this specific paywall.\n */\n id?: string;\n className?: string;\n}\n\nexport const FreemiumPaywall = forwardRef<HTMLDivElement, FreemiumPaywallProps>(\n (\n {\n open,\n onOpenChange,\n plans,\n selectedPlanId,\n defaultSelectedPlanId,\n onSelectedPlanChange,\n usage,\n onUpgrade,\n onCancel,\n title,\n description,\n id,\n layout = 'centered',\n density = 'full',\n className,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const titleId = useId();\n const descId = useId();\n\n const [currentSelectedRaw, handleSelectedChange] =\n useControllableState<string>({\n value: selectedPlanId,\n defaultValue: defaultSelectedPlanId ?? plans[0]?.id ?? '',\n onChange: onSelectedPlanChange,\n });\n const currentSelected = currentSelectedRaw ?? '';\n\n const handleCancel = () => {\n onCancel?.();\n onOpenChange(false);\n };\n\n const handleUpgrade = () => {\n if (!currentSelected) return;\n onUpgrade(currentSelected);\n };\n\n const openRef = useRef(open);\n openRef.current = open;\n const selectedRef = useRef<string>(currentSelected);\n selectedRef.current = currentSelected;\n\n const contentRef = useRef<HTMLDivElement>(null);\n useImperativeHandle(ref, () => contentRef.current as HTMLDivElement, []);\n\n const agentHandle = useMemo<FreemiumPaywallHandle>(\n () => ({\n isOpen: () => openRef.current,\n getSelectedPlanId: () => selectedRef.current || null,\n upgrade: () => handleUpgrade(),\n dismiss: () => handleCancel(),\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n );\n useAgentRegistration(freemiumPaywallAgent, agentHandle, id);\n\n const usagePercent = usage\n ? Math.min(\n 100,\n Math.max(0, (usage.used / Math.max(1, usage.limit)) * 100),\n )\n : 0;\n const usageFull = usage ? usage.used >= usage.limit : false;\n\n return (\n <RadixAlertDialog.Root open={open} onOpenChange={onOpenChange}>\n <RadixAlertDialog.Portal>\n <RadixAlertDialog.Overlay\n className={[\n 'ds:fixed ds:inset-0 ds:z-[var(--z-modal-backdrop)]',\n 'ds:bg-[color:var(--background)]/70',\n 'ds:motion-safe:data-[state=open]:animate-in ds:motion-safe:data-[state=closed]:animate-out',\n 'ds:[.theme-accessible_&]:animate-none',\n ].join(' ')}\n />\n <RadixAlertDialog.Content\n ref={contentRef}\n aria-labelledby={titleId}\n aria-describedby={descId}\n className={contentVariants({ layout, density, className })}\n data-component=\"freemium-paywall\"\n data-component-id={id}\n >\n <RadixAlertDialog.Title id={titleId} asChild>\n <h2 className=\"type-title-card\">{title ?? t('paywall.title')}</h2>\n </RadixAlertDialog.Title>\n <RadixAlertDialog.Description id={descId} asChild>\n <p className=\"ds:mt-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\">\n {description ?? t('paywall.description')}\n </p>\n </RadixAlertDialog.Description>\n\n {usage ? (\n <div className=\"ds:mt-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)] ds:mb-[var(--spacing-xs)]\">\n {usageFull ? (\n <AlertTriangle\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:text-[color:var(--destructive)]\"\n />\n ) : null}\n <span\n className={[\n 'type-body-sm',\n usageFull\n ? 'ds:text-[color:var(--destructive)]'\n : 'ds:text-[color:var(--muted-foreground)]',\n ].join(' ')}\n >\n {usageFull\n ? t('paywall.usageFull')\n : t('paywall.usageLabel', {\n used: usage.used,\n limit: usage.limit,\n })}\n </span>\n </div>\n <Progress\n value={usagePercent}\n max={100}\n ariaLabel={t('paywall.usageLabel', {\n used: usage.used,\n limit: usage.limit,\n })}\n className={\n usageFull\n ? 'ds:[&_[role=progressbar]>*]:bg-[color:var(--destructive)]'\n : ''\n }\n />\n </div>\n ) : null}\n\n <RadixRadioGroup.Root\n value={currentSelected}\n onValueChange={handleSelectedChange}\n aria-label={t('paywall.title')}\n className=\"ds:mt-[var(--spacing-md)] ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\"\n >\n {plans.map((plan) => {\n // Reuse the payment-form helper — it knows about\n // zero-decimal currencies (JPY, KRW, VND …) and applies\n // the right divisor. Raw `/ 100` would 100× the price in\n // those currencies.\n const formattedPrice = formatPaymentAmount(\n plan.priceAmount,\n plan.currency,\n i18n.language,\n );\n const period = plan.perKey ? t(plan.perKey) : undefined;\n const priceLine = period\n ? t('paywall.pricePer', { price: formattedPrice, period })\n : formattedPrice;\n const planName = t(plan.nameKey);\n return (\n <RadixRadioGroup.Item\n key={plan.id}\n value={plan.id}\n className={[\n 'ds:group ds:relative ds:flex ds:flex-col ds:items-stretch',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--card-border)] ds:[.theme-accessible_&]:border-2',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:pt-[var(--spacing-sm)] ds:pb-[var(--spacing-sm)]',\n 'ds:text-start ds:bg-[color:var(--card)] ds:text-[color:var(--card-foreground)]',\n 'ds:data-[state=checked]:border-[color:var(--primary)]',\n 'ds:data-[state=checked]:bg-[color:var(--primary)]/5',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n ].join(' ')}\n >\n <span className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <span className=\"ds:font-semibold\">{planName}</span>\n <span className=\"ds:tabular-nums\">{priceLine}</span>\n </span>\n {plan.featuresKeys && plan.featuresKeys.length > 0 ? (\n <ul\n aria-label={t('paywall.features')}\n className=\"ds:mt-[var(--spacing-xs)] ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n {plan.featuresKeys.map((key, i) => (\n <li\n key={i}\n className=\"ds:flex ds:items-start ds:gap-[var(--spacing-xs)] type-body-sm\"\n >\n <Check\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0 ds:text-[color:var(--primary)] ds:mt-[1px]\"\n />\n <span>{t(key)}</span>\n </li>\n ))}\n </ul>\n ) : null}\n </RadixRadioGroup.Item>\n );\n })}\n </RadixRadioGroup.Root>\n\n <div className=\"ds:mt-[var(--spacing-lg)] ds:flex ds:items-center ds:gap-[var(--spacing-sm)] ds:justify-end\">\n <RadixAlertDialog.Cancel asChild>\n <Button intent=\"outline\" onClick={handleCancel}>\n {t('paywall.notNow')}\n </Button>\n </RadixAlertDialog.Cancel>\n <RadixAlertDialog.Action asChild>\n <Button intent=\"primary\" onClick={handleUpgrade}>\n {t('paywall.upgrade')}\n </Button>\n </RadixAlertDialog.Action>\n </div>\n </RadixAlertDialog.Content>\n </RadixAlertDialog.Portal>\n </RadixAlertDialog.Root>\n );\n },\n);\n\nFreemiumPaywall.displayName = 'FreemiumPaywall';\n"],"names":["freemiumPaywallAgent","handle","contentVariants","cva","FreemiumPaywall","forwardRef","open","onOpenChange","plans","selectedPlanId","defaultSelectedPlanId","onSelectedPlanChange","usage","onUpgrade","onCancel","title","description","id","layout","density","className","ref","t","i18n","useTranslation","titleId","useId","descId","currentSelectedRaw","handleSelectedChange","useControllableState","_a","currentSelected","handleCancel","handleUpgrade","openRef","useRef","selectedRef","contentRef","useImperativeHandle","agentHandle","useMemo","useAgentRegistration","usagePercent","usageFull","jsx","RadixAlertDialog","jsxs","AlertTriangle","Progress","RadixRadioGroup","plan","formattedPrice","formatPaymentAmount","period","priceLine","planName","key","i","Check","Button"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"freemium-paywall-Dr2342_S.js","sources":["../../src/components/freemium-paywall/freemium-paywall.agent.ts","../../src/components/freemium-paywall/freemium-paywall.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — FreemiumPaywall. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { FreemiumPaywallHandle } from './freemium-paywall';\n\nexport const freemiumPaywallAgent: AgentAdapter<FreemiumPaywallHandle> = {\n id: 'freemium-paywall',\n capabilities: ['submit', 'dismiss'],\n state: {\n isOpen: {\n type: 'boolean',\n descriptionKey: 'ui.agent.freemiumPaywall.state.isOpen',\n description: 'True when the paywall dialog is open.',\n read: (handle) => handle.isOpen(),\n },\n selectedPlanId: {\n type: 'string | null',\n descriptionKey: 'ui.agent.freemiumPaywall.state.selectedPlanId',\n description: 'Opaque id of the currently-selected plan.',\n read: (handle) => handle.getSelectedPlanId(),\n },\n },\n actions: {\n upgrade: {\n safety: 'write',\n // Backs the `submit` capability: commits the current plan selection\n // to the host's upgrade flow (checkout / billing).\n openWorld: true,\n descriptionKey: 'ui.agent.freemiumPaywall.actions.upgrade',\n description: 'Fire onUpgrade with the currently-selected plan id.',\n errors: ['No plan selected — upgrade is a no-op until a plan is chosen.'],\n invoke: (handle) => {\n handle.upgrade();\n },\n },\n dismiss: {\n safety: 'destructive',\n // Backs the `dismiss` capability.\n descriptionKey: 'ui.agent.freemiumPaywall.actions.dismiss',\n description:\n 'Dismiss the paywall via the Not Now action. Irreversible from the same UI.',\n invoke: (handle) => {\n handle.dismiss();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'freemium-paywall',\n description: 'Marks the FreemiumPaywall dialog content.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","import {\n forwardRef,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n type ReactNode,\n} from 'react';\nimport * as RadixAlertDialog from '@radix-ui/react-alert-dialog';\nimport * as RadixRadioGroup from '@radix-ui/react-radio-group';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { useControllableState } from '../../hooks/use-controllable-state';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { freemiumPaywallAgent } from './freemium-paywall.agent';\nimport { TriangleAlert, Check } from 'lucide-react';\nimport { Button } from '../button';\nimport { Progress } from '../progress';\nimport { formatPaymentAmount } from '../payment-form';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport interface FreemiumPlan {\n id: string;\n /** Translation key for the plan name (e.g. `app.paywall.plans.pro`). */\n nameKey: string;\n /** Amount in minor units (cents, centesimi). */\n priceAmount: number;\n /** ISO 4217 currency code. */\n currency: string;\n /** Translation key for the cadence suffix (e.g. `app.paywall.period.month`). */\n perKey?: string;\n /** Per-line feature translation keys. */\n featuresKeys?: string[];\n}\n\nconst contentVariants = cva(\n [\n 'ds:fixed ds:z-[var(--z-modal)] ds:overflow-auto',\n 'ds:bg-[color:var(--popover)] ds:text-[color:var(--popover-foreground)]',\n 'ds:border ds:border-border ds:shadow-[var(--shadow-lg)]',\n // forced-colors: keep the dialog boundary visible under Windows High\n // Contrast, where `var(--border)` may collapse to system colours.\n 'ds:forced-colors:border-[CanvasText]',\n 'ds:focus:outline-none',\n ].join(' '),\n {\n variants: {\n layout: {\n centered:\n 'ds:start-1/2 ds:top-1/2 ds:-translate-x-1/2 ds:-translate-y-1/2 ds:rtl:translate-x-1/2 ds:rounded-[var(--radius-md)] ds:max-w-[var(--dialog-width-xl)] ds:w-[calc(100vw-2rem)] ds:max-h-[90vh]',\n sheet:\n // `inset-x-0` compiles to logical `inset-inline`; the\n // `inset-inline-0` spelling compiled to nothing.\n 'ds:inset-x-0 ds:bottom-0 ds:w-full ds:max-h-[90vh] ds:rounded-t-[var(--radius-md)]',\n },\n density: {\n compact:\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:pt-[var(--spacing-md)] ds:pb-[var(--spacing-md)]',\n full: 'ds:ps-[var(--spacing-lg)] ds:pe-[var(--spacing-lg)] ds:pt-[var(--spacing-lg)] ds:pb-[var(--spacing-lg)]',\n },\n },\n defaultVariants: { layout: 'centered', density: 'full' },\n },\n);\n\n/** Curated imperative handle for agent / external automation. */\nexport interface FreemiumPaywallHandle {\n isOpen: () => boolean;\n getSelectedPlanId: () => string | null;\n upgrade: () => void;\n dismiss: () => void;\n}\n\nexport interface FreemiumPaywallProps extends VariantProps<\n typeof contentVariants\n> {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n plans: FreemiumPlan[];\n /** Currently-selected plan id (controlled) or default. */\n selectedPlanId?: string;\n defaultSelectedPlanId?: string;\n onSelectedPlanChange?: (id: string) => void;\n /** Usage indicator values — omit the object to hide the bar. */\n usage?: { used: number; limit: number };\n /** Fires on upgrade. */\n onUpgrade: (planId: string) => void;\n /** Fires when the user dismisses via Not Now. */\n onCancel?: () => void;\n /** Title override; defaults to t('paywall.title'). */\n title?: ReactNode;\n /** Description override; defaults to t('paywall.description'). */\n description?: ReactNode;\n /**\n * Stable instance id. Emitted on the dialog content as\n * `data-component-id` and used as the agent-registry instance key so\n * a host can address this specific paywall.\n */\n id?: string;\n className?: string;\n}\n\nexport const FreemiumPaywall = forwardRef<HTMLDivElement, FreemiumPaywallProps>(\n (\n {\n open,\n onOpenChange,\n plans,\n selectedPlanId,\n defaultSelectedPlanId,\n onSelectedPlanChange,\n usage,\n onUpgrade,\n onCancel,\n title,\n description,\n id,\n layout = 'centered',\n density = 'full',\n className,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const titleId = useId();\n const descId = useId();\n\n const [currentSelectedRaw, handleSelectedChange] =\n useControllableState<string>({\n value: selectedPlanId,\n defaultValue: defaultSelectedPlanId ?? plans[0]?.id ?? '',\n onChange: onSelectedPlanChange,\n });\n const currentSelected = currentSelectedRaw ?? '';\n\n const handleCancel = () => {\n onCancel?.();\n onOpenChange(false);\n };\n\n const handleUpgrade = () => {\n if (!currentSelected) return;\n onUpgrade(currentSelected);\n };\n\n const openRef = useRef(open);\n openRef.current = open;\n const selectedRef = useRef<string>(currentSelected);\n selectedRef.current = currentSelected;\n\n const contentRef = useRef<HTMLDivElement>(null);\n useImperativeHandle(ref, () => contentRef.current as HTMLDivElement, []);\n\n const agentHandle = useMemo<FreemiumPaywallHandle>(\n () => ({\n isOpen: () => openRef.current,\n getSelectedPlanId: () => selectedRef.current || null,\n upgrade: () => handleUpgrade(),\n dismiss: () => handleCancel(),\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n );\n useAgentRegistration(freemiumPaywallAgent, agentHandle, id);\n\n const usagePercent = usage\n ? Math.min(\n 100,\n Math.max(0, (usage.used / Math.max(1, usage.limit)) * 100),\n )\n : 0;\n const usageFull = usage ? usage.used >= usage.limit : false;\n\n return (\n <RadixAlertDialog.Root open={open} onOpenChange={onOpenChange}>\n <RadixAlertDialog.Portal>\n <RadixAlertDialog.Overlay\n className={[\n 'ds:fixed ds:inset-0 ds:z-[var(--z-modal-backdrop)]',\n 'ds:bg-[color:var(--background)]/70',\n 'ds:motion-safe:data-[state=open]:animate-in ds:motion-safe:data-[state=closed]:animate-out',\n 'ds:[.theme-accessible_&]:animate-none',\n ].join(' ')}\n />\n <RadixAlertDialog.Content\n ref={contentRef}\n aria-labelledby={titleId}\n aria-describedby={descId}\n className={contentVariants({ layout, density, className })}\n data-component=\"freemium-paywall\"\n data-component-id={id}\n >\n <RadixAlertDialog.Title id={titleId} asChild>\n <h2 className=\"type-title-card\">{title ?? t('paywall.title')}</h2>\n </RadixAlertDialog.Title>\n <RadixAlertDialog.Description id={descId} asChild>\n <p className=\"ds:mt-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\">\n {description ?? t('paywall.description')}\n </p>\n </RadixAlertDialog.Description>\n\n {usage ? (\n <div className=\"ds:mt-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)] ds:mb-[var(--spacing-xs)]\">\n {usageFull ? (\n <TriangleAlert\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:text-[color:var(--destructive)]\"\n />\n ) : null}\n <span\n className={[\n 'type-body-sm',\n usageFull\n ? 'ds:text-[color:var(--destructive)]'\n : 'ds:text-[color:var(--muted-foreground)]',\n ].join(' ')}\n >\n {usageFull\n ? t('paywall.usageFull')\n : t('paywall.usageLabel', {\n used: usage.used,\n limit: usage.limit,\n })}\n </span>\n </div>\n <Progress\n value={usagePercent}\n max={100}\n ariaLabel={t('paywall.usageLabel', {\n used: usage.used,\n limit: usage.limit,\n })}\n className={\n usageFull\n ? 'ds:[&_[role=progressbar]>*]:bg-[color:var(--destructive)]'\n : ''\n }\n />\n </div>\n ) : null}\n\n <RadixRadioGroup.Root\n value={currentSelected}\n onValueChange={handleSelectedChange}\n aria-label={t('paywall.title')}\n className=\"ds:mt-[var(--spacing-md)] ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\"\n >\n {plans.map((plan) => {\n // Reuse the payment-form helper — it knows about\n // zero-decimal currencies (JPY, KRW, VND …) and applies\n // the right divisor. Raw `/ 100` would 100× the price in\n // those currencies.\n const formattedPrice = formatPaymentAmount(\n plan.priceAmount,\n plan.currency,\n i18n.language,\n );\n const period = plan.perKey ? t(plan.perKey) : undefined;\n const priceLine = period\n ? t('paywall.pricePer', { price: formattedPrice, period })\n : formattedPrice;\n const planName = t(plan.nameKey);\n return (\n <RadixRadioGroup.Item\n key={plan.id}\n value={plan.id}\n className={[\n 'ds:group ds:relative ds:flex ds:flex-col ds:items-stretch',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--card-border)] ds:[.theme-accessible_&]:border-2',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:pt-[var(--spacing-sm)] ds:pb-[var(--spacing-sm)]',\n 'ds:text-start ds:bg-[color:var(--card)] ds:text-[color:var(--card-foreground)]',\n 'ds:data-[state=checked]:border-[color:var(--primary)]',\n 'ds:data-[state=checked]:bg-[color:var(--primary)]/5',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n ].join(' ')}\n >\n <span className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <span className=\"ds:font-semibold\">{planName}</span>\n <span className=\"ds:tabular-nums\">{priceLine}</span>\n </span>\n {plan.featuresKeys && plan.featuresKeys.length > 0 ? (\n <ul\n aria-label={t('paywall.features')}\n className=\"ds:mt-[var(--spacing-xs)] ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n {plan.featuresKeys.map((key, i) => (\n <li\n key={i}\n className=\"ds:flex ds:items-start ds:gap-[var(--spacing-xs)] type-body-sm\"\n >\n <Check\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0 ds:text-[color:var(--primary)] ds:mt-[1px]\"\n />\n <span>{t(key)}</span>\n </li>\n ))}\n </ul>\n ) : null}\n </RadixRadioGroup.Item>\n );\n })}\n </RadixRadioGroup.Root>\n\n <div className=\"ds:mt-[var(--spacing-lg)] ds:flex ds:items-center ds:gap-[var(--spacing-sm)] ds:justify-end\">\n <RadixAlertDialog.Cancel asChild>\n <Button intent=\"outline\" onClick={handleCancel}>\n {t('paywall.notNow')}\n </Button>\n </RadixAlertDialog.Cancel>\n <RadixAlertDialog.Action asChild>\n <Button intent=\"primary\" onClick={handleUpgrade}>\n {t('paywall.upgrade')}\n </Button>\n </RadixAlertDialog.Action>\n </div>\n </RadixAlertDialog.Content>\n </RadixAlertDialog.Portal>\n </RadixAlertDialog.Root>\n );\n },\n);\n\nFreemiumPaywall.displayName = 'FreemiumPaywall';\n"],"names":["freemiumPaywallAgent","handle","contentVariants","cva","FreemiumPaywall","forwardRef","open","onOpenChange","plans","selectedPlanId","defaultSelectedPlanId","onSelectedPlanChange","usage","onUpgrade","onCancel","title","description","id","layout","density","className","ref","t","i18n","useTranslation","titleId","useId","descId","currentSelectedRaw","handleSelectedChange","useControllableState","_a","currentSelected","handleCancel","handleUpgrade","openRef","useRef","selectedRef","contentRef","useImperativeHandle","agentHandle","useMemo","useAgentRegistration","usagePercent","usageFull","jsx","RadixAlertDialog","jsxs","TriangleAlert","Progress","RadixRadioGroup","plan","formattedPrice","formatPaymentAmount","period","priceLine","planName","key","i","Check","Button"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iban-input-DXIA8Ln_.js","sources":["../../src/components/iban-input/iban-input.agent.ts","../../src/components/iban-input/is-valid-iban.ts","../../src/components/iban-input/iban-input.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — IbanInput. */\n/* */\n/* See `src/docs/26-agent-readiness.mdx` for the contract. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { IbanInputHandle } from './iban-input';\n\nexport const ibanInputAgent: AgentAdapter<IbanInputHandle> = {\n id: 'iban-input',\n capabilities: ['set_value'],\n state: {\n value: {\n type: 'string',\n descriptionKey: 'ui.agent.ibanInput.state.value',\n description:\n 'Current IBAN, normalised (uppercased, [A-Z0-9], no spaces, ≤34 characters).',\n read: (handle) => handle.getValue(),\n },\n isValid: {\n type: 'boolean',\n descriptionKey: 'ui.agent.ibanInput.state.isValid',\n description:\n 'Whether the value is a structurally complete IBAN with a passing mod-97-10 checksum.',\n read: (handle) => handle.isValid(),\n },\n },\n actions: {\n set_value: {\n safety: 'write',\n argsType: '{ value: string }',\n argsSchema: {\n type: 'object',\n properties: { value: { type: 'string' } },\n required: ['value'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.ibanInput.actions.setValue',\n description:\n 'Replace the IBAN. The value is uppercased and stripped to [A-Z0-9], capped at 34 characters.',\n examples: [\n {\n args: { value: 'DE89370400440532013000' },\n note: 'A complete, checksum-valid German IBAN.',\n },\n ],\n invoke: (handle, args: { value: string }) => {\n handle.setValue(args.value);\n },\n },\n clear: {\n safety: 'destructive',\n idempotent: true,\n descriptionKey: 'ui.agent.ibanInput.actions.clear',\n description: 'Empty the input. Loses any typed value.',\n invoke: (handle) => {\n handle.clear();\n },\n },\n focus: {\n safety: 'read',\n descriptionKey: 'ui.agent.ibanInput.actions.focus',\n description: 'Move keyboard focus to the IBAN input.',\n invoke: (handle) => {\n handle.focus();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'iban-input',\n description: 'Marks the IbanInput wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","/* -------------------------------------------------------------------- */\n/* IBAN validation — ISO 13616 structure + ISO 7064 mod-97-10 checksum. */\n/* */\n/* No third-party dependency: the mod-97 reduction is done in chunks so */\n/* no BigInt is needed, and the per-country length table is the published */\n/* IBAN registry (SEPA + common others). Mirrors the validation-helper */\n/* shape of `is-valid-codice-fiscale.ts`. */\n/* -------------------------------------------------------------------- */\n\n/** Why an IBAN is (in)valid — drives the component's error messaging. */\nexport type IbanReason =\n | 'valid'\n | 'empty'\n | 'incomplete'\n | 'badFormat'\n | 'badChecksum';\n\n/**\n * Published IBAN lengths by ISO-3166 alpha-2 country code (the SEPA zone plus\n * the common non-SEPA registry entries). Used to decide when a typed value is\n * \"complete\" so the component never flags a partially-entered IBAN as invalid.\n */\nexport const IBAN_LENGTHS: Record<string, number> = {\n AD: 24,\n AE: 23,\n AL: 28,\n AT: 20,\n AZ: 28,\n BA: 20,\n BE: 16,\n BG: 22,\n BH: 22,\n BR: 29,\n BY: 28,\n CH: 21,\n CR: 22,\n CY: 28,\n CZ: 24,\n DE: 22,\n DK: 18,\n DO: 28,\n EE: 20,\n EG: 29,\n ES: 24,\n FI: 18,\n FO: 18,\n FR: 27,\n GB: 22,\n GE: 22,\n GI: 23,\n GL: 18,\n GR: 27,\n GT: 28,\n HR: 21,\n HU: 28,\n IE: 22,\n IL: 23,\n IS: 26,\n IT: 27,\n JO: 30,\n KW: 30,\n KZ: 20,\n LB: 28,\n LC: 32,\n LI: 21,\n LT: 20,\n LU: 20,\n LV: 21,\n MC: 27,\n MD: 24,\n ME: 22,\n MK: 19,\n MR: 27,\n MT: 31,\n MU: 30,\n NL: 18,\n NO: 15,\n PK: 24,\n PL: 28,\n PS: 29,\n PT: 25,\n QA: 29,\n RO: 24,\n RS: 22,\n SA: 24,\n SC: 31,\n SE: 24,\n SI: 19,\n SK: 24,\n SM: 27,\n TN: 24,\n TR: 26,\n UA: 29,\n VG: 24,\n XK: 20,\n};\n\n/** The shortest registered IBAN (Norway, 15) — the completeness floor for an\n * unknown country code. */\nexport const MIN_IBAN_LENGTH = 15;\n/** The longest registered IBAN (34) — the hard input cap. */\nexport const MAX_IBAN_LENGTH = 34;\n\n/**\n * ISO 7064 mod-97-10. Moves the leading 4 characters (country + check digits)\n * to the end, maps letters A–Z to 10–35, and reduces the resulting decimal\n * string modulo 97 in chunks (avoids BigInt). A valid IBAN yields `1`.\n *\n * Assumes `value` is already normalised to `[A-Z0-9]` (uppercase, no spaces).\n */\nexport function ibanMod97(value: string): number {\n const rearranged = value.slice(4) + value.slice(0, 4);\n let remainder = 0;\n for (let i = 0; i < rearranged.length; i += 1) {\n const code = rearranged.charCodeAt(i);\n // A–Z (65–90) → \"10\"..\"35\"; 0–9 stay as the single digit character.\n const mapped =\n code >= 65 && code <= 90 ? String(code - 55) : String.fromCharCode(code);\n for (let j = 0; j < mapped.length; j += 1) {\n remainder = (remainder * 10 + (mapped.charCodeAt(j) - 48)) % 97;\n }\n }\n return remainder;\n}\n\n/**\n * Classify a normalised (uppercased, `[A-Z0-9]`, ≤34-char) IBAN string. Returns\n * `'incomplete'` while the value is shorter than its country expects so the\n * caller can stay silent mid-entry, and only `'badFormat'` / `'badChecksum'`\n * once the value is structurally complete.\n */\nexport function classifyIban(raw: string): IbanReason {\n if (raw === '') return 'empty';\n const country = /^[A-Z]{2}/.test(raw) ? raw.slice(0, 2) : undefined;\n const expected = country ? IBAN_LENGTHS[country] : undefined;\n // Over-length for a known country is a definite format error.\n if (expected && raw.length > expected) return 'badFormat';\n const complete = expected\n ? raw.length === expected\n : raw.length >= MIN_IBAN_LENGTH;\n if (!complete) return 'incomplete';\n // Structural shape: 2 letters, 2 check digits, then BBAN alphanumerics.\n if (!/^[A-Z]{2}\\d{2}[A-Z0-9]+$/.test(raw)) return 'badFormat';\n return ibanMod97(raw) === 1 ? 'valid' : 'badChecksum';\n}\n\n/** Convenience boolean wrapper around {@link classifyIban}. */\nexport function isValidIban(raw: string): boolean {\n return classifyIban(raw) === 'valid';\n}\n","import {\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type ClipboardEvent,\n type CompositionEvent,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { AlertCircle, CheckCircle2 } from 'lucide-react';\nimport {\n FormFieldContext,\n useFormField,\n} from '../form-field/form-field-context';\nimport {\n INPUT_SURFACE_CHROME,\n INPUT_SURFACE_HEIGHT,\n INPUT_SURFACE_TEXT,\n INPUT_SURFACE_TONE,\n} from '../_shared/input-surface';\nimport { composeRefs } from '../_shared/compose-refs';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport { useAgentRegistration } from '../../agent';\nimport { ibanInputAgent } from './iban-input.agent';\nimport {\n classifyIban,\n MAX_IBAN_LENGTH,\n type IbanReason,\n} from './is-valid-iban';\n\n/** Agent-readiness curated handle for IbanInput. */\nexport interface IbanInputHandle {\n getValue: () => string;\n setValue: (value: string) => void;\n clear: () => void;\n focus: () => void;\n isValid: () => boolean;\n}\n\n/** Structured payload emitted on every keystroke alongside the raw value. */\nexport interface IbanChangeMeta {\n /** Structurally complete AND the mod-97-10 checksum matches. */\n isValid: boolean;\n /** Whether the value has reached its country's expected length. */\n isComplete: boolean;\n /** Why the value is (in)valid — drives consumer messaging. */\n reason: IbanReason;\n}\n\nexport interface IbanInputProps {\n /** Controlled value (raw, uppercased, no spaces). Pair with onChange. */\n value?: string;\n /** Uncontrolled initial value. Normalised on mount. */\n defaultValue?: string;\n /** Fires on every keystroke with the normalised raw string + meta. */\n onChange?: (raw: string, meta: IbanChangeMeta) => void;\n size?: 'sm' | 'md' | 'lg';\n tone?: 'default' | 'error';\n /** When the invalid tone + error string surface. Never marks partial input invalid. */\n validateOn?: 'change' | 'blur' | 'submit';\n /** Controlled escape hatch to force the invalid state (e.g. bank rejection). */\n showError?: boolean;\n /** Overrides the kit's default i18n error string. */\n errorMessage?: string;\n disabled?: boolean;\n readOnly?: boolean;\n required?: boolean;\n placeholder?: string;\n /** Render the format caption when NOT inside a FormField. */\n showFormatHint?: boolean;\n id?: string;\n name?: string;\n className?: string;\n 'aria-label'?: string;\n}\n\nconst wrapperVariants = cva(\n ['ds:relative ds:flex ds:items-center ds:w-full', INPUT_SURFACE_CHROME].join(\n ' ',\n ),\n {\n variants: {\n size: {\n sm: INPUT_SURFACE_HEIGHT.sm,\n md: INPUT_SURFACE_HEIGHT.md,\n lg: INPUT_SURFACE_HEIGHT.lg,\n },\n tone: {\n default: INPUT_SURFACE_TONE.default,\n error: `${INPUT_SURFACE_TONE.error} ds:focus-within:outline-destructive`,\n },\n },\n defaultVariants: { size: 'md', tone: 'default' },\n },\n);\n\nconst inputVariants = cva(\n [\n // dir=\"ltr\" + tabular-nums keep the IBAN rendering left-to-right and evenly\n // spaced even under an RTL/CJK surrounding UI — this is a value-RENDERING\n // concern (the IBAN is never mirrored), not a layout-direction violation,\n // so logical-prop rules don't apply to the IBAN glyphs themselves.\n 'ds:w-full ds:min-w-0 ds:bg-transparent ds:text-foreground ds:placeholder:text-muted-foreground',\n 'ds:border-0 ds:outline-none ds:tabular-nums ds:uppercase ds:tracking-wide',\n 'ds:disabled:cursor-not-allowed',\n 'ds:read-only:cursor-default',\n ].join(' '),\n {\n variants: {\n size: {\n sm: `ds:ps-3 ds:pe-3 ${INPUT_SURFACE_TEXT.sm}`,\n md: `ds:ps-3 ds:pe-3 ${INPUT_SURFACE_TEXT.md}`,\n lg: `ds:ps-4 ds:pe-4 ${INPUT_SURFACE_TEXT.lg}`,\n },\n hasEnd: {\n true: 'ds:pe-10',\n false: '',\n },\n },\n defaultVariants: { size: 'md', hasEnd: false },\n },\n);\n\nconst adornmentEnd =\n 'ds:absolute ds:inset-y-0 ds:end-0 ds:pe-3 ds:flex ds:items-center ds:pointer-events-none ds:[&_svg]:size-4';\n\nconst captionBase = 'type-body-sm ds:mt-[var(--spacing-xs)]';\n\n/** Uppercase, strip non-[A-Z0-9], normalise full-width / Eastern-Arabic\n * digits, and cap at 34 characters. */\nfunction normaliseIban(input: string): string {\n return (\n input\n .normalize('NFKC')\n // Eastern-Arabic & Extended-Arabic-Indic digits → ASCII (otp-input precedent).\n .replace(/[٠-٩]/g, (c) => String(c.charCodeAt(0) - 0x0660))\n .replace(/[۰-۹]/g, (c) => String(c.charCodeAt(0) - 0x06f0))\n .toUpperCase()\n .replace(/[^A-Z0-9]/g, '')\n .slice(0, MAX_IBAN_LENGTH)\n );\n}\n\n/** Count [A-Z0-9] characters before `position` in the RAW (pre-normalise)\n * string, so the caret can be restored after re-normalising. */\nfunction countKeptBefore(str: string, position: number): number {\n let kept = 0;\n for (let i = 0; i < position && i < str.length; i += 1) {\n const c = str[i];\n if (\n (c >= '0' && c <= '9') ||\n (c >= 'A' && c <= 'Z') ||\n (c >= 'a' && c <= 'z')\n ) {\n kept += 1;\n }\n }\n return kept;\n}\n\nexport const IbanInput = forwardRef<HTMLInputElement, IbanInputProps>(\n function IbanInput(\n {\n value,\n defaultValue,\n onChange,\n size = 'md',\n tone = 'default',\n validateOn = 'blur',\n showError,\n errorMessage,\n disabled,\n readOnly,\n required,\n placeholder,\n showFormatHint = true,\n id,\n name,\n className,\n 'aria-label': ariaLabel,\n },\n ref,\n ) {\n const { t } = useTranslation();\n const ctx = useFormField();\n const inFormField = useContext(FormFieldContext) !== null;\n\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState<string>(() =>\n normaliseIban(defaultValue ?? ''),\n );\n const currentValue = isControlled\n ? normaliseIban(value ?? '')\n : internalValue;\n\n const [blurred, setBlurred] = useState(false);\n const composingRef = useRef(false);\n const pendingCaretRef = useRef<number | null>(null);\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n const composedRef = composeRefs(ref, inputRef);\n\n const reactId = useId();\n const generatedHintId = `${reactId}-hint`;\n const generatedStatusId = `${reactId}-status`;\n const generatedErrorId = `${reactId}-error`;\n\n // DEV-time guard: a standalone field with no visible label needs an\n // aria-label, mirroring Button's icon-only guard. No-op in production.\n useEffect(() => {\n const isDev =\n typeof import.meta !== 'undefined' &&\n typeof import.meta.env !== 'undefined' &&\n import.meta.env.DEV === true;\n if (isDev && !inFormField && !ariaLabel) {\n console.warn(\n '[IbanInput] No FormField/label and no `aria-label` — the field has no accessible name. Wrap it in a FormField or pass `aria-label`.',\n );\n }\n }, [inFormField, ariaLabel]);\n\n const reason = useMemo(() => classifyIban(currentValue), [currentValue]);\n // \"Complete\" = the value has reached its country's expected length, so the\n // classifier has moved past 'incomplete' to a definitive verdict.\n const isComplete = reason !== 'empty' && reason !== 'incomplete';\n const isValid = reason === 'valid';\n\n const effectiveDisabled =\n (inFormField ? ctx.disabled : false) || Boolean(disabled);\n const effectiveRequired =\n (inFormField ? ctx.required : false) || Boolean(required);\n\n // Whether the component's OWN feedback should surface. `showError` is a\n // controlled escape hatch (e.g. the bank rejected the IBAN); otherwise the\n // client only flags a COMPLETE value that fails its structural/checksum\n // check — never a partially-typed one — and `validateOn` governs the trigger.\n const ownFeedbackActive =\n !readOnly &&\n (Boolean(showError) ||\n (isComplete &&\n !isValid &&\n (validateOn === 'change' || (validateOn === 'blur' && blurred))));\n\n // When inside a FormField with its own error, FormField's role=alert wins\n // and this component stays silent (no double message / duplicate\n // aria-describedby target).\n const formFieldHasError = inFormField && ctx.invalid;\n const showOwnError = ownFeedbackActive && !formFieldHasError;\n\n const effectiveInvalid = formFieldHasError || showOwnError;\n const effectiveTone: 'default' | 'error' =\n effectiveInvalid || tone === 'error' ? 'error' : 'default';\n\n const ownErrorText = useMemo(() => {\n if (errorMessage) return errorMessage;\n if (reason === 'badChecksum') return t('inputs.iban.errorChecksum');\n if (reason === 'badFormat') return t('inputs.iban.errorFormat');\n return t('inputs.iban.errorIncomplete');\n }, [errorMessage, reason, t]);\n\n const wantsHint = !inFormField && showFormatHint && !readOnly;\n const standaloneDescribedBy = inFormField\n ? undefined\n : [\n wantsHint ? generatedHintId : null,\n showOwnError ? generatedErrorId : generatedStatusId,\n ]\n .filter(Boolean)\n .join(' ') || undefined;\n const describedBy = inFormField\n ? ctx.describedBy || undefined\n : standaloneDescribedBy;\n\n const inputId = id ?? ctx.id;\n\n const emit = useCallback(\n (next: string) => {\n const nextReason = classifyIban(next);\n onChange?.(next, {\n isValid: nextReason === 'valid',\n isComplete: nextReason !== 'empty' && nextReason !== 'incomplete',\n reason: nextReason,\n });\n },\n [onChange],\n );\n\n const commit = useCallback(\n (next: string) => {\n if (!isControlled) setInternalValue(next);\n emit(next);\n },\n [isControlled, emit],\n );\n\n // Restore caret after a normalising re-render that may have changed the\n // string length (mid-string edit / paste). Mirrors phone-input's caret\n // discipline.\n useIsomorphicLayoutEffect(() => {\n if (pendingCaretRef.current == null) return;\n const pos = pendingCaretRef.current;\n pendingCaretRef.current = null;\n const node = inputRef.current;\n if (node && document.activeElement === node) {\n const safePos = Math.min(pos, node.value.length);\n node.setSelectionRange(safePos, safePos);\n }\n });\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (readOnly) return;\n if (composingRef.current) return;\n const target = event.target;\n const raw = target.value;\n const caret = target.selectionStart ?? raw.length;\n const keptBefore = countKeptBefore(raw, caret);\n const next = normaliseIban(raw);\n pendingCaretRef.current = Math.min(keptBefore, next.length);\n commit(next);\n };\n\n const handleCompositionStart = () => {\n composingRef.current = true;\n };\n\n const handleCompositionEnd = (\n event: CompositionEvent<HTMLInputElement>,\n ) => {\n composingRef.current = false;\n if (readOnly) return;\n const next = normaliseIban(event.currentTarget.value);\n pendingCaretRef.current = next.length;\n commit(next);\n };\n\n const handlePaste = (event: ClipboardEvent<HTMLInputElement>) => {\n if (readOnly) return;\n const text = event.clipboardData.getData('text');\n event.preventDefault();\n const node = inputRef.current;\n const selStart = node?.selectionStart ?? currentValue.length;\n const selEnd = node?.selectionEnd ?? currentValue.length;\n const cleaned = normaliseIban(text);\n const before = currentValue.slice(0, selStart);\n const after = currentValue.slice(selEnd);\n const next = normaliseIban(before + cleaned + after);\n pendingCaretRef.current = Math.min(\n (before + cleaned).length,\n next.length,\n );\n commit(next);\n };\n\n const handleBlur = () => {\n if (validateOn === 'blur') setBlurred(true);\n };\n\n const agentHandle = useMemo<IbanInputHandle>(\n () => ({\n getValue: () => currentValue,\n setValue: (next) => {\n const normalised = normaliseIban(next);\n if (!isControlled) setInternalValue(normalised);\n emit(normalised);\n inputRef.current?.focus();\n },\n clear: () => {\n if (!isControlled) setInternalValue('');\n emit('');\n inputRef.current?.focus();\n },\n focus: () => inputRef.current?.focus(),\n isValid: () => classifyIban(currentValue) === 'valid',\n }),\n [currentValue, isControlled, emit],\n );\n useAgentRegistration(ibanInputAgent, agentHandle, id);\n\n const resolvedPlaceholder = placeholder ?? t('inputs.iban.placeholder');\n\n const statusMessage =\n readOnly || inFormField\n ? ''\n : isValid\n ? t('inputs.iban.valid')\n : currentValue.length > 0 && !isComplete\n ? t('inputs.iban.charactersEntered', { count: currentValue.length })\n : '';\n\n const errorText = showOwnError ? ownErrorText : '';\n\n const showEndIcon =\n !readOnly && (showOwnError || (isValid && !inFormField));\n\n return (\n <div\n className=\"ds:flex ds:flex-col\"\n data-component=\"iban-input\"\n data-component-id={id}\n >\n <div\n data-slot=\"iban-input\"\n className={wrapperVariants({ size, tone: effectiveTone, className })}\n >\n <input\n ref={composedRef}\n id={inputId}\n name={name}\n // dir=\"ltr\": the IBAN glyphs render LTR even under an RTL surrounding\n // UI — a value-rendering concern, not a layout-direction violation.\n dir=\"ltr\"\n type=\"text\"\n inputMode=\"text\"\n autoCapitalize=\"characters\"\n autoCorrect=\"off\"\n autoComplete=\"off\"\n spellCheck={false}\n maxLength={MAX_IBAN_LENGTH}\n // Loose structural mirror (2 letters + 2 digits + alphanumerics) as a\n // non-JS fallback. The real per-country length + mod-97 rule lives in\n // classifyIban.\n pattern=\"[A-Za-z]{2}[0-9]{2}[A-Za-z0-9]+\"\n value={currentValue}\n placeholder={resolvedPlaceholder}\n disabled={effectiveDisabled}\n readOnly={readOnly}\n aria-label={ariaLabel}\n aria-describedby={describedBy}\n aria-invalid={effectiveInvalid || undefined}\n aria-required={effectiveRequired || undefined}\n onChange={handleChange}\n onCompositionStart={handleCompositionStart}\n onCompositionEnd={handleCompositionEnd}\n onPaste={handlePaste}\n onBlur={handleBlur}\n className={inputVariants({ size, hasEnd: showEndIcon })}\n />\n {showEndIcon ? (\n <span\n aria-hidden=\"true\"\n className={`${adornmentEnd} ${\n showOwnError ? 'ds:text-destructive' : 'ds:text-success'\n }`}\n >\n {showOwnError ? <AlertCircle /> : <CheckCircle2 />}\n </span>\n ) : null}\n </div>\n\n {wantsHint ? (\n <p\n id={generatedHintId}\n className={`${captionBase} ds:text-muted-foreground`}\n >\n {t('inputs.iban.formatHint')}\n </p>\n ) : null}\n\n {/* Polite live region (role=status): announces the valid affordance and\n the typing-progress count as TEXT, satisfying 1.4.1 (never\n colour-only). Never carries an actionable error — that goes to the\n assertive node below, mirroring the kit's input-error convention. */}\n <p\n id={generatedStatusId}\n role=\"status\"\n aria-live=\"polite\"\n className={`${captionBase} ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] ${\n isValid ? 'ds:text-success' : 'ds:text-muted-foreground'\n } ${statusMessage ? '' : 'ds:sr-only'}`}\n >\n {statusMessage ? (\n <>\n {isValid ? (\n <CheckCircle2\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0\"\n />\n ) : null}\n <span>{statusMessage}</span>\n </>\n ) : null}\n </p>\n\n {/* Assertive error region (role=alert): a validation error the user\n must correct is announced assertively. Rendered only when the\n component owns the error — inside a FormField, FormField's\n role=alert wins. */}\n {errorText ? (\n <p\n id={generatedErrorId}\n role=\"alert\"\n className={`${captionBase} ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] ds:text-destructive`}\n >\n <AlertCircle aria-hidden=\"true\" className=\"ds:size-4 ds:shrink-0\" />\n <span>{errorText}</span>\n </p>\n ) : null}\n </div>\n );\n },\n);\n\nIbanInput.displayName = 'IbanInput';\n\nexport { wrapperVariants as ibanWrapperVariants };\n"],"names":["ibanInputAgent","handle","args","IBAN_LENGTHS","MIN_IBAN_LENGTH","MAX_IBAN_LENGTH","ibanMod97","value","rearranged","remainder","i","code","mapped","j","classifyIban","raw","country","expected","isValidIban","wrapperVariants","cva","INPUT_SURFACE_CHROME","INPUT_SURFACE_HEIGHT","INPUT_SURFACE_TONE","inputVariants","INPUT_SURFACE_TEXT","adornmentEnd","captionBase","normaliseIban","input","c","countKeptBefore","str","position","kept","IbanInput","forwardRef","defaultValue","onChange","size","tone","validateOn","showError","errorMessage","disabled","readOnly","required","placeholder","showFormatHint","id","name","className","ariaLabel","ref","t","useTranslation","ctx","useFormField","inFormField","useContext","FormFieldContext","isControlled","internalValue","setInternalValue","useState","currentValue","blurred","setBlurred","composingRef","useRef","pendingCaretRef","inputRef","composedRef","composeRefs","reactId","useId","generatedHintId","generatedStatusId","generatedErrorId","useEffect","reason","useMemo","isComplete","isValid","effectiveDisabled","effectiveRequired","ownFeedbackActive","formFieldHasError","showOwnError","effectiveInvalid","effectiveTone","ownErrorText","wantsHint","standaloneDescribedBy","describedBy","inputId","emit","useCallback","next","nextReason","commit","useIsomorphicLayoutEffect","pos","node","safePos","handleChange","event","target","caret","keptBefore","handleCompositionStart","handleCompositionEnd","handlePaste","text","selStart","selEnd","cleaned","before","after","handleBlur","agentHandle","normalised","_a","useAgentRegistration","resolvedPlaceholder","statusMessage","errorText","showEndIcon","jsxs","jsx","AlertCircle","CheckCircle2","Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"iban-input-DXIA8Ln_.js","sources":["../../src/components/iban-input/iban-input.agent.ts","../../src/components/iban-input/is-valid-iban.ts","../../src/components/iban-input/iban-input.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — IbanInput. */\n/* */\n/* See `src/docs/26-agent-readiness.mdx` for the contract. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { IbanInputHandle } from './iban-input';\n\nexport const ibanInputAgent: AgentAdapter<IbanInputHandle> = {\n id: 'iban-input',\n capabilities: ['set_value'],\n state: {\n value: {\n type: 'string',\n descriptionKey: 'ui.agent.ibanInput.state.value',\n description:\n 'Current IBAN, normalised (uppercased, [A-Z0-9], no spaces, ≤34 characters).',\n read: (handle) => handle.getValue(),\n },\n isValid: {\n type: 'boolean',\n descriptionKey: 'ui.agent.ibanInput.state.isValid',\n description:\n 'Whether the value is a structurally complete IBAN with a passing mod-97-10 checksum.',\n read: (handle) => handle.isValid(),\n },\n },\n actions: {\n set_value: {\n safety: 'write',\n argsType: '{ value: string }',\n argsSchema: {\n type: 'object',\n properties: { value: { type: 'string' } },\n required: ['value'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.ibanInput.actions.setValue',\n description:\n 'Replace the IBAN. The value is uppercased and stripped to [A-Z0-9], capped at 34 characters.',\n examples: [\n {\n args: { value: 'DE89370400440532013000' },\n note: 'A complete, checksum-valid German IBAN.',\n },\n ],\n invoke: (handle, args: { value: string }) => {\n handle.setValue(args.value);\n },\n },\n clear: {\n safety: 'destructive',\n idempotent: true,\n descriptionKey: 'ui.agent.ibanInput.actions.clear',\n description: 'Empty the input. Loses any typed value.',\n invoke: (handle) => {\n handle.clear();\n },\n },\n focus: {\n safety: 'read',\n descriptionKey: 'ui.agent.ibanInput.actions.focus',\n description: 'Move keyboard focus to the IBAN input.',\n invoke: (handle) => {\n handle.focus();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'iban-input',\n description: 'Marks the IbanInput wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","/* -------------------------------------------------------------------- */\n/* IBAN validation — ISO 13616 structure + ISO 7064 mod-97-10 checksum. */\n/* */\n/* No third-party dependency: the mod-97 reduction is done in chunks so */\n/* no BigInt is needed, and the per-country length table is the published */\n/* IBAN registry (SEPA + common others). Mirrors the validation-helper */\n/* shape of `is-valid-codice-fiscale.ts`. */\n/* -------------------------------------------------------------------- */\n\n/** Why an IBAN is (in)valid — drives the component's error messaging. */\nexport type IbanReason =\n | 'valid'\n | 'empty'\n | 'incomplete'\n | 'badFormat'\n | 'badChecksum';\n\n/**\n * Published IBAN lengths by ISO-3166 alpha-2 country code (the SEPA zone plus\n * the common non-SEPA registry entries). Used to decide when a typed value is\n * \"complete\" so the component never flags a partially-entered IBAN as invalid.\n */\nexport const IBAN_LENGTHS: Record<string, number> = {\n AD: 24,\n AE: 23,\n AL: 28,\n AT: 20,\n AZ: 28,\n BA: 20,\n BE: 16,\n BG: 22,\n BH: 22,\n BR: 29,\n BY: 28,\n CH: 21,\n CR: 22,\n CY: 28,\n CZ: 24,\n DE: 22,\n DK: 18,\n DO: 28,\n EE: 20,\n EG: 29,\n ES: 24,\n FI: 18,\n FO: 18,\n FR: 27,\n GB: 22,\n GE: 22,\n GI: 23,\n GL: 18,\n GR: 27,\n GT: 28,\n HR: 21,\n HU: 28,\n IE: 22,\n IL: 23,\n IS: 26,\n IT: 27,\n JO: 30,\n KW: 30,\n KZ: 20,\n LB: 28,\n LC: 32,\n LI: 21,\n LT: 20,\n LU: 20,\n LV: 21,\n MC: 27,\n MD: 24,\n ME: 22,\n MK: 19,\n MR: 27,\n MT: 31,\n MU: 30,\n NL: 18,\n NO: 15,\n PK: 24,\n PL: 28,\n PS: 29,\n PT: 25,\n QA: 29,\n RO: 24,\n RS: 22,\n SA: 24,\n SC: 31,\n SE: 24,\n SI: 19,\n SK: 24,\n SM: 27,\n TN: 24,\n TR: 26,\n UA: 29,\n VG: 24,\n XK: 20,\n};\n\n/** The shortest registered IBAN (Norway, 15) — the completeness floor for an\n * unknown country code. */\nexport const MIN_IBAN_LENGTH = 15;\n/** The longest registered IBAN (34) — the hard input cap. */\nexport const MAX_IBAN_LENGTH = 34;\n\n/**\n * ISO 7064 mod-97-10. Moves the leading 4 characters (country + check digits)\n * to the end, maps letters A–Z to 10–35, and reduces the resulting decimal\n * string modulo 97 in chunks (avoids BigInt). A valid IBAN yields `1`.\n *\n * Assumes `value` is already normalised to `[A-Z0-9]` (uppercase, no spaces).\n */\nexport function ibanMod97(value: string): number {\n const rearranged = value.slice(4) + value.slice(0, 4);\n let remainder = 0;\n for (let i = 0; i < rearranged.length; i += 1) {\n const code = rearranged.charCodeAt(i);\n // A–Z (65–90) → \"10\"..\"35\"; 0–9 stay as the single digit character.\n const mapped =\n code >= 65 && code <= 90 ? String(code - 55) : String.fromCharCode(code);\n for (let j = 0; j < mapped.length; j += 1) {\n remainder = (remainder * 10 + (mapped.charCodeAt(j) - 48)) % 97;\n }\n }\n return remainder;\n}\n\n/**\n * Classify a normalised (uppercased, `[A-Z0-9]`, ≤34-char) IBAN string. Returns\n * `'incomplete'` while the value is shorter than its country expects so the\n * caller can stay silent mid-entry, and only `'badFormat'` / `'badChecksum'`\n * once the value is structurally complete.\n */\nexport function classifyIban(raw: string): IbanReason {\n if (raw === '') return 'empty';\n const country = /^[A-Z]{2}/.test(raw) ? raw.slice(0, 2) : undefined;\n const expected = country ? IBAN_LENGTHS[country] : undefined;\n // Over-length for a known country is a definite format error.\n if (expected && raw.length > expected) return 'badFormat';\n const complete = expected\n ? raw.length === expected\n : raw.length >= MIN_IBAN_LENGTH;\n if (!complete) return 'incomplete';\n // Structural shape: 2 letters, 2 check digits, then BBAN alphanumerics.\n if (!/^[A-Z]{2}\\d{2}[A-Z0-9]+$/.test(raw)) return 'badFormat';\n return ibanMod97(raw) === 1 ? 'valid' : 'badChecksum';\n}\n\n/** Convenience boolean wrapper around {@link classifyIban}. */\nexport function isValidIban(raw: string): boolean {\n return classifyIban(raw) === 'valid';\n}\n","import {\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type ClipboardEvent,\n type CompositionEvent,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { CircleAlert, CircleCheck } from 'lucide-react';\nimport {\n FormFieldContext,\n useFormField,\n} from '../form-field/form-field-context';\nimport {\n INPUT_SURFACE_CHROME,\n INPUT_SURFACE_HEIGHT,\n INPUT_SURFACE_TEXT,\n INPUT_SURFACE_TONE,\n} from '../_shared/input-surface';\nimport { composeRefs } from '../_shared/compose-refs';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport { useAgentRegistration } from '../../agent';\nimport { ibanInputAgent } from './iban-input.agent';\nimport {\n classifyIban,\n MAX_IBAN_LENGTH,\n type IbanReason,\n} from './is-valid-iban';\n\n/** Agent-readiness curated handle for IbanInput. */\nexport interface IbanInputHandle {\n getValue: () => string;\n setValue: (value: string) => void;\n clear: () => void;\n focus: () => void;\n isValid: () => boolean;\n}\n\n/** Structured payload emitted on every keystroke alongside the raw value. */\nexport interface IbanChangeMeta {\n /** Structurally complete AND the mod-97-10 checksum matches. */\n isValid: boolean;\n /** Whether the value has reached its country's expected length. */\n isComplete: boolean;\n /** Why the value is (in)valid — drives consumer messaging. */\n reason: IbanReason;\n}\n\nexport interface IbanInputProps {\n /** Controlled value (raw, uppercased, no spaces). Pair with onChange. */\n value?: string;\n /** Uncontrolled initial value. Normalised on mount. */\n defaultValue?: string;\n /** Fires on every keystroke with the normalised raw string + meta. */\n onChange?: (raw: string, meta: IbanChangeMeta) => void;\n size?: 'sm' | 'md' | 'lg';\n tone?: 'default' | 'error';\n /** When the invalid tone + error string surface. Never marks partial input invalid. */\n validateOn?: 'change' | 'blur' | 'submit';\n /** Controlled escape hatch to force the invalid state (e.g. bank rejection). */\n showError?: boolean;\n /** Overrides the kit's default i18n error string. */\n errorMessage?: string;\n disabled?: boolean;\n readOnly?: boolean;\n required?: boolean;\n placeholder?: string;\n /** Render the format caption when NOT inside a FormField. */\n showFormatHint?: boolean;\n id?: string;\n name?: string;\n className?: string;\n 'aria-label'?: string;\n}\n\nconst wrapperVariants = cva(\n ['ds:relative ds:flex ds:items-center ds:w-full', INPUT_SURFACE_CHROME].join(\n ' ',\n ),\n {\n variants: {\n size: {\n sm: INPUT_SURFACE_HEIGHT.sm,\n md: INPUT_SURFACE_HEIGHT.md,\n lg: INPUT_SURFACE_HEIGHT.lg,\n },\n tone: {\n default: INPUT_SURFACE_TONE.default,\n error: `${INPUT_SURFACE_TONE.error} ds:focus-within:outline-destructive`,\n },\n },\n defaultVariants: { size: 'md', tone: 'default' },\n },\n);\n\nconst inputVariants = cva(\n [\n // dir=\"ltr\" + tabular-nums keep the IBAN rendering left-to-right and evenly\n // spaced even under an RTL/CJK surrounding UI — this is a value-RENDERING\n // concern (the IBAN is never mirrored), not a layout-direction violation,\n // so logical-prop rules don't apply to the IBAN glyphs themselves.\n 'ds:w-full ds:min-w-0 ds:bg-transparent ds:text-foreground ds:placeholder:text-muted-foreground',\n 'ds:border-0 ds:outline-none ds:tabular-nums ds:uppercase ds:tracking-wide',\n 'ds:disabled:cursor-not-allowed',\n 'ds:read-only:cursor-default',\n ].join(' '),\n {\n variants: {\n size: {\n sm: `ds:ps-3 ds:pe-3 ${INPUT_SURFACE_TEXT.sm}`,\n md: `ds:ps-3 ds:pe-3 ${INPUT_SURFACE_TEXT.md}`,\n lg: `ds:ps-4 ds:pe-4 ${INPUT_SURFACE_TEXT.lg}`,\n },\n hasEnd: {\n true: 'ds:pe-10',\n false: '',\n },\n },\n defaultVariants: { size: 'md', hasEnd: false },\n },\n);\n\nconst adornmentEnd =\n 'ds:absolute ds:inset-y-0 ds:end-0 ds:pe-3 ds:flex ds:items-center ds:pointer-events-none ds:[&_svg]:size-4';\n\nconst captionBase = 'type-body-sm ds:mt-[var(--spacing-xs)]';\n\n/** Uppercase, strip non-[A-Z0-9], normalise full-width / Eastern-Arabic\n * digits, and cap at 34 characters. */\nfunction normaliseIban(input: string): string {\n return (\n input\n .normalize('NFKC')\n // Eastern-Arabic & Extended-Arabic-Indic digits → ASCII (otp-input precedent).\n .replace(/[٠-٩]/g, (c) => String(c.charCodeAt(0) - 0x0660))\n .replace(/[۰-۹]/g, (c) => String(c.charCodeAt(0) - 0x06f0))\n .toUpperCase()\n .replace(/[^A-Z0-9]/g, '')\n .slice(0, MAX_IBAN_LENGTH)\n );\n}\n\n/** Count [A-Z0-9] characters before `position` in the RAW (pre-normalise)\n * string, so the caret can be restored after re-normalising. */\nfunction countKeptBefore(str: string, position: number): number {\n let kept = 0;\n for (let i = 0; i < position && i < str.length; i += 1) {\n const c = str[i];\n if (\n (c >= '0' && c <= '9') ||\n (c >= 'A' && c <= 'Z') ||\n (c >= 'a' && c <= 'z')\n ) {\n kept += 1;\n }\n }\n return kept;\n}\n\nexport const IbanInput = forwardRef<HTMLInputElement, IbanInputProps>(\n function IbanInput(\n {\n value,\n defaultValue,\n onChange,\n size = 'md',\n tone = 'default',\n validateOn = 'blur',\n showError,\n errorMessage,\n disabled,\n readOnly,\n required,\n placeholder,\n showFormatHint = true,\n id,\n name,\n className,\n 'aria-label': ariaLabel,\n },\n ref,\n ) {\n const { t } = useTranslation();\n const ctx = useFormField();\n const inFormField = useContext(FormFieldContext) !== null;\n\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState<string>(() =>\n normaliseIban(defaultValue ?? ''),\n );\n const currentValue = isControlled\n ? normaliseIban(value ?? '')\n : internalValue;\n\n const [blurred, setBlurred] = useState(false);\n const composingRef = useRef(false);\n const pendingCaretRef = useRef<number | null>(null);\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n const composedRef = composeRefs(ref, inputRef);\n\n const reactId = useId();\n const generatedHintId = `${reactId}-hint`;\n const generatedStatusId = `${reactId}-status`;\n const generatedErrorId = `${reactId}-error`;\n\n // DEV-time guard: a standalone field with no visible label needs an\n // aria-label, mirroring Button's icon-only guard. No-op in production.\n useEffect(() => {\n const isDev =\n typeof import.meta !== 'undefined' &&\n typeof import.meta.env !== 'undefined' &&\n import.meta.env.DEV === true;\n if (isDev && !inFormField && !ariaLabel) {\n console.warn(\n '[IbanInput] No FormField/label and no `aria-label` — the field has no accessible name. Wrap it in a FormField or pass `aria-label`.',\n );\n }\n }, [inFormField, ariaLabel]);\n\n const reason = useMemo(() => classifyIban(currentValue), [currentValue]);\n // \"Complete\" = the value has reached its country's expected length, so the\n // classifier has moved past 'incomplete' to a definitive verdict.\n const isComplete = reason !== 'empty' && reason !== 'incomplete';\n const isValid = reason === 'valid';\n\n const effectiveDisabled =\n (inFormField ? ctx.disabled : false) || Boolean(disabled);\n const effectiveRequired =\n (inFormField ? ctx.required : false) || Boolean(required);\n\n // Whether the component's OWN feedback should surface. `showError` is a\n // controlled escape hatch (e.g. the bank rejected the IBAN); otherwise the\n // client only flags a COMPLETE value that fails its structural/checksum\n // check — never a partially-typed one — and `validateOn` governs the trigger.\n const ownFeedbackActive =\n !readOnly &&\n (Boolean(showError) ||\n (isComplete &&\n !isValid &&\n (validateOn === 'change' || (validateOn === 'blur' && blurred))));\n\n // When inside a FormField with its own error, FormField's role=alert wins\n // and this component stays silent (no double message / duplicate\n // aria-describedby target).\n const formFieldHasError = inFormField && ctx.invalid;\n const showOwnError = ownFeedbackActive && !formFieldHasError;\n\n const effectiveInvalid = formFieldHasError || showOwnError;\n const effectiveTone: 'default' | 'error' =\n effectiveInvalid || tone === 'error' ? 'error' : 'default';\n\n const ownErrorText = useMemo(() => {\n if (errorMessage) return errorMessage;\n if (reason === 'badChecksum') return t('inputs.iban.errorChecksum');\n if (reason === 'badFormat') return t('inputs.iban.errorFormat');\n return t('inputs.iban.errorIncomplete');\n }, [errorMessage, reason, t]);\n\n const wantsHint = !inFormField && showFormatHint && !readOnly;\n const standaloneDescribedBy = inFormField\n ? undefined\n : [\n wantsHint ? generatedHintId : null,\n showOwnError ? generatedErrorId : generatedStatusId,\n ]\n .filter(Boolean)\n .join(' ') || undefined;\n const describedBy = inFormField\n ? ctx.describedBy || undefined\n : standaloneDescribedBy;\n\n const inputId = id ?? ctx.id;\n\n const emit = useCallback(\n (next: string) => {\n const nextReason = classifyIban(next);\n onChange?.(next, {\n isValid: nextReason === 'valid',\n isComplete: nextReason !== 'empty' && nextReason !== 'incomplete',\n reason: nextReason,\n });\n },\n [onChange],\n );\n\n const commit = useCallback(\n (next: string) => {\n if (!isControlled) setInternalValue(next);\n emit(next);\n },\n [isControlled, emit],\n );\n\n // Restore caret after a normalising re-render that may have changed the\n // string length (mid-string edit / paste). Mirrors phone-input's caret\n // discipline.\n useIsomorphicLayoutEffect(() => {\n if (pendingCaretRef.current == null) return;\n const pos = pendingCaretRef.current;\n pendingCaretRef.current = null;\n const node = inputRef.current;\n if (node && document.activeElement === node) {\n const safePos = Math.min(pos, node.value.length);\n node.setSelectionRange(safePos, safePos);\n }\n });\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (readOnly) return;\n if (composingRef.current) return;\n const target = event.target;\n const raw = target.value;\n const caret = target.selectionStart ?? raw.length;\n const keptBefore = countKeptBefore(raw, caret);\n const next = normaliseIban(raw);\n pendingCaretRef.current = Math.min(keptBefore, next.length);\n commit(next);\n };\n\n const handleCompositionStart = () => {\n composingRef.current = true;\n };\n\n const handleCompositionEnd = (\n event: CompositionEvent<HTMLInputElement>,\n ) => {\n composingRef.current = false;\n if (readOnly) return;\n const next = normaliseIban(event.currentTarget.value);\n pendingCaretRef.current = next.length;\n commit(next);\n };\n\n const handlePaste = (event: ClipboardEvent<HTMLInputElement>) => {\n if (readOnly) return;\n const text = event.clipboardData.getData('text');\n event.preventDefault();\n const node = inputRef.current;\n const selStart = node?.selectionStart ?? currentValue.length;\n const selEnd = node?.selectionEnd ?? currentValue.length;\n const cleaned = normaliseIban(text);\n const before = currentValue.slice(0, selStart);\n const after = currentValue.slice(selEnd);\n const next = normaliseIban(before + cleaned + after);\n pendingCaretRef.current = Math.min(\n (before + cleaned).length,\n next.length,\n );\n commit(next);\n };\n\n const handleBlur = () => {\n if (validateOn === 'blur') setBlurred(true);\n };\n\n const agentHandle = useMemo<IbanInputHandle>(\n () => ({\n getValue: () => currentValue,\n setValue: (next) => {\n const normalised = normaliseIban(next);\n if (!isControlled) setInternalValue(normalised);\n emit(normalised);\n inputRef.current?.focus();\n },\n clear: () => {\n if (!isControlled) setInternalValue('');\n emit('');\n inputRef.current?.focus();\n },\n focus: () => inputRef.current?.focus(),\n isValid: () => classifyIban(currentValue) === 'valid',\n }),\n [currentValue, isControlled, emit],\n );\n useAgentRegistration(ibanInputAgent, agentHandle, id);\n\n const resolvedPlaceholder = placeholder ?? t('inputs.iban.placeholder');\n\n const statusMessage =\n readOnly || inFormField\n ? ''\n : isValid\n ? t('inputs.iban.valid')\n : currentValue.length > 0 && !isComplete\n ? t('inputs.iban.charactersEntered', { count: currentValue.length })\n : '';\n\n const errorText = showOwnError ? ownErrorText : '';\n\n const showEndIcon =\n !readOnly && (showOwnError || (isValid && !inFormField));\n\n return (\n <div\n className=\"ds:flex ds:flex-col\"\n data-component=\"iban-input\"\n data-component-id={id}\n >\n <div\n data-slot=\"iban-input\"\n className={wrapperVariants({ size, tone: effectiveTone, className })}\n >\n <input\n ref={composedRef}\n id={inputId}\n name={name}\n // dir=\"ltr\": the IBAN glyphs render LTR even under an RTL surrounding\n // UI — a value-rendering concern, not a layout-direction violation.\n dir=\"ltr\"\n type=\"text\"\n inputMode=\"text\"\n autoCapitalize=\"characters\"\n autoCorrect=\"off\"\n autoComplete=\"off\"\n spellCheck={false}\n maxLength={MAX_IBAN_LENGTH}\n // Loose structural mirror (2 letters + 2 digits + alphanumerics) as a\n // non-JS fallback. The real per-country length + mod-97 rule lives in\n // classifyIban.\n pattern=\"[A-Za-z]{2}[0-9]{2}[A-Za-z0-9]+\"\n value={currentValue}\n placeholder={resolvedPlaceholder}\n disabled={effectiveDisabled}\n readOnly={readOnly}\n aria-label={ariaLabel}\n aria-describedby={describedBy}\n aria-invalid={effectiveInvalid || undefined}\n aria-required={effectiveRequired || undefined}\n onChange={handleChange}\n onCompositionStart={handleCompositionStart}\n onCompositionEnd={handleCompositionEnd}\n onPaste={handlePaste}\n onBlur={handleBlur}\n className={inputVariants({ size, hasEnd: showEndIcon })}\n />\n {showEndIcon ? (\n <span\n aria-hidden=\"true\"\n className={`${adornmentEnd} ${\n showOwnError ? 'ds:text-destructive' : 'ds:text-success'\n }`}\n >\n {showOwnError ? <CircleAlert /> : <CircleCheck />}\n </span>\n ) : null}\n </div>\n\n {wantsHint ? (\n <p\n id={generatedHintId}\n className={`${captionBase} ds:text-muted-foreground`}\n >\n {t('inputs.iban.formatHint')}\n </p>\n ) : null}\n\n {/* Polite live region (role=status): announces the valid affordance and\n the typing-progress count as TEXT, satisfying 1.4.1 (never\n colour-only). Never carries an actionable error — that goes to the\n assertive node below, mirroring the kit's input-error convention. */}\n <p\n id={generatedStatusId}\n role=\"status\"\n aria-live=\"polite\"\n className={`${captionBase} ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] ${\n isValid ? 'ds:text-success' : 'ds:text-muted-foreground'\n } ${statusMessage ? '' : 'ds:sr-only'}`}\n >\n {statusMessage ? (\n <>\n {isValid ? (\n <CircleCheck\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0\"\n />\n ) : null}\n <span>{statusMessage}</span>\n </>\n ) : null}\n </p>\n\n {/* Assertive error region (role=alert): a validation error the user\n must correct is announced assertively. Rendered only when the\n component owns the error — inside a FormField, FormField's\n role=alert wins. */}\n {errorText ? (\n <p\n id={generatedErrorId}\n role=\"alert\"\n className={`${captionBase} ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] ds:text-destructive`}\n >\n <CircleAlert aria-hidden=\"true\" className=\"ds:size-4 ds:shrink-0\" />\n <span>{errorText}</span>\n </p>\n ) : null}\n </div>\n );\n },\n);\n\nIbanInput.displayName = 'IbanInput';\n\nexport { wrapperVariants as ibanWrapperVariants };\n"],"names":["ibanInputAgent","handle","args","IBAN_LENGTHS","MIN_IBAN_LENGTH","MAX_IBAN_LENGTH","ibanMod97","value","rearranged","remainder","i","code","mapped","j","classifyIban","raw","country","expected","isValidIban","wrapperVariants","cva","INPUT_SURFACE_CHROME","INPUT_SURFACE_HEIGHT","INPUT_SURFACE_TONE","inputVariants","INPUT_SURFACE_TEXT","adornmentEnd","captionBase","normaliseIban","input","c","countKeptBefore","str","position","kept","IbanInput","forwardRef","defaultValue","onChange","size","tone","validateOn","showError","errorMessage","disabled","readOnly","required","placeholder","showFormatHint","id","name","className","ariaLabel","ref","t","useTranslation","ctx","useFormField","inFormField","useContext","FormFieldContext","isControlled","internalValue","setInternalValue","useState","currentValue","blurred","setBlurred","composingRef","useRef","pendingCaretRef","inputRef","composedRef","composeRefs","reactId","useId","generatedHintId","generatedStatusId","generatedErrorId","useEffect","reason","useMemo","isComplete","isValid","effectiveDisabled","effectiveRequired","ownFeedbackActive","formFieldHasError","showOwnError","effectiveInvalid","effectiveTone","ownErrorText","wantsHint","standaloneDescribedBy","describedBy","inputId","emit","useCallback","next","nextReason","commit","useIsomorphicLayoutEffect","pos","node","safePos","handleChange","event","target","caret","keptBefore","handleCompositionStart","handleCompositionEnd","handlePaste","text","selStart","selEnd","cleaned","before","after","handleBlur","agentHandle","normalised","_a","useAgentRegistration","resolvedPlaceholder","statusMessage","errorText","showEndIcon","jsxs","jsx","CircleAlert","CircleCheck","Fragment"],"mappings":"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"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { jsxs as u, jsx as i } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as I, useState as O, useRef as m, useEffect as k, useMemo as z } from "react";
|
|
3
|
+
import { c as C } from "./index-D2ZczOXr.js";
|
|
4
|
+
import { useTranslation as D } from "react-i18next";
|
|
5
|
+
import { P as o } from "./popover-Cc0a69sw.js";
|
|
6
|
+
import { u as P } from "./registry-DvAUVLHh.js";
|
|
7
|
+
import { I as A } from "./info-CGn22peZ.js";
|
|
8
|
+
const R = {
|
|
9
|
+
id: "info-tip",
|
|
10
|
+
capabilities: ["open", "close"],
|
|
11
|
+
state: {
|
|
12
|
+
isOpen: {
|
|
13
|
+
type: "boolean",
|
|
14
|
+
descriptionKey: "ui.agent.infoTip.state.isOpen",
|
|
15
|
+
description: "True when the info tip card is currently open.",
|
|
16
|
+
read: (t) => t.getIsOpen()
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
actions: {
|
|
20
|
+
open: {
|
|
21
|
+
safety: "read",
|
|
22
|
+
idempotent: !0,
|
|
23
|
+
descriptionKey: "ui.agent.infoTip.actions.open",
|
|
24
|
+
description: "Open the info tip card.",
|
|
25
|
+
invoke: (t) => {
|
|
26
|
+
t.open();
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
close: {
|
|
30
|
+
safety: "read",
|
|
31
|
+
idempotent: !0,
|
|
32
|
+
descriptionKey: "ui.agent.infoTip.actions.close",
|
|
33
|
+
description: "Close the info tip card.",
|
|
34
|
+
invoke: (t) => {
|
|
35
|
+
t.close();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
domHooks: {
|
|
40
|
+
root: {
|
|
41
|
+
attr: "data-component",
|
|
42
|
+
value: "info-tip",
|
|
43
|
+
description: "Marks the InfoTip trigger button."
|
|
44
|
+
},
|
|
45
|
+
instanceId: {
|
|
46
|
+
attr: "data-component-id",
|
|
47
|
+
sourceProp: "id",
|
|
48
|
+
description: "Sourced from the id prop on InfoTip."
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}, S = C(
|
|
52
|
+
[
|
|
53
|
+
"ds:relative ds:inline-flex ds:shrink-0 ds:items-center ds:justify-center",
|
|
54
|
+
"ds:rounded-[var(--radius-full)]",
|
|
55
|
+
"ds:bg-[var(--card)]",
|
|
56
|
+
"ds:text-[var(--accent)]",
|
|
57
|
+
// Single ring: the Lucide Info glyph draws its own accent circle, so the
|
|
58
|
+
// trigger carries NO CSS border of its own (a border would read as a
|
|
59
|
+
// second, concentric ring). The white circle comes from `bg-card` showing
|
|
60
|
+
// through the glyph, lifted by the drop shadow.
|
|
61
|
+
"ds:shadow-[var(--shadow-sm)]",
|
|
62
|
+
"ds:cursor-pointer",
|
|
63
|
+
"ds:transition-[color,box-shadow] ds:motion-reduce:transition-none",
|
|
64
|
+
"ds:hover:text-[var(--accent-hover)] ds:hover:shadow-[var(--shadow-md)]",
|
|
65
|
+
"ds:data-[state=open]:text-[var(--accent-hover)] ds:data-[state=open]:shadow-[var(--shadow-md)]",
|
|
66
|
+
"ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]",
|
|
67
|
+
"ds:forced-colors:focus-visible:outline-[CanvasText]"
|
|
68
|
+
].join(" "),
|
|
69
|
+
{
|
|
70
|
+
variants: {
|
|
71
|
+
size: {
|
|
72
|
+
// Both diameters sit below `--min-target-size` (44/48px), so each
|
|
73
|
+
// re-uses IconButton's invisible `::before` hit-area expansion to a
|
|
74
|
+
// full touch target on touch / small screens. From the `sm:`
|
|
75
|
+
// breakpoint up the pointer is precise, so the expansion relaxes —
|
|
76
|
+
// but the interactive target must never fall below WCAG 2.5.8's 24px:
|
|
77
|
+
// • md (24px visual) already meets the 24px floor, so its `::before`
|
|
78
|
+
// is hidden on desktop and the 24px circle IS the target.
|
|
79
|
+
// • sm (20px visual) would fall to 20px if hidden — below the floor
|
|
80
|
+
// — so instead of hiding, its `::before` shrinks to a persistent
|
|
81
|
+
// `--spacing-lg` (24px) minimum that holds on desktop too.
|
|
82
|
+
sm: 'ds:w-5 ds:h-5 ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[""] ds:sm:before:inset-x-[calc((var(--spacing-lg)-100%)/-2)] ds:sm:before:inset-y-[calc((var(--spacing-lg)-100%)/-2)]',
|
|
83
|
+
md: 'ds:w-6 ds:h-6 ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[""] ds:sm:before:hidden'
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
defaultVariants: {
|
|
87
|
+
size: "md"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
), j = I(
|
|
91
|
+
({
|
|
92
|
+
content: t,
|
|
93
|
+
heading: r,
|
|
94
|
+
size: a = "md",
|
|
95
|
+
side: v = "top",
|
|
96
|
+
align: g = "center",
|
|
97
|
+
"aria-label": h,
|
|
98
|
+
id: l,
|
|
99
|
+
className: b
|
|
100
|
+
}, w) => {
|
|
101
|
+
const { t: y } = D(), [s, d] = O(!1), n = m(s);
|
|
102
|
+
k(() => {
|
|
103
|
+
n.current = s;
|
|
104
|
+
}, [s]);
|
|
105
|
+
const T = z(
|
|
106
|
+
() => ({
|
|
107
|
+
getIsOpen: () => n.current,
|
|
108
|
+
open: () => d(!0),
|
|
109
|
+
close: () => d(!1)
|
|
110
|
+
}),
|
|
111
|
+
[]
|
|
112
|
+
);
|
|
113
|
+
P(R, T, l);
|
|
114
|
+
const c = m(null), p = () => {
|
|
115
|
+
c.current = n.current;
|
|
116
|
+
}, f = h ?? y("infoTip.triggerLabel", "More information");
|
|
117
|
+
return /* @__PURE__ */ u(o, { openOn: "hover-or-click", open: s, onOpenChange: d, children: [
|
|
118
|
+
/* @__PURE__ */ i(
|
|
119
|
+
o.Trigger,
|
|
120
|
+
{
|
|
121
|
+
ref: w,
|
|
122
|
+
"aria-label": f,
|
|
123
|
+
className: S({ size: a, className: b }),
|
|
124
|
+
"data-component": "info-tip",
|
|
125
|
+
"data-component-id": l,
|
|
126
|
+
onPointerDown: p,
|
|
127
|
+
onKeyDown: (e) => {
|
|
128
|
+
(e.key === "Enter" || e.key === " ") && p();
|
|
129
|
+
},
|
|
130
|
+
onClick: (e) => {
|
|
131
|
+
const x = c.current;
|
|
132
|
+
c.current = null, x === !1 && n.current && e.preventDefault();
|
|
133
|
+
},
|
|
134
|
+
children: /* @__PURE__ */ i(
|
|
135
|
+
A,
|
|
136
|
+
{
|
|
137
|
+
"aria-hidden": "true",
|
|
138
|
+
className: a === "sm" ? "ds:size-5" : "ds:size-6"
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
),
|
|
143
|
+
/* @__PURE__ */ u(
|
|
144
|
+
o.Content,
|
|
145
|
+
{
|
|
146
|
+
side: v,
|
|
147
|
+
align: g,
|
|
148
|
+
size: a === "sm" ? "sm" : "md",
|
|
149
|
+
"aria-label": r == null ? f : void 0,
|
|
150
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
151
|
+
onCloseAutoFocus: (e) => e.preventDefault(),
|
|
152
|
+
children: [
|
|
153
|
+
r != null && /* @__PURE__ */ i(o.Heading, { children: r }),
|
|
154
|
+
/* @__PURE__ */ i(o.Description, { children: t })
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
)
|
|
158
|
+
] });
|
|
159
|
+
}
|
|
160
|
+
);
|
|
161
|
+
j.displayName = "InfoTip";
|
|
162
|
+
export {
|
|
163
|
+
j as I,
|
|
164
|
+
R as i
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=info-tip-Bxk3w6UM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"info-tip-Bxk3w6UM.js","sources":["../../src/components/info-tip/info-tip.agent.ts","../../src/components/info-tip/info-tip.tsx"],"sourcesContent":["import type { AgentAdapter } from '../../agent/types';\nimport type { InfoTipHandle } from './info-tip';\n\nexport const infoTipAgent: AgentAdapter<InfoTipHandle> = {\n id: 'info-tip',\n capabilities: ['open', 'close'],\n state: {\n isOpen: {\n type: 'boolean',\n descriptionKey: 'ui.agent.infoTip.state.isOpen',\n description: 'True when the info tip card is currently open.',\n read: (handle) => handle.getIsOpen(),\n },\n },\n actions: {\n open: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.infoTip.actions.open',\n description: 'Open the info tip card.',\n invoke: (handle) => {\n handle.open();\n },\n },\n close: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.infoTip.actions.close',\n description: 'Close the info tip card.',\n invoke: (handle) => {\n handle.close();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'info-tip',\n description: 'Marks the InfoTip trigger button.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop on InfoTip.',\n },\n },\n};\n","import {\n forwardRef,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Info } from 'lucide-react';\nimport { Popover } from '../popover';\nimport { useAgentRegistration } from '../../agent';\nimport { infoTipAgent } from './info-tip.agent';\n\n/* -------------------------------------------------------------------- */\n/* Trigger — a small circular, branded affordance: card surface inside */\n/* the circle, accent ring + accent \"i\" glyph, and a soft drop shadow. */\n/* The accent alias is safe here: `--accent` resolves to magenta-700 in */\n/* light mode (the AA-safe interactive step) and the dark accent on dark */\n/* surfaces — never reference a raw magenta ramp step. */\n/* -------------------------------------------------------------------- */\n\nconst infoTipTriggerVariants = cva(\n [\n 'ds:relative ds:inline-flex ds:shrink-0 ds:items-center ds:justify-center',\n 'ds:rounded-[var(--radius-full)]',\n 'ds:bg-[var(--card)]',\n 'ds:text-[var(--accent)]',\n // Single ring: the Lucide Info glyph draws its own accent circle, so the\n // trigger carries NO CSS border of its own (a border would read as a\n // second, concentric ring). The white circle comes from `bg-card` showing\n // through the glyph, lifted by the drop shadow.\n 'ds:shadow-[var(--shadow-sm)]',\n 'ds:cursor-pointer',\n 'ds:transition-[color,box-shadow] ds:motion-reduce:transition-none',\n 'ds:hover:text-[var(--accent-hover)] ds:hover:shadow-[var(--shadow-md)]',\n 'ds:data-[state=open]:text-[var(--accent-hover)] ds:data-[state=open]:shadow-[var(--shadow-md)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n // Both diameters sit below `--min-target-size` (44/48px), so each\n // re-uses IconButton's invisible `::before` hit-area expansion to a\n // full touch target on touch / small screens. From the `sm:`\n // breakpoint up the pointer is precise, so the expansion relaxes —\n // but the interactive target must never fall below WCAG 2.5.8's 24px:\n // • md (24px visual) already meets the 24px floor, so its `::before`\n // is hidden on desktop and the 24px circle IS the target.\n // • sm (20px visual) would fall to 20px if hidden — below the floor\n // — so instead of hiding, its `::before` shrinks to a persistent\n // `--spacing-lg` (24px) minimum that holds on desktop too.\n sm: 'ds:w-5 ds:h-5 ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[\"\"] ds:sm:before:inset-x-[calc((var(--spacing-lg)-100%)/-2)] ds:sm:before:inset-y-[calc((var(--spacing-lg)-100%)/-2)]',\n md: 'ds:w-6 ds:h-6 ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[\"\"] ds:sm:before:hidden',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n);\n\n// Curated agent-readiness handle — see info-tip.agent.ts.\nexport interface InfoTipHandle {\n getIsOpen: () => boolean;\n open: () => void;\n close: () => void;\n}\n\nexport interface InfoTipProps {\n /** Body of the tip — explanatory text shown in the floating card. */\n content: ReactNode;\n /** Optional heading rendered above the body. */\n heading?: ReactNode;\n /**\n * Trigger diameter. Also maps the floating card width:\n * `sm` → `--popover-size-sm`, `md` → `--popover-size-md`.\n */\n size?: 'sm' | 'md';\n /** Logical side the card opens on. Default `'top'`. */\n side?: 'start' | 'top' | 'end' | 'bottom';\n /** Alignment along the side axis. Default `'center'`. */\n align?: 'start' | 'center' | 'end';\n /**\n * Accessible name for the trigger. Defaults to the translated\n * \"More information\" chrome string.\n */\n 'aria-label'?: string;\n /**\n * Opaque instance id — emitted as `data-component-id` on the trigger and\n * used to register the instance with the host agent registry.\n */\n id?: string;\n /** Extra classes merged onto the trigger button. */\n className?: string;\n}\n\n/**\n * InfoTip — a deliberate, branded \"more information\" affordance: a small\n * circular trigger that reveals an explanatory card on hover **and** click\n * (click also serves touch devices). Composes the kit Popover in\n * `openOn=\"hover-or-click\"` mode — hover intent, keyboard focus, Escape and\n * focus-return are all handled by the Popover/Radix layer.\n */\nexport const InfoTip = forwardRef<HTMLButtonElement, InfoTipProps>(\n (\n {\n content,\n heading,\n size = 'md',\n side = 'top',\n align = 'center',\n 'aria-label': ariaLabelProp,\n id,\n className,\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n\n // Agent handle.\n const openRef = useRef(open);\n useEffect(() => {\n openRef.current = open;\n }, [open]);\n\n const agentHandle = useMemo<InfoTipHandle>(\n () => ({\n getIsOpen: () => openRef.current,\n open: () => setOpen(true),\n close: () => setOpen(false),\n }),\n [],\n );\n useAgentRegistration(infoTipAgent, agentHandle, id);\n\n // Press bookkeeping. In hover-or-click mode the Popover opens as soon as\n // the trigger receives focus — which happens on pointerdown, BEFORE the\n // click event that Radix uses to toggle. Without intervention every\n // click/tap on a closed tip opens it (focus) and instantly toggles it\n // closed again (click). So each press (pointerdown, or Enter/Space)\n // snapshots the open state and the click handler consumes it: if the\n // press itself opened the card, swallow Radix's toggle so the card stays\n // open; if it was already open, let the toggle close it.\n //\n // `null` means \"no press recorded for this click\" — an orphan click\n // (programmatic .click(), or assistive tech dispatching click with no\n // pointer/key event). Those must fall through to Radix's default toggle\n // rather than read a stale snapshot, so the guard treats `null` as\n // \"don't suppress\" and every click clears the snapshot back to `null`.\n const pressStateRef = useRef<boolean | null>(null);\n const handlePressStart = () => {\n pressStateRef.current = openRef.current;\n };\n\n const ariaLabel =\n ariaLabelProp ?? t('infoTip.triggerLabel', 'More information');\n\n return (\n <Popover openOn=\"hover-or-click\" open={open} onOpenChange={setOpen}>\n <Popover.Trigger\n ref={ref}\n aria-label={ariaLabel}\n className={infoTipTriggerVariants({ size, className })}\n data-component=\"info-tip\"\n data-component-id={id}\n onPointerDown={handlePressStart}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n handlePressStart();\n }\n }}\n onClick={(event) => {\n // Consume this click's press snapshot. A genuine pointer/keyboard\n // press recorded `false`/`true` on press-start; an orphan click\n // with no preceding pointerdown/keydown finds `null` and is left\n // to Radix's default toggle.\n const wasOpenAtPressStart = pressStateRef.current;\n pressStateRef.current = null;\n if (wasOpenAtPressStart === false && openRef.current) {\n // This press opened the card via focus — keep it open and\n // skip Radix's click toggle.\n event.preventDefault();\n }\n }}\n >\n <Info\n aria-hidden=\"true\"\n // Fills the circle so the glyph's own ring IS the trigger's\n // visible edge and the drop shadow hugs it.\n className={size === 'sm' ? 'ds:size-5' : 'ds:size-6'}\n />\n </Popover.Trigger>\n <Popover.Content\n side={side}\n align={align}\n size={size === 'sm' ? 'sm' : 'md'}\n // The card is a Radix `role=\"dialog\"` surface, which axe requires\n // to have an accessible name (aria-dialog-name). With a heading,\n // Popover wires aria-labelledby; without one, fall back to the\n // trigger's label.\n aria-label={heading == null ? ariaLabel : undefined}\n // Toggletip focus contract: the card is explanatory text, never\n // interactive, so focus stays on the trigger for the whole\n // open/close cycle. Preventing the open move also keeps Escape\n // reliable — if Radix pulled focus into the card, closing would\n // refocus the trigger and re-fire the hover-mode focus handler,\n // reopening the card it just closed. Preventing the close move\n // keeps an unhover-close from stealing focus mid-task.\n onOpenAutoFocus={(event) => event.preventDefault()}\n onCloseAutoFocus={(event) => event.preventDefault()}\n >\n {heading != null && <Popover.Heading>{heading}</Popover.Heading>}\n <Popover.Description>{content}</Popover.Description>\n </Popover.Content>\n </Popover>\n );\n },\n);\n\nInfoTip.displayName = 'InfoTip';\n"],"names":["infoTipAgent","handle","infoTipTriggerVariants","cva","InfoTip","forwardRef","content","heading","size","side","align","ariaLabelProp","id","className","ref","t","useTranslation","open","setOpen","useState","openRef","useRef","useEffect","agentHandle","useMemo","useAgentRegistration","pressStateRef","handlePressStart","ariaLabel","Popover","jsx","event","wasOpenAtPressStart","Info","jsxs"],"mappings":"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"}
|
package/dist/_chunks/{marketplace-app-shell-Br2yebEK.js → marketplace-app-shell-Chcj4q4z.js}
RENAMED
|
@@ -4,7 +4,7 @@ import { useTranslation as T } from "react-i18next";
|
|
|
4
4
|
import { c as u } from "./index-D2ZczOXr.js";
|
|
5
5
|
import { A as E } from "./app-frame-DIEMIC5V.js";
|
|
6
6
|
import { A as C } from "./avatar-BNQNhoyL.js";
|
|
7
|
-
import { A as D } from "./alert-
|
|
7
|
+
import { A as D } from "./alert-Cxaqd-QO.js";
|
|
8
8
|
import { C as w } from "./card-DPmk26CL.js";
|
|
9
9
|
import { D as m } from "./dropdown-menu-DU-Hrf33.js";
|
|
10
10
|
import { T as F } from "./tab-bar-Axhk6xzx.js";
|
|
@@ -510,4 +510,4 @@ export {
|
|
|
510
510
|
va as M,
|
|
511
511
|
g as P
|
|
512
512
|
};
|
|
513
|
-
//# sourceMappingURL=marketplace-app-shell-
|
|
513
|
+
//# sourceMappingURL=marketplace-app-shell-Chcj4q4z.js.map
|