@alfadocs/ui-kit-debug 0.11.0 → 0.13.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/_commonjsHelpers-C6fGbg64.js +7 -0
- package/dist/_chunks/_commonjsHelpers-C6fGbg64.js.map +1 -0
- package/dist/_chunks/{ai-prompt-input-bAJwYu84.js → ai-prompt-input-DEiQwIMn.js} +22 -21
- package/dist/_chunks/ai-prompt-input-DEiQwIMn.js.map +1 -0
- package/dist/_chunks/{audio-recorder-BHBonrFf.js → audio-recorder-CRh4uyFL.js} +2 -2
- package/dist/_chunks/{audio-recorder-BHBonrFf.js.map → audio-recorder-CRh4uyFL.js.map} +1 -1
- package/dist/_chunks/{autocomplete-C34hbfKh.js → autocomplete-mOg7WLOh.js} +2 -2
- package/dist/_chunks/{autocomplete-C34hbfKh.js.map → autocomplete-mOg7WLOh.js.map} +1 -1
- package/dist/_chunks/{chat-input-Bov-gkwP.js → chat-input-UK-bXU7u.js} +9 -8
- package/dist/_chunks/chat-input-UK-bXU7u.js.map +1 -0
- package/dist/_chunks/{combobox-BHhnR3qm.js → combobox-D5tWe0t_.js} +2 -2
- package/dist/_chunks/{combobox-BHhnR3qm.js.map → combobox-D5tWe0t_.js.map} +1 -1
- package/dist/_chunks/{contact-card-VJIUqKB2.js → contact-card-DTQUMetD.js} +22 -38
- package/dist/_chunks/contact-card-DTQUMetD.js.map +1 -0
- package/dist/_chunks/{date-picker-BD5FYW08.js → date-picker-BlhtBhPo.js} +2 -2
- package/dist/_chunks/{date-picker-BD5FYW08.js.map → date-picker-BlhtBhPo.js.map} +1 -1
- package/dist/_chunks/{date-range-picker-BZLVgcXE.js → date-range-picker-C2hRu_Ke.js} +2 -2
- package/dist/_chunks/{date-range-picker-BZLVgcXE.js.map → date-range-picker-C2hRu_Ke.js.map} +1 -1
- package/dist/_chunks/{date-time-picker-CCoRWX7R.js → date-time-picker-B67mPZmP.js} +2 -2
- package/dist/_chunks/{date-time-picker-CCoRWX7R.js.map → date-time-picker-B67mPZmP.js.map} +1 -1
- package/dist/_chunks/external-link-C6F25E6k.js +16 -0
- package/dist/_chunks/external-link-C6F25E6k.js.map +1 -0
- package/dist/_chunks/{file-upload-DIecAfC-.js → file-upload-nMh-1jDD.js} +2 -2
- package/dist/_chunks/{file-upload-DIecAfC-.js.map → file-upload-nMh-1jDD.js.map} +1 -1
- package/dist/_chunks/{index-CeY1nNvd.js → index-CFoBa86t.js} +61 -63
- package/dist/_chunks/{index-CeY1nNvd.js.map → index-CFoBa86t.js.map} +1 -1
- package/dist/_chunks/{input-surface-u4QB0lxe.js → input-surface-xyERuLU_.js} +9 -3
- package/dist/_chunks/input-surface-xyERuLU_.js.map +1 -0
- package/dist/_chunks/{leo-sidebar-B054wsZm.js → leo-sidebar-D3TuyH5_.js} +2 -2
- package/dist/_chunks/{leo-sidebar-B054wsZm.js.map → leo-sidebar-D3TuyH5_.js.map} +1 -1
- package/dist/_chunks/{link-BGpwaFik.js → link-DmM5IevO.js} +16 -26
- package/dist/_chunks/link-DmM5IevO.js.map +1 -0
- package/dist/_chunks/map-pin-B8STOPMJ.js +21 -0
- package/dist/_chunks/map-pin-B8STOPMJ.js.map +1 -0
- package/dist/_chunks/map-view-Dd48BxVB.js +1941 -0
- package/dist/_chunks/map-view-Dd48BxVB.js.map +1 -0
- package/dist/_chunks/{multi-select-Bh-xR8kP.js → multi-select-DooDzQIp.js} +2 -2
- package/dist/_chunks/{multi-select-Bh-xR8kP.js.map → multi-select-DooDzQIp.js.map} +1 -1
- package/dist/_chunks/{number-input-mpSLk-ld.js → number-input-DH00o0DN.js} +28 -27
- package/dist/_chunks/number-input-DH00o0DN.js.map +1 -0
- package/dist/_chunks/{otp-input-CI-Zv5q6.js → otp-input-BBXYvLx5.js} +49 -48
- package/dist/_chunks/otp-input-BBXYvLx5.js.map +1 -0
- package/dist/_chunks/{phone-input-DtBVs5fz.js → phone-input-DKSHX7NQ.js} +23 -22
- package/dist/_chunks/phone-input-DKSHX7NQ.js.map +1 -0
- package/dist/_chunks/{react-day-picker-C04L_28V.js → react-day-picker-C5F3-TTX.js} +6 -3
- package/dist/_chunks/{react-day-picker-C04L_28V.js.map → react-day-picker-C5F3-TTX.js.map} +1 -1
- package/dist/_chunks/{search-bar-DmZZ9UvV.js → search-bar-DORSAzNt.js} +2 -2
- package/dist/_chunks/{search-bar-DmZZ9UvV.js.map → search-bar-DORSAzNt.js.map} +1 -1
- package/dist/_chunks/{search-input-BBtSRH-Q.js → search-input-BtEJAJHa.js} +2 -2
- package/dist/_chunks/{search-input-BBtSRH-Q.js.map → search-input-BtEJAJHa.js.map} +1 -1
- package/dist/_chunks/{select-i9MwQeQy.js → select-Ca6ibiDL.js} +13 -12
- package/dist/_chunks/select-Ca6ibiDL.js.map +1 -0
- package/dist/_chunks/{tabs-Cg794H0Q.js → tabs-CRCyPpJo.js} +2 -2
- package/dist/_chunks/{tabs-Cg794H0Q.js.map → tabs-CRCyPpJo.js.map} +1 -1
- package/dist/_chunks/{text-area-DHtcpcLv.js → text-area-D5GAe8pV.js} +26 -25
- package/dist/_chunks/text-area-D5GAe8pV.js.map +1 -0
- package/dist/_chunks/{text-input-1oqFRbVI.js → text-input-CakysYnD.js} +26 -25
- package/dist/_chunks/text-input-CakysYnD.js.map +1 -0
- package/dist/_chunks/{transcript-panel-BpJqPr7I.js → transcript-panel-DUrjx5sa.js} +2 -2
- package/dist/_chunks/{transcript-panel-BpJqPr7I.js.map → transcript-panel-DUrjx5sa.js.map} +1 -1
- package/dist/_chunks/{use-password-requirements-DbPZMfV9.js → use-password-requirements-BOgFsoIe.js} +2 -2
- package/dist/_chunks/{use-password-requirements-DbPZMfV9.js.map → use-password-requirements-BOgFsoIe.js.map} +1 -1
- package/dist/_chunks/whatsapp-button-Bj5FIhpC.js +175 -0
- package/dist/_chunks/whatsapp-button-Bj5FIhpC.js.map +1 -0
- package/dist/agent-catalog.json +53 -1
- package/dist/components/_shared/date-picker-variants.d.ts.map +1 -1
- package/dist/components/_shared/input-surface.d.ts.map +1 -1
- package/dist/components/ai-prompt-input/ai-prompt-input.d.ts.map +1 -1
- package/dist/components/ai-prompt-input/index.js +1 -1
- package/dist/components/audio-recorder/index.js +1 -1
- package/dist/components/autocomplete/index.js +1 -1
- package/dist/components/chat-input/chat-input.d.ts.map +1 -1
- package/dist/components/chat-input/index.js +1 -1
- package/dist/components/combobox/index.js +1 -1
- package/dist/components/contact-card/index.js +1 -1
- package/dist/components/date-picker/index.js +1 -1
- package/dist/components/date-range-picker/index.js +1 -1
- package/dist/components/date-time-picker/index.js +1 -1
- package/dist/components/file-upload/index.js +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/link/index.js +1 -1
- package/dist/components/map-view/index.d.ts +3 -0
- package/dist/components/map-view/index.d.ts.map +1 -0
- package/dist/components/map-view/index.js +5 -0
- package/dist/components/map-view/index.js.map +1 -0
- package/dist/components/map-view/map-view.agent.d.ts +4 -0
- package/dist/components/map-view/map-view.agent.d.ts.map +1 -0
- package/dist/components/map-view/map-view.d.ts +78 -0
- package/dist/components/map-view/map-view.d.ts.map +1 -0
- package/dist/components/multi-select/index.js +1 -1
- package/dist/components/number-input/index.js +1 -1
- package/dist/components/number-input/number-input.d.ts.map +1 -1
- package/dist/components/otp-input/index.js +1 -1
- package/dist/components/otp-input/otp-input.d.ts.map +1 -1
- package/dist/components/password-input/index.js +1 -1
- package/dist/components/phone-input/index.js +1 -1
- package/dist/components/phone-input/phone-input.d.ts.map +1 -1
- package/dist/components/search-bar/index.js +1 -1
- package/dist/components/search-input/index.js +1 -1
- package/dist/components/select/index.js +1 -1
- package/dist/components/select/select.d.ts.map +1 -1
- package/dist/components/tabs/index.js +1 -1
- package/dist/components/text-area/index.js +1 -1
- package/dist/components/text-area/text-area.d.ts.map +1 -1
- package/dist/components/text-input/index.js +1 -1
- package/dist/components/text-input/text-input.d.ts.map +1 -1
- package/dist/components/transcript-panel/index.js +1 -1
- package/dist/components/whatsapp-button/index.d.ts +3 -0
- package/dist/components/whatsapp-button/index.d.ts.map +1 -0
- package/dist/components/whatsapp-button/index.js +5 -0
- package/dist/components/whatsapp-button/index.js.map +1 -0
- package/dist/components/whatsapp-button/whatsapp-button.d.ts +32 -0
- package/dist/components/whatsapp-button/whatsapp-button.d.ts.map +1 -0
- package/dist/i18n/config.js +45 -6
- package/dist/i18n/config.js.map +1 -1
- package/dist/i18n/resources.d.ts +39 -0
- package/dist/i18n/resources.d.ts.map +1 -1
- package/dist/index.js +361 -357
- package/dist/index.js.map +1 -1
- package/dist/locales/de.json +13 -0
- package/dist/locales/en.json +13 -0
- package/dist/locales/it.json +13 -0
- package/dist/patterns/leo-assistant/index.js +1 -1
- package/dist/tokens/google-maps-theme.d.ts +15 -0
- package/dist/tokens/google-maps-theme.d.ts.map +1 -0
- package/dist/tokens.css +1 -1
- package/package.json +15 -1
- package/dist/_chunks/ai-prompt-input-bAJwYu84.js.map +0 -1
- package/dist/_chunks/chat-input-Bov-gkwP.js.map +0 -1
- package/dist/_chunks/contact-card-VJIUqKB2.js.map +0 -1
- package/dist/_chunks/input-surface-u4QB0lxe.js.map +0 -1
- package/dist/_chunks/link-BGpwaFik.js.map +0 -1
- package/dist/_chunks/number-input-mpSLk-ld.js.map +0 -1
- package/dist/_chunks/otp-input-CI-Zv5q6.js.map +0 -1
- package/dist/_chunks/phone-input-DtBVs5fz.js.map +0 -1
- package/dist/_chunks/select-i9MwQeQy.js.map +0 -1
- package/dist/_chunks/text-area-DHtcpcLv.js.map +0 -1
- package/dist/_chunks/text-input-1oqFRbVI.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.13.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",
|
|
@@ -227,6 +227,10 @@
|
|
|
227
227
|
"types": "./dist/components/logo/index.d.ts",
|
|
228
228
|
"import": "./dist/components/logo/index.js"
|
|
229
229
|
},
|
|
230
|
+
"./map-view": {
|
|
231
|
+
"types": "./dist/components/map-view/index.d.ts",
|
|
232
|
+
"import": "./dist/components/map-view/index.js"
|
|
233
|
+
},
|
|
230
234
|
"./matrix-rain": {
|
|
231
235
|
"types": "./dist/components/matrix-rain/index.d.ts",
|
|
232
236
|
"import": "./dist/components/matrix-rain/index.js"
|
|
@@ -451,6 +455,10 @@
|
|
|
451
455
|
"types": "./dist/components/warning-stack/index.d.ts",
|
|
452
456
|
"import": "./dist/components/warning-stack/index.js"
|
|
453
457
|
},
|
|
458
|
+
"./whatsapp-button": {
|
|
459
|
+
"types": "./dist/components/whatsapp-button/index.d.ts",
|
|
460
|
+
"import": "./dist/components/whatsapp-button/index.js"
|
|
461
|
+
},
|
|
454
462
|
"./workflow": {
|
|
455
463
|
"types": "./dist/components/workflow/index.d.ts",
|
|
456
464
|
"import": "./dist/components/workflow/index.js"
|
|
@@ -518,6 +526,7 @@
|
|
|
518
526
|
"@tiptap/pm": "^3.22.3",
|
|
519
527
|
"@tiptap/react": "^3.22.3",
|
|
520
528
|
"@tiptap/starter-kit": "^3.22.3",
|
|
529
|
+
"@vis.gl/react-google-maps": "^1.1.0 || ^2",
|
|
521
530
|
"ag-grid-community": "^35.2.1",
|
|
522
531
|
"ag-grid-react": "^35.2.1",
|
|
523
532
|
"apexcharts": "^5.10.1",
|
|
@@ -607,6 +616,9 @@
|
|
|
607
616
|
"@tiptap/starter-kit": {
|
|
608
617
|
"optional": true
|
|
609
618
|
},
|
|
619
|
+
"@vis.gl/react-google-maps": {
|
|
620
|
+
"optional": true
|
|
621
|
+
},
|
|
610
622
|
"ag-grid-community": {
|
|
611
623
|
"optional": true
|
|
612
624
|
},
|
|
@@ -694,8 +706,10 @@
|
|
|
694
706
|
"@tiptap/react": "^3.22.3",
|
|
695
707
|
"@tiptap/starter-kit": "^3.22.3",
|
|
696
708
|
"@types/dompurify": "^3.0.5",
|
|
709
|
+
"@types/google.maps": "^3.58.1",
|
|
697
710
|
"@types/react": "^18.3.28",
|
|
698
711
|
"@types/react-dom": "^18.3.7",
|
|
712
|
+
"@vis.gl/react-google-maps": "^1.5.5",
|
|
699
713
|
"@vitejs/plugin-react": "^4.7.0",
|
|
700
714
|
"@vitest/browser-playwright": "^4.1.4",
|
|
701
715
|
"@vitest/coverage-v8": "^4.1.4",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ai-prompt-input-bAJwYu84.js","sources":["../../src/components/ai-prompt-input/ai-prompt-input.agent.ts","../../src/components/ai-prompt-input/ai-prompt-input.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — AIPromptInput. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { AIPromptInputHandle } from './ai-prompt-input';\n\nexport const aiPromptInputAgent: AgentAdapter<AIPromptInputHandle> = {\n id: 'ai-prompt-input',\n capabilities: ['edit_inline', 'submit'],\n state: {\n value: {\n type: 'string',\n descriptionKey: 'ui.agent.aiPromptInput.state.value',\n description: 'Current text in the composer (no PHI processing).',\n read: (handle) => handle.getValue(),\n },\n isEmpty: {\n type: 'boolean',\n descriptionKey: 'ui.agent.aiPromptInput.state.isEmpty',\n description: 'True when the composer has no text and no attachments.',\n read: (handle) => handle.isEmpty(),\n },\n isSubmitting: {\n type: 'boolean',\n descriptionKey: 'ui.agent.aiPromptInput.state.isSubmitting',\n description:\n 'True while an onSubmit invocation is in flight (best-effort).',\n read: (handle) => handle.isSubmitting(),\n },\n },\n actions: {\n set_value: {\n safety: 'write',\n argsType: '{ value: string }',\n descriptionKey: 'ui.agent.aiPromptInput.actions.setValue',\n description: 'Replace the composer text with the given value.',\n invoke: (handle, args: { value: string }) => {\n handle.setValue(args.value);\n },\n },\n clear: {\n safety: 'destructive',\n descriptionKey: 'ui.agent.aiPromptInput.actions.clear',\n description: 'Clear text and attachments. Irreversible from the same UI.',\n invoke: (handle) => {\n handle.clear();\n },\n },\n submit: {\n safety: 'write',\n descriptionKey: 'ui.agent.aiPromptInput.actions.submit',\n description: 'Submit the current composer state via onSubmit.',\n invoke: (handle) => {\n handle.submit();\n },\n },\n focus: {\n safety: 'read',\n descriptionKey: 'ui.agent.aiPromptInput.actions.focus',\n description: 'Move keyboard focus into the textarea.',\n invoke: (handle) => {\n handle.focus();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'ai-prompt-input',\n description: 'Marks the AIPromptInput wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop; addresses a specific composer instance.',\n },\n },\n};\n","import {\n forwardRef,\n useCallback,\n useId,\n useImperativeHandle,\n useMemo,\n useLayoutEffect,\n useRef,\n useState,\n type ChangeEvent,\n type ClipboardEvent,\n type CompositionEvent,\n type KeyboardEvent,\n type ReactNode,\n type TextareaHTMLAttributes,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { aiPromptInputAgent } from './ai-prompt-input.agent';\nimport { Command } from 'cmdk';\nimport { useDropzone } from 'react-dropzone';\nimport { Send, X } from 'lucide-react';\nimport { IconButton } from '../button';\nimport { Select, type SelectOption } from '../select/select';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport interface AIPromptCommand {\n id: string;\n label: string;\n description?: string;\n}\n\nexport interface AIPromptModel {\n id: string;\n label: string;\n}\n\nexport interface AIPromptAttachment {\n id: string;\n file: File;\n}\n\nexport interface AIPromptSubmitPayload {\n text: string;\n command?: string;\n attachments: AIPromptAttachment[];\n modelId?: string;\n}\n\ntype NativeTextareaProps = Omit<\n TextareaHTMLAttributes<HTMLTextAreaElement>,\n 'size' | 'onSubmit' | 'children'\n>;\n\nconst rootVariants = cva(\n [\n 'ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:w-full',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-border ds:bg-background',\n 'ds:transition-[border-color] ds:duration-[var(--animation-duration)]',\n 'ds:focus-within:border-[color:var(--primary)]',\n 'ds:motion-reduce:transition-none',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:text-[length:var(--font-size-sm)]',\n md: 'ds:text-[length:var(--font-size-base)]',\n lg: 'ds:text-[length:var(--font-size-lg)]',\n },\n },\n defaultVariants: { size: 'md' },\n },\n);\n\n/** Curated imperative handle for agent / external automation. */\nexport interface AIPromptInputHandle {\n /** Current composer text. */\n getValue: () => string;\n /** True when text is empty and no attachments are pending. */\n isEmpty: () => boolean;\n /** True while a submit is in flight. */\n isSubmitting: () => boolean;\n /** Replace the composer text. */\n setValue: (value: string) => void;\n /** Clear text and attachments. */\n clear: () => void;\n /** Programmatically submit. */\n submit: () => void;\n /** Move keyboard focus into the textarea. */\n focus: () => void;\n}\n\nexport interface AIPromptInputProps\n extends NativeTextareaProps, VariantProps<typeof rootVariants> {\n /** Slash-command catalog. The DS owns the menu; apps own the commands. */\n commands?: AIPromptCommand[];\n /** Model catalog rendered as a Radix Select in the footer. */\n models?: AIPromptModel[];\n defaultModelId?: string;\n modelId?: string;\n onModelChange?: (id: string) => void;\n /** Maximum attachment size in bytes. */\n maxSize?: number;\n /** `accept` forwarded to react-dropzone. */\n accept?: Record<string, string[]>;\n /** Optional active context pill — dismissible via Backspace when focused. */\n context?: string;\n onContextDismiss?: () => void;\n onSubmit?: (payload: AIPromptSubmitPayload) => void;\n onAttach?: (files: File[]) => void;\n onAttachmentRejected?: (reason: string) => void;\n minRows?: number;\n maxRows?: number;\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const AIPromptInput = forwardRef<HTMLDivElement, AIPromptInputProps>(\n (\n {\n commands = [],\n models,\n defaultModelId,\n modelId,\n onModelChange,\n maxSize,\n accept,\n context,\n onContextDismiss,\n onSubmit,\n onAttach,\n onAttachmentRejected,\n minRows = 2,\n maxRows = 8,\n value,\n defaultValue,\n size = 'md',\n disabled,\n className,\n placeholder,\n onChange,\n onKeyDown,\n onCompositionStart,\n onCompositionEnd,\n onPaste,\n id,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const textareaId = useId();\n const innerRef = useRef<HTMLTextAreaElement | null>(null);\n const composingRef = useRef(false);\n const slashMenuRef = useRef<HTMLDivElement | null>(null);\n\n const setRefs = useCallback((node: HTMLTextAreaElement | null) => {\n innerRef.current = node;\n }, []);\n\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState<string>(\n String(defaultValue ?? ''),\n );\n const currentValue = isControlled ? String(value) : internalValue;\n\n const [attachments, setAttachments] = useState<AIPromptAttachment[]>([]);\n const [slashOpen, setSlashOpen] = useState(false);\n const [slashQuery, setSlashQuery] = useState('');\n\n const [internalModel, setInternalModel] = useState<string>(\n defaultModelId ?? models?.[0]?.id ?? '',\n );\n const isModelControlled = modelId !== undefined;\n const currentModel = isModelControlled ? modelId : internalModel;\n\n /* ── Auto-grow ── */\n const resize = useCallback(() => {\n const el = innerRef.current;\n if (!el) return;\n const styles = window.getComputedStyle(el);\n const lineHeight = parseFloat(styles.lineHeight) || 24;\n const padTop = parseFloat(styles.paddingTop) || 0;\n const padBot = parseFloat(styles.paddingBottom) || 0;\n const borderTop = parseFloat(styles.borderTopWidth) || 0;\n const borderBot = parseFloat(styles.borderBottomWidth) || 0;\n const chrome = padTop + padBot + borderTop + borderBot;\n const minH = lineHeight * minRows + chrome;\n const maxH = lineHeight * maxRows + chrome;\n el.style.height = 'auto';\n const next = Math.max(minH, Math.min(el.scrollHeight, maxH));\n el.style.height = `${next}px`;\n el.style.overflowY = el.scrollHeight > maxH ? 'auto' : 'hidden';\n }, [minRows, maxRows]);\n\n useLayoutEffect(() => {\n resize();\n }, [resize, currentValue]);\n\n /* ── Slash detection ── */\n const detectSlash = useCallback((text: string, caretPos: number) => {\n // Find the start of the current line.\n const before = text.slice(0, caretPos);\n const lineStart = before.lastIndexOf('\\n') + 1;\n const lineText = text.slice(lineStart, caretPos);\n if (lineText.startsWith('/')) {\n const afterSlash = lineText.slice(1);\n // Only open if the characters after '/' contain no whitespace.\n if (!/\\s/.test(afterSlash)) {\n setSlashOpen(true);\n setSlashQuery(afterSlash);\n return;\n }\n }\n setSlashOpen(false);\n setSlashQuery('');\n }, []);\n\n const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setInternalValue(e.target.value);\n if (composingRef.current) return;\n onChange?.(e);\n const caret = e.target.selectionStart ?? e.target.value.length;\n detectSlash(e.target.value, caret);\n };\n\n const handleCompositionStart = (\n e: CompositionEvent<HTMLTextAreaElement>,\n ) => {\n composingRef.current = true;\n onCompositionStart?.(e);\n };\n const handleCompositionEnd = (e: CompositionEvent<HTMLTextAreaElement>) => {\n composingRef.current = false;\n onCompositionEnd?.(e);\n };\n\n const isIMEKey = (e: KeyboardEvent<HTMLTextAreaElement>) =>\n e.nativeEvent.isComposing || e.keyCode === 229 || composingRef.current;\n\n const handleSubmit = useCallback(() => {\n const text = currentValue.trim();\n if (!text && attachments.length === 0) return;\n // Extract any leading command token.\n let command: string | undefined;\n let body = currentValue;\n const m = currentValue.match(/^\\/(\\S+)\\s?/);\n if (m) {\n command = m[1];\n body = currentValue.slice(m[0].length);\n }\n onSubmit?.({\n text: body,\n command,\n attachments,\n modelId: currentModel || undefined,\n });\n if (!isControlled) setInternalValue('');\n setAttachments([]);\n }, [currentValue, attachments, onSubmit, currentModel, isControlled]);\n\n const rootRef = useRef<HTMLDivElement>(null);\n useImperativeHandle(ref, () => rootRef.current as HTMLDivElement, []);\n\n const agentHandle = useMemo<AIPromptInputHandle>(\n () => ({\n getValue: () => currentValue,\n isEmpty: () => !currentValue.trim() && attachments.length === 0,\n isSubmitting: () => false,\n setValue: (next: string) => {\n if (!isControlled) setInternalValue(next);\n },\n clear: () => {\n if (!isControlled) setInternalValue('');\n setAttachments([]);\n },\n submit: () => {\n handleSubmit();\n },\n focus: () => {\n innerRef.current?.focus();\n },\n }),\n [currentValue, attachments, isControlled, handleSubmit],\n );\n useAgentRegistration(aiPromptInputAgent, agentHandle, id);\n\n const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n onKeyDown?.(e);\n if (e.defaultPrevented) return;\n if (isIMEKey(e)) return;\n\n // Slash menu open — Escape closes; ArrowDown/ArrowUp/Enter handled by cmdk.\n if (slashOpen) {\n if (e.key === 'Escape') {\n e.preventDefault();\n setSlashOpen(false);\n return;\n }\n }\n\n if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n const insertCommand = (cmd: AIPromptCommand) => {\n const el = innerRef.current;\n if (!el) return;\n const caret = el.selectionStart ?? currentValue.length;\n const before = currentValue.slice(0, caret);\n const lineStart = before.lastIndexOf('\\n') + 1;\n // Extend past any non-whitespace characters that follow the caret so\n // we replace the ENTIRE slash token (\"/fi|xBug more\" → \"/fixBug more\"),\n // not just the part before the caret (which would garble the tail).\n let endOfSlashToken = caret;\n while (\n endOfSlashToken < currentValue.length &&\n !/\\s/.test(currentValue[endOfSlashToken])\n ) {\n endOfSlashToken += 1;\n }\n const afterSlash = currentValue.slice(endOfSlashToken);\n const nextValue =\n currentValue.slice(0, lineStart) + `/${cmd.id} ` + afterSlash;\n if (!isControlled) setInternalValue(nextValue);\n // External consumers mirror the same synthetic event pattern other\n // text inputs in the system use — the native `onChange` fires via React.\n setSlashOpen(false);\n setSlashQuery('');\n queueMicrotask(() => el.focus());\n };\n\n /* ── Clipboard paste: strip rich HTML to plaintext, hand files to onAttach ── */\n const handlePaste = (e: ClipboardEvent<HTMLTextAreaElement>) => {\n onPaste?.(e);\n if (e.defaultPrevented) return;\n const { clipboardData } = e;\n if (!clipboardData) return;\n const files: File[] = [];\n for (let i = 0; i < clipboardData.items.length; i += 1) {\n const item = clipboardData.items[i];\n if (item.kind === 'file') {\n const f = item.getAsFile();\n if (f) files.push(f);\n }\n }\n if (files.length > 0) {\n e.preventDefault();\n acceptFiles(files);\n }\n };\n\n /* ── Dropzone ── */\n const acceptFiles = useCallback(\n (files: File[]) => {\n const next: AIPromptAttachment[] = [];\n for (const f of files) {\n if (typeof maxSize === 'number' && f.size > maxSize) {\n onAttachmentRejected?.(\n t('chat.attachment.rejected', { reason: 'size' }),\n );\n continue;\n }\n next.push({\n id: crypto.randomUUID?.() ?? `att-${Math.random()}`,\n file: f,\n });\n }\n if (next.length > 0) {\n setAttachments((prev) => [...prev, ...next]);\n onAttach?.(next.map((a) => a.file));\n }\n },\n [maxSize, onAttach, onAttachmentRejected, t],\n );\n\n const { getRootProps, getInputProps, isDragActive } = useDropzone({\n onDrop: acceptFiles,\n maxSize,\n accept,\n noClick: true,\n noKeyboard: true,\n });\n\n const removeAttachment = (id: string) => {\n setAttachments((prev) => prev.filter((a) => a.id !== id));\n };\n\n const effectiveId = id ?? textareaId;\n const labelId = `${effectiveId}-label`;\n const slashListId = `${effectiveId}-slash-list`;\n\n const modelOptions: SelectOption<string>[] =\n models?.map((m) => ({ value: m.id, label: m.label })) ?? [];\n\n return (\n <div\n ref={rootRef}\n {...getRootProps({\n className: [\n rootVariants({ size, className }),\n isDragActive\n ? 'ds:outline ds:outline-dashed ds:outline-[color:var(--primary)] ds:outline-offset-2 ds:bg-[color:var(--primary)]/5'\n : '',\n ].join(' '),\n })}\n aria-label={t('chat.attachmentZone')}\n data-component=\"ai-prompt-input\"\n data-component-id={id}\n >\n {/* Hidden file input owned by react-dropzone. The aria-label\n covers axe's `label` rule (the input is visually-hidden but\n still reachable programmatically). */}\n <input aria-label={t('chat.attachmentZone')} {...getInputProps()} />\n\n {context ? (\n <div className=\"ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-xs)] ds:pt-[var(--spacing-xs)]\">\n {/* Native <button> — not a span with role=\"button\" — per\n 05-accessibility \"Interactive elements use the right tag\".\n Enter/Space dispatch naturally via the native button;\n Backspace/Delete also dismiss (pill convention). */}\n <button\n type=\"button\"\n aria-label={t('chat.contextActive', { name: context })}\n onClick={onContextDismiss}\n onKeyDown={(e) => {\n if (e.key === 'Backspace' || e.key === 'Delete') {\n e.preventDefault();\n onContextDismiss?.();\n }\n }}\n className={[\n 'ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]',\n 'ds:rounded-[var(--radius-full)] ds:border ds:border-[color:var(--accent)]/30',\n 'ds:bg-[color:var(--accent)]/10 ds:text-[color:var(--foreground)]',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:pt-[var(--spacing-xs)] ds:pb-[var(--spacing-xs)]',\n 'ds:min-h-[var(--min-target-size)]',\n 'type-body-sm',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[color:var(--ring)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n ].join(' ')}\n >\n {t('chat.contextActive', { name: context })}\n </button>\n </div>\n ) : null}\n\n <label id={labelId} htmlFor={effectiveId} className=\"ds:sr-only\">\n {t('chat.prompt')}\n </label>\n\n <div className=\"ds:relative\">\n {/* The textarea takes on a combobox role only while the slash\n popup is open. ARIA 1.2 permits `role=\"combobox\"` on a\n textarea — that's what makes `aria-expanded` / `aria-controls`\n valid here. When the popup is closed the textarea reverts to\n its plain implicit role so we don't add the aria attrs at all. */}\n <textarea\n ref={setRefs}\n id={effectiveId}\n rows={minRows}\n value={isControlled ? currentValue : undefined}\n defaultValue={!isControlled ? defaultValue : undefined}\n disabled={disabled}\n placeholder={placeholder ?? t('chat.input.placeholder')}\n aria-labelledby={labelId}\n role={slashOpen ? 'combobox' : undefined}\n aria-controls={slashOpen ? slashListId : undefined}\n aria-expanded={slashOpen ? true : undefined}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n onCompositionStart={handleCompositionStart}\n onCompositionEnd={handleCompositionEnd}\n className={[\n 'ds:w-full ds:resize-none ds:bg-transparent ds:outline-none',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:pt-[var(--spacing-sm)] ds:pb-[var(--spacing-xs)]',\n 'ds:placeholder:text-[color:var(--muted-foreground)]',\n 'ds:leading-[var(--line-height-base)]',\n 'ds:disabled:opacity-50 ds:disabled:cursor-not-allowed',\n ].join(' ')}\n {...rest}\n />\n\n {slashOpen ? (\n <div\n ref={slashMenuRef}\n className={[\n 'ds:absolute ds:start-[var(--spacing-md)] ds:top-full ds:z-50',\n 'ds:mt-[var(--spacing-xs)]',\n 'ds:min-w-[240px] ds:rounded-[var(--radius-md)] ds:border ds:border-border',\n 'ds:bg-[color:var(--popover)] ds:text-[color:var(--popover-foreground)]',\n 'ds:shadow-[var(--shadow-md)]',\n // Match the Dialog / DropdownMenu open pattern: fade + scale\n // in from 95%. Origin set to the block-start so the menu\n // appears to expand from the textarea it sits beneath.\n 'ds:origin-top ds:motion-safe:animate-in ds:motion-safe:fade-in-0 ds:motion-safe:zoom-in-95',\n 'ds:duration-[var(--animation-duration)] ds:ease-[var(--ease-out)]',\n ].join(' ')}\n id={slashListId}\n >\n <Command label={t('chat.slashMenu.label')} loop>\n <Command.Input\n value={slashQuery}\n onValueChange={setSlashQuery}\n className=\"ds:sr-only\"\n />\n <Command.List className=\"ds:max-h-60 ds:overflow-y-auto ds:pt-[var(--spacing-xs)] ds:pb-[var(--spacing-xs)]\">\n <Command.Empty className=\"type-body-sm ds:text-[color:var(--muted-foreground)] ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:pt-[var(--spacing-sm)] ds:pb-[var(--spacing-sm)]\">\n {t('chat.slashMenu.empty')}\n </Command.Empty>\n {commands.map((cmd) => (\n <Command.Item\n key={cmd.id}\n value={cmd.id}\n onSelect={() => insertCommand(cmd)}\n className={[\n 'ds:flex ds:flex-col ds:gap-[2px]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:pt-[var(--spacing-xs)] ds:pb-[var(--spacing-xs)]',\n 'type-body-sm ds:cursor-pointer',\n 'ds:aria-selected:bg-muted/20',\n 'ds:data-[selected=true]:bg-muted/20',\n ].join(' ')}\n >\n <span className=\"ds:font-medium\">/{cmd.id}</span>\n {cmd.description ? (\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {cmd.description}\n </span>\n ) : null}\n </Command.Item>\n ))}\n </Command.List>\n </Command>\n </div>\n ) : null}\n </div>\n\n {attachments.length > 0 ? (\n <div\n role=\"group\"\n aria-label={t('chat.attachmentZone')}\n className=\"ds:flex ds:flex-wrap ds:gap-[var(--spacing-xs)] ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)]\"\n >\n {attachments.map((att) => (\n <AttachmentChip\n key={att.id}\n file={att.file}\n onRemove={() => removeAttachment(att.id)}\n />\n ))}\n </div>\n ) : null}\n\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)] ds:ps-[var(--spacing-xs)] ds:pe-[var(--spacing-xs)] ds:pb-[var(--spacing-xs)]\">\n {models && models.length > 0 ? (\n <div className=\"ds:me-auto ds:min-w-[140px]\">\n <Select\n aria-label={t('chat.model.select')}\n options={modelOptions}\n value={currentModel || ''}\n onValueChange={(v) => {\n if (!isModelControlled) setInternalModel(v);\n onModelChange?.(v);\n }}\n size=\"sm\"\n />\n </div>\n ) : (\n <div className=\"ds:me-auto\" />\n )}\n <span className=\"ds:sr-only\">{t('chat.input.sendHint')}</span>\n <IconButton\n icon={<Send />}\n aria-label={t('chat.send')}\n intent=\"primary\"\n size=\"sm\"\n disabled={\n disabled || (!currentValue.trim() && attachments.length === 0)\n }\n onClick={handleSubmit}\n aria-keyshortcuts=\"Meta+Enter Control+Enter\"\n />\n </div>\n </div>\n );\n },\n);\n\nAIPromptInput.displayName = 'AIPromptInput';\n\n/* ------------------------------------------------------------------ */\n/* Attachment chip */\n/* ------------------------------------------------------------------ */\n\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction AttachmentChip({\n file,\n onRemove,\n}: {\n file: File;\n onRemove: () => void;\n}): ReactNode {\n const { t } = useTranslation();\n return (\n <span\n className={[\n 'ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]',\n 'ds:rounded-[var(--radius-full)] ds:bg-muted/30',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-xs)]',\n 'ds:pt-[var(--spacing-xs)] ds:pb-[var(--spacing-xs)]',\n 'type-meta',\n // Entrance when a file is attached via drop / paste / picker.\n 'ds:motion-safe:animate-in ds:motion-safe:fade-in-0 ds:motion-safe:slide-in-from-bottom-1',\n 'ds:duration-[var(--animation-duration)] ds:ease-[var(--ease-out)]',\n ].join(' ')}\n >\n <span className=\"ds:truncate ds:max-w-[16ch]\">{file.name}</span>\n <span className=\"ds:text-[color:var(--muted-foreground)] ds:tabular-nums\">\n {formatSize(file.size)}\n </span>\n <IconButton\n icon={<X />}\n aria-label={t('chat.attachment.remove', { name: file.name })}\n intent=\"ghost\"\n size=\"sm\"\n onClick={onRemove}\n />\n </span>\n );\n}\n"],"names":["aiPromptInputAgent","handle","args","rootVariants","cva","AIPromptInput","forwardRef","commands","models","defaultModelId","modelId","onModelChange","maxSize","accept","context","onContextDismiss","onSubmit","onAttach","onAttachmentRejected","minRows","maxRows","value","defaultValue","size","disabled","className","placeholder","onChange","onKeyDown","onCompositionStart","onCompositionEnd","onPaste","id","rest","ref","t","useTranslation","textareaId","useId","innerRef","useRef","composingRef","slashMenuRef","setRefs","useCallback","node","isControlled","internalValue","setInternalValue","useState","currentValue","attachments","setAttachments","slashOpen","setSlashOpen","slashQuery","setSlashQuery","internalModel","setInternalModel","_a","isModelControlled","currentModel","resize","el","styles","lineHeight","padTop","padBot","borderTop","borderBot","chrome","minH","maxH","next","useLayoutEffect","detectSlash","text","caretPos","lineStart","lineText","afterSlash","handleChange","caret","handleCompositionStart","handleCompositionEnd","isIMEKey","handleSubmit","command","body","m","rootRef","useImperativeHandle","agentHandle","useMemo","useAgentRegistration","handleKeyDown","insertCommand","cmd","endOfSlashToken","nextValue","handlePaste","clipboardData","files","i","item","f","acceptFiles","prev","a","getRootProps","getInputProps","isDragActive","useDropzone","removeAttachment","effectiveId","labelId","slashListId","modelOptions","jsxs","jsx","Command","att","AttachmentChip","Select","v","IconButton","Send","formatSize","bytes","file","onRemove","X"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chat-input-Bov-gkwP.js","sources":["../../node_modules/lucide-react/dist/esm/icons/paperclip.js","../../src/components/chat-input/chat-input.agent.ts","../../src/components/chat-input/chat-input.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 [\n \"path\",\n {\n d: \"m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551\",\n key: \"1miecu\"\n }\n ]\n];\nconst Paperclip = createLucideIcon(\"paperclip\", __iconNode);\n\nexport { __iconNode, Paperclip as default };\n//# sourceMappingURL=paperclip.js.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — ChatInput. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { ChatInputHandle } from './chat-input';\n\nexport const chatInputAgent: AgentAdapter<ChatInputHandle> = {\n id: 'chat-input',\n capabilities: ['edit_inline', 'submit'],\n state: {\n value: {\n type: 'string',\n descriptionKey: 'ui.agent.chatInput.state.value',\n description: 'Current text in the composer.',\n read: (handle) => handle.getValue(),\n },\n isEmpty: {\n type: 'boolean',\n descriptionKey: 'ui.agent.chatInput.state.isEmpty',\n description: 'True when the composer has no text.',\n read: (handle) => handle.isEmpty(),\n },\n },\n actions: {\n set_value: {\n safety: 'write',\n argsType: '{ value: string }',\n descriptionKey: 'ui.agent.chatInput.actions.setValue',\n description: 'Replace the composer text.',\n invoke: (handle, args: { value: string }) => {\n handle.setValue(args.value);\n },\n },\n clear: {\n safety: 'destructive',\n descriptionKey: 'ui.agent.chatInput.actions.clear',\n description: 'Clear the composer. Irreversible from the same UI.',\n invoke: (handle) => {\n handle.clear();\n },\n },\n submit: {\n safety: 'write',\n descriptionKey: 'ui.agent.chatInput.actions.submit',\n description: 'Submit the current composer state via onSubmit.',\n invoke: (handle) => {\n handle.submit();\n },\n },\n focus: {\n safety: 'read',\n descriptionKey: 'ui.agent.chatInput.actions.focus',\n description: 'Move keyboard focus into the textarea.',\n invoke: (handle) => {\n handle.focus();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'chat-input',\n description: 'Marks the ChatInput 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 useId,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type CompositionEvent,\n type KeyboardEvent,\n type ReactNode,\n type TextareaHTMLAttributes,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { AlertCircle, Paperclip, Send } from 'lucide-react';\nimport { IconButton } from '../button';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { chatInputAgent } from './chat-input.agent';\n\nconst rootVariants = cva(\n [\n 'ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:w-full',\n // Soft drop-shadow + transparent border replaces a flat\n // `border-border` (grey-800 since the WCAG 1.4.11 bump). Border kept\n // at 1px so the focus-within color override + forced-colors\n // fallback still paint a visible edge.\n 'ds:rounded-[var(--radius-md)] ds:shadow-[var(--shadow-sm)] ds:border ds:border-transparent',\n 'ds:bg-background ds:focus-within:border-[color:var(--primary)]',\n 'ds:transition-[border-color] ds:duration-[var(--animation-duration)]',\n 'ds:motion-reduce:transition-none',\n 'ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:text-[length:var(--font-size-sm)]',\n md: 'ds:text-[length:var(--font-size-base)]',\n lg: 'ds:text-[length:var(--font-size-lg)]',\n },\n },\n defaultVariants: { size: 'md' },\n },\n);\n\ntype NativeTextareaProps = Omit<\n TextareaHTMLAttributes<HTMLTextAreaElement>,\n 'size' | 'onSubmit' | 'children'\n>;\n\n/** Curated imperative handle for agent / external automation. */\nexport interface ChatInputHandle {\n getValue: () => string;\n isEmpty: () => boolean;\n setValue: (value: string) => void;\n clear: () => void;\n submit: () => void;\n focus: () => void;\n}\n\nexport interface ChatInputProps\n extends NativeTextareaProps, VariantProps<typeof rootVariants> {\n /** Invoked when the user submits (Cmd/Ctrl+Enter, or send button). */\n onSubmit?: (text: string) => void;\n /** Maximum allowed characters (grapheme clusters via Intl.Segmenter when available). */\n maxLength?: number;\n /** When true, plain Enter submits and Shift+Enter inserts a newline.\n * Default false (Enter inserts newline; Cmd/Ctrl+Enter submits). */\n submitOnEnter?: boolean;\n /** Minimum visible rows. Default 1. */\n minRows?: number;\n /** Maximum visible rows before the field scrolls. Default 8. */\n maxRows?: number;\n /** Optional attachment handler — when provided, renders the attachment button. */\n onAttach?: (files: FileList) => void;\n /** `accept` forwarded to the hidden file input. */\n accept?: string;\n /** Controls whether the textarea is disabled and submit is blocked. */\n disabled?: boolean;\n /** Optional slot placed between the textarea and the send button. */\n toolbar?: ReactNode;\n /** Visible label above the textarea. When omitted, a visually-hidden label is used. */\n label?: string;\n}\n\nfunction graphemeCount(value: string, locale: string): number {\n if (typeof Intl !== 'undefined' && typeof Intl.Segmenter === 'function') {\n try {\n const seg = new Intl.Segmenter(locale, { granularity: 'grapheme' });\n let n = 0;\n for (const _s of seg.segment(value)) n += 1;\n return n;\n } catch {\n /* fall through to Array.from */\n }\n }\n return Array.from(value).length;\n}\n\nexport const ChatInput = forwardRef<HTMLDivElement, ChatInputProps>(\n (\n {\n size = 'md',\n value,\n defaultValue,\n maxLength,\n submitOnEnter = false,\n minRows = 1,\n maxRows = 8,\n onSubmit,\n onAttach,\n accept,\n disabled,\n toolbar,\n label,\n placeholder,\n className,\n onChange,\n onKeyDown,\n onCompositionStart,\n onCompositionEnd,\n id,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const textareaId = useId();\n const composingRef = useRef(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const innerRef = useRef<HTMLTextAreaElement | null>(null);\n\n const setRefs = useCallback((node: HTMLTextAreaElement | null) => {\n innerRef.current = node;\n }, []);\n\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState<string>(\n String(defaultValue ?? ''),\n );\n const currentValue = isControlled ? String(value) : internalValue;\n\n const count = graphemeCount(currentValue, i18n.language);\n const hasMaxLength = typeof maxLength === 'number' && maxLength > 0;\n const remaining = hasMaxLength ? Math.max(0, maxLength - count) : 0;\n const showCounter = hasMaxLength && count > (maxLength as number) * 0.9;\n const atLimit = hasMaxLength && count >= maxLength;\n\n /* Auto-grow — compute height from scrollHeight, clamped to [minRows, maxRows].\n Imperative `.style` write is permitted per 23-constraints\n §Runtime-computed dimensions (textarea scrollHeight measurement). */\n const resize = useCallback(() => {\n const el = innerRef.current;\n if (!el) return;\n const styles = window.getComputedStyle(el);\n const lineHeight = parseFloat(styles.lineHeight) || 24;\n const padTop = parseFloat(styles.paddingTop) || 0;\n const padBot = parseFloat(styles.paddingBottom) || 0;\n const borderTop = parseFloat(styles.borderTopWidth) || 0;\n const borderBot = parseFloat(styles.borderBottomWidth) || 0;\n const chrome = padTop + padBot + borderTop + borderBot;\n const minH = lineHeight * minRows + chrome;\n const maxH = lineHeight * maxRows + chrome;\n el.style.height = 'auto';\n const next = Math.max(minH, Math.min(el.scrollHeight, maxH));\n el.style.height = `${next}px`;\n el.style.overflowY = el.scrollHeight > maxH ? 'auto' : 'hidden';\n }, [minRows, maxRows]);\n\n useLayoutEffect(() => {\n resize();\n }, [resize, currentValue]);\n\n const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setInternalValue(e.target.value);\n if (composingRef.current) return;\n onChange?.(e);\n };\n\n const handleCompositionStart = (\n e: CompositionEvent<HTMLTextAreaElement>,\n ) => {\n composingRef.current = true;\n onCompositionStart?.(e);\n };\n const handleCompositionEnd = (e: CompositionEvent<HTMLTextAreaElement>) => {\n composingRef.current = false;\n onCompositionEnd?.(e);\n };\n\n const isIMEKey = (e: KeyboardEvent<HTMLTextAreaElement>) =>\n e.nativeEvent.isComposing || e.keyCode === 229 || composingRef.current;\n\n const submit = () => {\n const text = currentValue.trim();\n if (!text || disabled || atLimit) return;\n onSubmit?.(currentValue);\n if (!isControlled) setInternalValue('');\n };\n\n const rootRef = useRef<HTMLDivElement>(null);\n useImperativeHandle(ref, () => rootRef.current as HTMLDivElement, []);\n\n const agentHandle = useMemo<ChatInputHandle>(\n () => ({\n getValue: () => currentValue,\n isEmpty: () => !currentValue.trim(),\n setValue: (next: string) => {\n if (!isControlled) setInternalValue(next);\n },\n clear: () => {\n if (!isControlled) setInternalValue('');\n },\n submit: () => {\n submit();\n },\n focus: () => {\n innerRef.current?.focus();\n },\n }),\n // `submit` is a local closure that always sees the latest currentValue\n // via React's render cycle — depend on currentValue + isControlled so\n // the handle picks up new values across renders.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [currentValue, isControlled],\n );\n useAgentRegistration(chatInputAgent, agentHandle, id);\n\n const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n onKeyDown?.(e);\n if (e.defaultPrevented) return;\n if (isIMEKey(e)) return;\n\n if (e.key === 'Enter') {\n const explicitSubmit = e.metaKey || e.ctrlKey;\n const plainEnterSubmits = submitOnEnter && !e.shiftKey;\n if (explicitSubmit || plainEnterSubmits) {\n e.preventDefault();\n submit();\n }\n }\n };\n\n const handleAttach = () => {\n fileInputRef.current?.click();\n };\n\n const handleFilePick = (e: ChangeEvent<HTMLInputElement>) => {\n if (e.target.files && e.target.files.length > 0) {\n onAttach?.(e.target.files);\n }\n // Reset so picking the same file twice still fires change.\n e.target.value = '';\n };\n\n const effectiveId = id ?? textareaId;\n const labelId = `${effectiveId}-label`;\n const counterId = hasMaxLength ? `${effectiveId}-counter` : undefined;\n const hintId = `${effectiveId}-hint`;\n\n const resolvedPlaceholder = placeholder ?? t('chat.input.placeholder');\n const resolvedLabel = label ?? t('chat.prompt');\n\n return (\n <div\n ref={rootRef}\n data-component=\"chat-input\"\n data-component-id={id}\n className={rootVariants({ size, className })}\n >\n <label\n id={labelId}\n htmlFor={effectiveId}\n className={\n label\n ? 'type-label ds:ps-[var(--spacing-sm)] ds:pt-[var(--spacing-sm)]'\n : 'ds:sr-only'\n }\n >\n {resolvedLabel}\n </label>\n <textarea\n ref={setRefs}\n id={effectiveId}\n value={isControlled ? currentValue : undefined}\n defaultValue={!isControlled ? defaultValue : undefined}\n disabled={disabled}\n rows={minRows}\n maxLength={maxLength}\n placeholder={resolvedPlaceholder}\n aria-labelledby={labelId}\n aria-describedby={\n [counterId, hintId].filter(Boolean).join(' ') || undefined\n }\n aria-invalid={atLimit || undefined}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onCompositionStart={handleCompositionStart}\n onCompositionEnd={handleCompositionEnd}\n className={[\n 'ds:w-full ds:resize-none ds:bg-transparent',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:pt-[var(--spacing-sm)] ds:pb-[var(--spacing-xs)]',\n 'ds:placeholder:text-[color:var(--muted-foreground)]',\n 'ds:leading-[var(--line-height-base)]',\n 'ds:disabled:opacity-50 ds:disabled:cursor-not-allowed',\n // Tokenised focus ring on the textarea itself — the 1px border\n // shift on the wrapper alone fails the 3px accessible-theme\n // requirement. See a11y-critical-fixes.mdx.\n 'ds:outline-none',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n ].join(' ')}\n {...rest}\n />\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)] ds:ps-[var(--spacing-xs)] ds:pe-[var(--spacing-xs)] ds:pb-[var(--spacing-xs)]\">\n {onAttach ? (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n className=\"ds:sr-only\"\n multiple\n accept={accept}\n onChange={handleFilePick}\n aria-label={t('chat.input.attach')}\n tabIndex={-1}\n />\n <IconButton\n icon={<Paperclip />}\n aria-label={t('chat.input.attach')}\n intent=\"ghost\"\n size=\"sm\"\n onClick={handleAttach}\n disabled={disabled}\n />\n </>\n ) : null}\n {toolbar}\n <div className=\"ds:ms-auto ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n {showCounter ? (\n <span\n id={counterId}\n aria-live=\"polite\"\n className={[\n 'ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]',\n 'type-meta ds:tabular-nums',\n atLimit\n ? 'ds:text-[color:var(--destructive)]'\n : 'ds:text-[color:var(--muted-foreground)]',\n ].join(' ')}\n >\n {atLimit ? (\n // Icon pairs with --destructive colour so the at-limit\n // state is not conveyed by hue alone (WCAG 1.4.1).\n <AlertCircle aria-hidden=\"true\" className=\"ds:size-3.5\" />\n ) : null}\n {t('chat.input.remaining', { count: remaining })}\n </span>\n ) : null}\n <span id={hintId} className=\"ds:sr-only\">\n {t('chat.input.sendHint')}\n </span>\n <IconButton\n icon={<Send />}\n aria-label={t('chat.send')}\n intent=\"primary\"\n size=\"sm\"\n disabled={disabled || !currentValue.trim() || atLimit}\n onClick={submit}\n aria-keyshortcuts=\"Meta+Enter Control+Enter\"\n />\n </div>\n </div>\n </div>\n );\n },\n);\n\nChatInput.displayName = 'ChatInput';\n"],"names":["__iconNode","Paperclip","createLucideIcon","chatInputAgent","handle","args","rootVariants","cva","graphemeCount","value","locale","seg","n","_s","ChatInput","forwardRef","size","defaultValue","maxLength","submitOnEnter","minRows","maxRows","onSubmit","onAttach","accept","disabled","toolbar","label","placeholder","className","onChange","onKeyDown","onCompositionStart","onCompositionEnd","id","rest","ref","t","i18n","useTranslation","textareaId","useId","composingRef","useRef","fileInputRef","innerRef","setRefs","useCallback","node","isControlled","internalValue","setInternalValue","useState","currentValue","count","hasMaxLength","remaining","showCounter","atLimit","resize","el","styles","lineHeight","padTop","padBot","borderTop","borderBot","chrome","minH","maxH","next","useLayoutEffect","handleChange","handleCompositionStart","handleCompositionEnd","isIMEKey","submit","rootRef","useImperativeHandle","agentHandle","useMemo","_a","useAgentRegistration","handleKeyDown","explicitSubmit","plainEnterSubmits","handleAttach","handleFilePick","effectiveId","labelId","counterId","hintId","resolvedPlaceholder","resolvedLabel","jsxs","jsx","Fragment","IconButton","AlertCircle","Send"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"contact-card-VJIUqKB2.js","sources":["../../node_modules/lucide-react/dist/esm/icons/map-pin.js","../../src/components/contact-card/contact-card.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 [\n \"path\",\n {\n d: \"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0\",\n key: \"1r0f0z\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"10\", r: \"3\", key: \"ilqhr7\" }]\n];\nconst MapPin = createLucideIcon(\"map-pin\", __iconNode);\n\nexport { __iconNode, MapPin as default };\n//# sourceMappingURL=map-pin.js.map\n","import {\n forwardRef,\n Fragment,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { MapPin } from 'lucide-react';\nimport { Card } from '../card/card';\nimport { Link } from '../link/link';\n\n/* ------------------------------------------------------------------ */\n/* Phone helper */\n/* ------------------------------------------------------------------ */\n\n/**\n * Strip everything that's not a digit or a leading `+` so the display\n * string (`\"+49 (0)89 51871478\"`) becomes a valid `tel:` URI target\n * (`\"tel:+498951871478\"`). RFC 3966 allows visual separators, but most\n * dialer apps still trip on them — collapsing to a strict E.164-ish\n * form is the safe default. The `(0)` trunk-prefix convention is\n * intentionally dropped: it's not a real digit in international\n * dialling, only a hint for in-country dialling.\n */\nfunction buildTelHref(display: string): string {\n const trunkStripped = display.replace(/\\(0\\)/g, '');\n const digits = trunkStripped.replace(/[^\\d+]/g, '');\n return `tel:${digits}`;\n}\n\n/* ------------------------------------------------------------------ */\n/* Root */\n/* ------------------------------------------------------------------ */\n\nexport interface ContactCardProps extends Omit<\n HTMLAttributes<HTMLElement>,\n 'title'\n> {\n /**\n * Optional card heading rendered inside `Card.Header` as an `<h2>` —\n * e.g. \"Contact information\" above one or more office blocks. Omit\n * when the card sits inside a section that already has a heading.\n */\n title?: ReactNode;\n /**\n * `Card` variant. Defaults to `default` (subtle border on `--card`\n * surface) to match the marketing site's treatment.\n */\n variant?: 'default' | 'outlined' | 'elevated';\n children: ReactNode;\n}\n\nconst ContactCardRoot = forwardRef<HTMLElement, ContactCardProps>(\n ({ title, variant = 'default', className, children, ...props }, ref) => (\n <Card\n ref={ref}\n variant={variant}\n data-component=\"contact-card\"\n className={className}\n {...props}\n >\n {title !== undefined ? (\n <Card.Header>\n <h2 className=\"type-title-card ds:text-foreground\">{title}</h2>\n </Card.Header>\n ) : null}\n <Card.Body\n className={[\n 'ds:flex ds:flex-col ds:gap-[var(--spacing-md)]',\n // Tighten the body padding-block-start when a header sits\n // above so the whole card reads as one cohesive block rather\n // than two stacked sections — Card.Header already paints\n // bottom padding via `pb-0` + Card.Body's `p-md`.\n ].join(' ')}\n >\n {children}\n </Card.Body>\n </Card>\n ),\n);\nContactCardRoot.displayName = 'ContactCard';\n\n/* ------------------------------------------------------------------ */\n/* Office */\n/* ------------------------------------------------------------------ */\n\nexport interface ContactCardOfficeProps extends Omit<\n HTMLAttributes<HTMLElement>,\n 'children'\n> {\n /**\n * Office name — rendered as the block's bold label next to the pin\n * glyph. Not a heading element by default so a card with multiple\n * offices doesn't fragment the heading outline; pass `nameAs=\"h3\"`\n * (or `h4` etc.) when the consuming page wants a real heading.\n */\n name: ReactNode;\n /**\n * Address lines in document order, one per `<br>`-equivalent. Country\n * / region / postcode formatting is the consumer's responsibility —\n * the kit only inserts the line breaks.\n */\n lines: ReadonlyArray<string>;\n /**\n * VAT / tax-ID number. Rendered on its own line with the kit-owned\n * `ui.contactCard.vatNumberLabel` prefix.\n */\n vatNumber?: string;\n /**\n * Phone number as it should display (with separators, parens, trunk\n * prefix). The kit normalises this into a `tel:` URI internally —\n * see `buildTelHref` for the rules.\n */\n phone?: string;\n /** Heading element used for `name`. Defaults to a non-heading `<p>`. */\n nameAs?: 'p' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n}\n\nconst ContactCardOffice = forwardRef<HTMLElement, ContactCardOfficeProps>(\n (\n { name, lines, vatNumber, phone, nameAs = 'p', className, ...props },\n ref,\n ) => {\n const { t } = useTranslation();\n const NameTag = nameAs as 'p';\n\n return (\n <address\n ref={ref as React.Ref<HTMLElement>}\n data-component=\"contact-card-office\"\n className={[\n // `not-italic` overrides the UA default for `<address>` since\n // the kit's type ramp already encodes intent — italic would\n // double up with a heading-bold name and read as emphasis.\n 'ds:not-italic ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n >\n <NameTag className=\"ds:m-0 ds:flex ds:items-center ds:gap-[var(--spacing-xs)] type-label ds:font-semibold ds:text-foreground\">\n <MapPin\n aria-hidden=\"true\"\n className=\"ds:size-[1.25em] ds:text-primary ds:shrink-0\"\n />\n <span>{name}</span>\n </NameTag>\n <div className=\"type-body-sm ds:text-foreground ds:[unicode-bidi:isolate]\">\n {lines.map((line, i) => (\n <Fragment key={i}>\n {line}\n {i < lines.length - 1 ? <br /> : null}\n </Fragment>\n ))}\n </div>\n {vatNumber ? (\n <div className=\"type-body-sm ds:text-muted-foreground\">\n <span className=\"ds:me-[var(--spacing-2xs)]\">\n {t('contactCard.vatNumberLabel')}\n </span>\n <span className=\"ds:[unicode-bidi:isolate]\">{vatNumber}</span>\n </div>\n ) : null}\n {phone ? (\n <div className=\"type-body-sm ds:text-muted-foreground ds:inline-flex ds:items-baseline ds:gap-[var(--spacing-2xs)] ds:flex-wrap\">\n <span>{t('contactCard.phoneLabel')}</span>\n <Link href={buildTelHref(phone)} intent=\"default\">\n <span className=\"ds:[unicode-bidi:isolate]\">{phone}</span>\n </Link>\n </div>\n ) : null}\n </address>\n );\n },\n);\nContactCardOffice.displayName = 'ContactCard.Office';\n\n/* ------------------------------------------------------------------ */\n/* Links */\n/* ------------------------------------------------------------------ */\n\nexport type ContactCardLinksProps = HTMLAttributes<HTMLUListElement>;\n\nconst ContactCardLinks = forwardRef<HTMLUListElement, ContactCardLinksProps>(\n ({ className, children, ...props }, ref) => (\n <ul\n ref={ref}\n data-component=\"contact-card-links\"\n className={[\n 'ds:m-0 ds:p-0 ds:list-none',\n 'ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n >\n {children}\n </ul>\n ),\n);\nContactCardLinks.displayName = 'ContactCard.Links';\n\n/* ------------------------------------------------------------------ */\n/* Link */\n/* ------------------------------------------------------------------ */\n\nexport interface ContactCardLinkProps {\n href: string;\n /**\n * Leading glyph. Rendered with `--primary` so the link list reads as\n * a coloured-icon menu (matches the marketing site's treatment).\n * Consumers pass a bare lucide-react icon; the kit handles colour /\n * size / aria-hidden.\n */\n icon: ReactNode;\n /** Open in a new tab — adds `target=\"_blank\"` and `rel` via `Link`. */\n external?: boolean;\n children: ReactNode;\n}\n\nconst ContactCardLink = forwardRef<HTMLLIElement, ContactCardLinkProps>(\n ({ href, icon, external, children }, ref) => (\n <li ref={ref} className=\"ds:m-0\">\n <Link\n href={href}\n external={external}\n // Wrap in a `text-primary` span so the lucide glyph (which uses\n // `currentColor`) picks up the brand tint without the consumer\n // having to thread a className through every icon. Link adds\n // its own aria-hidden wrapper + `[&_svg]:size-[1em]` outside\n // this; the colour cascades through.\n startIcon={<span className=\"ds:text-primary\">{icon}</span>}\n >\n {children}\n </Link>\n </li>\n ),\n);\nContactCardLink.displayName = 'ContactCard.Link';\n\n/* ------------------------------------------------------------------ */\n/* Compound export */\n/* ------------------------------------------------------------------ */\n\nexport const ContactCard = Object.assign(ContactCardRoot, {\n Office: ContactCardOffice,\n Links: ContactCardLinks,\n Link: ContactCardLink,\n});\n\nexport { buildTelHref as __buildTelHref };\n"],"names":["__iconNode","MapPin","createLucideIcon","buildTelHref","display","ContactCardRoot","forwardRef","title","variant","className","children","props","ref","jsxs","Card","jsx","ContactCardOffice","name","lines","vatNumber","phone","nameAs","t","useTranslation","NameTag","line","i","Fragment","Link","ContactCardLinks","ContactCardLink","href","icon","external","ContactCard"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"input-surface-u4QB0lxe.js","sources":["../../src/components/_shared/input-surface.ts"],"sourcesContent":["// Shared \"input surface\" tokens consumed by TextInput, Autocomplete, Combobox,\n// and MultiSelect. Centralising these prevents the hand-rolled cmdk wrappers\n// from drifting away from TextInput when the styling evolves.\n//\n// Rename or removal is a MAJOR per src/docs/13-maintainability.mdx.\n\nexport const INPUT_SURFACE_CHROME = [\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:border ds:border-border ds:bg-background ds:text-foreground',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:focus-within:outline-[length:var(--focus-ring-width)] ds:focus-within:outline-solid',\n 'ds:focus-within:outline-ring ds:focus-within:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-within:outline-[CanvasText]',\n 'ds:has-[:disabled]:cursor-not-allowed ds:has-[:disabled]:opacity-50',\n].join(' ');\n\nexport const INPUT_SURFACE_TONE = {\n default: 'ds:border-border',\n error: 'ds:border-destructive',\n} as const;\n\n// Fixed heights per size. `md` follows --min-target-size so the accessible\n// theme bumps it automatically. `sm` is a dense opt-in (32px) and `lg` is 48px.\nexport const INPUT_SURFACE_HEIGHT = {\n sm: 'ds:h-8',\n md: 'ds:h-[var(--min-target-size)]',\n lg: 'ds:h-12',\n} as const;\n\n// Text size per input size — matches the typography ramp.\nexport const INPUT_SURFACE_TEXT = {\n sm: 'ds:text-[var(--font-size-sm)]',\n md: 'ds:text-[var(--font-size-base)]',\n lg: 'ds:text-[var(--font-size-lg)]',\n} as const;\n\n// Horizontal padding per size — `lg` gets a bit more breathing room.\nexport const INPUT_SURFACE_PADDING_X = {\n sm: 'ds:ps-3 ds:pe-3',\n md: 'ds:ps-3 ds:pe-3',\n lg: 'ds:ps-4 ds:pe-4',\n} as const;\n\nexport type InputSurfaceSize = keyof typeof INPUT_SURFACE_HEIGHT;\nexport type InputSurfaceTone = keyof typeof INPUT_SURFACE_TONE;\n"],"names":["INPUT_SURFACE_CHROME","INPUT_SURFACE_TONE","INPUT_SURFACE_HEIGHT","INPUT_SURFACE_TEXT","INPUT_SURFACE_PADDING_X"],"mappings":"AAMO,MAAMA,IAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAEGC,IAAqB;AAAA,EAChC,SAAS;AAAA,EACT,OAAO;AACT,GAIaC,IAAuB;AAAA,EAClC,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN,GAGaC,IAAqB;AAAA,EAChC,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN,GAGaC,IAA0B;AAAA,EACrC,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"link-BGpwaFik.js","sources":["../../node_modules/lucide-react/dist/esm/icons/external-link.js","../../src/components/link/link.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: \"M15 3h6v6\", key: \"1q9fwt\" }],\n [\"path\", { d: \"M10 14 21 3\", key: \"gplh6r\" }],\n [\"path\", { d: \"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\", key: \"a6xqqp\" }]\n];\nconst ExternalLink = createLucideIcon(\"external-link\", __iconNode);\n\nexport { __iconNode, ExternalLink as default };\n//# sourceMappingURL=external-link.js.map\n","import { forwardRef, type AnchorHTMLAttributes, type ReactNode } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { ExternalLink } from 'lucide-react';\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\n/**\n * Link is the semantic anchor primitive for inline navigation —\n * privacy / terms in form copy, external \"remote support\" links in\n * sidebars, in-paragraph references inside info-tip body copy.\n *\n * For action affordances that *look* like a link but trigger UI rather\n * than navigation, use `<Button intent=\"link\">` instead — the semantic\n * boundary matters for screen readers and keyboard users.\n */\nconst linkVariants = cva(\n [\n 'ds:underline-offset-4',\n 'ds:rounded-[var(--radius-xs)]',\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:aria-disabled:cursor-not-allowed ds:aria-disabled:opacity-50 ds:aria-disabled:no-underline',\n ].join(' '),\n {\n variants: {\n intent: {\n // `--primary` already maps to `magenta-700` in light-accent and\n // `magenta-500` in dark (see tokens/index.css), so the accent\n // contrast trade-off in §11 of CLAUDE.md is handled at the\n // token layer, not here.\n default:\n 'ds:text-primary ds:underline ds:hover:text-primary-hover ds:active:opacity-80',\n subtle:\n 'ds:text-muted-foreground ds:no-underline ds:hover:text-foreground ds:hover:underline ds:active:opacity-80',\n inverted:\n 'ds:text-primary-foreground ds:underline ds:hover:opacity-90 ds:active:opacity-80',\n },\n weight: {\n normal: 'ds:font-normal',\n strong: 'ds:font-semibold',\n },\n // When the link carries an icon, the anchor itself becomes a flex\n // container so glyphs centre on the text optical centre — the\n // previous `vertical-align: -0.125em` heuristic over-corrected when\n // the link was the only thing on its line (e.g. each <li> of a\n // vertical sidebar nav). Text-only links remain plain `inline` so\n // they wrap naturally inside a paragraph.\n hasIcon: {\n no: 'ds:inline',\n yes: 'ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]',\n },\n },\n defaultVariants: {\n intent: 'default',\n weight: 'normal',\n hasIcon: 'no',\n },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------ */\n\nexport interface LinkProps\n extends\n Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'>,\n VariantProps<typeof linkVariants> {\n /** Anchor target. Required — the whole point of the component. */\n href: string;\n /**\n * Flag the link as opening in a new browsing context. Automatically\n * adds `target=\"_blank\"` + `rel=\"noopener noreferrer\"` and renders a\n * trailing `ExternalLink` icon with an i18n'd aria-label.\n */\n external?: boolean;\n /**\n * Render the link in a non-interactive disabled state. Strips `href`,\n * adds `aria-disabled` + `role=\"link\"`, suppresses the underline.\n * Prefer hiding the link entirely when possible — disabled links are\n * a usability anti-pattern outside of state-machine flows.\n */\n disabled?: boolean;\n /** Optional leading icon (inline-start). */\n startIcon?: ReactNode;\n /** Optional trailing icon (inline-end). Ignored when `external`. */\n endIcon?: ReactNode;\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const Link = forwardRef<HTMLAnchorElement, LinkProps>(\n (\n {\n href,\n external = false,\n disabled = false,\n startIcon,\n endIcon,\n intent,\n weight,\n className,\n children,\n target,\n rel,\n onClick,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n\n const effectiveTarget = external ? '_blank' : target;\n const effectiveRel = external\n ? [rel, 'noopener', 'noreferrer'].filter(Boolean).join(' ')\n : rel;\n\n const externalLabel = t('link.opensInNewTab', 'Opens in a new tab');\n\n const handleClick: AnchorHTMLAttributes<HTMLAnchorElement>['onClick'] = (\n event,\n ) => {\n if (disabled) {\n event.preventDefault();\n return;\n }\n onClick?.(event);\n };\n\n const hasIcon = Boolean(startIcon || endIcon || external);\n\n return (\n <a\n ref={ref}\n // When disabled, drop href so the link is not actionable; pair\n // with aria-disabled + role=\"link\" so AT still announces the\n // role (the implicit role disappears once href is removed).\n href={disabled ? undefined : href}\n role={disabled ? 'link' : undefined}\n aria-disabled={disabled || undefined}\n target={effectiveTarget}\n rel={effectiveRel || undefined}\n onClick={handleClick}\n data-component=\"link\"\n data-intent={intent ?? 'default'}\n className={linkVariants({\n intent,\n weight,\n hasIcon: hasIcon ? 'yes' : 'no',\n className,\n })}\n {...rest}\n >\n {startIcon ? (\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-flex ds:items-center ds:[&_svg]:size-[1em]\"\n >\n {startIcon}\n </span>\n ) : null}\n {children}\n {external ? (\n <span\n className=\"ds:inline-flex ds:items-center\"\n aria-label={externalLabel}\n >\n <ExternalLink aria-hidden=\"true\" className=\"ds:size-[1em]\" />\n </span>\n ) : endIcon ? (\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-flex ds:items-center ds:[&_svg]:size-[1em]\"\n >\n {endIcon}\n </span>\n ) : null}\n </a>\n );\n },\n);\n\nLink.displayName = 'Link';\n"],"names":["__iconNode","ExternalLink","createLucideIcon","linkVariants","cva","Link","forwardRef","href","external","disabled","startIcon","endIcon","intent","weight","className","children","target","rel","onClick","rest","ref","t","useTranslation","effectiveTarget","effectiveRel","externalLabel","jsxs","event","jsx"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"number-input-mpSLk-ld.js","sources":["../../src/components/number-input/number-input.agent.ts","../../src/components/number-input/use-locale-number.ts","../../src/components/number-input/number-input.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — NumberInput. */\n/* */\n/* See `src/docs/26-agent-readiness.mdx` for the contract. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { NumberInputHandle } from './number-input';\n\nexport const numberInputAgent: AgentAdapter<NumberInputHandle> = {\n id: 'number-input',\n capabilities: ['edit_inline'],\n state: {\n value: {\n type: 'number | null',\n descriptionKey: 'ui.agent.numberInput.state.value',\n description: 'Current numeric value, or null when empty.',\n read: (handle) => handle.getValue(),\n },\n isEmpty: {\n type: 'boolean',\n descriptionKey: 'ui.agent.numberInput.state.isEmpty',\n description: 'Whether the input has no value.',\n read: (handle) => handle.getValue() === null,\n },\n },\n actions: {\n set_value: {\n safety: 'write',\n argsType: '{ value: number | null }',\n descriptionKey: 'ui.agent.numberInput.actions.setValue',\n description: 'Replace the numeric value, or pass null to clear.',\n invoke: (handle, args: { value: number | null }) => {\n handle.setValue(args.value);\n },\n },\n clear: {\n safety: 'destructive',\n descriptionKey: 'ui.agent.numberInput.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.numberInput.actions.focus',\n description: 'Move keyboard focus to the input.',\n invoke: (handle) => {\n handle.focus();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'number-input',\n description: 'Marks the NumberInput wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","import { useMemo } from 'react';\n\nexport type NumberInputMode = 'integer' | 'decimal' | 'currency' | 'percentage';\n\nexport interface LocaleNumber {\n /** Format a JS number for display (e.g. `1234.5` → `1.234,5` in de-DE). */\n format: (value: number) => string;\n /** Parse a locale-formatted string back to a JS number. Returns `NaN` for invalid input. */\n parse: (text: string) => number;\n /** The decimal separator for this locale (e.g. `.` or `,`). */\n decimalSeparator: string;\n /** The grouping separator for this locale (e.g. `,` or `.` or ` `). */\n groupingSeparator: string;\n /** The correct `inputMode` for the virtual keyboard. */\n inputMode: 'numeric' | 'decimal';\n}\n\nfunction normalizeDigits(text: string): string {\n let result = '';\n for (const ch of text) {\n const code = ch.codePointAt(0);\n if (code === undefined) continue;\n if (code >= 0x0660 && code <= 0x0669) {\n result += String.fromCodePoint(0x30 + (code - 0x0660));\n } else if (code >= 0x06f0 && code <= 0x06f9) {\n result += String.fromCodePoint(0x30 + (code - 0x06f0));\n } else {\n result += ch;\n }\n }\n return result;\n}\n\nexport function useLocaleNumber(\n locale: string,\n mode: NumberInputMode,\n currency?: string,\n): LocaleNumber {\n return useMemo(() => {\n const parts = new Intl.NumberFormat(locale).formatToParts(1234.5);\n const decimalSeparator =\n parts.find((p) => p.type === 'decimal')?.value ?? '.';\n const groupingSeparator =\n parts.find((p) => p.type === 'group')?.value ?? ',';\n\n const displayFormatter: Intl.NumberFormat = (() => {\n if (mode === 'currency') {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: currency ?? 'USD',\n });\n }\n if (mode === 'percentage') {\n return new Intl.NumberFormat(locale, {\n style: 'percent',\n maximumFractionDigits: 4,\n });\n }\n if (mode === 'integer') {\n return new Intl.NumberFormat(locale, { maximumFractionDigits: 0 });\n }\n return new Intl.NumberFormat(locale, { maximumFractionDigits: 10 });\n })();\n\n const format = (value: number): string => {\n if (!Number.isFinite(value)) return '';\n return displayFormatter.format(value);\n };\n\n const parse = (text: string): number => {\n if (!text) return NaN;\n const normalized = normalizeDigits(text);\n const trimmed = normalized.trim();\n const hasMinus = trimmed.startsWith('-') || trimmed.startsWith('\\u2212');\n\n let cleaned = '';\n for (const ch of normalized) {\n if (ch >= '0' && ch <= '9') {\n cleaned += ch;\n } else if (ch === decimalSeparator) {\n cleaned += '.';\n }\n }\n if (!cleaned || cleaned === '.') return NaN;\n\n let n = Number(cleaned);\n if (!Number.isFinite(n)) return NaN;\n if (hasMinus) n = -n;\n if (mode === 'percentage') n = n / 100;\n return n;\n };\n\n let inputMode: 'numeric' | 'decimal' = 'decimal';\n if (mode === 'integer') {\n inputMode = 'numeric';\n } else if (mode === 'currency') {\n try {\n const { maximumFractionDigits } = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: currency ?? 'USD',\n }).resolvedOptions();\n inputMode = maximumFractionDigits === 0 ? 'numeric' : 'decimal';\n } catch {\n inputMode = 'decimal';\n }\n }\n\n return {\n format,\n parse,\n decimalSeparator,\n groupingSeparator,\n inputMode,\n };\n }, [locale, mode, currency]);\n}\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type FocusEvent,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type MouseEvent,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { ChevronDown, ChevronUp } from 'lucide-react';\nimport { useFormField } from '../form-field/form-field-context';\nimport { composeRefs } from '../_shared/compose-refs';\nimport { useAgentRegistration } from '../../agent';\nimport { numberInputAgent } from './number-input.agent';\nimport { useLocaleNumber, type NumberInputMode } from './use-locale-number';\n\n/** Agent-readiness curated handle for NumberInput. */\nexport interface NumberInputHandle {\n getValue: () => number | null;\n setValue: (value: number | null) => void;\n clear: () => void;\n focus: () => void;\n}\n\nconst numberInputVariants = cva(\n [\n 'ds:flex ds:items-center ds:w-full ds:rounded-[var(--radius-sm)]',\n 'ds:border ds:bg-background ds:text-foreground',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:focus-within:outline-[length:var(--focus-ring-width)] ds:focus-within:outline-solid',\n 'ds:focus-within:outline-ring ds:focus-within:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:has-[:disabled]:cursor-not-allowed ds:has-[:disabled]:opacity-50',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:h-8 ds:text-[length:var(--font-size-sm)]',\n md: 'ds:h-[var(--min-target-size)] ds:text-[length:var(--font-size-base)]',\n lg: 'ds:h-12 ds:text-[length:var(--font-size-lg)]',\n },\n tone: {\n default: 'ds:border-border',\n error: 'ds:border-destructive ds:focus-within:outline-destructive',\n },\n },\n defaultVariants: { size: 'md', tone: 'default' },\n },\n);\n\nconst spinnerButton = [\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:h-full ds:shrink-0',\n 'ds:text-muted-foreground ds:hover:text-foreground',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:disabled:cursor-not-allowed ds:disabled:opacity-50',\n].join(' ');\n\nexport type { NumberInputMode };\n\nexport interface NumberInputProps\n extends\n Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'type' | 'onChange' | 'value' | 'defaultValue' | 'size'\n >,\n VariantProps<typeof numberInputVariants> {\n /** Current numeric value (controlled). */\n value?: number | null;\n /** Initial value (uncontrolled). */\n defaultValue?: number;\n /** Fires with the parsed number (not a string). `null` when the field is empty. */\n onChange?: (value: number | null) => void;\n /** Minimum allowed value. Maps to `aria-valuemin`. */\n min?: number;\n /** Maximum allowed value. Maps to `aria-valuemax`. */\n max?: number;\n /** Increment step. Defaults to `1`. */\n step?: number;\n /** Display/parse mode. Defaults to `'integer'`. */\n mode?: NumberInputMode;\n /** ISO 4217 currency code, required when `mode='currency'`. */\n currency?: string;\n /** BCP 47 locale. Defaults to `navigator.language` or `'en-US'`. */\n locale?: string;\n /** Size variant. */\n size?: 'sm' | 'md' | 'lg';\n /** Additional class names on the wrapper. */\n className?: string;\n}\n\nconst resolveDefaultLocale = (): string => {\n if (typeof navigator !== 'undefined' && navigator.language) {\n return navigator.language;\n }\n return 'en-US';\n};\n\nfunction decimalPlaces(n: number): number {\n if (!Number.isFinite(n)) return 0;\n const s = String(n);\n const dot = s.indexOf('.');\n if (dot === -1) return 0;\n return s.length - dot - 1;\n}\n\nfunction roundToStep(value: number, step: number): number {\n if (step <= 0 || !Number.isFinite(step)) return value;\n const precision = decimalPlaces(step);\n const factor = 10 ** precision;\n return Math.round(value * factor) / factor;\n}\n\nexport const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(\n (\n {\n value,\n defaultValue,\n onChange,\n min,\n max,\n step = 1,\n mode = 'integer',\n currency,\n locale,\n size = 'md',\n tone,\n className,\n id,\n disabled,\n onFocus,\n onBlur,\n onKeyDown,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const ctx = useFormField();\n const inputId = id ?? ctx.id;\n const effectiveDisabled = Boolean(ctx.disabled || disabled);\n\n const resolvedLocale = locale ?? resolveDefaultLocale();\n const localeNumber = useLocaleNumber(resolvedLocale, mode, currency);\n const {\n decimalSeparator,\n format: localeFormat,\n parse: localeParse,\n } = localeNumber;\n\n const innerInputRef = useRef<HTMLInputElement | null>(null);\n const composedRef = composeRefs(ref, innerInputRef);\n\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState<number | null>(\n defaultValue ?? null,\n );\n const currentValue: number | null = isControlled\n ? (value ?? null)\n : internalValue;\n\n const currentValueRef = useRef<number | null>(currentValue);\n currentValueRef.current = currentValue;\n\n const formatForEdit = useCallback(\n (n: number): string => {\n const displayed = mode === 'percentage' ? n * 100 : n;\n const raw = Number.isInteger(displayed)\n ? String(displayed)\n : displayed.toString();\n return raw.replace('.', decimalSeparator);\n },\n [mode, decimalSeparator],\n );\n\n const formatCurrent = useCallback(\n (n: number | null | undefined): string =>\n n === null || n === undefined || Number.isNaN(n) ? '' : localeFormat(n),\n [localeFormat],\n );\n\n const [inputText, setInputText] = useState<string>(() =>\n formatCurrent(currentValue),\n );\n const isFocusedRef = useRef(false);\n const [crossedBounds, setCrossedBounds] = useState(false);\n\n useEffect(() => {\n if (!isFocusedRef.current) {\n setInputText(formatCurrent(currentValue));\n }\n }, [currentValue, formatCurrent]);\n\n const computedInvalid =\n crossedBounds ||\n (currentValue !== null &&\n ((min !== undefined && currentValue < min) ||\n (max !== undefined && currentValue > max)));\n const ariaInvalid = ctx.invalid || computedInvalid;\n const effectiveTone: 'default' | 'error' = ariaInvalid\n ? 'error'\n : (tone ?? 'default');\n\n const commitValue = (next: number | null) => {\n if (!isControlled) setInternalValue(next);\n onChange?.(next);\n };\n\n const applyDelta = (multiplier: number) => {\n const base = currentValue ?? 0;\n let next = base + step * multiplier;\n if (min !== undefined) next = Math.max(min, next);\n if (max !== undefined) next = Math.min(max, next);\n next = roundToStep(next, step);\n commitValue(next);\n setCrossedBounds(false);\n setInputText(\n isFocusedRef.current ? formatForEdit(next) : formatCurrent(next),\n );\n };\n\n const jumpTo = (target: number) => {\n commitValue(target);\n setCrossedBounds(false);\n setInputText(\n isFocusedRef.current ? formatForEdit(target) : formatCurrent(target),\n );\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented) return;\n if (effectiveDisabled) return;\n\n const { key, shiftKey } = event;\n if (key === 'ArrowUp') {\n event.preventDefault();\n applyDelta(shiftKey ? 10 : 1);\n } else if (key === 'ArrowDown') {\n event.preventDefault();\n applyDelta(shiftKey ? -10 : -1);\n } else if (key === 'PageUp') {\n event.preventDefault();\n applyDelta(100);\n } else if (key === 'PageDown') {\n event.preventDefault();\n applyDelta(-100);\n } else if (key === 'Home' && min !== undefined) {\n event.preventDefault();\n jumpTo(min);\n } else if (key === 'End' && max !== undefined) {\n event.preventDefault();\n jumpTo(max);\n }\n };\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n const text = event.target.value;\n setInputText(text);\n if (text.trim() === '') {\n commitValue(null);\n setCrossedBounds(false);\n return;\n }\n const parsed = localeParse(text);\n if (!Number.isNaN(parsed)) {\n commitValue(parsed);\n }\n };\n\n const handleFocus = (event: FocusEvent<HTMLInputElement>) => {\n onFocus?.(event);\n isFocusedRef.current = true;\n if (currentValue !== null && currentValue !== undefined) {\n setInputText(formatForEdit(currentValue));\n }\n };\n\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\n onBlur?.(event);\n isFocusedRef.current = false;\n\n if (inputText.trim() === '') {\n commitValue(null);\n setCrossedBounds(false);\n setInputText('');\n return;\n }\n const parsed = localeParse(inputText);\n if (Number.isNaN(parsed)) {\n setInputText(formatCurrent(currentValue));\n return;\n }\n const crossed =\n (min !== undefined && parsed < min) ||\n (max !== undefined && parsed > max);\n setCrossedBounds(crossed);\n commitValue(parsed);\n setInputText(formatCurrent(parsed));\n };\n\n const preventButtonBlur = (event: MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n };\n\n const handleIncrement = () => applyDelta(1);\n const handleDecrement = () => applyDelta(-1);\n\n const agentHandle = useMemo<NumberInputHandle>(\n () => ({\n getValue: () => currentValueRef.current,\n setValue: (next) => {\n commitValue(next);\n setInputText(\n next === null\n ? ''\n : isFocusedRef.current\n ? formatForEdit(next)\n : formatCurrent(next),\n );\n },\n clear: () => {\n commitValue(null);\n setInputText('');\n setCrossedBounds(false);\n },\n focus: () => innerInputRef.current?.focus(),\n }),\n // The handle is reconstructed per render; consumers (the agent runtime)\n // re-register only when the identity changes, which is a cheap no-op.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [formatForEdit, formatCurrent],\n );\n useAgentRegistration(numberInputAgent, agentHandle, id);\n\n const decrementDisabled =\n effectiveDisabled ||\n (min !== undefined && currentValue !== null && currentValue <= min);\n const incrementDisabled =\n effectiveDisabled ||\n (max !== undefined && currentValue !== null && currentValue >= max);\n\n const valueNow = currentValue ?? undefined;\n const valueTextNeeded =\n (mode === 'currency' || mode === 'percentage') && currentValue !== null;\n const valueText =\n valueTextNeeded && currentValue !== null\n ? localeFormat(currentValue)\n : undefined;\n\n const patternAttr =\n localeNumber.inputMode === 'numeric' ? '[0-9]*' : undefined;\n\n return (\n <div\n className={numberInputVariants({\n size,\n tone: effectiveTone,\n className,\n })}\n data-component=\"number-input\"\n data-component-id={id}\n data-mode={mode}\n >\n <button\n type=\"button\"\n tabIndex={-1}\n aria-label={t('inputs.number.decrement', 'Decrement')}\n onClick={handleDecrement}\n onMouseDown={preventButtonBlur}\n disabled={decrementDisabled}\n className={`${spinnerButton} ds:ps-2 ds:pe-1`}\n >\n <ChevronDown aria-hidden=\"true\" className=\"ds:size-4\" />\n </button>\n <input\n ref={composedRef}\n id={inputId}\n type=\"text\"\n role=\"spinbutton\"\n inputMode={localeNumber.inputMode}\n pattern={patternAttr}\n autoComplete=\"off\"\n value={inputText}\n disabled={effectiveDisabled}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={valueNow}\n aria-valuetext={valueText}\n aria-invalid={ariaInvalid || undefined}\n aria-required={ctx.required || undefined}\n aria-describedby={ctx.describedBy || undefined}\n onChange={handleInputChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n className=\"ds:flex-1 ds:w-full ds:min-w-0 ds:bg-transparent ds:outline-none ds:ps-2 ds:pe-2 ds:text-start ds:tabular-nums ds:disabled:cursor-not-allowed\"\n {...rest}\n />\n <button\n type=\"button\"\n tabIndex={-1}\n aria-label={t('inputs.number.increment', 'Increment')}\n onClick={handleIncrement}\n onMouseDown={preventButtonBlur}\n disabled={incrementDisabled}\n className={`${spinnerButton} ds:ps-1 ds:pe-2`}\n >\n <ChevronUp aria-hidden=\"true\" className=\"ds:size-4\" />\n </button>\n </div>\n );\n },\n);\n\nNumberInput.displayName = 'NumberInput';\n"],"names":["numberInputAgent","handle","args","normalizeDigits","text","result","ch","code","useLocaleNumber","locale","mode","currency","useMemo","parts","decimalSeparator","_a","p","groupingSeparator","_b","displayFormatter","format","value","parse","normalized","trimmed","hasMinus","cleaned","n","inputMode","maximumFractionDigits","numberInputVariants","cva","spinnerButton","resolveDefaultLocale","decimalPlaces","s","dot","roundToStep","step","factor","NumberInput","forwardRef","defaultValue","onChange","min","max","size","tone","className","id","disabled","onFocus","onBlur","onKeyDown","rest","ref","t","useTranslation","ctx","useFormField","inputId","effectiveDisabled","resolvedLocale","localeNumber","localeFormat","localeParse","innerInputRef","useRef","composedRef","composeRefs","isControlled","internalValue","setInternalValue","useState","currentValue","currentValueRef","formatForEdit","useCallback","displayed","formatCurrent","inputText","setInputText","isFocusedRef","crossedBounds","setCrossedBounds","useEffect","computedInvalid","ariaInvalid","effectiveTone","commitValue","next","applyDelta","multiplier","jumpTo","target","handleKeyDown","event","key","shiftKey","handleInputChange","parsed","handleFocus","handleBlur","crossed","preventButtonBlur","handleIncrement","handleDecrement","agentHandle","useAgentRegistration","decrementDisabled","incrementDisabled","valueNow","valueText","patternAttr","jsxs","jsx","ChevronDown","ChevronUp"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"otp-input-CI-Zv5q6.js","sources":["../../src/components/otp-input/otp-input.agent.ts","../../src/components/otp-input/otp-input.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — OTPInput. */\n/* */\n/* See `src/docs/26-agent-readiness.mdx` for the contract. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { OTPInputHandle } from './otp-input';\n\nexport const otpInputAgent: AgentAdapter<OTPInputHandle> = {\n id: 'otp-input',\n capabilities: ['edit_inline', 'submit'],\n state: {\n value: {\n type: 'string',\n descriptionKey: 'ui.agent.otpInput.state.value',\n description: 'Current digits entered, packed into a single string.',\n read: (handle) => handle.getValue(),\n },\n isComplete: {\n type: 'boolean',\n descriptionKey: 'ui.agent.otpInput.state.isComplete',\n description: 'Whether all required digits have been entered.',\n read: (handle) => handle.isComplete(),\n },\n },\n actions: {\n set_value: {\n safety: 'write',\n argsType: '{ value: string }',\n descriptionKey: 'ui.agent.otpInput.actions.setValue',\n description: 'Replace the entered digits.',\n invoke: (handle, args: { value: string }) => {\n handle.setValue(args.value);\n },\n },\n clear: {\n safety: 'destructive',\n descriptionKey: 'ui.agent.otpInput.actions.clear',\n description: 'Empty all digit cells. Loses any typed value.',\n invoke: (handle) => {\n handle.clear();\n },\n },\n focus: {\n safety: 'read',\n descriptionKey: 'ui.agent.otpInput.actions.focus',\n description: 'Move keyboard focus to the active digit cell.',\n invoke: (handle) => {\n handle.focus();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'otp-input',\n description:\n 'Marks the OTPInput wrapper. Completion is observable via state.isComplete; the host onComplete callback fires once when all digits are filled.',\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 useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type ClipboardEvent,\n type FocusEvent,\n type KeyboardEvent,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { useFormField } from '../form-field/form-field-context';\nimport { useAgentRegistration } from '../../agent';\nimport { otpInputAgent } from './otp-input.agent';\n\n/** Agent-readiness curated handle for OTPInput. */\nexport interface OTPInputHandle {\n getValue: () => string;\n setValue: (value: string) => void;\n clear: () => void;\n focus: () => void;\n isComplete: () => boolean;\n}\n\nconst wrapperVariants = cva('ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]');\n\nconst boxVariants = cva(\n [\n 'ds:w-[var(--min-target-size)] ds:h-[var(--min-target-size)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:border ds:bg-background ds:text-foreground ds:text-center ds:font-medium ds:text-[length:var(--font-size-lg)]',\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:disabled:cursor-not-allowed ds:disabled:opacity-50',\n ].join(' '),\n {\n variants: {\n tone: {\n default: 'ds:border-border',\n error: 'ds:border-destructive',\n },\n },\n defaultVariants: { tone: 'default' },\n },\n);\n\nexport interface OTPInputProps {\n length?: 4 | 6 | 8;\n value?: string;\n defaultValue?: string;\n onChange?: (value: string) => void;\n onComplete?: (code: string) => void;\n disabled?: boolean;\n error?: boolean;\n label?: string;\n /** Stable id, used to address this instance from the agent runtime. */\n id?: string;\n className?: string;\n}\n\nfunction normaliseDigits(str: string): string {\n return str\n .replace(/[\\u0660-\\u0669]/g, (c) => String(c.charCodeAt(0) - 0x0660))\n .replace(/[\\u06F0-\\u06F9]/g, (c) => String(c.charCodeAt(0) - 0x06f0));\n}\n\nfunction packValue(value: string, length: number): string {\n return normaliseDigits(value).replace(/\\D/g, '').slice(0, length);\n}\n\nfunction valueToArray(value: string, length: number): string[] {\n const packed = packValue(value, length);\n const arr = new Array<string>(length).fill('');\n for (let i = 0; i < packed.length; i += 1) {\n arr[i] = packed[i];\n }\n return arr;\n}\n\nexport const OTPInput = forwardRef<HTMLDivElement, OTPInputProps>(\n (\n {\n length = 6,\n value,\n defaultValue,\n onChange,\n onComplete,\n disabled,\n error,\n label,\n id,\n className,\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const ctx = useFormField();\n const generatedLabelId = useId();\n const labelId = label ? generatedLabelId : undefined;\n\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState<string>(() =>\n packValue(defaultValue ?? '', length),\n );\n const currentValue = packValue(\n isControlled ? value : internalValue,\n length,\n );\n const digits = valueToArray(currentValue, length);\n\n const effectiveDisabled = ctx.disabled || Boolean(disabled);\n const effectiveError = ctx.invalid || Boolean(error);\n const effectiveTone = effectiveError ? 'error' : 'default';\n\n const inputsRef = useRef<Array<HTMLInputElement | null>>([]);\n const completedRef = useRef(currentValue.length === length);\n const valueRef = useRef(currentValue);\n valueRef.current = currentValue;\n\n const computeInitialIndex = () => {\n const firstEmpty = currentValue.length;\n if (firstEmpty >= length) return length - 1;\n return firstEmpty;\n };\n const [activeIndex, setActiveIndex] = useState<number>(computeInitialIndex);\n\n useEffect(() => {\n if (activeIndex >= length) setActiveIndex(length - 1);\n }, [activeIndex, length]);\n\n const focusBox = useCallback(\n (index: number) => {\n const clamped = Math.max(0, Math.min(length - 1, index));\n setActiveIndex(clamped);\n const node = inputsRef.current[clamped];\n if (node) {\n node.focus();\n node.select();\n }\n },\n [length],\n );\n\n const commit = useCallback(\n (next: string) => {\n const packed = packValue(next, length);\n if (!isControlled) setInternalValue(packed);\n valueRef.current = packed;\n onChange?.(packed);\n if (packed.length === length) {\n if (!completedRef.current) {\n completedRef.current = true;\n onComplete?.(packed);\n }\n } else {\n completedRef.current = false;\n }\n },\n [isControlled, length, onChange, onComplete],\n );\n\n const handleChange =\n (index: number) => (event: ChangeEvent<HTMLInputElement>) => {\n const raw = event.target.value;\n const norm = normaliseDigits(raw).replace(/\\D/g, '');\n const current = valueRef.current;\n\n if (norm.length === 0) {\n if (raw === '' && index < current.length) {\n const newValue = current.slice(0, index) + current.slice(index + 1);\n commit(newValue);\n }\n return;\n }\n\n const before = current.slice(0, index);\n const after = current.slice(index + norm.length);\n const newValue = (before + norm + after).slice(0, length);\n commit(newValue);\n\n const focusTarget = Math.min(index + norm.length, length - 1);\n focusBox(focusTarget);\n };\n\n const handleKeyDown =\n (index: number) => (event: KeyboardEvent<HTMLInputElement>) => {\n const current = valueRef.current;\n if (event.key === 'Backspace') {\n if (current[index]) {\n event.preventDefault();\n const newValue = current.slice(0, index) + current.slice(index + 1);\n commit(newValue);\n return;\n }\n if (index > 0) {\n event.preventDefault();\n const newValue = current.slice(0, index - 1) + current.slice(index);\n commit(newValue);\n focusBox(index - 1);\n }\n return;\n }\n if (event.key === 'ArrowLeft') {\n event.preventDefault();\n if (index > 0) focusBox(index - 1);\n return;\n }\n if (event.key === 'ArrowRight') {\n event.preventDefault();\n if (index < length - 1) focusBox(index + 1);\n return;\n }\n if (event.key === 'Home') {\n event.preventDefault();\n focusBox(0);\n return;\n }\n if (event.key === 'End') {\n event.preventDefault();\n focusBox(length - 1);\n }\n };\n\n const handlePaste =\n (index: number) => (event: ClipboardEvent<HTMLInputElement>) => {\n const text = event.clipboardData.getData('text');\n const stripped = text.replace(/\\s+/g, '');\n const norm = normaliseDigits(stripped);\n if (!/^[0-9]+$/.test(norm)) return;\n event.preventDefault();\n const current = valueRef.current;\n const before = current.slice(0, index);\n const after = current.slice(index + norm.length);\n const newValue = (before + norm + after).slice(0, length);\n commit(newValue);\n const focusTarget = Math.min(index + norm.length, length - 1);\n focusBox(focusTarget);\n };\n\n const handleFocus =\n (index: number) => (event: FocusEvent<HTMLInputElement>) => {\n setActiveIndex(index);\n event.currentTarget.select();\n };\n\n const baseId = ctx.id;\n\n const agentHandle = useMemo<OTPInputHandle>(\n () => ({\n getValue: () => valueRef.current,\n setValue: (next) => commit(next),\n clear: () => commit(''),\n focus: () => focusBox(activeIndex),\n isComplete: () => valueRef.current.length === length,\n }),\n [commit, focusBox, activeIndex, length],\n );\n useAgentRegistration(otpInputAgent, agentHandle, id);\n\n return (\n <div className={wrapperVariants({ className })}>\n {label ? (\n <label\n id={labelId}\n htmlFor={`${baseId}-0`}\n className=\"type-label ds:text-foreground\"\n >\n {label}\n </label>\n ) : null}\n {/* eslint-disable-next-line jsx-a11y/role-supports-aria-props -- aria-invalid is a global ARIA state; conveys group-level validation */}\n <div\n ref={ref}\n role=\"group\"\n dir=\"ltr\"\n aria-labelledby={labelId}\n aria-invalid={effectiveError || undefined}\n aria-describedby={ctx.describedBy || undefined}\n aria-disabled={effectiveDisabled || undefined}\n data-component=\"otp-input\"\n data-component-id={id}\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\"\n >\n {digits.map((digit, index) => {\n const isTabbable = !effectiveDisabled && index === activeIndex;\n return (\n <input\n key={index}\n ref={(node) => {\n inputsRef.current[index] = node;\n }}\n id={`${baseId}-${index}`}\n type=\"text\"\n inputMode=\"numeric\"\n pattern=\"[0-9]*\"\n autoComplete={index === 0 ? 'one-time-code' : 'off'}\n maxLength={1}\n value={digit}\n disabled={effectiveDisabled}\n tabIndex={isTabbable ? 0 : -1}\n aria-label={t('inputs.otp.digitLabel', {\n current: index + 1,\n total: length,\n })}\n onChange={handleChange(index)}\n onKeyDown={handleKeyDown(index)}\n onPaste={handlePaste(index)}\n onFocus={handleFocus(index)}\n className={boxVariants({ tone: effectiveTone })}\n />\n );\n })}\n </div>\n </div>\n );\n },\n);\n\nOTPInput.displayName = 'OTPInput';\n"],"names":["otpInputAgent","handle","args","wrapperVariants","cva","boxVariants","normaliseDigits","str","c","packValue","value","length","valueToArray","packed","arr","i","OTPInput","forwardRef","defaultValue","onChange","onComplete","disabled","error","label","id","className","ref","t","useTranslation","ctx","useFormField","generatedLabelId","useId","labelId","isControlled","internalValue","setInternalValue","useState","currentValue","digits","effectiveDisabled","effectiveError","effectiveTone","inputsRef","useRef","completedRef","valueRef","computeInitialIndex","firstEmpty","activeIndex","setActiveIndex","useEffect","focusBox","useCallback","index","clamped","node","commit","next","handleChange","event","raw","norm","current","newValue","before","after","focusTarget","handleKeyDown","handlePaste","stripped","handleFocus","baseId","agentHandle","useMemo","useAgentRegistration","jsx","digit","isTabbable"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"phone-input-DtBVs5fz.js","sources":["../../src/components/phone-input/phone-input.agent.ts","../../src/components/phone-input/phone-input.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — PhoneInput. */\n/* */\n/* See `src/docs/26-agent-readiness.mdx` for the contract. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { PhoneInputHandle } from './phone-input';\n\nexport const phoneInputAgent: AgentAdapter<PhoneInputHandle> = {\n id: 'phone-input',\n capabilities: ['edit_inline'],\n state: {\n value: {\n type: 'string',\n descriptionKey: 'ui.agent.phoneInput.state.value',\n description:\n 'Current E.164 phone number, or empty string when not yet valid.',\n read: (handle) => handle.getValue(),\n },\n isEmpty: {\n type: 'boolean',\n descriptionKey: 'ui.agent.phoneInput.state.isEmpty',\n description: 'Whether the input has no value.',\n read: (handle) => handle.getValue() === '',\n },\n },\n actions: {\n set_value: {\n safety: 'write',\n argsType: '{ value: string }',\n descriptionKey: 'ui.agent.phoneInput.actions.setValue',\n description:\n 'Replace the phone number (E.164 or national format; parser will infer country).',\n invoke: (handle, args: { value: string }) => {\n handle.setValue(args.value);\n },\n },\n clear: {\n safety: 'destructive',\n descriptionKey: 'ui.agent.phoneInput.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.phoneInput.actions.focus',\n description: 'Move keyboard focus to the phone-number input.',\n invoke: (handle) => {\n handle.focus();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'phone-input',\n description: 'Marks the PhoneInput 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 useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n} from 'react';\nimport { useAgentRegistration } from '../../agent';\nimport { phoneInputAgent } from './phone-input.agent';\n\n/** Agent-readiness curated handle for PhoneInput. */\nexport interface PhoneInputHandle {\n getValue: () => string;\n setValue: (value: string) => void;\n clear: () => void;\n focus: () => void;\n}\nimport * as Popover from '@radix-ui/react-popover';\nimport { Command, defaultFilter } from 'cmdk';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { ChevronDown } from 'lucide-react';\nimport {\n AsYouType,\n getCountries,\n getCountryCallingCode,\n parsePhoneNumberFromString,\n type CountryCode,\n} from 'libphonenumber-js/min';\nimport {\n FormFieldContext,\n useFormField,\n} from '../form-field/form-field-context';\nimport { composeRefs } from '../_shared/compose-refs';\nimport { normalizeDiacritics } from '../_shared/normalize-diacritics';\nimport { Flag } from '../flag';\n\nexport interface PhoneInputChangeMeta {\n country: CountryCode;\n isValid: boolean;\n isPossible: boolean;\n type?: string;\n}\n\nexport interface PhoneInputProps {\n value?: string;\n defaultValue?: string;\n /**\n * Country pre-selected when no value is supplied. Defaults to `IT`\n * (AlfaDocs's dominant user base is Italian). Pass a different\n * `CountryCode` to override, or enable `detectBrowserCountry` to\n * derive it from the browser locale.\n */\n defaultCountry?: CountryCode;\n /**\n * When true, infer the default country from `navigator.language` /\n * `Intl.Locale` before falling back to `defaultCountry` (or `IT`).\n * Off by default — most AlfaDocs flows should stay on IT regardless\n * of the visitor's browser locale.\n */\n detectBrowserCountry?: boolean;\n onChange?: (e164: string, meta: PhoneInputChangeMeta) => void;\n size?: 'sm' | 'md' | 'lg';\n tone?: 'default' | 'error';\n disabled?: boolean;\n readOnly?: boolean;\n placeholder?: string;\n popularCountries?: CountryCode[];\n className?: string;\n id?: string;\n name?: string;\n required?: boolean;\n 'aria-label'?: string;\n}\n\nconst phoneInputWrapperVariants = cva(\n [\n 'ds:group ds:relative ds:inline-flex ds:items-stretch ds:w-full',\n 'ds:rounded-[var(--radius-sm)] ds:border ds:border-border ds:bg-background',\n 'ds:text-foreground',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:focus-within:outline-[length:var(--focus-ring-width)] ds:focus-within:outline-solid',\n 'ds:focus-within:outline-ring ds:focus-within:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-within:outline-[CanvasText]',\n 'ds:has-[:disabled]:cursor-not-allowed ds:has-[:disabled]:opacity-50',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:h-8 ds:text-[length:var(--font-size-sm)]',\n md: 'ds:h-[var(--min-target-size)] ds:text-[length:var(--font-size-base)]',\n lg: 'ds:h-12 ds:text-[length:var(--font-size-lg)]',\n },\n tone: {\n default: '',\n error: 'ds:border-destructive ds:focus-within:outline-destructive',\n },\n },\n defaultVariants: {\n size: 'md',\n tone: 'default',\n },\n },\n);\n\nconst countryTriggerVariants = cva(\n [\n 'ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]',\n 'ds:bg-transparent ds:text-foreground',\n 'ds:border-0 ds:border-e ds:border-e-border',\n 'ds:rounded-s-[var(--radius-sm)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:hover:bg-muted',\n 'ds:focus:outline-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',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:ps-3 ds:pe-2',\n md: 'ds:ps-3 ds:pe-2',\n lg: 'ds:ps-4 ds:pe-3',\n },\n },\n defaultVariants: { size: 'md' },\n },\n);\n\nconst phoneNumberInputVariants = cva(\n [\n 'ds:flex-1 ds:min-w-0 ds:bg-transparent ds:text-foreground ds:placeholder:text-muted-foreground',\n 'ds:border-0 ds:outline-none',\n 'ds:disabled:cursor-not-allowed',\n 'ds:read-only:cursor-default',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:ps-2 ds:pe-3 ds:text-[length:var(--font-size-sm)]',\n md: 'ds:ps-2 ds:pe-3 ds:text-[length:var(--font-size-base)]',\n lg: 'ds:ps-3 ds:pe-4 ds:text-[length:var(--font-size-lg)]',\n },\n },\n defaultVariants: { size: 'md' },\n },\n);\n\nconst pickerContentClasses = [\n 'ds:z-[var(--z-popover)] ds:overflow-hidden ds:w-72',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-border ds:bg-background ds:text-foreground',\n 'ds:shadow-[var(--shadow-lg)]',\n 'ds:animate-in ds:fade-in ds:zoom-in-95',\n 'ds:data-[state=closed]:animate-out ds:data-[state=closed]:fade-out',\n 'ds:data-[state=closed]:zoom-out-95',\n 'ds:data-[side=bottom]:slide-in-from-top-2',\n 'ds:data-[side=top]:slide-in-from-bottom-2',\n 'ds:motion-reduce:animate-none',\n].join(' ');\n\nconst pickerSearchClasses = [\n 'ds:w-full ds:bg-transparent ds:text-foreground ds:placeholder:text-muted-foreground',\n 'ds:border-0 ds:border-b ds:border-b-border ds:outline-none',\n 'ds:ps-3 ds:pe-3 ds:py-2 ds:text-[var(--font-size-sm)]',\n 'ds:focus:outline-none',\n].join(' ');\n\nconst pickerListClasses =\n 'ds:max-h-72 ds:overflow-y-auto ds:p-[var(--spacing-xs)]';\n\nconst pickerItemClasses = [\n 'ds:relative ds:flex ds:cursor-pointer ds:items-center ds:gap-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-sm)] ds:ps-3 ds:pe-3 ds:py-2 ds:text-[var(--font-size-sm)]',\n 'ds:text-foreground ds:outline-none ds:select-none',\n 'ds:data-[highlighted]:bg-muted ds:data-[highlighted]:text-foreground',\n 'ds:data-[highlighted]:border-s-2 ds:data-[highlighted]:border-s-primary',\n 'ds:aria-selected:bg-muted',\n].join(' ');\n\nconst pickerGroupHeadingClasses = [\n 'ds:ps-3 ds:pe-3 ds:py-1.5',\n 'type-eyebrow ds:text-muted-foreground',\n].join(' ');\n\nconst pickerEmptyClasses =\n 'ds:ps-3 ds:pe-3 ds:py-2 type-body-sm ds:text-muted-foreground';\n\nconst chevronSizeBySize = {\n sm: 'ds:size-3.5',\n md: 'ds:size-4',\n lg: 'ds:size-5',\n} as const;\n\nconst flagSizeBySize = {\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n} as const satisfies Record<'sm' | 'md' | 'lg', 'sm' | 'md' | 'lg'>;\n\nfunction countDigitsBefore(str: string, position: number): number {\n let digits = 0;\n for (let i = 0; i < position && i < str.length; i++) {\n if (str[i] >= '0' && str[i] <= '9') digits++;\n }\n return digits;\n}\n\nfunction positionAfterDigits(str: string, targetDigits: number): number {\n if (targetDigits === 0) return 0;\n let count = 0;\n for (let i = 0; i < str.length; i++) {\n if (str[i] >= '0' && str[i] <= '9') {\n count++;\n if (count === targetDigits) return i + 1;\n }\n }\n return str.length;\n}\n\nfunction resolveDefaultCountry(\n explicit: CountryCode | undefined,\n supported: Set<string>,\n detectBrowser: boolean,\n locale: string,\n): CountryCode {\n if (explicit && supported.has(explicit)) return explicit;\n\n if (detectBrowser) {\n const fromNavigator =\n typeof navigator !== 'undefined' ? navigator.language : undefined;\n if (fromNavigator) {\n const match = fromNavigator.match(/-([A-Za-z]{2})/);\n if (match) {\n const candidate = match[1].toUpperCase();\n if (supported.has(candidate)) return candidate as CountryCode;\n }\n }\n\n try {\n const region = new Intl.Locale(locale).region;\n if (region && supported.has(region.toUpperCase())) {\n return region.toUpperCase() as CountryCode;\n }\n } catch {\n // Intl.Locale may throw on malformed BCP-47 — fall through.\n }\n }\n\n return 'IT';\n}\n\ninterface CountryRow {\n code: CountryCode;\n name: string;\n dialCode: string;\n}\n\nfunction buildCountryRows(\n locale: string,\n countries: CountryCode[],\n): CountryRow[] {\n let displayNames: Intl.DisplayNames;\n try {\n displayNames = new Intl.DisplayNames([locale], { type: 'region' });\n } catch {\n displayNames = new Intl.DisplayNames(['en'], { type: 'region' });\n }\n const rows = countries.map<CountryRow>((code) => ({\n code,\n name: displayNames.of(code) ?? code,\n dialCode: getCountryCallingCode(code),\n }));\n const collator = new Intl.Collator(locale);\n return rows.sort((a, b) => collator.compare(a.name, b.name));\n}\n\nexport const PhoneInput = forwardRef<HTMLInputElement, PhoneInputProps>(\n function PhoneInput(\n {\n value,\n defaultValue,\n defaultCountry,\n detectBrowserCountry = false,\n onChange,\n size = 'md',\n tone = 'default',\n disabled,\n readOnly,\n placeholder,\n popularCountries,\n className,\n id,\n name,\n required,\n 'aria-label': ariaLabel,\n },\n ref,\n ) {\n const { t, i18n } = useTranslation();\n const ctx = useFormField();\n const inFormField = useContext(FormFieldContext) !== null;\n\n const supportedCountries = useMemo(\n () => new Set(getCountries() as string[]),\n [],\n );\n\n const initialState = useMemo(() => {\n const resolvedCountry = resolveDefaultCountry(\n defaultCountry,\n supportedCountries,\n detectBrowserCountry,\n i18n.language,\n );\n const raw = value ?? defaultValue;\n if (raw) {\n const parsed = parsePhoneNumberFromString(raw);\n if (parsed?.country) {\n return {\n country: parsed.country,\n display: parsed.formatNational(),\n };\n }\n return { country: resolvedCountry, display: raw };\n }\n return { country: resolvedCountry, display: '' };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const [country, setCountry] = useState<CountryCode>(initialState.country);\n const [displayValue, setDisplayValue] = useState<string>(\n initialState.display,\n );\n const [pickerOpen, setPickerOpen] = useState(false);\n const [pickerSearch, setPickerSearch] = useState('');\n\n const isControlled = value !== undefined;\n const lastEmittedRef = useRef<string>('');\n const pendingCaretRef = useRef<number | null>(null);\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n const composedInputRef = composeRefs(ref, inputRef);\n\n // Sync state back from a controlled `value` prop change that did not\n // originate from this component (e.g. parent reset). Skip the sync when\n // the incoming value matches what we just emitted.\n useEffect(() => {\n if (!isControlled) return;\n const current = value ?? '';\n if (current === lastEmittedRef.current) return;\n if (current === '') {\n setDisplayValue('');\n return;\n }\n const parsed = parsePhoneNumberFromString(current);\n if (parsed?.country) {\n setCountry(parsed.country);\n setDisplayValue(parsed.formatNational());\n } else {\n setDisplayValue(current);\n }\n }, [value, isControlled]);\n\n useLayoutEffect(() => {\n if (pendingCaretRef.current == null) return;\n const pos = pendingCaretRef.current;\n pendingCaretRef.current = null;\n const node = inputRef.current;\n if (node && document.activeElement === node) {\n node.setSelectionRange(pos, pos);\n }\n });\n\n const emit = useCallback(\n (nextDisplay: string, nextCountry: CountryCode) => {\n const parsed = parsePhoneNumberFromString(nextDisplay, nextCountry);\n const e164 = parsed?.number ?? '';\n lastEmittedRef.current = e164;\n onChange?.(e164, {\n country: nextCountry,\n isValid: parsed?.isValid() ?? false,\n isPossible: parsed?.isPossible() ?? false,\n type: parsed?.getType(),\n });\n },\n [onChange],\n );\n\n const inputId = id ?? (inFormField ? ctx.id : undefined);\n const effectiveDisabled =\n (inFormField ? ctx.disabled : false) || Boolean(disabled);\n const effectiveRequired =\n (inFormField ? ctx.required : false) || Boolean(required);\n const effectiveInvalid = inFormField ? ctx.invalid : false;\n const effectiveTone = effectiveInvalid ? 'error' : tone;\n const describedBy =\n inFormField && ctx.describedBy ? ctx.describedBy : undefined;\n\n const resolvedPlaceholder =\n placeholder ?? t('inputs.phone.placeholder', 'Phone number');\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (readOnly) return;\n const target = event.target;\n const raw = target.value;\n const caret = target.selectionStart ?? raw.length;\n const digitsBefore = countDigitsBefore(raw, caret);\n\n const formatter = new AsYouType(country);\n const formatted = formatter.input(raw);\n\n pendingCaretRef.current = positionAfterDigits(formatted, digitsBefore);\n setDisplayValue(formatted);\n emit(formatted, country);\n };\n\n const lastEmittedRefForHandle = lastEmittedRef;\n const agentHandle = useMemo<PhoneInputHandle>(\n () => ({\n getValue: () => lastEmittedRefForHandle.current,\n setValue: (next) => {\n if (next === '') {\n setDisplayValue('');\n emit('', country);\n return;\n }\n const parsed = parsePhoneNumberFromString(next);\n if (parsed?.country) {\n setCountry(parsed.country);\n setDisplayValue(parsed.formatNational());\n emit(parsed.formatNational(), parsed.country);\n } else {\n const formatter = new AsYouType(country);\n const formatted = formatter.input(next);\n setDisplayValue(formatted);\n emit(formatted, country);\n }\n },\n clear: () => {\n setDisplayValue('');\n emit('', country);\n },\n focus: () => inputRef.current?.focus(),\n }),\n [country, emit, lastEmittedRefForHandle],\n );\n useAgentRegistration(phoneInputAgent, agentHandle, id);\n\n const handleCountrySelect = (nextCountry: CountryCode) => {\n if (nextCountry === country) {\n setPickerOpen(false);\n return;\n }\n const digits = displayValue.replace(/\\D/g, '');\n const formatter = new AsYouType(nextCountry);\n const reformatted = digits ? formatter.input(digits) : '';\n setCountry(nextCountry);\n setDisplayValue(reformatted);\n setPickerOpen(false);\n setPickerSearch('');\n emit(reformatted, nextCountry);\n requestAnimationFrame(() => {\n inputRef.current?.focus();\n });\n };\n\n const countryRows = useMemo(\n () =>\n buildCountryRows(\n i18n.language,\n Array.from(supportedCountries) as CountryCode[],\n ),\n [i18n.language, supportedCountries],\n );\n\n const popularRows = useMemo(() => {\n if (!popularCountries || popularCountries.length === 0) return [];\n const byCode = new Map(countryRows.map((row) => [row.code, row]));\n return popularCountries\n .filter((code): code is CountryCode => supportedCountries.has(code))\n .map((code) => byCode.get(code))\n .filter((row): row is CountryRow => Boolean(row));\n }, [popularCountries, countryRows, supportedCountries]);\n\n const popularCodes = useMemo(\n () => new Set(popularRows.map((row) => row.code)),\n [popularRows],\n );\n\n const remainingRows = useMemo(\n () =>\n popularCodes.size > 0\n ? countryRows.filter((row) => !popularCodes.has(row.code))\n : countryRows,\n [countryRows, popularCodes],\n );\n\n const selected = useMemo(\n () => countryRows.find((row) => row.code === country),\n [countryRows, country],\n );\n const selectedDialCode = selected ? selected.dialCode : '';\n const selectedName = selected ? selected.name : country;\n\n const triggerLabel = t('inputs.phone.countryPickerLabel', 'Country');\n const triggerAccessibleName = `${triggerLabel}: ${selectedName}, +${selectedDialCode}`;\n\n const filterFn = useCallback(\n (candidate: string, searchStr: string, keywords?: string[]) => {\n const normalizedCandidate = normalizeDiacritics(candidate);\n const normalizedSearch = normalizeDiacritics(searchStr);\n const normalizedKeywords = keywords?.map(normalizeDiacritics);\n return defaultFilter(\n normalizedCandidate,\n normalizedSearch,\n normalizedKeywords,\n );\n },\n [],\n );\n\n const renderRow = (row: CountryRow) => {\n const accessibleLabel = `${row.name}, +${row.dialCode}`;\n return (\n <Command.Item\n key={row.code}\n value={row.code}\n keywords={[row.name, row.dialCode, `+${row.dialCode}`]}\n onSelect={() => handleCountrySelect(row.code)}\n className={pickerItemClasses}\n aria-label={accessibleLabel}\n >\n <Flag country={row.code} size={flagSizeBySize[size]} />\n <span className=\"ds:flex-1 ds:truncate\">{row.name}</span>\n <bdi dir=\"ltr\" className=\"ds:text-muted-foreground ds:tabular-nums\">\n +{row.dialCode}\n </bdi>\n </Command.Item>\n );\n };\n\n return (\n <div\n data-component=\"phone-input\"\n data-component-id={id}\n data-slot=\"phone-input\"\n className={phoneInputWrapperVariants({\n size,\n tone: effectiveTone,\n className,\n })}\n >\n <Popover.Root open={pickerOpen} onOpenChange={setPickerOpen}>\n <Popover.Trigger asChild>\n <button\n type=\"button\"\n disabled={effectiveDisabled}\n aria-haspopup=\"listbox\"\n aria-expanded={pickerOpen}\n aria-label={triggerAccessibleName}\n className={countryTriggerVariants({ size })}\n >\n <Flag country={country} size={flagSizeBySize[size]} />\n <bdi dir=\"ltr\" className=\"ds:tabular-nums\">\n +{selectedDialCode}\n </bdi>\n <ChevronDown\n aria-hidden=\"true\"\n className={[\n chevronSizeBySize[size],\n 'ds:shrink-0 ds:text-muted-foreground',\n 'ds:transition-transform ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n pickerOpen ? 'ds:rotate-180' : '',\n ].join(' ')}\n />\n </button>\n </Popover.Trigger>\n <Popover.Portal>\n <Popover.Content\n sideOffset={6}\n align=\"start\"\n className={pickerContentClasses}\n >\n <Command filter={filterFn} shouldFilter loop label={triggerLabel}>\n <Command.Input\n asChild\n value={pickerSearch}\n onValueChange={setPickerSearch}\n >\n <input\n data-phone-country-search=\"true\"\n type=\"text\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n placeholder={t(\n 'inputs.phone.searchCountry',\n 'Search countries…',\n )}\n className={pickerSearchClasses}\n />\n </Command.Input>\n <Command.List className={pickerListClasses}>\n <Command.Empty className={pickerEmptyClasses}>\n {t('inputs.phone.noCountryFound', 'No country found')}\n </Command.Empty>\n {popularRows.length > 0 ? (\n <Command.Group\n heading={\n <span className={pickerGroupHeadingClasses}>\n {t('inputs.phone.popularCountries', 'Popular')}\n </span>\n }\n >\n {popularRows.map(renderRow)}\n </Command.Group>\n ) : null}\n <Command.Group\n heading={\n popularRows.length > 0 ? (\n <span className={pickerGroupHeadingClasses}>\n {t('inputs.phone.allCountries', 'All countries')}\n </span>\n ) : undefined\n }\n >\n {remainingRows.map(renderRow)}\n </Command.Group>\n </Command.List>\n </Command>\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n <input\n ref={composedInputRef}\n id={inputId}\n name={name}\n type=\"tel\"\n inputMode=\"tel\"\n autoComplete=\"tel-national\"\n value={displayValue}\n placeholder={resolvedPlaceholder}\n disabled={effectiveDisabled}\n readOnly={readOnly}\n required={effectiveRequired}\n aria-label={ariaLabel}\n aria-describedby={describedBy}\n aria-invalid={effectiveInvalid || undefined}\n onChange={handleInputChange}\n className={phoneNumberInputVariants({ size })}\n />\n </div>\n );\n },\n);\n\nPhoneInput.displayName = 'PhoneInput';\n\nexport {\n phoneInputWrapperVariants,\n countryTriggerVariants,\n phoneNumberInputVariants,\n};\n"],"names":["phoneInputAgent","handle","args","phoneInputWrapperVariants","cva","countryTriggerVariants","phoneNumberInputVariants","pickerContentClasses","pickerSearchClasses","pickerListClasses","pickerItemClasses","pickerGroupHeadingClasses","pickerEmptyClasses","chevronSizeBySize","flagSizeBySize","countDigitsBefore","str","position","digits","i","positionAfterDigits","targetDigits","count","resolveDefaultCountry","explicit","supported","detectBrowser","locale","fromNavigator","match","candidate","region","buildCountryRows","countries","displayNames","rows","code","getCountryCallingCode","collator","a","b","PhoneInput","forwardRef","value","defaultValue","defaultCountry","detectBrowserCountry","onChange","size","tone","disabled","readOnly","placeholder","popularCountries","className","id","name","required","ariaLabel","ref","t","i18n","useTranslation","ctx","useFormField","inFormField","useContext","FormFieldContext","supportedCountries","useMemo","getCountries","initialState","resolvedCountry","raw","parsed","parsePhoneNumberFromString","country","setCountry","useState","displayValue","setDisplayValue","pickerOpen","setPickerOpen","pickerSearch","setPickerSearch","isControlled","lastEmittedRef","useRef","pendingCaretRef","inputRef","composedInputRef","composeRefs","useEffect","current","useLayoutEffect","pos","node","emit","useCallback","nextDisplay","nextCountry","e164","inputId","effectiveDisabled","effectiveRequired","effectiveInvalid","effectiveTone","describedBy","resolvedPlaceholder","handleInputChange","event","target","caret","digitsBefore","formatted","AsYouType","lastEmittedRefForHandle","agentHandle","next","_a","useAgentRegistration","handleCountrySelect","formatter","reformatted","countryRows","popularRows","byCode","row","popularCodes","remainingRows","selected","selectedDialCode","selectedName","triggerLabel","triggerAccessibleName","filterFn","searchStr","keywords","normalizedCandidate","normalizeDiacritics","normalizedSearch","normalizedKeywords","defaultFilter","renderRow","accessibleLabel","jsxs","Command","jsx","Flag","Popover","ChevronDown"],"mappings":";;;;;;;;;;;;;AASO,MAAMA,KAAkD;AAAA,EAC7D,IAAI;AAAA,EACJ,cAAc,CAAC,aAAa;AAAA,EAC5B,OAAO;AAAA,IACL,OAAO;AAAA,MACL,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACC,MAAWA,EAAO,SAAA;AAAA,IAAS;AAAA,IAEpC,SAAS;AAAA,MACP,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACA,MAAWA,EAAO,eAAe;AAAA,IAAA;AAAA,EAC1C;AAAA,EAEF,SAAS;AAAA,IACP,WAAW;AAAA,MACT,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,QAAQ,CAACA,GAAQC,MAA4B;AAC3C,QAAAD,EAAO,SAASC,EAAK,KAAK;AAAA,MAC5B;AAAA,IAAA;AAAA,IAEF,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACD,MAAW;AAClB,QAAAA,EAAO,MAAA;AAAA,MACT;AAAA,IAAA;AAAA,IAEF,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACA,MAAW;AAClB,QAAAA,EAAO,MAAA;AAAA,MACT;AAAA,IAAA;AAAA,EACF;AAAA,EAEF,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IAAA;AAAA,IAEf,YAAY;AAAA,MACV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,aAAa;AAAA,IAAA;AAAA,EACf;AAEJ,GCYME,KAA4BC;AAAA,EAChC;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MAAA;AAAA,MAEN,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,IAEF,iBAAiB;AAAA,MACf,MAAM;AAAA,MACN,MAAM;AAAA,IAAA;AAAA,EACR;AAEJ,GAEMC,KAAyBD;AAAA,EAC7B;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MAAA;AAAA,IACN;AAAA,IAEF,iBAAiB,EAAE,MAAM,KAAA;AAAA,EAAK;AAElC,GAEME,KAA2BF;AAAA,EAC/B;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MAAA;AAAA,IACN;AAAA,IAEF,iBAAiB,EAAE,MAAM,KAAA;AAAA,EAAK;AAElC,GAEMG,KAAuB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAEJC,KAAsB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAEJC,KACJ,2DAEIC,KAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAEJC,KAA4B;AAAA,EAChC;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAEJC,KACJ,iEAEIC,KAAoB;AAAA,EACxB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN,GAEMC,KAAiB;AAAA,EACrB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEA,SAASC,GAAkBC,GAAaC,GAA0B;AAChE,MAAIC,IAAS;AACb,WAASC,IAAI,GAAGA,IAAIF,KAAYE,IAAIH,EAAI,QAAQG;AAC9C,IAAIH,EAAIG,CAAC,KAAK,OAAOH,EAAIG,CAAC,KAAK,OAAKD;AAEtC,SAAOA;AACT;AAEA,SAASE,GAAoBJ,GAAaK,GAA8B;AACtE,MAAIA,MAAiB,EAAG,QAAO;AAC/B,MAAIC,IAAQ;AACZ,WAASH,IAAI,GAAGA,IAAIH,EAAI,QAAQG;AAC9B,QAAIH,EAAIG,CAAC,KAAK,OAAOH,EAAIG,CAAC,KAAK,QAC7BG,KACIA,MAAUD;AAAc,aAAOF,IAAI;AAG3C,SAAOH,EAAI;AACb;AAEA,SAASO,GACPC,GACAC,GACAC,GACAC,GACa;AACb,MAAIH,KAAYC,EAAU,IAAID,CAAQ,EAAG,QAAOA;AAEhD,MAAIE,GAAe;AACjB,UAAME,IACJ,OAAO,YAAc,MAAc,UAAU,WAAW;AAC1D,QAAIA,GAAe;AACjB,YAAMC,IAAQD,EAAc,MAAM,gBAAgB;AAClD,UAAIC,GAAO;AACT,cAAMC,IAAYD,EAAM,CAAC,EAAE,YAAA;AAC3B,YAAIJ,EAAU,IAAIK,CAAS,EAAG,QAAOA;AAAA,MACvC;AAAA,IACF;AAEA,QAAI;AACF,YAAMC,IAAS,IAAI,KAAK,OAAOJ,CAAM,EAAE;AACvC,UAAII,KAAUN,EAAU,IAAIM,EAAO,YAAA,CAAa;AAC9C,eAAOA,EAAO,YAAA;AAAA,IAElB,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AACT;AAQA,SAASC,GACPL,GACAM,GACc;AACd,MAAIC;AACJ,MAAI;AACF,IAAAA,IAAe,IAAI,KAAK,aAAa,CAACP,CAAM,GAAG,EAAE,MAAM,UAAU;AAAA,EACnE,QAAQ;AACN,IAAAO,IAAe,IAAI,KAAK,aAAa,CAAC,IAAI,GAAG,EAAE,MAAM,UAAU;AAAA,EACjE;AACA,QAAMC,IAAOF,EAAU,IAAgB,CAACG,OAAU;AAAA,IAChD,MAAAA;AAAA,IACA,MAAMF,EAAa,GAAGE,CAAI,KAAKA;AAAA,IAC/B,UAAUC,GAAsBD,CAAI;AAAA,EAAA,EACpC,GACIE,IAAW,IAAI,KAAK,SAASX,CAAM;AACzC,SAAOQ,EAAK,KAAK,CAACI,GAAGC,MAAMF,EAAS,QAAQC,EAAE,MAAMC,EAAE,IAAI,CAAC;AAC7D;AAEO,MAAMC,KAAaC;AAAA,EACxB,SACE;AAAA,IACE,OAAAC;AAAA,IACA,cAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,sBAAAC,IAAuB;AAAA,IACvB,UAAAC;AAAA,IACA,MAAAC,IAAO;AAAA,IACP,MAAAC,KAAO;AAAA,IACP,UAAAC;AAAA,IACA,UAAAC;AAAA,IACA,aAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,WAAAC;AAAA,IACA,IAAAC;AAAA,IACA,MAAAC;AAAA,IACA,UAAAC;AAAA,IACA,cAAcC;AAAA,EAAA,GAEhBC,IACA;AACA,UAAM,EAAE,GAAAC,GAAG,MAAAC,EAAA,IAASC,GAAA,GACdC,IAAMC,GAAA,GACNC,IAAcC,GAAWC,EAAgB,MAAM,MAE/CC,IAAqBC;AAAA,MACzB,MAAM,IAAI,IAAIC,IAA0B;AAAA,MACxC,CAAA;AAAA,IAAC,GAGGC,IAAeF,EAAQ,MAAM;AACjC,YAAMG,IAAkBjD;AAAA,QACtBsB;AAAA,QACAuB;AAAA,QACAtB;AAAA,QACAe,EAAK;AAAA,MAAA,GAEDY,IAAM9B,KAASC;AACrB,UAAI6B,GAAK;AACP,cAAMC,IAASC,EAA2BF,CAAG;AAC7C,eAAIC,KAAA,QAAAA,EAAQ,UACH;AAAA,UACL,SAASA,EAAO;AAAA,UAChB,SAASA,EAAO,eAAA;AAAA,QAAe,IAG5B,EAAE,SAASF,GAAiB,SAASC,EAAA;AAAA,MAC9C;AACA,aAAO,EAAE,SAASD,GAAiB,SAAS,GAAA;AAAA,IAE9C,GAAG,CAAA,CAAE,GAEC,CAACI,GAASC,CAAU,IAAIC,EAAsBP,EAAa,OAAO,GAClE,CAACQ,GAAcC,CAAe,IAAIF;AAAA,MACtCP,EAAa;AAAA,IAAA,GAET,CAACU,GAAYC,CAAa,IAAIJ,EAAS,EAAK,GAC5C,CAACK,IAAcC,CAAe,IAAIN,EAAS,EAAE,GAE7CO,IAAe1C,MAAU,QACzB2C,IAAiBC,EAAe,EAAE,GAClCC,IAAkBD,EAAsB,IAAI,GAE5CE,IAAWF,EAAgC,IAAI,GAC/CG,KAAmBC,GAAYhC,IAAK8B,CAAQ;AAKlD,IAAAG,GAAU,MAAM;AACd,UAAI,CAACP,EAAc;AACnB,YAAMQ,IAAUlD,KAAS;AACzB,UAAIkD,MAAYP,EAAe,QAAS;AACxC,UAAIO,MAAY,IAAI;AAClB,QAAAb,EAAgB,EAAE;AAClB;AAAA,MACF;AACA,YAAMN,IAASC,EAA2BkB,CAAO;AACjD,MAAInB,KAAA,QAAAA,EAAQ,WACVG,EAAWH,EAAO,OAAO,GACzBM,EAAgBN,EAAO,gBAAgB,KAEvCM,EAAgBa,CAAO;AAAA,IAE3B,GAAG,CAAClD,GAAO0C,CAAY,CAAC,GAExBS,GAAgB,MAAM;AACpB,UAAIN,EAAgB,WAAW,KAAM;AACrC,YAAMO,IAAMP,EAAgB;AAC5B,MAAAA,EAAgB,UAAU;AAC1B,YAAMQ,IAAOP,EAAS;AACtB,MAAIO,KAAQ,SAAS,kBAAkBA,KACrCA,EAAK,kBAAkBD,GAAKA,CAAG;AAAA,IAEnC,CAAC;AAED,UAAME,IAAOC;AAAA,MACX,CAACC,GAAqBC,MAA6B;AACjD,cAAM1B,IAASC,EAA2BwB,GAAaC,CAAW,GAC5DC,KAAO3B,KAAA,gBAAAA,EAAQ,WAAU;AAC/B,QAAAY,EAAe,UAAUe,GACzBtD,KAAA,QAAAA,EAAWsD,GAAM;AAAA,UACf,SAASD;AAAA,UACT,UAAS1B,KAAA,gBAAAA,EAAQ,cAAa;AAAA,UAC9B,aAAYA,KAAA,gBAAAA,EAAQ,iBAAgB;AAAA,UACpC,MAAMA,KAAA,gBAAAA,EAAQ;AAAA,QAAQ;AAAA,MAE1B;AAAA,MACA,CAAC3B,CAAQ;AAAA,IAAA,GAGLuD,KAAU/C,MAAOU,IAAcF,EAAI,KAAK,SACxCwC,KACHtC,IAAcF,EAAI,WAAW,OAAU,EAAQb,IAC5CsD,MACHvC,IAAcF,EAAI,WAAW,OAAU,EAAQN,IAC5CgD,IAAmBxC,IAAcF,EAAI,UAAU,IAC/C2C,KAAgBD,IAAmB,UAAUxD,IAC7C0D,KACJ1C,KAAeF,EAAI,cAAcA,EAAI,cAAc,QAE/C6C,KACJxD,MAAeQ,EAAE,4BAA4B,cAAc,GAEvDiD,KAAoB,CAACC,MAAyC;AAClE,UAAI3D,EAAU;AACd,YAAM4D,IAASD,EAAM,QACfrC,IAAMsC,EAAO,OACbC,IAAQD,EAAO,kBAAkBtC,EAAI,QACrCwC,IAAelG,GAAkB0D,GAAKuC,CAAK,GAG3CE,IADY,IAAIC,EAAUvC,CAAO,EACX,MAAMH,CAAG;AAErC,MAAAe,EAAgB,UAAUpE,GAAoB8F,GAAWD,CAAY,GACrEjC,EAAgBkC,CAAS,GACzBjB,EAAKiB,GAAWtC,CAAO;AAAA,IACzB,GAEMwC,IAA0B9B,GAC1B+B,KAAchD;AAAA,MAClB,OAAO;AAAA,QACL,UAAU,MAAM+C,EAAwB;AAAA,QACxC,UAAU,CAACE,MAAS;AAClB,cAAIA,MAAS,IAAI;AACf,YAAAtC,EAAgB,EAAE,GAClBiB,EAAK,IAAIrB,CAAO;AAChB;AAAA,UACF;AACA,gBAAMF,IAASC,EAA2B2C,CAAI;AAC9C,cAAI5C,KAAA,QAAAA,EAAQ;AACV,YAAAG,EAAWH,EAAO,OAAO,GACzBM,EAAgBN,EAAO,gBAAgB,GACvCuB,EAAKvB,EAAO,kBAAkBA,EAAO,OAAO;AAAA,eACvC;AAEL,kBAAMwC,IADY,IAAIC,EAAUvC,CAAO,EACX,MAAM0C,CAAI;AACtC,YAAAtC,EAAgBkC,CAAS,GACzBjB,EAAKiB,GAAWtC,CAAO;AAAA,UACzB;AAAA,QACF;AAAA,QACA,OAAO,MAAM;AACX,UAAAI,EAAgB,EAAE,GAClBiB,EAAK,IAAIrB,CAAO;AAAA,QAClB;AAAA,QACA,OAAO,MAAA;;AAAM,kBAAA2C,IAAA9B,EAAS,YAAT,gBAAA8B,EAAkB;AAAA;AAAA,MAAM;AAAA,MAEvC,CAAC3C,GAASqB,GAAMmB,CAAuB;AAAA,IAAA;AAEzC,IAAAI,GAAqBxH,IAAiBqH,IAAa9D,CAAE;AAErD,UAAMkE,KAAsB,CAACrB,MAA6B;AACxD,UAAIA,MAAgBxB,GAAS;AAC3B,QAAAM,EAAc,EAAK;AACnB;AAAA,MACF;AACA,YAAMhE,IAAS6D,EAAa,QAAQ,OAAO,EAAE,GACvC2C,IAAY,IAAIP,EAAUf,CAAW,GACrCuB,IAAczG,IAASwG,EAAU,MAAMxG,CAAM,IAAI;AACvD,MAAA2D,EAAWuB,CAAW,GACtBpB,EAAgB2C,CAAW,GAC3BzC,EAAc,EAAK,GACnBE,EAAgB,EAAE,GAClBa,EAAK0B,GAAavB,CAAW,GAC7B,sBAAsB,MAAM;;AAC1B,SAAAmB,IAAA9B,EAAS,YAAT,QAAA8B,EAAkB;AAAA,MACpB,CAAC;AAAA,IACH,GAEMK,IAAcvD;AAAA,MAClB,MACErC;AAAA,QACE6B,EAAK;AAAA,QACL,MAAM,KAAKO,CAAkB;AAAA,MAAA;AAAA,MAEjC,CAACP,EAAK,UAAUO,CAAkB;AAAA,IAAA,GAG9ByD,IAAcxD,EAAQ,MAAM;AAChC,UAAI,CAAChB,KAAoBA,EAAiB,WAAW,UAAU,CAAA;AAC/D,YAAMyE,IAAS,IAAI,IAAIF,EAAY,IAAI,CAACG,MAAQ,CAACA,EAAI,MAAMA,CAAG,CAAC,CAAC;AAChE,aAAO1E,EACJ,OAAO,CAACjB,MAA8BgC,EAAmB,IAAIhC,CAAI,CAAC,EAClE,IAAI,CAACA,MAAS0F,EAAO,IAAI1F,CAAI,CAAC,EAC9B,OAAO,CAAC2F,MAA2B,EAAQA,CAAI;AAAA,IACpD,GAAG,CAAC1E,GAAkBuE,GAAaxD,CAAkB,CAAC,GAEhD4D,IAAe3D;AAAA,MACnB,MAAM,IAAI,IAAIwD,EAAY,IAAI,CAACE,MAAQA,EAAI,IAAI,CAAC;AAAA,MAChD,CAACF,CAAW;AAAA,IAAA,GAGRI,KAAgB5D;AAAA,MACpB,MACE2D,EAAa,OAAO,IAChBJ,EAAY,OAAO,CAACG,MAAQ,CAACC,EAAa,IAAID,EAAI,IAAI,CAAC,IACvDH;AAAA,MACN,CAACA,GAAaI,CAAY;AAAA,IAAA,GAGtBE,IAAW7D;AAAA,MACf,MAAMuD,EAAY,KAAK,CAACG,MAAQA,EAAI,SAASnD,CAAO;AAAA,MACpD,CAACgD,GAAahD,CAAO;AAAA,IAAA,GAEjBuD,IAAmBD,IAAWA,EAAS,WAAW,IAClDE,KAAeF,IAAWA,EAAS,OAAOtD,GAE1CyD,IAAezE,EAAE,mCAAmC,SAAS,GAC7D0E,KAAwB,GAAGD,CAAY,KAAKD,EAAY,MAAMD,CAAgB,IAE9EI,KAAWrC;AAAA,MACf,CAACpE,GAAmB0G,GAAmBC,MAAwB;AAC7D,cAAMC,IAAsBC,EAAoB7G,CAAS,GACnD8G,IAAmBD,EAAoBH,CAAS,GAChDK,KAAqBJ,KAAA,gBAAAA,EAAU,IAAIE;AACzC,eAAOG;AAAAA,UACLJ;AAAA,UACAE;AAAA,UACAC;AAAA,QAAA;AAAA,MAEJ;AAAA,MACA,CAAA;AAAA,IAAC,GAGGE,KAAY,CAAChB,MAAoB;AACrC,YAAMiB,IAAkB,GAAGjB,EAAI,IAAI,MAAMA,EAAI,QAAQ;AACrD,aACE,gBAAAkB;AAAA,QAACC,EAAQ;AAAA,QAAR;AAAA,UAEC,OAAOnB,EAAI;AAAA,UACX,UAAU,CAACA,EAAI,MAAMA,EAAI,UAAU,IAAIA,EAAI,QAAQ,EAAE;AAAA,UACrD,UAAU,MAAMN,GAAoBM,EAAI,IAAI;AAAA,UAC5C,WAAWrH;AAAA,UACX,cAAYsI;AAAA,UAEZ,UAAA;AAAA,YAAA,gBAAAG,EAACC,MAAK,SAASrB,EAAI,MAAM,MAAMjH,GAAekC,CAAI,GAAG;AAAA,YACrD,gBAAAmG,EAAC,QAAA,EAAK,WAAU,yBAAyB,YAAI,MAAK;AAAA,YAClD,gBAAAF,EAAC,OAAA,EAAI,KAAI,OAAM,WAAU,4CAA2C,UAAA;AAAA,cAAA;AAAA,cAChElB,EAAI;AAAA,YAAA,EAAA,CACR;AAAA,UAAA;AAAA,QAAA;AAAA,QAXKA,EAAI;AAAA,MAAA;AAAA,IAcf;AAEA,WACE,gBAAAkB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,kBAAe;AAAA,QACf,qBAAmB1F;AAAA,QACnB,aAAU;AAAA,QACV,WAAWpD,GAA0B;AAAA,UACnC,MAAA6C;AAAA,UACA,MAAM0D;AAAA,UACN,WAAApD;AAAA,QAAA,CACD;AAAA,QAED,UAAA;AAAA,UAAA,gBAAA2F,EAACI,EAAQ,MAAR,EAAa,MAAMpE,GAAY,cAAcC,GAC5C,UAAA;AAAA,YAAA,gBAAAiE,EAACE,EAAQ,SAAR,EAAgB,SAAO,IACtB,UAAA,gBAAAJ;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,UAAU1C;AAAA,gBACV,iBAAc;AAAA,gBACd,iBAAetB;AAAA,gBACf,cAAYqD;AAAA,gBACZ,WAAWjI,GAAuB,EAAE,MAAA2C,GAAM;AAAA,gBAE1C,UAAA;AAAA,kBAAA,gBAAAmG,EAACC,IAAA,EAAK,SAAAxE,GAAkB,MAAM9D,GAAekC,CAAI,GAAG;AAAA,kBACpD,gBAAAiG,EAAC,OAAA,EAAI,KAAI,OAAM,WAAU,mBAAkB,UAAA;AAAA,oBAAA;AAAA,oBACvCd;AAAA,kBAAA,GACJ;AAAA,kBACA,gBAAAgB;AAAA,oBAACG;AAAA,oBAAA;AAAA,sBACC,eAAY;AAAA,sBACZ,WAAW;AAAA,wBACTzI,GAAkBmC,CAAI;AAAA,wBACtB;AAAA,wBACA;AAAA,wBACAiC,IAAa,kBAAkB;AAAA,sBAAA,EAC/B,KAAK,GAAG;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBACZ;AAAA,cAAA;AAAA,YAAA,GAEJ;AAAA,YACA,gBAAAkE,EAACE,EAAQ,QAAR,EACC,UAAA,gBAAAF;AAAA,cAACE,EAAQ;AAAA,cAAR;AAAA,gBACC,YAAY;AAAA,gBACZ,OAAM;AAAA,gBACN,WAAW9I;AAAA,gBAEX,UAAA,gBAAA0I,EAACC,KAAQ,QAAQX,IAAU,cAAY,IAAC,MAAI,IAAC,OAAOF,GAClD,UAAA;AAAA,kBAAA,gBAAAc;AAAA,oBAACD,EAAQ;AAAA,oBAAR;AAAA,sBACC,SAAO;AAAA,sBACP,OAAO/D;AAAA,sBACP,eAAeC;AAAA,sBAEf,UAAA,gBAAA+D;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,6BAA0B;AAAA,0BAC1B,MAAK;AAAA,0BACL,cAAa;AAAA,0BACb,aAAY;AAAA,0BACZ,YAAY;AAAA,0BACZ,aAAavF;AAAA,4BACX;AAAA,4BACA;AAAA,0BAAA;AAAA,0BAEF,WAAWpD;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBACb;AAAA,kBAAA;AAAA,kBAEF,gBAAAyI,EAACC,EAAQ,MAAR,EAAa,WAAWzI,IACvB,UAAA;AAAA,oBAAA,gBAAA0I,EAACD,EAAQ,OAAR,EAAc,WAAWtI,IACvB,UAAAgD,EAAE,+BAA+B,kBAAkB,GACtD;AAAA,oBACCiE,EAAY,SAAS,IACpB,gBAAAsB;AAAA,sBAACD,EAAQ;AAAA,sBAAR;AAAA,wBACC,2BACG,QAAA,EAAK,WAAWvI,IACd,UAAAiD,EAAE,iCAAiC,SAAS,GAC/C;AAAA,wBAGD,UAAAiE,EAAY,IAAIkB,EAAS;AAAA,sBAAA;AAAA,oBAAA,IAE1B;AAAA,oBACJ,gBAAAI;AAAA,sBAACD,EAAQ;AAAA,sBAAR;AAAA,wBACC,SACErB,EAAY,SAAS,IACnB,gBAAAsB,EAAC,QAAA,EAAK,WAAWxI,IACd,UAAAiD,EAAE,6BAA6B,eAAe,EAAA,CACjD,IACE;AAAA,wBAGL,UAAAqE,GAAc,IAAIc,EAAS;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAC9B,EAAA,CACF;AAAA,gBAAA,EAAA,CACF;AAAA,cAAA;AAAA,YAAA,EACF,CACF;AAAA,UAAA,GACF;AAAA,UACA,gBAAAI;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,KAAKzD;AAAA,cACL,IAAIY;AAAA,cACJ,MAAA9C;AAAA,cACA,MAAK;AAAA,cACL,WAAU;AAAA,cACV,cAAa;AAAA,cACb,OAAOuB;AAAA,cACP,aAAa6B;AAAA,cACb,UAAUL;AAAA,cACV,UAAApD;AAAA,cACA,UAAUqD;AAAA,cACV,cAAY9C;AAAA,cACZ,oBAAkBiD;AAAA,cAClB,gBAAcF,KAAoB;AAAA,cAClC,UAAUI;AAAA,cACV,WAAWvG,GAAyB,EAAE,MAAA0C,EAAA,CAAM;AAAA,YAAA;AAAA,UAAA;AAAA,QAC9C;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEAP,GAAW,cAAc;"}
|