@alfadocs/ui-kit-debug 0.9.0 → 0.10.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/{agenda-card-DU13wUTA.js → agenda-card-CsCm7hQv.js} +2 -2
- package/dist/_chunks/{agenda-card-DU13wUTA.js.map → agenda-card-CsCm7hQv.js.map} +1 -1
- package/dist/_chunks/{agenda-tray-gQUXklO4.js → agenda-tray-B8QZ3wEp.js} +2 -2
- package/dist/_chunks/agenda-tray-B8QZ3wEp.js.map +1 -0
- package/dist/_chunks/audio-recorder-BHBonrFf.js.map +1 -1
- package/dist/_chunks/checkbox-group-Qkm3Rg1S.js.map +1 -1
- package/dist/_chunks/{combobox-DUpWoPPk.js → combobox-BHhnR3qm.js} +4 -8
- package/dist/_chunks/{combobox-DUpWoPPk.js.map → combobox-BHhnR3qm.js.map} +1 -1
- package/dist/_chunks/{file-upload-BVbfiANR.js → file-upload-DIecAfC-.js} +4 -8
- package/dist/_chunks/file-upload-DIecAfC-.js.map +1 -0
- package/dist/_chunks/freemium-paywall-BTEiVkes.js.map +1 -1
- package/dist/_chunks/{notification-card-CRIE2Cuk.js → notification-card-ejOw5g6g.js} +2 -5
- package/dist/_chunks/{notification-card-CRIE2Cuk.js.map → notification-card-ejOw5g6g.js.map} +1 -1
- package/dist/_chunks/{notification-tray-CfXNYrxv.js → notification-tray-C3dYdLAF.js} +3 -6
- package/dist/_chunks/notification-tray-C3dYdLAF.js.map +1 -0
- package/dist/_chunks/{patient-shell-BS2V6V1b.js → patient-shell-CL20JnVJ.js} +2 -2
- package/dist/_chunks/{patient-shell-BS2V6V1b.js.map → patient-shell-CL20JnVJ.js.map} +1 -1
- package/dist/_chunks/rating-BRD7O74e.js +171 -0
- package/dist/_chunks/rating-BRD7O74e.js.map +1 -0
- package/dist/_chunks/{sidebar-CoLHtVrP.js → sidebar-D8Lq065m.js} +107 -121
- package/dist/_chunks/{sidebar-CoLHtVrP.js.map → sidebar-D8Lq065m.js.map} +1 -1
- package/dist/_chunks/{sparkline-D4Np8ikf.js → sparkline-B5Ms55PZ.js} +2 -2
- package/dist/_chunks/sparkline-B5Ms55PZ.js.map +1 -0
- package/dist/_chunks/star-vav0SJ9e.js +20 -0
- package/dist/_chunks/star-vav0SJ9e.js.map +1 -0
- package/dist/_chunks/{timeline-BaSULpSJ.js → timeline-rmls7dIh.js} +9 -9
- package/dist/_chunks/timeline-rmls7dIh.js.map +1 -0
- package/dist/_chunks/{transaction-chip-eVbolm0B.js → transaction-chip-z9ENE50O.js} +2 -2
- package/dist/_chunks/{transaction-chip-eVbolm0B.js.map → transaction-chip-z9ENE50O.js.map} +1 -1
- package/dist/_chunks/{use-password-requirements-B1M8lE2t.js → use-password-requirements-DbPZMfV9.js} +2 -2
- package/dist/_chunks/use-password-requirements-DbPZMfV9.js.map +1 -0
- package/dist/_chunks/warning-stack-CeRihME9.js.map +1 -1
- package/dist/agent-catalog.json +15 -1
- package/dist/components/agenda-card/index.js +1 -1
- package/dist/components/agenda-tray/agenda-tray.d.ts.map +1 -1
- package/dist/components/agenda-tray/index.js +1 -1
- package/dist/components/audio-recorder/audio-recorder.d.ts.map +1 -1
- package/dist/components/checkbox-group/checkbox-group.d.ts.map +1 -1
- package/dist/components/combobox/combobox.d.ts.map +1 -1
- package/dist/components/combobox/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/freemium-paywall.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/notification-card/index.js +1 -1
- package/dist/components/notification-card/notification-card.d.ts.map +1 -1
- package/dist/components/notification-tray/index.js +1 -1
- package/dist/components/notification-tray/notification-tray.d.ts.map +1 -1
- package/dist/components/password-input/index.js +1 -1
- package/dist/components/password-input/password-input.d.ts.map +1 -1
- package/dist/components/rating/index.d.ts +3 -0
- package/dist/components/rating/index.d.ts.map +1 -0
- package/dist/components/rating/index.js +5 -0
- package/dist/components/rating/index.js.map +1 -0
- package/dist/components/rating/rating.d.ts +29 -0
- package/dist/components/rating/rating.d.ts.map +1 -0
- package/dist/components/sidebar/index.js +1 -1
- package/dist/components/sparkline/index.js +1 -1
- package/dist/components/timeline/index.js +1 -1
- package/dist/components/transaction-chip/index.js +1 -1
- package/dist/components/warning-stack/warning-stack.d.ts.map +1 -1
- package/dist/i18n/config.d.ts +1 -1
- package/dist/i18n/config.d.ts.map +1 -1
- package/dist/i18n/config.js +18 -0
- package/dist/i18n/config.js.map +1 -1
- package/dist/i18n/resources.d.ts +15 -0
- package/dist/i18n/resources.d.ts.map +1 -1
- package/dist/index.js +324 -322
- package/dist/index.js.map +1 -1
- package/dist/locales/de.json +5 -0
- package/dist/locales/en.json +5 -0
- package/dist/locales/it.json +5 -0
- package/dist/patterns/patient-shell/index.js +1 -1
- package/dist/tokens.css +1 -1
- package/package.json +5 -1
- package/dist/_chunks/agenda-tray-gQUXklO4.js.map +0 -1
- package/dist/_chunks/file-upload-BVbfiANR.js.map +0 -1
- package/dist/_chunks/notification-tray-CfXNYrxv.js.map +0 -1
- package/dist/_chunks/sparkline-D4Np8ikf.js.map +0 -1
- package/dist/_chunks/timeline-BaSULpSJ.js.map +0 -1
- package/dist/_chunks/use-password-requirements-B1M8lE2t.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfadocs/ui-kit-debug",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AlfaDocs shared design system — tokens, components, patterns, and translations for platform, booking, and alfascribe. (debug build — identical runtime to @alfadocs/ui-kit, ships source maps for symbolication).",
|
|
6
6
|
"license": "BUSL-1.1",
|
|
@@ -299,6 +299,10 @@
|
|
|
299
299
|
"types": "./dist/components/radio-group/index.d.ts",
|
|
300
300
|
"import": "./dist/components/radio-group/index.js"
|
|
301
301
|
},
|
|
302
|
+
"./rating": {
|
|
303
|
+
"types": "./dist/components/rating/index.d.ts",
|
|
304
|
+
"import": "./dist/components/rating/index.js"
|
|
305
|
+
},
|
|
302
306
|
"./recaptcha-widget": {
|
|
303
307
|
"types": "./dist/components/recaptcha-widget/index.d.ts",
|
|
304
308
|
"import": "./dist/components/recaptcha-widget/index.js"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agenda-tray-gQUXklO4.js","sources":["../../node_modules/lucide-react/dist/esm/icons/calendar-days.js","../../src/components/agenda-tray/agenda-tray.agent.ts","../../src/components/agenda-tray/agenda-tray.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M8 2v4\", key: \"1cmpym\" }],\n [\"path\", { d: \"M16 2v4\", key: \"4m81vk\" }],\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"4\", rx: \"2\", key: \"1hopcy\" }],\n [\"path\", { d: \"M3 10h18\", key: \"8toen8\" }],\n [\"path\", { d: \"M8 14h.01\", key: \"6423bh\" }],\n [\"path\", { d: \"M12 14h.01\", key: \"1etili\" }],\n [\"path\", { d: \"M16 14h.01\", key: \"1gbofw\" }],\n [\"path\", { d: \"M8 18h.01\", key: \"lrp35t\" }],\n [\"path\", { d: \"M12 18h.01\", key: \"mhygvu\" }],\n [\"path\", { d: \"M16 18h.01\", key: \"kzsmim\" }]\n];\nconst CalendarDays = createLucideIcon(\"calendar-days\", __iconNode);\n\nexport { __iconNode, CalendarDays as default };\n//# sourceMappingURL=calendar-days.js.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — AgendaTray. */\n/* */\n/* Tray-level surface: read appointment ids + lifecycle status (never */\n/* patient names / treatments), and route an activation through the */\n/* curated handle. AgendaTray is in-page (no open/close). */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { AgendaTrayHandle } from './agenda-tray';\n\nexport const agendaTrayAgent: AgentAdapter<AgendaTrayHandle> = {\n id: 'agenda-tray',\n capabilities: ['select_single'],\n state: {\n items: {\n type: 'Array<{ id: string; status: string }>',\n descriptionKey: 'ui.agent.agendaTray.state.items',\n description:\n 'Currently-displayed appointments. Ids + status only — never patient identity.',\n read: (handle) => handle.getItems(),\n },\n },\n actions: {\n select_item: {\n safety: 'read',\n argsType: '{ id: string }',\n descriptionKey: 'ui.agent.agendaTray.actions.selectItem',\n description: 'Activate the appointment with the given id.',\n invoke: (handle, args: { id: string }) => {\n handle.selectItem(args.id);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'agenda-tray',\n description: 'Marks the AgendaTray wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific tray from the agent.',\n },\n item: {\n attr: 'data-appointment-id',\n description:\n 'Stable appointment id emitted on each rendered AgendaCard inside the tray.',\n },\n },\n};\n","import {\n forwardRef,\n useImperativeHandle,\n useMemo,\n useRef,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { CalendarDays, Plus } from 'lucide-react';\nimport { IconButton } from '../button/icon-button';\nimport { Skeleton } from '../skeleton/skeleton';\nimport { EmptyState } from '../empty-state/empty-state';\nimport { AgendaCard, type AgendaItem } from '../agenda-card';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { agendaTrayAgent } from './agenda-tray.agent';\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst agendaTrayVariants = cva(\n [\n 'ds:flex ds:flex-col',\n 'ds:rounded-[var(--radius-md)] ds:shadow-[var(--shadow-card)]',\n 'ds:bg-[color:var(--card)] ds:text-[color:var(--card-foreground)]',\n 'ds:overflow-hidden',\n ].join(' '),\n {\n variants: {\n size: {\n sm: '',\n md: '',\n },\n },\n defaultVariants: {\n size: 'sm',\n },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\n/**\n * Curated imperative handle for AgendaTray. Exposed as the forwardRef\n * target so a future agent / MCP UI bridge can drive the tray without\n * touching the DOM. See `agenda-tray.agent.ts`.\n */\nexport interface AgendaTrayHandle {\n getItems: () => Array<{ id: string; status: string }>;\n selectItem: (id: string) => void;\n}\n\nexport interface AgendaTrayProps\n extends\n Omit<HTMLAttributes<HTMLElement>, 'onClick' | 'id'>,\n VariantProps<typeof agendaTrayVariants> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so\n * an agent / MCP UI bridge can address this specific tray.\n */\n id?: string;\n items: AgendaItem[];\n /** Section title — rendered in the header. Localised by the consumer. */\n title?: string;\n /** Optional small caption (e.g. localised date) shown next to the title. */\n caption?: string;\n size?: 'sm' | 'md';\n onOpenAppointment?: (item: AgendaItem) => void;\n onAddAppointment?: () => void;\n /** Localised label for the \"Add\" affordance. */\n addLabel?: string;\n loading?: boolean;\n emptyTitle?: string;\n emptyDescription?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const AgendaTray = forwardRef<HTMLElement, AgendaTrayProps>(\n (\n {\n id,\n items,\n title,\n caption,\n size = 'sm',\n onOpenAppointment,\n onAddAppointment,\n addLabel,\n loading = false,\n emptyTitle,\n emptyDescription,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const heading = title ?? t('agendaTray.title', \"Today's appointments\");\n const resolvedAddLabel =\n addLabel ?? t('agendaTray.add', 'Add appointment');\n const isEmpty = !loading && items.length === 0;\n\n let body: ReactNode;\n if (loading) {\n body = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)]\">\n {[0, 1, 2].map((i) => (\n <Skeleton key={i} variant=\"rectangular\" height=\"2.5rem\" />\n ))}\n </div>\n );\n } else if (isEmpty) {\n body = (\n <div className=\"ds:p-[var(--spacing-md)]\">\n <EmptyState\n variant=\"first-use\"\n size=\"sm\"\n title={\n emptyTitle ?? t('agendaTray.empty.title', 'No appointments')\n }\n description={\n emptyDescription ??\n t(\n 'agendaTray.empty.description',\n 'New appointments will appear here.',\n )\n }\n />\n </div>\n );\n } else {\n body = (\n <ul className=\"ds:flex ds:list-none ds:flex-col\">\n {items.map((item) => (\n <AgendaCard\n key={item.id}\n item={item}\n size={size}\n onActivate={onOpenAppointment}\n data-appointment-id={item.id}\n />\n ))}\n </ul>\n );\n }\n\n /* Curated imperative handle for agent integration. See\n * agenda-tray.agent.ts. */\n const itemsRef = useRef<AgendaItem[]>(items);\n itemsRef.current = items;\n\n const innerRef = useRef<HTMLElement>(null);\n useImperativeHandle(ref, () => innerRef.current as HTMLElement, []);\n\n const handle = useMemo<AgendaTrayHandle>(\n () => ({\n getItems: () =>\n itemsRef.current.map((i) => ({\n id: i.id,\n status: i.status ?? 'confirmed',\n })),\n selectItem: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onOpenAppointment?.(found);\n },\n }),\n [onOpenAppointment],\n );\n\n useAgentRegistration(agendaTrayAgent, handle, id);\n\n return (\n <section\n ref={innerRef}\n aria-label={heading}\n data-component=\"agenda-tray\"\n data-component-id={id}\n className={agendaTrayVariants({ size, className })}\n {...rest}\n >\n <header className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)]\">\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)] ds:min-w-0\">\n <h3 className=\"ds:m-0 ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] type-title-card\">\n <CalendarDays aria-hidden=\"true\" className=\"ds:size-4\" />\n {heading}\n </h3>\n {caption ? (\n <span className=\"type-eyebrow ds:text-[color:var(--muted-foreground)]\">\n {caption}\n </span>\n ) : null}\n </div>\n {onAddAppointment ? (\n <IconButton\n icon={<Plus />}\n intent=\"outline\"\n size=\"sm\"\n aria-label={resolvedAddLabel}\n onClick={onAddAppointment}\n />\n ) : null}\n </header>\n {body}\n </section>\n );\n },\n);\n\nAgendaTray.displayName = 'AgendaTray';\n"],"names":["__iconNode","CalendarDays","createLucideIcon","agendaTrayAgent","handle","args","agendaTrayVariants","cva","AgendaTray","forwardRef","id","items","title","caption","size","onOpenAppointment","onAddAppointment","addLabel","loading","emptyTitle","emptyDescription","className","rest","ref","t","useTranslation","heading","resolvedAddLabel","isEmpty","body","jsx","i","Skeleton","EmptyState","item","AgendaCard","itemsRef","useRef","innerRef","useImperativeHandle","useMemo","targetId","found","useAgentRegistration","jsxs","IconButton","Plus"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload-BVbfiANR.js","sources":["../../node_modules/lucide-react/dist/esm/icons/cloud-upload.js","../../node_modules/lucide-react/dist/esm/icons/file-archive.js","../../node_modules/lucide-react/dist/esm/icons/file-image.js","../../node_modules/lucide-react/dist/esm/icons/file-spreadsheet.js","../../node_modules/lucide-react/dist/esm/icons/file.js","../../node_modules/lucide-react/dist/esm/icons/loader-circle.js","../../node_modules/lucide-react/dist/esm/icons/upload.js","../../src/components/file-upload/file-upload.agent.ts","../../src/components/file-upload/file-upload.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 13v8\", key: \"1l5pq0\" }],\n [\"path\", { d: \"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242\", key: \"1pljnt\" }],\n [\"path\", { d: \"m8 17 4-4 4 4\", key: \"1quai1\" }]\n];\nconst CloudUpload = createLucideIcon(\"cloud-upload\", __iconNode);\n\nexport { __iconNode, CloudUpload as default };\n//# sourceMappingURL=cloud-upload.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M13.659 22H18a2 2 0 0 0 2-2V8a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 14 2H6a2 2 0 0 0-2 2v11.5\",\n key: \"4pqfef\"\n }\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\", key: \"wfsgrz\" }],\n [\"path\", { d: \"M8 12v-1\", key: \"1ej8lb\" }],\n [\"path\", { d: \"M8 18v-2\", key: \"qcmpov\" }],\n [\"path\", { d: \"M8 7V6\", key: \"1nbb54\" }],\n [\"circle\", { cx: \"8\", cy: \"20\", r: \"2\", key: \"ckkr5m\" }]\n];\nconst FileArchive = createLucideIcon(\"file-archive\", __iconNode);\n\nexport { __iconNode, FileArchive as default };\n//# sourceMappingURL=file-archive.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n key: \"1oefj6\"\n }\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\", key: \"wfsgrz\" }],\n [\"circle\", { cx: \"10\", cy: \"12\", r: \"2\", key: \"737tya\" }],\n [\"path\", { d: \"m20 17-1.296-1.296a2.41 2.41 0 0 0-3.408 0L9 22\", key: \"wt3hpn\" }]\n];\nconst FileImage = createLucideIcon(\"file-image\", __iconNode);\n\nexport { __iconNode, FileImage as default };\n//# sourceMappingURL=file-image.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n key: \"1oefj6\"\n }\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\", key: \"wfsgrz\" }],\n [\"path\", { d: \"M8 13h2\", key: \"yr2amv\" }],\n [\"path\", { d: \"M14 13h2\", key: \"un5t4a\" }],\n [\"path\", { d: \"M8 17h2\", key: \"2yhykz\" }],\n [\"path\", { d: \"M14 17h2\", key: \"10kma7\" }]\n];\nconst FileSpreadsheet = createLucideIcon(\"file-spreadsheet\", __iconNode);\n\nexport { __iconNode, FileSpreadsheet as default };\n//# sourceMappingURL=file-spreadsheet.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n key: \"1oefj6\"\n }\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\", key: \"wfsgrz\" }]\n];\nconst File = createLucideIcon(\"file\", __iconNode);\n\nexport { __iconNode, File as default };\n//# sourceMappingURL=file.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"path\", { d: \"M21 12a9 9 0 1 1-6.219-8.56\", key: \"13zald\" }]];\nconst LoaderCircle = createLucideIcon(\"loader-circle\", __iconNode);\n\nexport { __iconNode, LoaderCircle as default };\n//# sourceMappingURL=loader-circle.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 3v12\", key: \"1x0j5s\" }],\n [\"path\", { d: \"m17 8-5-5-5 5\", key: \"7q97r8\" }],\n [\"path\", { d: \"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\", key: \"ih7n3h\" }]\n];\nconst Upload = createLucideIcon(\"upload\", __iconNode);\n\nexport { __iconNode, Upload as default };\n//# sourceMappingURL=upload.js.map\n","import type { AgentAdapter } from '../../agent/types';\nimport type { FileUploadHandle } from './file-upload';\n\nexport const fileUploadAgent: AgentAdapter<FileUploadHandle> = {\n id: 'file-upload',\n capabilities: ['submit', 'dismiss'],\n state: {\n files: {\n type: 'Array<{ id, name, size, status }>',\n description:\n 'Files currently tracked by the uploader. Identifiers and metadata only — never file content.',\n read: (handle) => handle.getFiles(),\n },\n },\n actions: {\n remove_file: {\n safety: 'destructive',\n argsType: '{ id: string }',\n description: 'Remove the file with the given id from the upload list.',\n invoke: (handle, args: { id: string }) => {\n handle.removeFile(args.id);\n },\n },\n clear: {\n safety: 'destructive',\n description: 'Remove all files from the upload list.',\n invoke: (handle) => {\n handle.clear();\n },\n },\n },\n domHooks: {\n root: { attr: 'data-component', value: 'file-upload' },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n item: {\n attr: 'data-file-id',\n description: 'Each tracked file emits its id as data-file-id.',\n },\n },\n};\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ClipboardEvent,\n type ReactNode,\n} from 'react';\nimport { useDropzone, type FileRejection } from 'react-dropzone';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport {\n AlertCircle,\n CheckCircle2,\n CloudUpload,\n File as FileIcon,\n FileArchive,\n FileImage,\n FileSpreadsheet,\n FileText,\n Loader2,\n Upload,\n X,\n} from 'lucide-react';\nimport { useFormField } from '../form-field/form-field-context';\nimport { useAgentRegistration } from '../../agent';\nimport { fileUploadAgent } from './file-upload.agent';\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\nexport interface FileUploadFile {\n file: File;\n id: string;\n status: 'pending' | 'uploading' | 'complete' | 'error';\n progress: number;\n preview?: string;\n error?: string;\n}\n\nexport interface FileUploadRejection {\n file: File;\n reason:\n | 'file-too-large'\n | 'file-too-small'\n | 'file-invalid-type'\n | 'too-many-files';\n}\n\n// Curated agent-readiness handle — see file-upload.agent.ts.\nexport interface FileUploadHandle {\n getFiles: () => Array<{\n id: string;\n name: string;\n size: number;\n status: FileUploadFile['status'];\n }>;\n removeFile: (id: string) => void;\n clear: () => void;\n}\n\nexport interface FileUploadProps {\n /** Opaque instance id — emitted as `data-component-id` for the agent registry. */\n id?: string;\n accept?: Record<string, string[]>;\n maxSize?: number;\n minSize?: number;\n maxFiles?: number;\n multiple?: boolean;\n disabled?: boolean;\n strictAccept?: boolean;\n onDrop?: (accepted: File[], rejected: FileUploadRejection[]) => void;\n onUpload?: (\n file: File,\n helpers: {\n signal: AbortSignal;\n onProgress: (percent: number) => void;\n },\n ) => Promise<void>;\n onRemove?: (file: FileUploadFile) => void;\n onReject?: (rejections: FileUploadRejection[]) => void;\n variant?: 'dropzone' | 'button' | 'both';\n showPreview?: boolean;\n className?: string;\n}\n\n/* -------------------------------------------------------------------------- */\n/* CVA */\n/* -------------------------------------------------------------------------- */\n\nconst dropzoneVariants = cva(\n [\n 'ds:relative ds:flex ds:flex-col ds:items-center ds:justify-center',\n 'ds:min-h-48 ds:px-[var(--spacing-lg)] ds:py-[var(--spacing-xl)]',\n 'ds:rounded-[var(--radius-lg)] ds:border-2 ds:border-dashed',\n 'ds:bg-background',\n 'ds:transition-all ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:cursor-pointer',\n 'ds:group',\n ].join(' '),\n {\n variants: {\n isDragActive: {\n true: 'ds:border-primary ds:bg-primary/10 ds:scale-[1.01]',\n false:\n 'ds:border-border ds:hover:border-muted-foreground/40 ds:hover:bg-muted/5',\n },\n hasError: {\n true: 'ds:border-destructive ds:bg-destructive/5 ds:hover:border-destructive',\n false: '',\n },\n isDisabled: {\n true: 'ds:cursor-not-allowed ds:opacity-50 ds:hover:border-border ds:hover:bg-background',\n false: '',\n },\n },\n defaultVariants: {\n isDragActive: false,\n hasError: false,\n isDisabled: false,\n },\n },\n);\n\nconst browseButtonVariants = cva(\n [\n 'ds:inline-flex ds:items-center ds:justify-center ds:gap-[var(--spacing-xs)]',\n 'ds:min-h-[var(--min-target-size)] ds:min-w-[var(--min-target-size)]',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-primary/30 ds:bg-primary/5',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:py-[var(--spacing-sm)]',\n 'ds:text-primary ds:text-[length:var(--font-size-sm)] ds:font-medium',\n 'ds:transition-all ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:hover:bg-primary/10 ds:hover:border-primary/50',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:disabled:cursor-not-allowed ds:disabled:opacity-50',\n ].join(' '),\n);\n\nconst fileItemVariants = cva(\n [\n 'ds:flex ds:items-center ds:gap-[var(--spacing-md)]',\n 'ds:rounded-[var(--radius-md)] ds:border ds:bg-background',\n 'ds:p-[var(--spacing-md)]',\n 'ds:text-[length:var(--font-size-sm)] ds:text-foreground',\n 'ds:transition-all ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n ].join(' '),\n {\n variants: {\n status: {\n pending: 'ds:border-border',\n uploading: 'ds:border-primary/30 ds:bg-primary/[0.02]',\n complete: 'ds:border-[var(--success)]/30 ds:bg-[var(--success)]/[0.02]',\n error: 'ds:border-destructive/30 ds:bg-destructive/[0.02]',\n },\n },\n defaultVariants: {\n status: 'pending',\n },\n },\n);\n\nconst actionButtonVariants = cva(\n [\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:min-h-[var(--min-target-size)] ds:min-w-[var(--min-target-size)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:text-muted-foreground',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:hover:text-foreground ds:hover:bg-muted/40',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n ].join(' '),\n);\n\n/* -------------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------------- */\n\nfunction generateId(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\nfunction isImageFile(file: File): boolean {\n return file.type.startsWith('image/');\n}\n\nfunction getFileIcon(file: File): ReactNode {\n const ext = file.name.split('.').pop()?.toLowerCase() ?? '';\n if (['pdf', 'doc', 'docx', 'txt', 'rtf'].includes(ext)) {\n return (\n <FileText\n aria-hidden=\"true\"\n className=\"ds:size-10 ds:shrink-0 ds:text-muted-foreground\"\n />\n );\n }\n if (['zip', 'rar', '7z', 'tar', 'gz'].includes(ext)) {\n return (\n <FileArchive\n aria-hidden=\"true\"\n className=\"ds:size-10 ds:shrink-0 ds:text-muted-foreground\"\n />\n );\n }\n if (['xls', 'xlsx', 'csv'].includes(ext)) {\n return (\n <FileSpreadsheet\n aria-hidden=\"true\"\n className=\"ds:size-10 ds:shrink-0 ds:text-muted-foreground\"\n />\n );\n }\n if (['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp'].includes(ext)) {\n return (\n <FileImage\n aria-hidden=\"true\"\n className=\"ds:size-10 ds:shrink-0 ds:text-muted-foreground\"\n />\n );\n }\n return (\n <FileIcon\n aria-hidden=\"true\"\n className=\"ds:size-10 ds:shrink-0 ds:text-muted-foreground\"\n />\n );\n}\n\nfunction getStatusIcon(status: FileUploadFile['status']): ReactNode {\n switch (status) {\n case 'uploading':\n return (\n <Loader2\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0 ds:text-primary ds:animate-spin\"\n />\n );\n case 'complete':\n return (\n <CheckCircle2\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0 ds:text-[var(--success)]\"\n />\n );\n case 'error':\n return (\n <AlertCircle\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0 ds:text-destructive\"\n />\n );\n default:\n return null;\n }\n}\n\nconst UNIT_KEYS = [\n 'inputs.fileUpload.units.bytes',\n 'inputs.fileUpload.units.kilobytes',\n 'inputs.fileUpload.units.megabytes',\n 'inputs.fileUpload.units.gigabytes',\n] as const;\n\nconst UNIT_FALLBACKS = ['B', 'KB', 'MB', 'GB'] as const;\n\nfunction formatFileSize(\n bytes: number,\n locale: string,\n t: (key: string, fallback: string) => string,\n): string {\n let value = bytes;\n let unitIndex = 0;\n while (value >= 1024 && unitIndex < UNIT_FALLBACKS.length - 1) {\n value /= 1024;\n unitIndex++;\n }\n const formatted = new Intl.NumberFormat(locale, {\n maximumFractionDigits: unitIndex === 0 ? 0 : 1,\n }).format(value);\n const unit = t(UNIT_KEYS[unitIndex], UNIT_FALLBACKS[unitIndex]);\n return `${formatted} ${unit}`;\n}\n\nfunction mapRejectionCode(code: string): FileUploadRejection['reason'] {\n switch (code) {\n case 'file-too-large':\n return 'file-too-large';\n case 'file-too-small':\n return 'file-too-small';\n case 'file-invalid-type':\n return 'file-invalid-type';\n case 'too-many-files':\n return 'too-many-files';\n default:\n return 'file-invalid-type';\n }\n}\n\nfunction getExtensionFromName(name: string): string {\n const parts = name.split('.');\n return parts.length > 1 ? `.${parts.pop()!.toLowerCase()}` : '';\n}\n\nfunction formatAcceptHint(accept: Record<string, string[]>): string {\n const extensions: string[] = [];\n for (const exts of Object.values(accept)) {\n for (const ext of exts) {\n extensions.push(ext.toUpperCase().replace('.', ''));\n }\n }\n if (extensions.length > 0) return extensions.join(', ');\n const mimeLabels: string[] = [];\n for (const mime of Object.keys(accept)) {\n if (mime.endsWith('/*')) {\n mimeLabels.push(mime.replace('/*', '').split('/').pop() ?? mime);\n } else {\n mimeLabels.push(mime.split('/').pop() ?? mime);\n }\n }\n return mimeLabels.join(', ');\n}\n\n/* -------------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------------- */\n\nexport const FileUpload = forwardRef<HTMLDivElement, FileUploadProps>(\n (\n {\n id,\n accept,\n maxSize,\n minSize,\n maxFiles = 1,\n multiple = false,\n disabled,\n strictAccept = false,\n onDrop: onDropProp,\n onUpload,\n onRemove,\n onReject,\n variant = 'both',\n showPreview = true,\n className,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const ctx = useFormField();\n const fallbackId = useId();\n\n const effectiveDisabled = ctx.disabled || disabled;\n const hasError = ctx.invalid;\n const inputId = ctx.id || fallbackId;\n\n const [files, setFiles] = useState<FileUploadFile[]>([]);\n const [rejections, setRejections] = useState<FileUploadRejection[]>([]);\n const abortControllers = useRef<Map<string, AbortController>>(new Map());\n const statusRef = useRef<HTMLSpanElement>(null);\n const filesRef = useRef<FileUploadFile[]>(files);\n filesRef.current = files;\n\n const announceStatus = useCallback((message: string) => {\n if (statusRef.current) {\n statusRef.current.textContent = message;\n }\n }, []);\n\n const validateStrictAccept = useCallback(\n (file: File): boolean => {\n if (!strictAccept || !accept) return true;\n for (const [mime, extensions] of Object.entries(accept)) {\n const mimeMatch =\n mime === '*/*' ||\n (mime.endsWith('/*') &&\n file.type.startsWith(mime.replace('/*', '/'))) ||\n file.type === mime;\n const fileExt = getExtensionFromName(file.name);\n const extMatch =\n extensions.length === 0 ||\n extensions.some((ext) => ext.toLowerCase() === fileExt);\n if (mimeMatch && extMatch) return true;\n }\n return false;\n },\n [strictAccept, accept],\n );\n\n const uploadFile = useCallback(\n async (uploadFileState: FileUploadFile) => {\n if (!onUpload) return;\n const controller = new AbortController();\n abortControllers.current.set(uploadFileState.id, controller);\n\n setFiles((prev) =>\n prev.map((f) =>\n f.id === uploadFileState.id\n ? { ...f, status: 'uploading', progress: 0 }\n : f,\n ),\n );\n announceStatus(t('inputs.fileUpload.uploading', 'Uploading\\u2026'));\n\n try {\n await onUpload(uploadFileState.file, {\n signal: controller.signal,\n onProgress: (percent: number) => {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === uploadFileState.id ? { ...f, progress: percent } : f,\n ),\n );\n announceStatus(\n t('inputs.fileUpload.progress', '{{percent}}% uploaded', {\n percent,\n }),\n );\n },\n });\n setFiles((prev) =>\n prev.map((f) =>\n f.id === uploadFileState.id\n ? { ...f, status: 'complete', progress: 100 }\n : f,\n ),\n );\n announceStatus(t('inputs.fileUpload.complete', 'Upload complete'));\n } catch (err: unknown) {\n if (controller.signal.aborted) {\n setFiles((prev) => prev.filter((f) => f.id !== uploadFileState.id));\n return;\n }\n const errorMessage =\n err instanceof Error\n ? err.message\n : t('inputs.fileUpload.errors.uploadFailed', 'Upload failed');\n setFiles((prev) =>\n prev.map((f) =>\n f.id === uploadFileState.id\n ? { ...f, status: 'error', error: errorMessage }\n : f,\n ),\n );\n } finally {\n abortControllers.current.delete(uploadFileState.id);\n }\n },\n [onUpload, announceStatus, t],\n );\n\n const handleDrop = useCallback(\n (accepted: File[], fileRejections: FileRejection[]) => {\n const mapped: FileUploadRejection[] = fileRejections.flatMap((r) =>\n r.errors.map((e) => ({\n file: r.file,\n reason: mapRejectionCode(e.code),\n })),\n );\n\n const strictRejected: FileUploadRejection[] = [];\n const strictAccepted: File[] = [];\n for (const file of accepted) {\n if (!validateStrictAccept(file)) {\n strictRejected.push({ file, reason: 'file-invalid-type' });\n } else {\n strictAccepted.push(file);\n }\n }\n\n const allRejections = [...mapped, ...strictRejected];\n setRejections(allRejections);\n\n if (allRejections.length > 0) {\n onReject?.(allRejections);\n }\n\n const newFiles: FileUploadFile[] = strictAccepted.map((file) => ({\n file,\n id: generateId(),\n status: 'pending' as const,\n progress: 0,\n preview: isImageFile(file) ? URL.createObjectURL(file) : undefined,\n }));\n\n setFiles((prev) => {\n if (!multiple && maxFiles === 1) {\n for (const f of prev) {\n if (f.preview) URL.revokeObjectURL(f.preview);\n }\n return newFiles;\n }\n return [...prev, ...newFiles];\n });\n\n onDropProp?.(strictAccepted, allRejections);\n announceStatus(\n t(\n 'inputs.fileUpload.filesSelected',\n '{{count}} file(s) selected',\n {\n count: strictAccepted.length,\n },\n ),\n );\n\n for (const nf of newFiles) {\n void uploadFile(nf);\n }\n },\n [\n multiple,\n maxFiles,\n onDropProp,\n onReject,\n validateStrictAccept,\n announceStatus,\n uploadFile,\n t,\n ],\n );\n\n const { getRootProps, getInputProps, isDragActive, open } = useDropzone({\n accept,\n maxSize,\n minSize,\n maxFiles: multiple ? maxFiles : 1,\n multiple,\n disabled: effectiveDisabled,\n onDrop: handleDrop,\n noClick: variant === 'button',\n noKeyboard: variant === 'button',\n });\n\n const handleCancel = useCallback((fileId: string) => {\n const controller = abortControllers.current.get(fileId);\n controller?.abort();\n setFiles((prev) => {\n const file = prev.find((f) => f.id === fileId);\n if (file?.preview) URL.revokeObjectURL(file.preview);\n return prev.filter((f) => f.id !== fileId);\n });\n }, []);\n\n const handleRemove = useCallback(\n (fileId: string) => {\n const removed = filesRef.current.find((f) => f.id === fileId);\n if (removed?.preview) URL.revokeObjectURL(removed.preview);\n setFiles((prev) => prev.filter((f) => f.id !== fileId));\n if (removed) {\n onRemove?.(removed);\n }\n },\n [onRemove],\n );\n\n const clearAll = useCallback(() => {\n for (const f of filesRef.current) {\n const controller = abortControllers.current.get(f.id);\n controller?.abort();\n if (f.preview) URL.revokeObjectURL(f.preview);\n }\n setFiles([]);\n }, []);\n\n const agentHandle = useMemo<FileUploadHandle>(\n () => ({\n getFiles: () =>\n filesRef.current.map((f) => ({\n id: f.id,\n name: f.file.name,\n size: f.file.size,\n status: f.status,\n })),\n removeFile: (fileId: string) => handleRemove(fileId),\n clear: () => clearAll(),\n }),\n [handleRemove, clearAll],\n );\n useAgentRegistration(fileUploadAgent, agentHandle, id);\n\n const validatePastedFiles = useCallback(\n (\n pastedFiles: File[],\n ): { accepted: File[]; rejected: FileUploadRejection[] } => {\n const accepted: File[] = [];\n const rejected: FileUploadRejection[] = [];\n const effectiveMaxFiles = multiple ? maxFiles : 1;\n\n for (const file of pastedFiles) {\n if (accepted.length >= effectiveMaxFiles) {\n rejected.push({ file, reason: 'too-many-files' });\n continue;\n }\n if (maxSize !== undefined && file.size > maxSize) {\n rejected.push({ file, reason: 'file-too-large' });\n continue;\n }\n if (minSize !== undefined && file.size < minSize) {\n rejected.push({ file, reason: 'file-too-small' });\n continue;\n }\n if (accept) {\n const fileExt = getExtensionFromName(file.name);\n const typeMatch = Object.entries(accept).some(\n ([mime, extensions]) => {\n const mimeOk =\n mime === '*/*' ||\n (mime.endsWith('/*') &&\n file.type.startsWith(mime.replace('/*', '/'))) ||\n file.type === mime;\n const extOk =\n extensions.length > 0 &&\n extensions.some((ext) => ext.toLowerCase() === fileExt);\n return mimeOk || extOk;\n },\n );\n if (!typeMatch) {\n rejected.push({ file, reason: 'file-invalid-type' });\n continue;\n }\n }\n accepted.push(file);\n }\n return { accepted, rejected };\n },\n [accept, maxSize, minSize, maxFiles, multiple],\n );\n\n const handlePaste = useCallback(\n (event: ClipboardEvent<HTMLDivElement>) => {\n if (effectiveDisabled) return;\n const pastedFiles = Array.from(event.clipboardData.files);\n if (pastedFiles.length > 0) {\n event.preventDefault();\n const { accepted, rejected } = validatePastedFiles(pastedFiles);\n const fileRejections: FileRejection[] = rejected.map((r) => ({\n file: r.file,\n errors: [{ code: r.reason, message: r.reason }],\n }));\n handleDrop(accepted, fileRejections);\n }\n },\n [effectiveDisabled, handleDrop, validatePastedFiles],\n );\n\n useEffect(() => {\n return () => {\n for (const f of filesRef.current) {\n if (f.preview) URL.revokeObjectURL(f.preview);\n }\n };\n }, []);\n\n const constraintHints = useMemo(() => {\n const hints: string[] = [];\n if (accept) {\n hints.push(formatAcceptHint(accept));\n }\n if (maxSize) {\n hints.push(\n t('inputs.fileUpload.maxSizeHint', 'Max {{size}}', {\n size: formatFileSize(maxSize, i18n.language, t),\n }),\n );\n }\n if (multiple && maxFiles > 1) {\n hints.push(\n t('inputs.fileUpload.maxFilesHint', 'Up to {{count}} files', {\n count: maxFiles,\n }),\n );\n }\n return hints;\n }, [accept, maxSize, multiple, maxFiles, t, i18n.language]);\n\n const errorMessages = useMemo(() => {\n return rejections.map((r) => {\n switch (r.reason) {\n case 'file-too-large':\n return t(\n 'inputs.fileUpload.errors.fileTooLarge',\n 'File exceeds {{maxSize}}',\n {\n maxSize: maxSize\n ? formatFileSize(maxSize, i18n.language, t)\n : '',\n },\n );\n case 'file-too-small':\n return t(\n 'inputs.fileUpload.errors.fileTooSmall',\n 'File is smaller than {{minSize}}',\n {\n minSize: minSize\n ? formatFileSize(minSize, i18n.language, t)\n : '',\n },\n );\n case 'file-invalid-type':\n return t(\n 'inputs.fileUpload.errors.fileInvalidType',\n 'File type not accepted',\n );\n case 'too-many-files':\n return t(\n 'inputs.fileUpload.errors.tooManyFiles',\n 'Maximum {{maxFiles}} files allowed',\n {\n maxFiles,\n },\n );\n }\n });\n }, [rejections, t, maxSize, minSize, maxFiles, i18n.language]);\n\n const renderFileList = () => {\n if (files.length === 0) return null;\n\n return (\n <ul className=\"ds:mt-[var(--spacing-md)] ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:list-none ds:p-0 ds:m-0\">\n {files.map((f) => (\n <li\n key={f.id}\n data-file-id={f.id}\n className={fileItemVariants({ status: f.status })}\n >\n {showPreview && f.preview ? (\n <img\n src={f.preview}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"ds:size-12 ds:shrink-0 ds:rounded-[var(--radius-md)] ds:object-cover ds:border ds:border-border\"\n />\n ) : (\n getFileIcon(f.file)\n )}\n\n <div className=\"ds:flex-1 ds:min-w-0\">\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <p className=\"ds:truncate type-label ds:m-0\">{f.file.name}</p>\n {getStatusIcon(f.status)}\n </div>\n <p className=\"type-meta ds:text-muted-foreground ds:m-0 ds:mt-0.5\">\n {formatFileSize(f.file.size, i18n.language, t)}\n {f.status === 'uploading' && (\n <span className=\"ds:ms-[var(--spacing-sm)] ds:text-primary ds:font-medium\">\n {f.progress}%\n </span>\n )}\n {f.status === 'complete' && (\n <span className=\"ds:ms-[var(--spacing-sm)] ds:text-[var(--success)] ds:font-medium\">\n {t('inputs.fileUpload.complete', 'Complete')}\n </span>\n )}\n </p>\n\n {f.status === 'uploading' && (\n <div\n role=\"progressbar\"\n aria-label={f.file.name}\n aria-valuenow={f.progress}\n aria-valuemin={0}\n aria-valuemax={100}\n className=\"ds:mt-[var(--spacing-sm)] ds:h-1.5 ds:w-full ds:rounded-[var(--radius-full)] ds:bg-muted ds:overflow-hidden\"\n >\n <div\n className=\"ds:h-full ds:rounded-[var(--radius-full)] ds:bg-primary ds:transition-[inline-size] ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none\"\n // eslint-disable-next-line react/forbid-dom-props -- progress bar width is runtime-computed\n style={{ inlineSize: `${f.progress}%` }}\n />\n </div>\n )}\n\n {f.status === 'error' && f.error && (\n <p\n role=\"alert\"\n className=\"type-meta ds:text-destructive ds:m-0 ds:mt-[var(--spacing-xs)]\"\n >\n {f.error}\n </p>\n )}\n </div>\n\n {f.status === 'uploading' && (\n <button\n type=\"button\"\n onClick={() => handleCancel(f.id)}\n aria-label={t('inputs.fileUpload.cancel', 'Cancel upload')}\n className={actionButtonVariants()}\n >\n <X aria-hidden=\"true\" className=\"ds:size-4\" />\n </button>\n )}\n {(f.status === 'complete' ||\n f.status === 'pending' ||\n f.status === 'error') && (\n <button\n type=\"button\"\n onClick={() => handleRemove(f.id)}\n aria-label={t('inputs.fileUpload.remove', 'Remove file')}\n className={actionButtonVariants()}\n >\n <X aria-hidden=\"true\" className=\"ds:size-4\" />\n </button>\n )}\n </li>\n ))}\n </ul>\n );\n };\n\n const renderDropzone = () => {\n if (variant === 'button') return null;\n\n const rootProps = getRootProps({\n className: dropzoneVariants({\n isDragActive,\n hasError: hasError ?? false,\n isDisabled: effectiveDisabled ?? false,\n className,\n }),\n tabIndex: effectiveDisabled ? -1 : 0,\n });\n\n // Compose the caller's forwarded ref with react-dropzone's internal\n // root ref. Spreading `{...rootProps}` and then setting `ref={ref}`\n // would clobber dropzone's ref callback, breaking its keydown guard\n // (`rootRef.current.isEqualNode(event.target)`).\n const rootRefFromDropzone = (\n rootProps as unknown as {\n ref?:\n | ((node: HTMLDivElement | null) => void)\n | { current: HTMLDivElement | null };\n }\n ).ref;\n const composedRef = (node: HTMLDivElement | null) => {\n if (typeof rootRefFromDropzone === 'function') {\n rootRefFromDropzone(node);\n } else if (rootRefFromDropzone) {\n (rootRefFromDropzone as { current: HTMLDivElement | null }).current =\n node;\n }\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n (ref as { current: HTMLDivElement | null }).current = node;\n }\n };\n return (\n <div\n {...rootProps}\n ref={composedRef}\n onPaste={handlePaste}\n id={inputId}\n aria-label={t(\n 'inputs.fileUpload.dropHere',\n 'Drop files here or click to browse',\n )}\n aria-describedby={ctx.describedBy || undefined}\n aria-invalid={ctx.invalid || undefined}\n aria-required={ctx.required || undefined}\n data-testid=\"file-upload-dropzone\"\n >\n <input\n {...getInputProps({\n 'aria-label': t(\n 'inputs.fileUpload.dropHere',\n 'Drop files here or click to browse',\n ),\n })}\n />\n\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-sm)]\">\n <div className=\"ds:flex ds:items-center ds:justify-center ds:size-14 ds:rounded-[var(--radius-full)] ds:bg-primary/10 ds:text-primary ds:transition-colors ds:duration-[var(--animation-duration)] ds:group-hover:bg-primary/15 ds:motion-reduce:transition-none\">\n {isDragActive ? (\n <CloudUpload aria-hidden=\"true\" className=\"ds:size-7\" />\n ) : (\n <Upload aria-hidden=\"true\" className=\"ds:size-7\" />\n )}\n </div>\n\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-xs)]\">\n <p className=\"type-label ds:text-foreground ds:text-center ds:m-0\">\n {isDragActive\n ? t('inputs.fileUpload.dropActive', 'Drop files here')\n : t(\n 'inputs.fileUpload.dropHere',\n 'Drop files here or click to browse',\n )}\n </p>\n\n {constraintHints.length > 0 && !isDragActive && (\n <p className=\"type-meta ds:text-muted-foreground ds:text-center ds:m-0\">\n {constraintHints.join(' \\u00b7 ')}\n </p>\n )}\n </div>\n\n {variant === 'both' && !isDragActive && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n open();\n }}\n disabled={effectiveDisabled}\n className={browseButtonVariants({\n className: 'ds:mt-[var(--spacing-xs)]',\n })}\n >\n <Upload aria-hidden=\"true\" className=\"ds:size-4\" />\n {t('inputs.fileUpload.browse', 'Browse files')}\n </button>\n )}\n </div>\n </div>\n );\n };\n\n const renderButton = () => {\n if (variant === 'dropzone') return null;\n\n if (variant === 'button') {\n return (\n <div onPaste={handlePaste} ref={ref}>\n <input\n {...getInputProps({\n 'aria-label': t('inputs.fileUpload.browse', 'Browse files'),\n })}\n />\n <button\n type=\"button\"\n onClick={open}\n disabled={effectiveDisabled}\n className={browseButtonVariants({ className })}\n id={variant === 'button' ? inputId : undefined}\n aria-describedby={\n variant === 'button' ? ctx.describedBy || undefined : undefined\n }\n aria-invalid={\n variant === 'button' ? ctx.invalid || undefined : undefined\n }\n aria-required={\n variant === 'button' ? ctx.required || undefined : undefined\n }\n >\n <Upload aria-hidden=\"true\" className=\"ds:size-4\" />\n {t('inputs.fileUpload.browse', 'Browse files')}\n </button>\n </div>\n );\n }\n\n return null;\n };\n\n return (\n <div data-component=\"file-upload\" data-component-id={id}>\n {renderDropzone()}\n {renderButton()}\n {renderFileList()}\n\n {errorMessages.length > 0 && (\n <div\n role=\"alert\"\n className=\"ds:mt-[var(--spacing-sm)] ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n {errorMessages.map((msg, i) => (\n <div\n key={i}\n className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n <AlertCircle\n aria-hidden=\"true\"\n className=\"ds:size-3.5 ds:shrink-0 ds:text-destructive\"\n />\n <p className=\"type-meta ds:text-destructive ds:m-0\">{msg}</p>\n </div>\n ))}\n </div>\n )}\n\n <span\n ref={statusRef}\n role=\"status\"\n aria-live=\"polite\"\n className=\"ds:sr-only\"\n />\n </div>\n );\n },\n);\n\nFileUpload.displayName = 'FileUpload';\n"],"names":["__iconNode","CloudUpload","createLucideIcon","FileArchive","FileImage","FileSpreadsheet","File","LoaderCircle","Upload","fileUploadAgent","handle","args","dropzoneVariants","cva","browseButtonVariants","fileItemVariants","actionButtonVariants","generateId","isImageFile","file","getFileIcon","ext","_a","jsx","FileText","FileIcon","getStatusIcon","status","Loader2","CheckCircle2","AlertCircle","UNIT_KEYS","UNIT_FALLBACKS","formatFileSize","bytes","locale","t","value","unitIndex","formatted","unit","mapRejectionCode","code","getExtensionFromName","name","parts","formatAcceptHint","accept","extensions","exts","mimeLabels","mime","FileUpload","forwardRef","id","maxSize","minSize","maxFiles","multiple","disabled","strictAccept","onDropProp","onUpload","onRemove","onReject","variant","showPreview","className","ref","i18n","useTranslation","ctx","useFormField","fallbackId","useId","effectiveDisabled","hasError","inputId","files","setFiles","useState","rejections","setRejections","abortControllers","useRef","statusRef","filesRef","announceStatus","useCallback","message","validateStrictAccept","mimeMatch","fileExt","extMatch","uploadFile","uploadFileState","controller","prev","f","percent","err","errorMessage","handleDrop","accepted","fileRejections","mapped","r","e","strictRejected","strictAccepted","allRejections","newFiles","nf","getRootProps","getInputProps","isDragActive","open","useDropzone","handleCancel","fileId","handleRemove","removed","clearAll","agentHandle","useMemo","useAgentRegistration","validatePastedFiles","pastedFiles","rejected","effectiveMaxFiles","mimeOk","extOk","handlePaste","event","useEffect","constraintHints","hints","errorMessages","renderFileList","jsxs","X","renderDropzone","rootProps","rootRefFromDropzone","node","renderButton","msg","i"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"notification-tray-CfXNYrxv.js","sources":["../../node_modules/lucide-react/dist/esm/icons/bell.js","../../src/components/notification-tray/notification-tray.agent.ts","../../src/components/notification-tray/notification-tray.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M10.268 21a2 2 0 0 0 3.464 0\", key: \"vwvbt9\" }],\n [\n \"path\",\n {\n d: \"M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326\",\n key: \"11g9vi\"\n }\n ]\n];\nconst Bell = createLucideIcon(\"bell\", __iconNode);\n\nexport { __iconNode, Bell as default };\n//# sourceMappingURL=bell.js.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — NotificationTray. */\n/* */\n/* Tray-level surface: an agent can open / close the panel, read the */\n/* current items (id + read flag only — never PHI), and route per-item */\n/* operations (dismiss, mark_read, select) through the curated handle. */\n/* All actions are routed through the imperative handle; the adapter */\n/* never touches the DOM directly. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { NotificationTrayHandle } from './notification-tray';\n\nexport const notificationTrayAgent: AgentAdapter<NotificationTrayHandle> = {\n id: 'notification-tray',\n capabilities: ['open', 'close', 'select_single', 'dismiss'],\n state: {\n items: {\n type: 'Array<{ id: string; read: boolean }>',\n descriptionKey: 'ui.agent.notificationTray.state.items',\n description:\n 'Currently-displayed notifications. Ids + read flag only — no PHI.',\n read: (handle) => handle.getItems(),\n },\n unreadCount: {\n type: 'number',\n descriptionKey: 'ui.agent.notificationTray.state.unreadCount',\n description: 'Badge unread count surfaced by the host.',\n read: (handle) => handle.getUnreadCount(),\n },\n isOpen: {\n type: 'boolean',\n descriptionKey: 'ui.agent.notificationTray.state.isOpen',\n description: 'Whether the dropdown panel is currently open.',\n read: (handle) => handle.isOpen(),\n },\n },\n actions: {\n open: {\n safety: 'read',\n descriptionKey: 'ui.agent.notificationTray.actions.open',\n description: 'Open the notification panel.',\n invoke: (handle) => {\n handle.open();\n },\n },\n close: {\n safety: 'read',\n descriptionKey: 'ui.agent.notificationTray.actions.close',\n description: 'Close the notification panel.',\n invoke: (handle) => {\n handle.close();\n },\n },\n select_item: {\n safety: 'read',\n argsType: '{ id: string }',\n descriptionKey: 'ui.agent.notificationTray.actions.selectItem',\n description: 'Activate the notification with the given id.',\n invoke: (handle, args: { id: string }) => {\n handle.selectItem(args.id);\n },\n },\n mark_read: {\n safety: 'write',\n argsType: '{ id: string }',\n descriptionKey: 'ui.agent.notificationTray.actions.markRead',\n description: 'Request the host to mark a notification as read.',\n invoke: (handle, args: { id: string }) => {\n handle.markRead(args.id);\n },\n },\n dismiss: {\n safety: 'destructive',\n argsType: '{ id: string }',\n descriptionKey: 'ui.agent.notificationTray.actions.dismiss',\n description:\n 'Request the host to dismiss the notification with the given id.',\n invoke: (handle, args: { id: string }) => {\n handle.dismiss(args.id);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'notification-tray',\n description: 'Marks the NotificationTray wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific tray from the agent.',\n },\n item: {\n attr: 'data-notification-id',\n description:\n 'Stable notification id emitted on each rendered NotificationCard inside the tray.',\n },\n },\n};\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n} from 'react';\nimport * as RadixPopover from '@radix-ui/react-popover';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Bell } from 'lucide-react';\nimport { IconButton } from '../button/icon-button';\nimport { Button } from '../button/button';\nimport { Separator } from '../separator/separator';\nimport { Skeleton } from '../skeleton/skeleton';\nimport {\n NotificationCard,\n type NotificationItem,\n} from '../notification-card/notification-card';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { notificationTrayAgent } from './notification-tray.agent';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\n/**\n * Curated imperative handle for NotificationTray. Exposed as the\n * forwardRef target so a future agent / MCP UI bridge can drive the\n * tray without touching the DOM. See `notification-tray.agent.ts`.\n */\nexport interface NotificationTrayHandle {\n open: () => void;\n close: () => void;\n isOpen: () => boolean;\n getItems: () => Array<{ id: string; read: boolean }>;\n getUnreadCount: () => number;\n selectItem: (id: string) => void;\n markRead: (id: string) => void;\n dismiss: (id: string) => void;\n}\n\nexport interface NotificationTrayProps\n extends\n Omit<\n HTMLAttributes<HTMLDivElement>,\n 'onClick' | 'children' | 'role' | 'id'\n >,\n VariantProps<typeof notificationTrayVariants> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so\n * an agent / MCP UI bridge can address this specific tray.\n */\n id?: string;\n /** Fires when the host should mark a single notification as read (used by agent integration). */\n onMarkRead?: (item: NotificationItem) => void;\n /** Notifications rendered in the dropdown panel. */\n items: NotificationItem[];\n /** Number of unseen notifications. Drives the badge count. */\n unseenCount?: number;\n /** Controlled open state. */\n open?: boolean;\n /** Fires when the open state changes. */\n onOpenChange?: (open: boolean) => void;\n /** Fires when the user activates an item (click or Enter/Space). */\n onItemClick?: (item: NotificationItem) => void;\n /** Fires when the user dismisses a notification. */\n onDismiss?: (item: NotificationItem) => void;\n /** Fires when the user clicks the header \"Mark all as read\" action. */\n onMarkAllRead?: () => void;\n /** When true the panel shows skeleton placeholders. */\n loading?: boolean;\n /** Advisory item count before the list scrolls. Consumers override the cap\n * via the `--notification-tray-max-block-size` custom property. */\n maxVisible?: number;\n /** When set renders a footer link that invokes `onViewAll`. */\n viewAllLabel?: string;\n /** Fires when the footer \"View all\" link is clicked. */\n onViewAll?: () => void;\n /** Panel alignment relative to the trigger. Default `'end'`. */\n align?: 'start' | 'center' | 'end';\n /** Side of the trigger to open on. Default `'bottom'`. */\n side?: 'top' | 'bottom';\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst notificationTrayVariants = cva(\n 'ds:relative ds:inline-flex ds:items-center',\n {\n variants: {\n size: {\n sm: '',\n md: '',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n);\n\nconst panelVariants = cva(\n [\n 'ds:flex ds:flex-col',\n 'ds:bg-[var(--popover)] ds:text-[var(--popover-foreground)]',\n // Border kept (transparent) so the forced-colors override below can\n // repaint a visible edge in HCM. In normal modes the soft drop-shadow\n // carries the edge cue.\n 'ds:border ds:border-transparent',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:shadow-[var(--shadow-lg)]',\n 'ds:z-[var(--z-popover)]',\n // Width: fluid below the design cap so narrow viewports keep a visible\n // gutter on *both* sides of the panel (shadow included). The legacy\n // `min-w` approach clamped at 20rem, which flush-mounted the panel\n // against the inline-start viewport edge on phones.\n 'ds:w-[min(24rem,calc(100vw-2*var(--spacing-md)))]',\n // Height: below the `sm` breakpoint the panel takes a near-full-screen\n // sheet shape so the user gets room to triage messages / notifications\n // without scrolling a tiny popover. `6rem` reserves space for the\n // Header (≈4rem) plus the sideOffset + collisionPadding (≈2rem).\n // Above `sm` it returns to `h-auto` so the list's own\n // `--*-tray-max-block-size` cap governs the height.\n 'ds:h-[calc(100dvh-6rem)] ds:sm:h-auto',\n 'ds:data-[state=open]:animate-in ds:data-[state=closed]:animate-out',\n 'ds:data-[state=closed]:fade-out-0 ds:data-[state=open]:fade-in-0',\n 'ds:data-[state=closed]:zoom-out-95 ds:data-[state=open]:zoom-in-95',\n 'ds:motion-reduce:transition-none ds:motion-reduce:animate-none',\n 'ds:focus-visible:outline-none',\n 'ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:p-[var(--spacing-xs)]',\n md: 'ds:p-[var(--spacing-sm)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n);\n\nconst badgeVariants = cva(\n [\n // Anchored to the top-end corner of the trigger, nudged outward so\n // the bell icon isn't covered.\n 'ds:absolute ds:-top-[var(--spacing-xs)] ds:-end-[var(--spacing-xs)]',\n 'ds:inline-flex ds:items-center ds:justify-center',\n // Circle at 1-2 digits; widens into a pill only for \"99+\".\n 'ds:min-w-[calc(var(--spacing-md)+var(--spacing-xs))] ds:h-[calc(var(--spacing-md)+var(--spacing-xs))] ds:ps-[calc(var(--spacing-xs)/1.5)] ds:pe-[calc(var(--spacing-xs)/1.5)]',\n 'ds:rounded-[var(--radius-full)]',\n 'ds:bg-[color:var(--destructive)] ds:text-[color:var(--destructive-foreground)]',\n 'ds:text-[length:var(--font-size-xs)] ds:font-semibold ds:leading-none',\n 'ds:pointer-events-none ds:select-none',\n 'ds:forced-colors:outline ds:forced-colors:outline-1 ds:forced-colors:outline-[CanvasText]',\n ].join(' '),\n);\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\nfunction formatBadgeCount(count: number, overflowLabel: string): string {\n return count > 99 ? overflowLabel : String(count);\n}\n\nfunction SkeletonRow() {\n return (\n <div\n aria-hidden=\"true\"\n className=\"ds:flex ds:items-start ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)]\"\n >\n <Skeleton variant=\"circular\" size=\"sm\" />\n <div className=\"ds:flex-1 ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <Skeleton variant=\"text\" size=\"md\" width=\"70%\" />\n <Skeleton variant=\"text\" size=\"sm\" width=\"90%\" />\n <Skeleton variant=\"text\" size=\"sm\" width=\"30%\" />\n </div>\n </div>\n );\n}\n\nfunction EmptyPanel() {\n const { t } = useTranslation();\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"ds:flex ds:flex-col ds:items-center ds:justify-center ds:gap-[var(--spacing-xs)] ds:p-[var(--spacing-lg)] ds:text-center\"\n >\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-flex ds:items-center ds:justify-center ds:size-10 ds:rounded-[var(--radius-full)] ds:bg-[color:var(--muted)] ds:text-[color:var(--muted-foreground)] ds:[&>svg]:size-5\"\n >\n <Bell />\n </span>\n <p className=\"type-title-item ds:text-[color:var(--foreground)]\">\n {t('notificationTray.noNotifications', 'No notifications')}\n </p>\n <p className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {t(\n 'notificationTray.noNotificationsDescription',\n \"You're all caught up.\",\n )}\n </p>\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Root */\n/* ------------------------------------------------------------------ */\n\nexport const NotificationTray = forwardRef<\n HTMLDivElement,\n NotificationTrayProps\n>(\n (\n {\n id,\n items,\n unseenCount,\n open,\n onOpenChange,\n onItemClick,\n onDismiss,\n onMarkRead,\n onMarkAllRead,\n loading = false,\n maxVisible,\n viewAllLabel,\n onViewAll,\n align = 'end',\n side = 'bottom',\n size = 'md',\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n\n const isControlled = open !== undefined;\n const [internalOpen, setInternalOpen] = useState(false);\n const isOpen = isControlled ? open : internalOpen;\n\n const handleOpenChange = useCallback(\n (next: boolean) => {\n if (!isControlled) setInternalOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n /* Exit-animation list (AnimatePresence-style).\n * `displayed` holds an entry per card that's currently mounted, even\n * briefly after the consumer removes an item from `items`. When the\n * consumer drops an id from `items`, we flip that entry to\n * `leaving: true` for one animation cycle, then prune it. */\n type Displayed = { item: NotificationItem; leaving: boolean };\n const [displayed, setDisplayed] = useState<Displayed[]>(() =>\n items.map((item) => ({ item, leaving: false })),\n );\n\n const animationDurationMs = useCallback((): number => {\n if (typeof window === 'undefined') return 200;\n const raw = window\n .getComputedStyle(document.documentElement)\n .getPropertyValue('--animation-duration');\n if (!raw) return 200;\n const trimmed = raw.trim();\n const n = parseFloat(trimmed);\n if (!Number.isFinite(n)) return 200;\n return trimmed.endsWith('ms') ? n : n * 1000;\n }, []);\n\n // `useLayoutEffect` so the `leaving=true` flip applies in the same paint\n // as the consumer's `items` update. With `useEffect` the browser paints\n // once with the dismissed card still at `leaving=false` (no animation)\n // before the flag flips — a visible lag before the exit animation starts.\n useLayoutEffect(() => {\n setDisplayed((prev) => {\n const nextIds = new Set(items.map((i) => i.id));\n const prevIds = new Set(prev.map((d) => d.item.id));\n\n const merged: Displayed[] = prev.map((d) => {\n if (nextIds.has(d.item.id)) {\n const fresh = items.find((i) => i.id === d.item.id);\n return fresh\n ? { item: fresh, leaving: false }\n : { ...d, leaving: true };\n }\n return { ...d, leaving: true };\n });\n\n for (const i of items) {\n if (!prevIds.has(i.id)) merged.push({ item: i, leaving: false });\n }\n return merged;\n });\n }, [items]);\n\n useEffect(() => {\n if (!displayed.some((d) => d.leaving)) return;\n const ms = animationDurationMs();\n const timer = setTimeout(() => {\n setDisplayed((prev) => prev.filter((d) => !d.leaving));\n }, ms);\n return () => clearTimeout(timer);\n }, [displayed, animationDurationMs]);\n\n /* Polite live region — announces when a new unread notification\n floats to the top of the list, even with the panel closed. */\n const liveRegionRef = useRef<HTMLDivElement | null>(null);\n const lastTopIdRef = useRef<string | undefined>(items[0]?.id);\n\n useEffect(() => {\n const topId = items[0]?.id;\n const prev = lastTopIdRef.current;\n if (prev && topId && prev !== topId && liveRegionRef.current) {\n const newest = items[0];\n if (newest && !newest.read) {\n liveRegionRef.current.textContent = t(\n 'notificationTray.newNotification',\n {\n title: newest.title,\n defaultValue: 'New notification: {{title}}',\n },\n );\n }\n }\n lastTopIdRef.current = topId;\n }, [items, t]);\n\n const displayCount = unseenCount ?? 0;\n const triggerAriaLabel =\n displayCount > 0\n ? t('notificationTray.triggerLabel', {\n count: displayCount,\n defaultValue: 'Notifications, {{count}} unread',\n })\n : t(\n 'notificationTray.triggerLabelNone',\n 'Notifications, none unread',\n );\n\n const badgeLabel = formatBadgeCount(\n displayCount,\n t('notificationTray.badgeCountOverflow', '99+'),\n );\n\n const panelClass = panelVariants({ size });\n\n /* Curated imperative handle for agent integration. Pure look-ups +\n * delegations into the consumer-supplied callbacks; never touches the\n * DOM. See notification-tray.agent.ts. */\n const itemsRef = useRef<NotificationItem[]>(items);\n itemsRef.current = items;\n const unseenRef = useRef<number | undefined>(unseenCount);\n unseenRef.current = unseenCount;\n const isOpenRef = useRef<boolean>(isOpen);\n isOpenRef.current = isOpen;\n\n const handle = useMemo<NotificationTrayHandle>(\n () => ({\n open: () => handleOpenChange(true),\n close: () => handleOpenChange(false),\n isOpen: () => isOpenRef.current,\n getItems: () =>\n itemsRef.current.map((i) => ({ id: i.id, read: !!i.read })),\n getUnreadCount: () =>\n unseenRef.current ?? itemsRef.current.filter((i) => !i.read).length,\n selectItem: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onItemClick?.(found);\n },\n markRead: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onMarkRead?.(found);\n },\n dismiss: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onDismiss?.(found);\n },\n }),\n [handleOpenChange, onItemClick, onMarkRead, onDismiss],\n );\n\n const rootRef = useRef<HTMLDivElement>(null);\n useImperativeHandle(ref, () => rootRef.current as HTMLDivElement, []);\n useAgentRegistration(notificationTrayAgent, handle, id);\n\n return (\n <div\n ref={rootRef}\n data-component=\"notification-tray\"\n data-component-id={id}\n className={[notificationTrayVariants({ size }), className]\n .filter(Boolean)\n .join(' ')}\n {...rest}\n >\n <RadixPopover.Root open={isOpen} onOpenChange={handleOpenChange}>\n <RadixPopover.Trigger asChild>\n <IconButton\n icon={<Bell />}\n intent=\"outline\"\n size={size === 'sm' ? 'sm' : 'md'}\n aria-label={triggerAriaLabel}\n aria-haspopup=\"dialog\"\n />\n </RadixPopover.Trigger>\n {displayCount > 0 ? (\n <span\n aria-hidden=\"true\"\n data-testid=\"notification-tray-badge\"\n className={badgeVariants()}\n >\n {badgeLabel}\n </span>\n ) : null}\n {/* Live region sits outside the popover so it announces even\n while the panel is closed. */}\n <div\n ref={liveRegionRef}\n aria-live=\"polite\"\n aria-atomic=\"true\"\n className=\"ds:sr-only\"\n />\n <RadixPopover.Portal>\n <RadixPopover.Content\n role=\"dialog\"\n aria-label={t('notificationTray.panelTitle', 'Notifications')}\n side={side}\n align={align}\n sideOffset={8}\n // `spacing-md` (16px) keeps Radix's collision-avoidance from\n // flush-mounting the panel against the viewport edge when the\n // trigger is near the inline-end of a narrow screen.\n collisionPadding={16}\n className={panelClass}\n >\n <div className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)] ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:pb-[var(--spacing-xs)]\">\n <h3 className=\"ds:m-0 type-title-card ds:text-[color:var(--foreground)]\">\n {t('notificationTray.panelTitle', 'Notifications')}\n </h3>\n {onMarkAllRead && items.some((item) => !item.read) ? (\n <Button\n intent=\"link\"\n size=\"sm\"\n onClick={onMarkAllRead}\n className=\"ds:text-[length:var(--font-size-xs)]\"\n >\n {t('notificationTray.markAllRead', 'Mark all as read')}\n </Button>\n ) : null}\n </div>\n <Separator />\n {/* Cap at ~24rem so ~5 items fit before the list scrolls.\n Consumers override via the --notification-tray-max-block-size\n custom property on the root element. */}\n <div\n // `role=\"list\"` requires `listitem` children — applied only\n // when we render NotificationCards. The empty / loading\n // states render a `role=\"status\"` panel which would violate\n // aria-required-children if the list role were always on.\n role={loading || displayed.length === 0 ? undefined : 'list'}\n data-max-visible={maxVisible}\n // Below `sm` the panel is a near-full-screen sheet (see\n // `panelVariants`) and the list expands to fill the\n // remaining space with `flex-1`. Above `sm` the list\n // caps at the `--notification-tray-max-block-size` custom\n // property so the popover stays compact.\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:overflow-y-auto ds:pt-[var(--spacing-xs)] ds:flex-1 ds:sm:flex-none ds:sm:[max-block-size:var(--notification-tray-max-block-size,24rem)]\"\n >\n {loading ? (\n <>\n <SkeletonRow />\n <SkeletonRow />\n <SkeletonRow />\n </>\n ) : displayed.length === 0 ? (\n <EmptyPanel />\n ) : (\n displayed.map(({ item, leaving }) => (\n <NotificationCard\n key={item.id}\n item={item}\n variant=\"compact\"\n leaving={leaving}\n onActivate={onItemClick}\n onDismiss={onDismiss}\n data-notification-id={item.id}\n />\n ))\n )}\n </div>\n {viewAllLabel ? (\n <>\n <Separator />\n <div className=\"ds:pt-[var(--spacing-xs)]\">\n <Button\n intent=\"link\"\n size=\"sm\"\n onClick={onViewAll}\n className=\"ds:w-full ds:justify-center\"\n >\n {viewAllLabel}\n </Button>\n </div>\n </>\n ) : null}\n </RadixPopover.Content>\n </RadixPopover.Portal>\n </RadixPopover.Root>\n </div>\n );\n },\n);\n\nNotificationTray.displayName = 'NotificationTray';\n"],"names":["__iconNode","Bell","createLucideIcon","notificationTrayAgent","handle","args","notificationTrayVariants","cva","panelVariants","badgeVariants","formatBadgeCount","count","overflowLabel","SkeletonRow","jsxs","jsx","Skeleton","EmptyPanel","t","useTranslation","NotificationTray","forwardRef","id","items","unseenCount","open","onOpenChange","onItemClick","onDismiss","onMarkRead","onMarkAllRead","loading","maxVisible","viewAllLabel","onViewAll","align","side","size","className","rest","ref","isControlled","internalOpen","setInternalOpen","useState","isOpen","handleOpenChange","useCallback","next","displayed","setDisplayed","item","animationDurationMs","raw","trimmed","n","useLayoutEffect","prev","nextIds","i","prevIds","d","merged","fresh","useEffect","ms","timer","liveRegionRef","useRef","lastTopIdRef","_a","topId","newest","displayCount","triggerAriaLabel","badgeLabel","panelClass","itemsRef","unseenRef","isOpenRef","useMemo","targetId","found","rootRef","useImperativeHandle","useAgentRegistration","RadixPopover","IconButton","Button","Separator","Fragment","leaving","NotificationCard"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sparkline-D4Np8ikf.js","sources":["../../src/components/sparkline/use-linear-trend.ts","../../src/components/sparkline/sparkline.agent.ts","../../src/components/sparkline/sparkline.tsx"],"sourcesContent":["export type TrendDirection = 'increasing' | 'decreasing' | 'steady';\n\nexport interface LinearTrendResult {\n slope: number;\n direction: TrendDirection;\n}\n\nexport function useLinearTrend(data: number[]): LinearTrendResult {\n if (data.length < 2) {\n return { slope: 0, direction: 'steady' };\n }\n\n const n = data.length;\n const xMean = (n - 1) / 2;\n const yMean = data.reduce((sum, y) => sum + y, 0) / n;\n\n let numerator = 0;\n let denominator = 0;\n\n for (let i = 0; i < n; i++) {\n const dx = i - xMean;\n numerator += dx * (data[i] - yMean);\n denominator += dx * dx;\n }\n\n const slope = denominator === 0 ? 0 : numerator / denominator;\n const range = Math.max(...data) - Math.min(...data);\n const threshold = 0.01 * (range || 1);\n\n const direction: TrendDirection =\n Math.abs(slope) < threshold\n ? 'steady'\n : slope > 0\n ? 'increasing'\n : 'decreasing';\n\n return { slope, direction };\n}\n","import type { AgentAdapter } from '../../agent/types';\nimport type { SparklineHandle } from './sparkline';\n\nexport const sparklineAgent: AgentAdapter<SparklineHandle> = {\n id: 'sparkline',\n capabilities: [],\n state: {},\n actions: {\n update_series: {\n safety: 'read',\n argsType: '{ data: number[] }',\n description: 'Replace the sparkline data without remounting.',\n invoke: (handle, args: { data: number[] }) => {\n handle.updateSeries(args.data);\n },\n },\n export_png: {\n safety: 'read',\n description: 'Return a PNG data URI of the sparkline.',\n invoke: (handle) => handle.dataURI(),\n },\n },\n domHooks: {\n root: { attr: 'data-component', value: 'sparkline' },\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 useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport ReactApexChart from 'react-apexcharts';\nimport ApexCharts from 'apexcharts';\nimport { getApexChartsTheme } from '../../tokens/apexcharts-theme';\nimport { useNeutraliseHiddenFocus } from '../_shared/use-neutralize-hidden-focus';\nimport { useLinearTrend } from './use-linear-trend';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { sparklineAgent } from './sparkline.agent';\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst sparklineVariants = cva('ds:relative ds:inline-block ds:w-full', {\n variants: {\n size: {\n xs: 'ds:h-6',\n sm: 'ds:h-8',\n md: 'ds:h-10',\n },\n },\n defaultVariants: { size: 'md' },\n});\n\n/* ------------------------------------------------------------------ */\n/* Constants */\n/* ------------------------------------------------------------------ */\n\nconst DIRECTION_ARROW = {\n increasing: '↑',\n decreasing: '↓',\n steady: '→',\n} as const;\n\nconst SIZE_HEIGHT: Record<'xs' | 'sm' | 'md', number> = {\n xs: 24,\n sm: 32,\n md: 40,\n};\n\nfunction prefersReducedMotion(): boolean {\n return (\n typeof window !== 'undefined' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------ */\n\nexport interface SparklineHandle {\n updateSeries: (data: number[]) => void;\n updateOptions: (opts: ApexCharts.ApexOptions) => void;\n dataURI: () => Promise<string>;\n}\n\nexport interface SparklineProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'role' | 'children'>,\n VariantProps<typeof sparklineVariants> {\n /** Array of numeric data points */\n data: number[];\n /** Chart visual style */\n variant?: 'line' | 'bar' | 'area';\n /** Size preset */\n size?: 'xs' | 'sm' | 'md';\n /** Accessible label prefix, e.g. \"Revenue, 30 days\" */\n label?: string;\n /** Stroke / bar colour override — defaults to var(--primary) via bridge */\n color?: string;\n /** Show end-point dot with trend direction arrow */\n showEndpoint?: boolean;\n /**\n * Show Apex's hover tooltip with the data point value. Defaults to\n * `false` — sparklines are intentionally minimal — opt in when the\n * sparkline is large enough to be a primary metric surface (e.g.\n * dashboard widgets) and the user benefits from per-point readout.\n */\n showTooltip?: boolean;\n /** Width override — defaults to 100% of container */\n width?: string | number;\n /** Height override — defaults to the size variant height */\n height?: string | number;\n}\n\n/* ------------------------------------------------------------------ */\n/* Sparkline component */\n/* ------------------------------------------------------------------ */\n\nexport const Sparkline = forwardRef<SparklineHandle, SparklineProps>(\n (\n {\n id,\n data,\n variant = 'line',\n size = 'md',\n label,\n color,\n showEndpoint = false,\n showTooltip = false,\n width,\n height,\n className,\n ...props\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const rawId = useId();\n const chartId = useMemo(\n () => `sparkline-${rawId.replace(/[^a-zA-Z0-9-_]/g, '')}`,\n [rawId],\n );\n const wrapperRef = useRef<HTMLDivElement>(null);\n const [containerWidth, setContainerWidth] = useState(0);\n\n const { direction } = useLinearTrend(data);\n\n /* ---- accessible summary ---------------------------------------- */\n const ariaLabel = useMemo(() => {\n if (data.length === 0) {\n return t('sparkline.noData', 'No data');\n }\n const fmt = (n: number) => new Intl.NumberFormat(i18n.language).format(n);\n const dirText = t(`ui.sparkline.direction.${direction}`);\n const nums = {\n min: fmt(Math.min(...data)),\n max: fmt(Math.max(...data)),\n current: fmt(data[data.length - 1]),\n direction: dirText,\n };\n if (label) {\n return t('sparkline.summary', { label, ...nums });\n }\n return t('sparkline.summaryNoLabel', nums);\n }, [data, label, direction, i18n.language, t]);\n\n /* ---- theme-reactive state -------------------------------------- */\n const [themeOptions, setThemeOptions] = useState<ApexCharts.ApexOptions>(\n () => {\n try {\n return getApexChartsTheme();\n } catch {\n return {};\n }\n },\n );\n\n /* ---- MutationObserver: re-read theme on class change ----------- */\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout>;\n const observer = new MutationObserver(() => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n try {\n setThemeOptions(getApexChartsTheme());\n } catch {\n /* no-op in non-browser environments */\n }\n }, 50);\n });\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class'],\n });\n return () => {\n clearTimeout(timer);\n observer.disconnect();\n };\n }, []);\n\n /* ---- ResizeObserver: track container width -------------------- */\n useEffect(() => {\n const el = wrapperRef.current;\n if (!el) return;\n const ro = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry) setContainerWidth(Math.floor(entry.contentRect.width));\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n /* ApexCharts injects focusable canvases inside the `aria-hidden` */\n /* chart wrapper. Neutralise their tabindex so axe's */\n /* `aria-hidden-focus` rule passes. Shared hook — same fix in */\n /* `Chart` (full apex) and the calendar's mirror events. */\n useNeutraliseHiddenFocus(wrapperRef);\n\n /* ---- imperative handle ---------------------------------------- */\n const agentHandle = useMemo<SparklineHandle>(\n () => ({\n updateSeries(newData: number[]) {\n ApexCharts.getChartByID(chartId)?.updateSeries([{ data: newData }]);\n },\n updateOptions(opts: ApexCharts.ApexOptions) {\n ApexCharts.getChartByID(chartId)?.updateOptions(opts);\n },\n async dataURI(): Promise<string> {\n const instance = ApexCharts.getChartByID(chartId);\n if (!instance) return '';\n const result = await instance.dataURI();\n return (result as { imgURI: string }).imgURI;\n },\n }),\n [chartId],\n );\n useImperativeHandle(ref, () => agentHandle, [agentHandle]);\n useAgentRegistration(sparklineAgent, agentHandle, id);\n\n /* ---- resolve color -------------------------------------------- */\n const resolvedColor = color ?? themeOptions.colors?.[0] ?? 'currentColor';\n\n /* ---- empty state ---------------------------------------------- */\n if (data.length === 0) {\n return (\n <div\n ref={wrapperRef}\n role=\"img\"\n aria-label={ariaLabel}\n dir=\"ltr\"\n className={sparklineVariants({ size, className })}\n {...props}\n />\n );\n }\n\n /* ---- chart config ---------------------------------------------- */\n const reducedMotion = prefersReducedMotion();\n\n const chartOptions: ApexCharts.ApexOptions = {\n ...themeOptions,\n chart: {\n ...themeOptions.chart,\n id: chartId,\n type: variant,\n sparkline: { enabled: true },\n toolbar: { show: false },\n animations: {\n enabled: !reducedMotion,\n dynamicAnimation: { enabled: !reducedMotion },\n },\n zoom: { enabled: false },\n parentHeightOffset: 0,\n },\n colors: [resolvedColor],\n stroke: {\n curve: 'smooth',\n width: variant === 'bar' ? 0 : 2,\n },\n fill: {\n opacity: variant === 'area' ? 0.15 : 1,\n },\n xaxis: {\n crosshairs: { show: false },\n },\n tooltip: { enabled: showTooltip },\n markers: showEndpoint\n ? {\n size: [0],\n discrete: [\n {\n seriesIndex: 0,\n dataPointIndex: data.length - 1,\n fillColor: resolvedColor,\n strokeColor: resolvedColor,\n size: 4,\n },\n ],\n }\n : { size: 0 },\n grid: {\n ...themeOptions.grid,\n show: false,\n // ApexCharts grid.padding uses physical keys (not CSS logical properties).\n // The chart wrapper enforces dir=\"ltr\" so these always resolve correctly.\n padding: { top: 2, right: 2, bottom: 2, left: 2 },\n },\n };\n\n const resolvedWidth =\n width ?? (containerWidth > 0 ? containerWidth : '100%');\n const resolvedHeight = height ?? SIZE_HEIGHT[size ?? 'md'];\n\n return (\n <div\n ref={wrapperRef}\n role=\"img\"\n aria-label={ariaLabel}\n dir=\"ltr\"\n className={sparklineVariants({ size, className })}\n data-component=\"sparkline\"\n data-component-id={id}\n {...props}\n >\n <ReactApexChart\n type={variant}\n series={[{ data }]}\n options={chartOptions}\n width={resolvedWidth}\n height={resolvedHeight}\n aria-hidden=\"true\"\n />\n {showEndpoint && (\n <span\n aria-hidden=\"true\"\n className=\"ds:pointer-events-none ds:absolute ds:end-0 ds:top-0 ds:text-[length:var(--font-size-xs)] ds:leading-none\"\n >\n {DIRECTION_ARROW[direction]}\n </span>\n )}\n </div>\n );\n },\n);\n\nSparkline.displayName = 'Sparkline';\n"],"names":["useLinearTrend","data","n","xMean","yMean","sum","y","numerator","denominator","i","dx","slope","threshold","direction","sparklineAgent","handle","args","sparklineVariants","cva","DIRECTION_ARROW","SIZE_HEIGHT","prefersReducedMotion","Sparkline","forwardRef","id","variant","size","label","color","showEndpoint","showTooltip","width","height","className","props","ref","t","i18n","useTranslation","rawId","useId","chartId","useMemo","wrapperRef","useRef","containerWidth","setContainerWidth","useState","ariaLabel","fmt","dirText","nums","themeOptions","setThemeOptions","getApexChartsTheme","useEffect","timer","observer","el","ro","entries","entry","useNeutraliseHiddenFocus","agentHandle","newData","_a","ApexCharts","opts","instance","useImperativeHandle","useAgentRegistration","resolvedColor","jsx","reducedMotion","chartOptions","resolvedWidth","resolvedHeight","jsxs","ReactApexChart"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"timeline-BaSULpSJ.js","sources":["../../src/components/timeline/timeline.agent.ts","../../src/components/timeline/timeline.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — Timeline. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { TimelineHandle } from './timeline';\n\nexport const timelineAgent: AgentAdapter<TimelineHandle> = {\n id: 'timeline',\n capabilities: ['pick', 'range_navigate'],\n state: {\n selectedEvent: {\n type: 'string | null',\n descriptionKey: 'ui.agent.timeline.state.selectedEvent',\n description: 'Opaque event id of the currently-active event, or null.',\n read: (handle) => handle.getSelectedEvent(),\n },\n },\n actions: {\n select_event: {\n safety: 'read',\n argsType: '{ id: string }',\n descriptionKey: 'ui.agent.timeline.actions.selectEvent',\n description: 'Scroll the given event into view and mark it as selected.',\n invoke: (handle, args: { id: string }) => {\n handle.selectEvent(args.id);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'timeline',\n description: 'Marks the Timeline root.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n item: {\n attr: 'data-event-id',\n description:\n 'Opaque event id emitted on each Timeline.Event when the `eventId` prop is provided.',\n },\n },\n};\n","import {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type LiHTMLAttributes,\n type OlHTMLAttributes,\n type ReactNode,\n type TimeHTMLAttributes,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { AlertTriangle, Check, Circle, Info, X } from 'lucide-react';\nimport { Avatar } from '../avatar';\nimport { Card } from '../card';\nimport { Timestamp } from '../timestamp';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { timelineAgent } from './timeline.agent';\n\n// TODO: optional @tanstack/react-virtual integration for 500+ events\n\n/* ------------------------------------------------------------------ */\n/* Context */\n/* ------------------------------------------------------------------ */\n\ntype EventType = 'info' | 'success' | 'warning' | 'error' | 'neutral';\ntype Layout = 'rail-start' | 'rail-end' | 'alternating';\n\ninterface TimelineContextValue {\n layout: Layout;\n order: 'newest-first' | 'oldest-first';\n}\n\nconst TimelineContext = createContext<TimelineContextValue>({\n layout: 'rail-start',\n order: 'newest-first',\n});\n\ninterface TimelineEventContextValue {\n type: EventType;\n}\n\nconst TimelineEventContext = createContext<TimelineEventContextValue>({\n type: 'neutral',\n});\n\n/* ------------------------------------------------------------------ */\n/* CVA — root */\n/* ------------------------------------------------------------------ */\n\nconst timelineVariants = cva('ds:flex ds:flex-col', {\n variants: {\n layout: {\n 'rail-start': 'ds:ps-4',\n 'rail-end': 'ds:pe-4',\n alternating:\n 'ds:grid ds:grid-cols-[1fr_2rem_1fr] ds:gap-x-[var(--spacing-md)]',\n },\n order: {\n 'newest-first': 'ds:flex-col',\n 'oldest-first': 'ds:flex-col-reverse',\n },\n },\n defaultVariants: { layout: 'rail-start', order: 'newest-first' },\n});\n\n/* ------------------------------------------------------------------ */\n/* CVA — event item */\n/* ------------------------------------------------------------------ */\n\nconst eventVariants = cva(\n 'ds:relative ds:flex ds:gap-[var(--spacing-md)] ds:pb-[var(--spacing-md)]',\n {\n variants: {\n layout: {\n 'rail-start': [\n 'ds:flex-row',\n // Rail: continuous border on the inline-start of the event list\n 'ds:before:absolute ds:before:top-8 ds:before:bottom-0',\n 'ds:before:border-inline-start-[2px] ds:before:border-[color:var(--border)]',\n 'ds:before:inset-inline-start-[-1rem]',\n 'ds:last:before:hidden',\n ].join(' '),\n 'rail-end': [\n 'ds:flex-row-reverse',\n 'ds:before:absolute ds:before:top-8 ds:before:bottom-0',\n 'ds:before:border-inline-end-[2px] ds:before:border-[color:var(--border)]',\n 'ds:before:inset-inline-end-[-1rem]',\n 'ds:last:before:hidden',\n ].join(' '),\n alternating: 'ds:contents',\n },\n },\n defaultVariants: { layout: 'rail-start' },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* CVA — dot */\n/* ------------------------------------------------------------------ */\n\nconst dotVariants = cva(\n [\n 'ds:relative ds:z-10 ds:flex ds:items-center ds:justify-center',\n 'ds:rounded-[var(--radius-full)] ds:shrink-0',\n 'ds:size-8',\n 'ds:ring-2 ds:ring-[var(--background)]',\n ].join(' '),\n {\n variants: {\n type: {\n info: 'ds:bg-[var(--info)] ds:text-[var(--info-solid-foreground)]',\n success:\n 'ds:bg-[var(--success)] ds:text-[var(--success-solid-foreground)]',\n warning:\n 'ds:bg-[var(--warning)] ds:text-[var(--warning-solid-foreground)]',\n error:\n 'ds:bg-[var(--destructive)] ds:text-[var(--destructive-foreground)]',\n neutral: 'ds:bg-[var(--muted)] ds:text-[var(--muted-foreground)]',\n },\n },\n defaultVariants: { type: 'neutral' },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport interface TimelineProps\n extends\n Omit<OlHTMLAttributes<HTMLOListElement>, 'color'>,\n VariantProps<typeof timelineVariants> {\n layout?: Layout;\n order?: 'newest-first' | 'oldest-first';\n children: ReactNode;\n className?: string;\n}\n\nexport interface TimelineEventProps extends LiHTMLAttributes<HTMLLIElement> {\n type?: EventType;\n /** Opaque event id — when set, the component emits `data-event-id` for agent addressing. */\n eventId?: string;\n children: ReactNode;\n className?: string;\n}\n\n/** Curated imperative handle for agent / external automation. */\nexport interface TimelineHandle {\n getSelectedEvent: () => string | null;\n selectEvent: (id: string) => void;\n}\n\nexport interface TimelineDotProps extends HTMLAttributes<HTMLDivElement> {\n icon?: ReactNode;\n className?: string;\n}\n\nexport interface TimelineContentProps extends HTMLAttributes<HTMLDivElement> {\n title: string;\n description?: string;\n actor?: { name: string; src?: string };\n children?: ReactNode;\n className?: string;\n}\n\nexport interface TimelineTimestampProps extends TimeHTMLAttributes<HTMLTimeElement> {\n date: Date | string;\n relative?: boolean;\n format?: Intl.DateTimeFormatOptions;\n className?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* Default icons per type */\n/* ------------------------------------------------------------------ */\n\nconst TYPE_ICONS: Record<EventType, ReactNode> = {\n info: <Info size={16} aria-hidden=\"true\" />,\n success: <Check size={16} aria-hidden=\"true\" />,\n warning: <AlertTriangle size={16} aria-hidden=\"true\" />,\n error: <X size={16} aria-hidden=\"true\" />,\n neutral: <Circle size={16} aria-hidden=\"true\" />,\n};\n\n/* ------------------------------------------------------------------ */\n/* Timeline root */\n/* ------------------------------------------------------------------ */\n\nconst TimelineRoot = forwardRef<HTMLOListElement, TimelineProps>(\n (\n {\n layout = 'rail-start',\n order = 'newest-first',\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const ctx = useMemo(() => ({ layout, order }), [layout, order]);\n const olRef = useRef<HTMLOListElement | null>(null);\n const [selectedEvent, setSelectedEvent] = useState<string | null>(null);\n const latestRef = useRef<string | null>(null);\n latestRef.current = selectedEvent;\n\n const selectEvent = useCallback((id: string) => {\n setSelectedEvent(id);\n const target = olRef.current?.querySelector(\n `[data-event-id=\"${id}\"]`,\n ) as HTMLElement | null;\n target?.scrollIntoView({ block: 'center', behavior: 'auto' });\n }, []);\n\n const agentHandle = useMemo<TimelineHandle>(\n () => ({\n getSelectedEvent: () => latestRef.current,\n selectEvent,\n }),\n [selectEvent],\n );\n useImperativeHandle(ref, () => olRef.current as HTMLOListElement, []);\n useAgentRegistration(timelineAgent, agentHandle, props.id);\n\n return (\n <TimelineContext.Provider value={ctx}>\n <ol\n ref={olRef}\n data-component=\"timeline\"\n data-component-id={props.id}\n data-selected-event={selectedEvent ?? undefined}\n className={timelineVariants({ layout, order, className })}\n {...props}\n >\n {children}\n </ol>\n </TimelineContext.Provider>\n );\n },\n);\nTimelineRoot.displayName = 'Timeline';\n\n/* ------------------------------------------------------------------ */\n/* Timeline.Event */\n/* ------------------------------------------------------------------ */\n\nconst TimelineEvent = forwardRef<HTMLLIElement, TimelineEventProps>(\n ({ type = 'neutral', eventId, className, children, ...props }, ref) => {\n const { layout } = useContext(TimelineContext);\n const { t } = useTranslation();\n\n const evtCtx = useMemo(() => ({ type }), [type]);\n\n if (layout === 'alternating') {\n // In alternating layout the <li> uses `contents` so its children\n // participate directly in the parent grid.\n return (\n <TimelineEventContext.Provider value={evtCtx}>\n <li\n ref={ref}\n data-event-id={eventId}\n className={['ds:contents', className].filter(Boolean).join(' ')}\n {...props}\n >\n {/* Visually-hidden type prefix for screen readers */}\n <span className=\"ds:sr-only\">{t(`ui.timeline.type.${type}`)}</span>\n {children}\n </li>\n </TimelineEventContext.Provider>\n );\n }\n\n return (\n <TimelineEventContext.Provider value={evtCtx}>\n <li\n ref={ref}\n data-event-id={eventId}\n className={eventVariants({ layout, className })}\n {...props}\n >\n {/* Visually-hidden type prefix for screen readers */}\n <span className=\"ds:sr-only\">{t(`ui.timeline.type.${type}`)}</span>\n {children}\n </li>\n </TimelineEventContext.Provider>\n );\n },\n);\nTimelineEvent.displayName = 'Timeline.Event';\n\n/* ------------------------------------------------------------------ */\n/* Timeline.Dot */\n/* ------------------------------------------------------------------ */\n\nconst TimelineDot = forwardRef<HTMLDivElement, TimelineDotProps>(\n ({ icon, className, ...props }, ref) => {\n const { type } = useContext(TimelineEventContext);\n const { layout } = useContext(TimelineContext);\n\n const dot = (\n <div\n ref={ref}\n aria-hidden=\"true\"\n className={dotVariants({ type, className })}\n {...props}\n >\n {icon ?? TYPE_ICONS[type]}\n </div>\n );\n\n if (layout === 'alternating') {\n // In alternating grid: col 2 (centre) for the dot with the rail line\n return (\n <div\n aria-hidden=\"true\"\n className=\"ds:col-start-2 ds:flex ds:flex-col ds:items-center\"\n >\n {/* Rail segment above the dot */}\n <div className=\"ds:w-[var(--border-width-md)] ds:flex-1 ds:bg-[var(--border)] ds:first:hidden\" />\n {dot}\n {/* Rail segment below the dot */}\n <div className=\"ds:w-[var(--border-width-md)] ds:flex-1 ds:bg-[var(--border)]\" />\n </div>\n );\n }\n\n return dot;\n },\n);\nTimelineDot.displayName = 'Timeline.Dot';\n\n/* ------------------------------------------------------------------ */\n/* Timeline.Content */\n/* ------------------------------------------------------------------ */\n\nconst TimelineContent = forwardRef<HTMLDivElement, TimelineContentProps>(\n ({ title, description, actor, children, className, ...props }, ref) => {\n const { layout } = useContext(TimelineContext);\n\n const inner = (\n <div\n ref={ref}\n className={[\n 'ds:flex-1 ds:min-w-0 ds:pb-[var(--spacing-md)]',\n 'ds:[&_*]:break-normal ds:[&_*]:[overflow-wrap:anywhere]',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n >\n <Card variant=\"outlined\">\n <Card.Body>\n <p className=\"type-label ds:text-[var(--foreground)]\">{title}</p>\n {description && (\n <p className=\"ds:mt-[var(--spacing-xs)] type-body-sm ds:text-[var(--muted-foreground)]\">\n {description}\n </p>\n )}\n {actor && (\n <div className=\"ds:mt-[var(--spacing-sm)] ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <Avatar size=\"xs\" name={actor.name} src={actor.src} />\n <span className=\"type-meta ds:text-[var(--muted-foreground)]\">\n {actor.name}\n </span>\n </div>\n )}\n {children}\n </Card.Body>\n </Card>\n </div>\n );\n\n if (layout === 'alternating') {\n // Alternating: odd events in col 1 (start), even events in col 3 (end).\n // We use CSS nth-child targeting via a wrapper that sets col placement.\n return (\n <div className=\"ds:col-span-1 ds:[li:nth-child(even)_&]:col-start-3 ds:[li:nth-child(odd)_&]:col-start-1\">\n {inner}\n </div>\n );\n }\n\n return inner;\n },\n);\nTimelineContent.displayName = 'Timeline.Content';\n\n/* ------------------------------------------------------------------ */\n/* Timeline.Timestamp — thin wrapper over the shared Timestamp */\n/* component. Keeps the existing API (`date`, `relative`, `format`) */\n/* for backward compatibility; adds tabular-nums because timeline */\n/* timestamps sit in a rail gutter and benefit from column-aligned */\n/* digits. */\n/* ------------------------------------------------------------------ */\n\nconst TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1000;\n\nconst TimelineTimestamp = forwardRef<HTMLTimeElement, TimelineTimestampProps>(\n (\n {\n date,\n relative = true,\n format = { dateStyle: 'medium', timeStyle: 'short' },\n className,\n ...props\n },\n ref,\n ) => (\n <Timestamp\n ref={ref}\n value={date}\n format={relative ? 'relative' : 'absolute'}\n relativeWindow={relative ? TWENTY_FOUR_HOURS_MS : undefined}\n absoluteFormat={format}\n className={[\n 'ds:text-[var(--muted-foreground)]',\n 'ds:[font-variant-numeric:var(--font-feature-tabular)]',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n />\n ),\n);\nTimelineTimestamp.displayName = 'Timeline.Timestamp';\n\n/* ------------------------------------------------------------------ */\n/* Compound export */\n/* ------------------------------------------------------------------ */\n\nexport const Timeline = Object.assign(TimelineRoot, {\n Event: TimelineEvent,\n Dot: TimelineDot,\n Content: TimelineContent,\n Timestamp: TimelineTimestamp,\n});\n"],"names":["timelineAgent","handle","args","TimelineContext","createContext","TimelineEventContext","timelineVariants","cva","eventVariants","dotVariants","TYPE_ICONS","jsx","Info","Check","AlertTriangle","X","Circle","TimelineRoot","forwardRef","layout","order","className","children","props","ref","ctx","useMemo","olRef","useRef","selectedEvent","setSelectedEvent","useState","latestRef","selectEvent","useCallback","id","target","_a","agentHandle","useImperativeHandle","useAgentRegistration","TimelineEvent","type","eventId","useContext","t","useTranslation","evtCtx","jsxs","TimelineDot","icon","dot","TimelineContent","title","description","actor","inner","Card","Avatar","TWENTY_FOUR_HOURS_MS","TimelineTimestamp","date","relative","format","Timestamp","Timeline"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-password-requirements-B1M8lE2t.js","sources":["../../node_modules/lucide-react/dist/esm/icons/eye.js","../../src/components/password-input/password-input.agent.ts","../../src/components/password-input/password-input.tsx","../../src/components/password-input/use-password-requirements.ts"],"sourcesContent":["/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\",\n key: \"1nclc0\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n];\nconst Eye = createLucideIcon(\"eye\", __iconNode);\n\nexport { __iconNode, Eye as default };\n//# sourceMappingURL=eye.js.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — PasswordInput. */\n/* */\n/* See `src/docs/26-agent-readiness.mdx` for the contract. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { PasswordInputHandle } from './password-input';\n\nexport const passwordInputAgent: AgentAdapter<PasswordInputHandle> = {\n id: 'password-input',\n capabilities: ['edit_inline'],\n state: {\n value: {\n type: 'string',\n descriptionKey: 'ui.agent.passwordInput.state.value',\n description:\n 'Current password value. Never log or persist this off-device.',\n read: (handle) => handle.getValue(),\n },\n isEmpty: {\n type: 'boolean',\n descriptionKey: 'ui.agent.passwordInput.state.isEmpty',\n description: 'Whether the input has no value.',\n read: (handle) => handle.getValue() === '',\n },\n isRevealed: {\n type: 'boolean',\n descriptionKey: 'ui.agent.passwordInput.state.isRevealed',\n description: 'Whether the password is currently shown in plain text.',\n read: (handle) => handle.isRevealed(),\n },\n },\n actions: {\n set_value: {\n safety: 'write',\n argsType: '{ value: string }',\n descriptionKey: 'ui.agent.passwordInput.actions.setValue',\n description: 'Replace the password value.',\n invoke: (handle, args: { value: string }) => {\n handle.setValue(args.value);\n },\n },\n clear: {\n safety: 'destructive',\n descriptionKey: 'ui.agent.passwordInput.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.passwordInput.actions.focus',\n description: 'Move keyboard focus to the input.',\n invoke: (handle) => {\n handle.focus();\n },\n },\n toggle_visibility: {\n safety: 'read',\n descriptionKey: 'ui.agent.passwordInput.actions.toggleVisibility',\n description: 'Toggle between masked and plain-text display.',\n invoke: (handle) => {\n handle.toggleVisibility();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'password-input',\n description: 'Marks the PasswordInput wrapper.',\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 useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type FocusEvent,\n type FormEvent,\n type KeyboardEvent,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { AlertTriangle, Check, Circle, Eye, EyeOff } from 'lucide-react';\nimport { TextInput, type TextInputProps } from '../text-input';\nimport { useFormField } from '../form-field/form-field-context';\nimport { composeRefs } from '../_shared/compose-refs';\nimport { useAgentRegistration } from '../../agent';\nimport { passwordInputAgent } from './password-input.agent';\n\n/** Agent-readiness curated handle for PasswordInput. */\nexport interface PasswordInputHandle {\n getValue: () => string;\n setValue: (value: string) => void;\n clear: () => void;\n focus: () => void;\n isRevealed: () => boolean;\n toggleVisibility: () => void;\n}\n\ntype Strength = 0 | 1 | 2 | 3;\n\ntype SizeKey = NonNullable<TextInputProps['size']>;\n\nconst iconSizeClassBySize: Record<SizeKey, string> = {\n sm: 'ds:size-4',\n md: 'ds:size-[18px]',\n lg: 'ds:size-5',\n};\n\nconst toggleVariants = cva(\n [\n 'ds:absolute ds:inset-y-0 ds:end-0 ds:ps-2 ds:pe-3',\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:text-muted-foreground ds:hover:text-foreground',\n 'ds:bg-transparent ds:border-0 ds:cursor-pointer',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:min-w-[var(--min-target-size)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n 'ds:disabled:cursor-not-allowed ds:disabled:opacity-50',\n ].join(' '),\n);\n\nconst strengthTrackVariants = cva(\n 'ds:h-1 ds:w-full ds:overflow-hidden ds:rounded-[var(--radius-full)] ds:bg-muted',\n);\n\nconst strengthBarVariants = cva(\n [\n 'ds:h-full ds:rounded-[var(--radius-full)]',\n 'ds:transition-all ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n ].join(' '),\n {\n variants: {\n level: {\n 0: 'ds:w-1/4 ds:bg-destructive',\n 1: 'ds:w-1/2 ds:bg-warning',\n 2: 'ds:w-3/4 ds:bg-success',\n 3: 'ds:w-full ds:bg-success',\n },\n },\n defaultVariants: { level: 0 },\n },\n);\n\nconst strengthLabelByLevel: Record<\n Strength,\n 'weak' | 'fair' | 'good' | 'strong'\n> = {\n 0: 'weak',\n 1: 'fair',\n 2: 'good',\n 3: 'strong',\n};\n\nconst requirementRowVariants = cva(\n 'ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] type-meta',\n {\n variants: {\n met: {\n true: 'ds:text-success',\n false: 'ds:text-muted-foreground',\n },\n },\n defaultVariants: { met: false },\n },\n);\n\n/**\n * One row in the live requirements checklist. Consumers either build\n * these inline or pull a pre-built set from `usePasswordRequirements`.\n */\nexport interface PasswordRequirement {\n /** Stable id — keyed render + a11y. */\n id: string;\n /** Already-translated label. The consumer owns the wording. */\n label: string;\n /** Predicate against the current value. Pure, runs on every keystroke. */\n test: (value: string) => boolean;\n}\n\nexport interface PasswordInputProps\n extends\n Omit<TextInputProps, 'type' | 'endAdornment' | 'startAdornment'>,\n VariantProps<typeof strengthBarVariants> {\n /** Callback when reveal state changes (for analytics). */\n onRevealChange?: (revealed: boolean) => void;\n /** Show the strength meter below the input. */\n showStrength?: boolean;\n /** Strength score: 0 = weak, 1 = fair, 2 = good, 3 = strong. */\n strength?: Strength;\n /**\n * Live requirements checklist rendered between the input and the\n * strength meter / caps-lock notice. Each row's predicate runs on\n * every keystroke and the row's `data-state` flips between `\"met\"`\n * and `\"unmet\"`. Backed by `aria-live=\"polite\"` so screen readers\n * announce each transition as a visually-hidden suffix span flips\n * between localised \"met\" / \"not yet met\" copy.\n *\n * Tip: hoist or `useMemo` the array — inlining it in JSX makes the\n * predicate-results memo bust every render. The kit's\n * `usePasswordRequirements` helper already does this.\n */\n requirements?: ReadonlyArray<PasswordRequirement>;\n /**\n * When `true` AND `strength` is not provided, derive a 0–3 score\n * from the proportion of `requirements` satisfied. Lets consumers\n * get the strength bar \"for free\" once they declare requirements.\n */\n deriveStrength?: boolean;\n /**\n * Autocomplete hint. Defaults to 'current-password'.\n * Use 'new-password' for registration/change-password forms.\n */\n autoComplete?: 'current-password' | 'new-password' | (string & {});\n}\n\nexport const PasswordInput = forwardRef<HTMLInputElement, PasswordInputProps>(\n (\n {\n onRevealChange,\n showStrength = false,\n strength,\n requirements,\n deriveStrength = false,\n autoComplete,\n size = 'md',\n disabled,\n name,\n id,\n onKeyDown,\n onKeyUp,\n onBlur,\n onInput,\n defaultValue,\n value,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const ctx = useFormField();\n const effectiveDisabled = ctx.disabled || disabled;\n\n const innerInputRef = useRef<HTMLInputElement | null>(null);\n const composedRef = composeRefs(ref, innerInputRef);\n\n const [revealed, setRevealed] = useState(false);\n const [capsLock, setCapsLock] = useState(false);\n\n // Track the current value internally so the requirements checklist\n // can re-evaluate predicates without forcing consumers to lift the\n // input into a controlled state. The seed is whichever of\n // `value` / `defaultValue` was passed; the `input` listener then\n // keeps it in sync on every keystroke (covers both controlled and\n // uncontrolled callers — for controlled callers we resync to the\n // incoming `value` prop in the effect below).\n const [internalValue, setInternalValue] = useState<string>(() => {\n if (typeof value === 'string') return value;\n if (typeof defaultValue === 'string') return defaultValue;\n return '';\n });\n\n useEffect(() => {\n if (typeof value === 'string') setInternalValue(value);\n }, [value]);\n\n const handleInput = useCallback(\n (event: FormEvent<HTMLInputElement>) => {\n setInternalValue(event.currentTarget.value);\n onInput?.(event);\n },\n [onInput],\n );\n\n const writeValueToInput = useCallback((next: string) => {\n const node = innerInputRef.current;\n if (!node) return;\n const prototype = Object.getPrototypeOf(node) as HTMLInputElement;\n const setter = Object.getOwnPropertyDescriptor(prototype, 'value')?.set;\n setter?.call(node, next);\n node.dispatchEvent(new Event('input', { bubbles: true }));\n node.dispatchEvent(new Event('change', { bubbles: true }));\n }, []);\n\n const handleToggle = useCallback(() => {\n setRevealed((prev) => {\n const next = !prev;\n onRevealChange?.(next);\n return next;\n });\n }, [onRevealChange]);\n\n const detectCaps = useCallback((event: KeyboardEvent<HTMLInputElement>) => {\n if (typeof event.getModifierState === 'function') {\n setCapsLock(event.getModifierState('CapsLock'));\n }\n }, []);\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n detectCaps(event);\n onKeyDown?.(event);\n },\n [detectCaps, onKeyDown],\n );\n\n const handleKeyUp = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n detectCaps(event);\n onKeyUp?.(event);\n },\n [detectCaps, onKeyUp],\n );\n\n const handleBlur = useCallback(\n (event: FocusEvent<HTMLInputElement>) => {\n setCapsLock(false);\n onBlur?.(event);\n },\n [onBlur],\n );\n\n const agentHandle = useMemo<PasswordInputHandle>(\n () => ({\n getValue: () => innerInputRef.current?.value ?? '',\n setValue: (next) => writeValueToInput(next),\n clear: () => writeValueToInput(''),\n focus: () => innerInputRef.current?.focus(),\n isRevealed: () => revealed,\n toggleVisibility: () => {\n setRevealed((prev) => {\n const next = !prev;\n onRevealChange?.(next);\n return next;\n });\n },\n }),\n [onRevealChange, revealed, writeValueToInput],\n );\n useAgentRegistration(passwordInputAgent, agentHandle, id);\n\n const iconSizeClass = iconSizeClassBySize[size];\n const toggleLabel = t(\n revealed\n ? 'inputs.password.toggleHide'\n : 'inputs.password.toggleShow',\n revealed ? 'Hide password' : 'Show password',\n );\n\n // Evaluate each requirement against the current value. Cheap by\n // construction — predicates are pure regex/length checks supplied\n // by the consumer; the kit doesn't memoise per-row because the\n // map is O(n) over a handful of rules and React would re-render\n // the row anyway when its `data-state` flips.\n const requirementResults = useMemo(\n () =>\n requirements?.map((req) => ({\n ...req,\n met: req.test(internalValue),\n })) ?? null,\n [requirements, internalValue],\n );\n\n // Derive a 0–3 score from the satisfied proportion when the\n // consumer hasn't supplied an explicit `strength`. Formula:\n // `floor((satisfied / total) * 4)`, clamped to 3 so a fully-met\n // checklist matches the explicit \"strong\" level. With zero\n // requirements we fall back to 0 — meaningless on its own but\n // never displayed since `showStrength` is what controls the bar.\n const derivedStrength: Strength = useMemo(() => {\n if (!deriveStrength || !requirementResults?.length) return 0;\n const satisfied = requirementResults.filter((r) => r.met).length;\n const total = requirementResults.length;\n return Math.min(3, Math.floor((satisfied / total) * 4)) as Strength;\n }, [deriveStrength, requirementResults]);\n\n const effectiveStrength: Strength =\n strength !== undefined ? strength : deriveStrength ? derivedStrength : 0;\n const strengthKey = strengthLabelByLevel[effectiveStrength];\n const strengthText = t(\n `ui.inputs.password.strength.${strengthKey}`,\n strengthKey.charAt(0).toUpperCase() + strengthKey.slice(1),\n );\n\n return (\n <div\n data-component=\"password-input\"\n data-component-id={id}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n <div className=\"ds:relative\">\n <TextInput\n ref={composedRef}\n id={id}\n type={revealed ? 'text' : 'password'}\n autoComplete={autoComplete ?? 'current-password'}\n name={name ?? 'password'}\n spellCheck={false}\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n size={size}\n disabled={effectiveDisabled}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n onBlur={handleBlur}\n onInput={handleInput}\n value={value}\n defaultValue={defaultValue}\n endAdornment={\n <span aria-hidden=\"true\" className=\"ds:block ds:size-4\" />\n }\n className={className}\n {...rest}\n />\n <button\n type=\"button\"\n aria-pressed={revealed}\n aria-label={toggleLabel}\n disabled={effectiveDisabled}\n onClick={handleToggle}\n className={toggleVariants()}\n >\n {revealed ? (\n <EyeOff aria-hidden=\"true\" className={iconSizeClass} />\n ) : (\n <Eye aria-hidden=\"true\" className={iconSizeClass} />\n )}\n </button>\n </div>\n\n {requirementResults && requirementResults.length > 0 ? (\n // `role=\"list\"` / `role=\"listitem\"` are set explicitly even\n // though they're the implicit roles on <ul>/<li> — Safari\n // VoiceOver strips the implicit list role when CSS sets\n // `list-style: none` (which `ds:list-none` does), so the\n // redundancy is load-bearing for AT, not a lint nit.\n //\n // aria-live=\"polite\" announces transitions as the per-row\n // `.ds:sr-only` state suffix flips between \"met\" / \"not yet\n // met\". aria-live observes text-content mutations, not\n // attribute or class changes, so the data-state attribute\n // alone wouldn't trigger an announcement — the sr-only span\n // is the load-bearing piece for AT users.\n // eslint-disable-next-line jsx-a11y/no-redundant-roles\n <ul\n role=\"list\"\n aria-live=\"polite\"\n data-component=\"password-requirements\"\n className=\"ds:list-none ds:m-0 ds:p-0 ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)]\"\n >\n {requirementResults.map((req) => (\n // eslint-disable-next-line jsx-a11y/no-redundant-roles\n <li\n key={req.id}\n role=\"listitem\"\n data-state={req.met ? 'met' : 'unmet'}\n className={requirementRowVariants({ met: req.met })}\n >\n {req.met ? (\n <Check\n aria-hidden=\"true\"\n className=\"ds:size-3.5 ds:text-success ds:shrink-0\"\n />\n ) : (\n <Circle\n aria-hidden=\"true\"\n className=\"ds:size-3.5 ds:shrink-0\"\n />\n )}\n <span>{req.label}</span>\n <span className=\"ds:sr-only\">\n {' — '}\n {req.met\n ? t('inputs.password.requirements.met', 'met')\n : t('inputs.password.requirements.unmet', 'not yet met')}\n </span>\n </li>\n ))}\n </ul>\n ) : null}\n\n {capsLock ? (\n <span\n role=\"status\"\n aria-live=\"polite\"\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] type-meta ds:text-warning\"\n >\n <AlertTriangle aria-hidden=\"true\" className=\"ds:size-3.5\" />\n {t('inputs.password.capsLock', 'Caps Lock is on')}\n </span>\n ) : null}\n\n {showStrength ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <div\n role=\"progressbar\"\n aria-valuenow={effectiveStrength}\n aria-valuemin={0}\n aria-valuemax={3}\n aria-label={t(\n 'inputs.password.strengthLabel',\n 'Password strength',\n )}\n aria-valuetext={strengthText}\n className={strengthTrackVariants()}\n >\n <div\n className={strengthBarVariants({ level: effectiveStrength })}\n />\n </div>\n <span\n aria-hidden=\"true\"\n className=\"type-meta ds:text-muted-foreground\"\n >\n {strengthText}\n </span>\n </div>\n ) : null}\n </div>\n );\n },\n);\n\nPasswordInput.displayName = 'PasswordInput';\n","import { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport type { PasswordRequirement } from './password-input';\n\nexport interface UsePasswordRequirementsOptions {\n /**\n * Minimum password length. When set, adds a \"length\" requirement.\n * Pass `12` (or whatever the server-side regex enforces) so the\n * inline checklist tells users the same rule they'll bounce off\n * server-side. When omitted, no length row is rendered.\n */\n minLength?: number;\n /** Adds an \"uppercase letter\" requirement when true. */\n uppercase?: boolean;\n /** Adds a \"lowercase letter\" requirement when true. */\n lowercase?: boolean;\n /** Adds a \"digit\" requirement when true. */\n digit?: boolean;\n /** Adds a \"symbol\" requirement when true. Matches anything outside `[A-Za-z0-9\\s]`. */\n symbol?: boolean;\n}\n\n/**\n * Builds the common set of password requirements with i18n-resolved\n * labels. Designed for the AlfaDocs platform's patient-registration\n * server-side regex (`/^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).{12,}$/`) but\n * generic enough for any consumer.\n *\n * Each opt-in flag adds one row to the returned array, in a stable\n * visual order (length → uppercase → lowercase → digit → symbol).\n * Predicates are pure and run on every keystroke.\n *\n * @example\n * const requirements = usePasswordRequirements({\n * minLength: 12,\n * uppercase: true,\n * lowercase: true,\n * digit: true,\n * });\n * <PasswordInput requirements={requirements} deriveStrength />\n */\nexport function usePasswordRequirements(\n opts: UsePasswordRequirementsOptions = {},\n): PasswordRequirement[] {\n const { t } = useTranslation();\n const { minLength, uppercase, lowercase, digit, symbol } = opts;\n\n return useMemo(() => {\n const list: PasswordRequirement[] = [];\n\n if (typeof minLength === 'number' && minLength > 0) {\n list.push({\n id: 'length',\n label: t('inputs.password.requirements.length', {\n count: minLength,\n defaultValue: `At least ${minLength} characters`,\n }),\n test: (v) => v.length >= minLength,\n });\n }\n\n if (uppercase) {\n list.push({\n id: 'uppercase',\n label: t(\n 'inputs.password.requirements.uppercase',\n 'One uppercase letter',\n ),\n test: (v) => /\\p{Lu}/u.test(v),\n });\n }\n\n if (lowercase) {\n list.push({\n id: 'lowercase',\n label: t(\n 'inputs.password.requirements.lowercase',\n 'One lowercase letter',\n ),\n test: (v) => /\\p{Ll}/u.test(v),\n });\n }\n\n if (digit) {\n list.push({\n id: 'digit',\n label: t('inputs.password.requirements.digit', 'One number'),\n test: (v) => /\\p{Nd}/u.test(v),\n });\n }\n\n if (symbol) {\n list.push({\n id: 'symbol',\n label: t('inputs.password.requirements.symbol', 'One symbol'),\n // Anything that isn't a letter, number, or whitespace counts.\n // `\\p{L}` + `\\p{N}` keep this Unicode-aware so non-Latin\n // alphabets (Arabic, Chinese, …) aren't mis-classified as\n // symbols.\n test: (v) => /[^\\p{L}\\p{N}\\s]/u.test(v),\n });\n }\n\n return list;\n }, [t, minLength, uppercase, lowercase, digit, symbol]);\n}\n"],"names":["__iconNode","Eye","createLucideIcon","passwordInputAgent","handle","args","iconSizeClassBySize","toggleVariants","cva","strengthTrackVariants","strengthBarVariants","strengthLabelByLevel","requirementRowVariants","PasswordInput","forwardRef","onRevealChange","showStrength","strength","requirements","deriveStrength","autoComplete","size","disabled","name","id","onKeyDown","onKeyUp","onBlur","onInput","defaultValue","value","className","rest","ref","t","useTranslation","effectiveDisabled","useFormField","innerInputRef","useRef","composedRef","composeRefs","revealed","setRevealed","useState","capsLock","setCapsLock","internalValue","setInternalValue","useEffect","handleInput","useCallback","event","writeValueToInput","next","node","prototype","setter","_a","handleToggle","prev","detectCaps","handleKeyDown","handleKeyUp","handleBlur","agentHandle","useMemo","useAgentRegistration","iconSizeClass","toggleLabel","requirementResults","req","derivedStrength","satisfied","r","total","effectiveStrength","strengthKey","strengthText","jsxs","jsx","TextInput","EyeOff","Check","Circle","AlertTriangle","usePasswordRequirements","opts","minLength","uppercase","lowercase","digit","symbol","list","v"],"mappings":"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","x_google_ignoreList":[0]}
|