@openzeppelin/ui-components 3.3.1 → 3.5.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/README.md +4 -0
- package/dist/index.cjs +1046 -192
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +438 -15
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +444 -21
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1029 -196
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["React","AccordionPrimitive","ChevronDown","TooltipPrimitive","React","React","Check","Copy","ExternalLink","Pencil","React","React","React","React","X","React","Slot","DayPicker","ChevronLeft","ChevronRight","CheckboxPrimitive","CheckIcon","PopoverPrimitive","React","CalendarIcon","DialogPrimitive","React","DropdownMenuPrimitive","React","ChevronRight","Check","Circle","React","ChevronDown","Check","FileText","React","ExternalLinkIcon","React","LabelPrimitive","FormProvider","React","Controller","Menu","React","React","Slot","Slottable","React","ChevronDown","Search","Check","MoreHorizontal","React","React","ProgressPrimitive","React","RadioGroupPrimitive","Circle","SelectPrimitive","React","ChevronDown","ChevronUp","Check","CollapsiblePrimitive","ChevronRight","TabsPrimitive","React","FileText","Check","Pencil","AlertCircle","React","X","ChevronLeft","ChevronRight","Controller","validateField","getValidationStateClasses","ErrorMessage","Controller","validation","getValidationStateClasses","ErrorMessage","Info","Plus","X","Plus","ClipboardPaste","PencilLine","React","React","Controller","validation","getValidationStateClasses","ErrorMessage","React","Controller","GripVertical","X","Plus","ErrorMessage","React","Controller","GripVertical","ChevronRight","ChevronDown","X","Plus","ErrorMessage","INTEGER_PATTERN","validateField","Controller","getValidationStateClasses","INTEGER_INPUT_PATTERN","INTEGER_HTML_PATTERN","ErrorMessage","validateField","Controller","getValidationStateClasses","ErrorMessage","Controller","getValidationStateClasses","ErrorMessage","validateField","Controller","getValidationStateClasses","ErrorMessage","Controller","validateField","getValidationStateClasses","ErrorMessage","selectedVariant","Controller","validateField","Upload","FileIcon","CheckCircle2","AlertCircle","X","ErrorMessage","React","Controller","X","Plus","ErrorMessage","React","React","validateMapEntries","validateField","Controller","getValidationStateClasses","ErrorMessage","Controller","ErrorMessage","validateField","Controller","getValidationStateClasses","EyeOff","Eye","ErrorMessage","Controller","validation","ErrorMessage","Controller","validation","ErrorMessage","Controller","validation","React","ErrorMessage","validateField","Controller","getValidationStateClasses","ErrorMessage","Controller","validateField","getValidationStateClasses","ErrorMessage","Info","AlertCircle","CheckCircle","Network","Hash","Loader2","DollarSign","Timer","CloudOff","Settings","Info","Sonner"],"sources":["../src/version.ts","../src/components/ui/accordion.tsx","../src/components/ui/tooltip.tsx","../src/components/ui/address-display/context.ts","../src/components/ui/address-display/address-display.tsx","../src/components/ui/address-display/address-label-context.tsx","../src/components/ui/address-display/use-address-label.ts","../src/components/ui/alert.tsx","../src/components/ui/banner.tsx","../src/utils/button-variants.ts","../src/components/ui/button.tsx","../src/components/ui/calendar.tsx","../src/components/ui/card.tsx","../src/components/ui/checkbox.tsx","../src/components/ui/popover.tsx","../src/components/ui/date-range-picker.tsx","../src/components/ui/dialog.tsx","../src/components/ui/dropdown-menu.tsx","../src/components/ui/ecosystem-dropdown.tsx","../src/components/icons/MidnightIcon.tsx","../src/components/ui/ecosystem-icon.tsx","../src/components/ui/empty-state.tsx","../src/components/ui/external-link.tsx","../src/components/ui/footer.tsx","../src/components/ui/label.tsx","../src/components/ui/form.tsx","../src/components/ui/header.tsx","../src/components/ui/input.tsx","../src/components/ui/loading-button.tsx","../src/components/ui/network-icon.tsx","../src/components/ui/network-selector.tsx","../src/components/ui/network-status-badge.tsx","../src/components/ui/overflow-menu.tsx","../src/components/ui/progress.tsx","../src/components/ui/radio-group.tsx","../src/components/ui/select.tsx","../src/components/ui/sidebar/SidebarButton.tsx","../src/components/ui/sidebar/SidebarGroup.tsx","../src/components/ui/sidebar/SidebarLayout.tsx","../src/components/ui/sidebar/SidebarSection.tsx","../src/components/ui/tabs.tsx","../src/components/ui/textarea.tsx","../src/components/ui/view-contract-state-button.tsx","../src/components/ui/wizard/WizardStepper.tsx","../src/components/ui/wizard/WizardNavigation.tsx","../src/components/ui/wizard/hooks.ts","../src/components/ui/wizard/WizardLayout.tsx","../src/components/fields/address-suggestion/context.ts","../src/components/fields/utils/accessibility.ts","../src/components/fields/utils/layout.ts","../src/components/fields/AddressField.tsx","../src/components/fields/TextAreaField.tsx","../src/components/fields/AddressListField/labels.ts","../src/components/fields/AddressListField/AddressListBulkEntry.tsx","../src/components/fields/AddressListField/AddressListEntries.tsx","../src/components/fields/AddressListField/AddressListSingleEntry.tsx","../src/components/fields/AddressListField/AddressListField.tsx","../src/components/fields/address-suggestion/address-suggestion-context.tsx","../src/components/fields/address-suggestion/useAddressSuggestions.ts","../src/components/fields/AmountField.tsx","../src/components/fields/ArrayField.tsx","../src/components/fields/ArrayObjectField.tsx","../src/components/fields/BaseField.tsx","../src/components/fields/BigIntField.tsx","../src/components/fields/BooleanField.tsx","../src/components/fields/BytesField.tsx","../src/components/fields/DateTimeField.tsx","../src/components/fields/EnumField.tsx","../src/components/fields/FileUploadField.tsx","../src/components/fields/MapField/MapField.tsx","../src/components/fields/MapField/MapEntryRow.tsx","../src/components/fields/MapField/hooks/useChildTouched.ts","../src/components/fields/MapField/hooks/useDuplicateKeyIndexes.ts","../src/components/fields/MapField/hooks/useMapFieldSync.ts","../src/components/fields/MapField/validation/validateMapStructure.ts","../src/components/fields/NumberField.tsx","../src/components/fields/ObjectField.tsx","../src/components/fields/PasswordField.tsx","../src/components/fields/RadioField.tsx","../src/components/fields/SelectField.tsx","../src/components/fields/SelectGroupedField.tsx","../src/components/fields/TextField.tsx","../src/components/fields/UrlField.tsx","../src/components/RelayerDetailsCard/RelayerDetailsCard.tsx","../src/components/network-errors/NetworkErrorContext.ts","../src/components/network-errors/NetworkErrorNotificationProvider.tsx","../src/components/network-errors/useNetworkErrors.ts","../src/components/network-errors/NetworkErrorAwareAdapter.tsx","../src/components/network-errors/NetworkServiceErrorBanner.tsx","../src/components/network-availability/NetworkAvailabilityNotice.tsx","../src/components/ui/sonner.tsx"],"sourcesContent":["declare const __PACKAGE_VERSION__: string;\nexport const VERSION: string = __PACKAGE_VERSION__;\n","import * as AccordionPrimitive from '@radix-ui/react-accordion';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { ChevronDown } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst accordionItemVariants = cva('', {\n variants: {\n variant: {\n default: 'border-b',\n card: 'mb-3 rounded-lg border bg-card overflow-hidden',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\nconst accordionTriggerVariants = cva(\n 'flex flex-1 items-center justify-between font-medium transition-all [&[data-state=open]>svg]:rotate-180',\n {\n variants: {\n variant: {\n default: 'py-4 hover:underline',\n card: 'px-4 py-3 hover:bg-muted/50',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n);\n\nconst accordionContentVariants = cva(\n 'overflow-hidden text-sm transition-all duration-300 ease-in-out will-change-[height,opacity] data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down',\n {\n variants: {\n variant: {\n default: '',\n card: '',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n);\n\nconst accordionContentInnerVariants = cva('', {\n variants: {\n variant: {\n default: 'pb-4 pt-0',\n card: 'px-4 pb-4 pt-1',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\n// Create a context for the variant\ntype AccordionVariant = 'default' | 'card';\nconst AccordionVariantContext = React.createContext<AccordionVariant>('default');\n\n// Extend the Accordion component to accept and provide variant\ntype AccordionProps = (\n | AccordionPrimitive.AccordionSingleProps\n | AccordionPrimitive.AccordionMultipleProps\n) & {\n variant?: AccordionVariant;\n};\n\nconst Accordion = React.forwardRef<HTMLDivElement, AccordionProps>(\n ({ variant = 'default', ...props }, ref) => (\n <AccordionVariantContext.Provider value={variant}>\n <AccordionPrimitive.Root ref={ref} {...props} />\n </AccordionVariantContext.Provider>\n )\n);\nAccordion.displayName = 'Accordion';\n\ninterface AccordionItemProps\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>,\n VariantProps<typeof accordionItemVariants> {}\n\nconst AccordionItem = React.forwardRef<HTMLDivElement, AccordionItemProps>(\n ({ className, variant: variantProp, ...props }, ref) => {\n const contextVariant = React.useContext(AccordionVariantContext);\n const variant = variantProp ?? contextVariant;\n\n return (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(accordionItemVariants({ variant }), className)}\n {...props}\n />\n );\n }\n);\nAccordionItem.displayName = 'AccordionItem';\n\ninterface AccordionTriggerProps\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>,\n VariantProps<typeof accordionTriggerVariants> {}\n\nconst AccordionTrigger = React.forwardRef<HTMLButtonElement, AccordionTriggerProps>(\n ({ className, children, variant: variantProp, ...props }, ref) => {\n const contextVariant = React.useContext(AccordionVariantContext);\n const variant = variantProp ?? contextVariant;\n\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(accordionTriggerVariants({ variant }), className)}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n );\n }\n);\nAccordionTrigger.displayName = 'AccordionTrigger';\n\ninterface AccordionContentProps\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>,\n VariantProps<typeof accordionContentVariants> {}\n\nconst AccordionContent = React.forwardRef<HTMLDivElement, AccordionContentProps>(\n ({ className, children, variant: variantProp, ...props }, ref) => {\n const contextVariant = React.useContext(AccordionVariantContext);\n const variant = variantProp ?? contextVariant;\n\n return (\n <AccordionPrimitive.Content\n ref={ref}\n className={cn(accordionContentVariants({ variant }), className)}\n {...props}\n >\n <div className={cn(accordionContentInnerVariants({ variant }))}>{children}</div>\n </AccordionPrimitive.Content>\n );\n }\n);\nAccordionContent.displayName = 'AccordionContent';\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\nexport type { AccordionProps, AccordionItemProps, AccordionTriggerProps, AccordionContentProps };\n","import * as TooltipPrimitive from '@radix-ui/react-tooltip';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst TooltipProvider = TooltipPrimitive.Provider;\n\nconst Tooltip = TooltipPrimitive.Root;\n\nconst TooltipTrigger = TooltipPrimitive.Trigger;\n\nconst TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 overflow-hidden rounded-md px-3 py-1.5 text-xs',\n className\n )}\n {...props}\n />\n </TooltipPrimitive.Portal>\n));\nTooltipContent.displayName = TooltipPrimitive.Content.displayName;\n\nexport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };\n","import { createContext } from 'react';\n\nimport type { AddressLabelResolver } from '@openzeppelin/ui-types';\n\n/**\n * @internal Shared context instance consumed by both AddressDisplay and\n * AddressLabelProvider. Kept in its own file so component files export\n * only components (required by React Fast Refresh).\n */\nexport const AddressLabelContext = createContext<AddressLabelResolver | null>(null);\n","import { Check, Copy, ExternalLink, Pencil } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn, truncateMiddle } from '@openzeppelin/ui-utils';\n\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../tooltip';\nimport { AddressLabelContext } from './context';\n\n/**\n * True when the primary input can hover (e.g. desktop with mouse).\n * Touch-first phones typically report false. SSR assumes hover-capable.\n */\nfunction usePrefersHover(): boolean {\n return React.useSyncExternalStore(\n React.useCallback((onStoreChange) => {\n if (typeof window === 'undefined' || typeof window.matchMedia === 'undefined') {\n return (): void => {};\n }\n const mq = window.matchMedia('(hover: hover)');\n mq.addEventListener('change', onStoreChange);\n return (): void => mq.removeEventListener('change', onStoreChange);\n }, []),\n () =>\n typeof window !== 'undefined' && typeof window.matchMedia !== 'undefined'\n ? window.matchMedia('(hover: hover)').matches\n : true,\n () => true\n );\n}\n\n/**\n * Visual style for the component container.\n *\n * - `\"chip\"` – rounded pill with a slate background (default).\n * - `\"inline\"` – no background, padding, or border-radius; just the text\n * and optional action buttons. Use when dropping into existing layouts\n * where the parent already provides styling (e.g. wallet display bars).\n */\nexport type AddressDisplayVariant = 'chip' | 'inline';\n\ninterface AddressDisplayProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * The blockchain address to display\n */\n address: string;\n\n /**\n * Whether to truncate the address in the middle.\n * When omitted, defaults to `true` unless `truncateWhenLabeled` applies.\n */\n truncate?: boolean;\n\n /**\n * When `true` and `truncate` is **not** explicitly set, the address truncates\n * only when a label is shown (via the `label` prop or\n * `AddressLabelContext`). Use this when a long raw address should stay\n * fully visible unless an alias already identifies the row.\n * @default false\n */\n truncateWhenLabeled?: boolean;\n\n /**\n * When `truncate` is true, show the full address while the pointer is over\n * the component (on devices that support hover), or toggle on tap\n * (on touch-first / `(hover: none)` devices).\n * Has no effect when `truncate` is false.\n * @default false\n */\n untruncateOnHover?: boolean;\n\n /**\n * Number of characters to show at the beginning when truncating\n * @default 6\n */\n startChars?: number;\n\n /**\n * Number of characters to show at the end when truncating\n * @default 4\n */\n endChars?: number;\n\n /**\n * Whether to show a copy button\n * @default false\n */\n showCopyButton?: boolean;\n\n /**\n * Whether to show the copy button only on hover\n * @default false\n */\n showCopyButtonOnHover?: boolean;\n\n /**\n * Optional explorer URL to make the address clickable\n */\n explorerUrl?: string;\n\n /**\n * Human-readable label to display alongside the address.\n * Takes priority over any label resolved via `AddressLabelContext`.\n */\n label?: string;\n\n /**\n * Callback to trigger label editing for this address.\n * When provided, a pencil icon is rendered. Takes priority over\n * the `onEditLabel` from `AddressLabelContext`.\n */\n onLabelEdit?: () => void;\n\n /**\n * Optional network identifier used when resolving labels and triggering\n * edits via `AddressLabelContext`. Important for multi-network scenarios\n * where the same address may have different aliases per network.\n */\n networkId?: string;\n\n /**\n * When `true`, skip label resolution from `AddressLabelContext`.\n * Useful for rendering an address without alias decoration (e.g. in\n * a contract selector where the contract name is already shown).\n * @default false\n */\n disableLabel?: boolean;\n\n /**\n * When `true` and the address is truncated, a tooltip shows the full\n * address on hover. Has no visual effect when `truncate` is `false`.\n * Mutually exclusive with `untruncateOnHover` — if both are set,\n * `showTooltip` takes precedence.\n * @default false\n */\n showTooltip?: boolean;\n\n /**\n * Visual variant of the component container.\n * @default \"chip\"\n */\n variant?: AddressDisplayVariant;\n\n /**\n * Additional CSS classes\n */\n className?: string;\n}\n\n/**\n * Displays a blockchain address with optional truncation, copy button,\n * explorer link, tooltip, and human-readable label.\n *\n * Labels are resolved in priority order:\n * 1. Explicit `label` prop\n * 2. `AddressLabelContext` resolver (via `AddressLabelProvider`)\n * 3. No label (renders address only, identical to previous behavior)\n *\n * Pass `disableLabel` to suppress context-based resolution (e.g. when the\n * surrounding UI already shows a name, such as a contract selector).\n *\n * @example\n * ```tsx\n * // Basic usage (unchanged)\n * <AddressDisplay address=\"0x742d35Cc...\" showCopyButton />\n *\n * // Explicit label\n * <AddressDisplay address=\"0x742d35Cc...\" label=\"Treasury\" />\n *\n * // Auto-resolved via context (no changes needed at call site)\n * <AddressLabelProvider resolveLabel={myResolver}>\n * <AddressDisplay address=\"0x742d35Cc...\" />\n * </AddressLabelProvider>\n *\n * // Suppress label resolution for a specific instance\n * <AddressDisplay address=\"0x742d35Cc...\" disableLabel />\n *\n * // Reveal full address on hover (still truncated when idle)\n * <AddressDisplay address=\"0x742d35Cc...\" untruncateOnHover />\n *\n * // Tooltip with full address on hover + copy icon on hover\n * <AddressDisplay address=\"0x742d35Cc...\" showTooltip showCopyButton showCopyButtonOnHover />\n *\n * // Inline variant (no chip background) — useful inside wallet bars\n * <AddressDisplay address=\"0x742d35Cc...\" variant=\"inline\" showTooltip showCopyButton />\n *\n * // Truncate only when an alias/label is present (full address when unlabeled)\n * <AddressDisplay address=\"G...\" truncateWhenLabeled />\n * ```\n */\nexport function AddressDisplay({\n address,\n truncate: truncateProp,\n truncateWhenLabeled = false,\n untruncateOnHover = false,\n startChars = 6,\n endChars = 4,\n showCopyButton = false,\n showCopyButtonOnHover = false,\n explorerUrl,\n label: labelProp,\n onLabelEdit: onLabelEditProp,\n networkId,\n disableLabel = false,\n showTooltip = false,\n variant = 'chip',\n className,\n onPointerEnter,\n onPointerLeave,\n onMouseEnter,\n onMouseLeave,\n onClick,\n ...props\n}: AddressDisplayProps): React.ReactElement {\n const [copied, setCopied] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n const copyTimeoutRef = React.useRef<number | null>(null);\n const prefersHover = usePrefersHover();\n\n const resolver = React.useContext(AddressLabelContext);\n\n const resolvedLabel = disableLabel\n ? undefined\n : (labelProp ?? resolver?.resolveLabel(address, networkId));\n\n const effectiveTruncate =\n truncateProp !== undefined ? truncateProp : truncateWhenLabeled ? Boolean(resolvedLabel) : true;\n\n const contextEditHandler = React.useCallback(() => {\n resolver?.onEditLabel?.(address, networkId);\n }, [resolver, address, networkId]);\n\n const editHandler = disableLabel\n ? undefined\n : (onLabelEditProp ?? (resolver?.onEditLabel ? contextEditHandler : undefined));\n\n const canUntruncate = untruncateOnHover && effectiveTruncate && !showTooltip;\n const showFullAddress = !effectiveTruncate || (canUntruncate && isHovered);\n const displayAddress = showFullAddress ? address : truncateMiddle(address, startChars, endChars);\n\n const addressTextClassName = cn(\n !showFullAddress && 'truncate',\n (showFullAddress || !effectiveTruncate) && 'break-all'\n );\n\n const expandInteractionClassName = canUntruncate && !prefersHover ? 'cursor-pointer' : undefined;\n\n const handlePointerEnter = (e: React.PointerEvent<HTMLDivElement>): void => {\n if (canUntruncate && prefersHover) {\n setIsHovered(true);\n }\n onPointerEnter?.(e);\n onMouseEnter?.(e as unknown as React.MouseEvent<HTMLDivElement>);\n };\n\n const handlePointerLeave = (e: React.PointerEvent<HTMLDivElement>): void => {\n if (canUntruncate && prefersHover) {\n setIsHovered(false);\n }\n onPointerLeave?.(e);\n onMouseLeave?.(e as unknown as React.MouseEvent<HTMLDivElement>);\n };\n\n const handleUntruncateClick = (e: React.MouseEvent<HTMLDivElement>): void => {\n if (canUntruncate && !prefersHover) {\n setIsHovered((open) => !open);\n }\n onClick?.(e);\n };\n\n const handleCopy = (e: React.MouseEvent): void => {\n e.stopPropagation();\n navigator.clipboard.writeText(address);\n setCopied(true);\n\n if (copyTimeoutRef.current) {\n window.clearTimeout(copyTimeoutRef.current);\n }\n copyTimeoutRef.current = window.setTimeout(() => {\n setCopied(false);\n copyTimeoutRef.current = null;\n }, 2000);\n };\n\n React.useEffect(() => {\n return (): void => {\n if (copyTimeoutRef.current) {\n window.clearTimeout(copyTimeoutRef.current);\n }\n };\n }, []);\n\n const isChip = variant === 'chip';\n\n const actionButtons = (\n <>\n {showCopyButton && (\n <button\n type=\"button\"\n onClick={handleCopy}\n className={cn(\n 'shrink-0 text-slate-500',\n !copied && 'hover:text-slate-700',\n showCopyButtonOnHover\n ? 'ml-0 w-0 overflow-hidden opacity-0 transition-all duration-150 group-hover:ml-1.5 group-hover:w-3.5 group-hover:opacity-100 focus:ml-1.5 focus:w-3.5 focus:opacity-100'\n : 'ml-1.5 transition-colors'\n )}\n aria-label={copied ? 'Copied' : 'Copy address'}\n >\n {copied ? (\n <Check className=\"h-3.5 w-3.5 text-emerald-600\" />\n ) : (\n <Copy className=\"h-3.5 w-3.5\" />\n )}\n </button>\n )}\n\n {explorerUrl && (\n <a\n href={explorerUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={(e) => {\n e.stopPropagation();\n }}\n className=\"ml-1.5 shrink-0 text-slate-500 transition-colors hover:text-slate-700\"\n aria-label=\"View in explorer\"\n >\n <ExternalLink className=\"h-3.5 w-3.5\" />\n </a>\n )}\n\n {editHandler && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n editHandler();\n }}\n className=\"ml-0 w-0 shrink-0 overflow-hidden text-slate-500 opacity-0 transition-all duration-150 hover:text-slate-700 group-hover:ml-1.5 group-hover:w-3.5 group-hover:opacity-100 focus:ml-1.5 focus:w-3.5 focus:opacity-100\"\n aria-label=\"Edit label\"\n >\n <Pencil className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </>\n );\n\n const shouldShowTooltip = showTooltip && effectiveTruncate;\n\n const wrapWithTooltip = (content: React.ReactElement): React.ReactElement => {\n if (!shouldShowTooltip) return content;\n return (\n <TooltipProvider delayDuration={300}>\n <Tooltip>\n <TooltipTrigger asChild>{content}</TooltipTrigger>\n <TooltipContent className=\"font-mono text-xs\">{address}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n };\n\n if (resolvedLabel) {\n return wrapWithTooltip(\n <div\n className={cn(\n 'group inline-flex max-w-full min-w-0 flex-col',\n isChip && 'rounded-md bg-slate-100 px-2 py-1',\n 'text-xs text-slate-700',\n expandInteractionClassName,\n className\n )}\n onPointerEnter={handlePointerEnter}\n onPointerLeave={handlePointerLeave}\n onClick={handleUntruncateClick}\n {...props}\n >\n <span className=\"truncate font-sans font-medium text-slate-900 leading-snug\">\n {resolvedLabel}\n </span>\n <div className=\"flex min-w-0 items-center font-mono text-[10px] text-slate-400 leading-snug\">\n <span className={addressTextClassName}>{displayAddress}</span>\n {actionButtons}\n </div>\n </div>\n );\n }\n\n return wrapWithTooltip(\n <div\n className={cn(\n 'group inline-flex max-w-full min-w-0 items-center',\n isChip && 'rounded-md bg-slate-100 px-2 py-1',\n 'text-xs font-mono text-slate-700',\n expandInteractionClassName,\n className\n )}\n onPointerEnter={handlePointerEnter}\n onPointerLeave={handlePointerLeave}\n onClick={handleUntruncateClick}\n {...props}\n >\n <span className={addressTextClassName}>{displayAddress}</span>\n {actionButtons}\n </div>\n );\n}\n","/**\n * Address Label Context\n *\n * Provides a React context for resolving human-readable labels for blockchain\n * addresses. When an `AddressLabelProvider` is mounted, every `AddressDisplay`\n * in the subtree automatically resolves and renders labels without any\n * call-site changes.\n *\n * @example\n * ```tsx\n * import { AddressLabelProvider } from '@openzeppelin/ui-components';\n *\n * function App() {\n * const resolver = useAliasLabelResolver(db);\n * return (\n * <AddressLabelProvider {...resolver}>\n * <MyApp />\n * </AddressLabelProvider>\n * );\n * }\n * ```\n */\nimport * as React from 'react';\n\nimport type { AddressLabelResolver } from '@openzeppelin/ui-types';\n\nimport { AddressLabelContext } from './context';\n\n// ============================================================================\n// Provider\n// ============================================================================\n\n/**\n * Props for `AddressLabelProvider`.\n *\n * Accepts the same shape as `AddressLabelResolver` so the provider can be\n * spread directly from a resolver hook: `<AddressLabelProvider {...resolver}>`.\n */\nexport interface AddressLabelProviderProps extends AddressLabelResolver {\n children: React.ReactNode;\n}\n\n/**\n * Provides address label resolution to all `AddressDisplay` instances in the\n * subtree. Wrap your application (or a subsection) with this provider and\n * supply a `resolveLabel` function.\n *\n * @param props - Resolver functions and children\n *\n * @example\n * ```tsx\n * <AddressLabelProvider\n * resolveLabel={(addr) => addressBook.get(addr)}\n * onEditLabel={(addr) => openEditor(addr)}\n * >\n * <App />\n * </AddressLabelProvider>\n * ```\n */\nexport function AddressLabelProvider({\n children,\n resolveLabel,\n onEditLabel,\n}: AddressLabelProviderProps): React.ReactElement {\n const value = React.useMemo<AddressLabelResolver>(\n () => ({ resolveLabel, onEditLabel }),\n [resolveLabel, onEditLabel]\n );\n\n return <AddressLabelContext.Provider value={value}>{children}</AddressLabelContext.Provider>;\n}\n","/**\n * Convenience hook for resolving an address label from the nearest\n * `AddressLabelProvider`.\n *\n * Kept in its own file so that `address-label-context.tsx` exports only\n * components (required by React Fast Refresh).\n */\nimport * as React from 'react';\n\nimport { AddressLabelContext } from './context';\n\n/**\n * Return type for the `useAddressLabel` convenience hook.\n */\nexport interface UseAddressLabelResult {\n /** Resolved label, or `undefined` if no resolver/label exists */\n label: string | undefined;\n /** Edit handler bound to this address, or `undefined` if editing is not supported */\n onEdit: (() => void) | undefined;\n}\n\n/**\n * Convenience hook that resolves a label for a specific address using the\n * nearest `AddressLabelProvider`. Returns `undefined` values when no provider\n * is mounted.\n *\n * @param address - The blockchain address to resolve\n * @param networkId - Optional network identifier for network-specific aliases\n * @returns Resolved label and edit handler for the address\n *\n * @example\n * ```tsx\n * function MyAddress({ address }: { address: string }) {\n * const { label, onEdit } = useAddressLabel(address, 'ethereum-mainnet');\n * return <span>{label ?? address}</span>;\n * }\n * ```\n */\nexport function useAddressLabel(address: string, networkId?: string): UseAddressLabelResult {\n const resolver = React.useContext(AddressLabelContext);\n\n const label = resolver?.resolveLabel(address, networkId);\n\n const onEdit = React.useCallback(() => {\n resolver?.onEditLabel?.(address, networkId);\n }, [resolver, address, networkId]);\n\n return { label, onEdit: resolver?.onEditLabel ? onEdit : undefined };\n}\n","import { cva, type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst alertVariants = cva(\n 'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground',\n {\n variants: {\n variant: {\n default: 'bg-background text-foreground',\n destructive:\n 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',\n success: 'border-green-500/50 text-green-700 dark:border-green-500 [&>svg]:text-green-700',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div ref={ref} role=\"alert\" className={cn(alertVariants({ variant }), className)} {...props} />\n));\nAlert.displayName = 'Alert';\n\nconst AlertTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(\n ({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn('mb-1 font-medium leading-none tracking-tight', className)}\n {...props}\n />\n )\n);\nAlertTitle.displayName = 'AlertTitle';\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn('text-sm [&_p]:leading-relaxed', className)} {...props} />\n));\nAlertDescription.displayName = 'AlertDescription';\n\nexport { Alert, AlertTitle, AlertDescription };\n","import { X } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport type BannerVariant = 'info' | 'success' | 'warning' | 'error' | 'neutral';\n\nexport type BannerSize = 'default' | 'compact';\n\nexport interface BannerProps {\n /**\n * The variant/style of the banner\n * @default 'info'\n */\n variant?: BannerVariant;\n\n /**\n * Density preset for padding and typography\n * @default 'default'\n */\n size?: BannerSize;\n\n /**\n * Title text displayed at the top of the banner\n */\n title?: React.ReactNode;\n\n /**\n * Body text/content of the banner\n */\n children: React.ReactNode;\n\n /**\n * Whether the banner can be dismissed\n * @default true\n */\n dismissible?: boolean;\n\n /**\n * Callback when the banner is dismissed\n */\n onDismiss?: () => void;\n\n /**\n * Icon to display on the left (replaces default based on variant)\n */\n icon?: React.ReactNode;\n\n /**\n * Additional CSS classes\n */\n className?: string;\n}\n\nconst variantStyles: Record<\n BannerVariant,\n { container: string; icon: string; title: string; body: string }\n> = {\n info: {\n container: 'border-blue-200 bg-blue-50',\n icon: 'text-blue-600',\n title: 'text-blue-900',\n body: 'text-blue-800',\n },\n success: {\n container: 'border-green-200 bg-green-50',\n icon: 'text-green-600',\n title: 'text-green-900',\n body: 'text-green-800',\n },\n warning: {\n container: 'border-amber-200 bg-amber-50',\n icon: 'text-amber-600',\n title: 'text-amber-900',\n body: 'text-amber-800',\n },\n error: {\n container: 'border-red-200 bg-red-50',\n icon: 'text-red-600',\n title: 'text-red-900',\n body: 'text-red-800',\n },\n neutral: {\n container: 'border-border bg-muted/30',\n icon: 'text-muted-foreground',\n title: 'text-foreground',\n body: 'text-muted-foreground',\n },\n};\n\nconst sizeStyles: Record<\n BannerSize,\n { container: string; gap: string; title: string; body: string; dismissIcon: string }\n> = {\n default: {\n container: 'p-4',\n gap: 'gap-3',\n title: 'mb-2 text-sm font-semibold',\n body: 'text-sm whitespace-pre-line',\n dismissIcon: 'h-5 w-5',\n },\n compact: {\n container: 'px-4 py-3',\n gap: 'gap-2',\n title: 'mb-1 text-xs font-medium',\n body: 'text-xs leading-relaxed whitespace-pre-line',\n dismissIcon: 'h-4 w-4',\n },\n};\n\n/**\n * Dismissible banner component for notifications and alerts\n * Can be used with various variants (info, success, warning, error, neutral)\n */\nexport const Banner = React.forwardRef<HTMLDivElement, BannerProps>(\n (\n {\n className,\n variant = 'info',\n size = 'default',\n title,\n children,\n dismissible = true,\n onDismiss,\n icon,\n },\n ref\n ) => {\n const styles = variantStyles[variant];\n const sizing = sizeStyles[size];\n\n return (\n <div\n ref={ref}\n role=\"alert\"\n className={cn('rounded-md border', sizing.container, styles.container, className)}\n >\n <div className={cn('flex', sizing.gap)}>\n {icon && <div className={cn('mt-0.5 shrink-0', styles.icon)}>{icon}</div>}\n <div className=\"min-w-0 flex-1\">\n {title && <h4 className={cn(sizing.title, styles.title)}>{title}</h4>}\n <div className={cn(sizing.body, styles.body)}>{children}</div>\n </div>\n {dismissible && (\n <button\n type=\"button\"\n onClick={onDismiss}\n className={cn('self-start shrink-0 transition-colors hover:opacity-70', styles.icon)}\n aria-label=\"Dismiss banner\"\n >\n <X className={sizing.dismissIcon} />\n </button>\n )}\n </div>\n </div>\n );\n }\n);\nBanner.displayName = 'Banner';\n","import { cva } from 'class-variance-authority';\n\nexport const buttonVariants = cva(\n 'ring-offset-background focus-visible:ring-ring inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\n outline:\n 'border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground border',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n ghost: 'text-foreground hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-10 px-4 py-2',\n sm: 'h-9 rounded-md px-3',\n lg: 'h-11 rounded-md px-8',\n icon: 'size-10',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n);\n","import { Slot } from '@radix-ui/react-slot';\nimport { type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { buttonVariants } from '../../utils/button-variants';\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button';\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant || 'default'}\n data-size={size || 'default'}\n className={cn(buttonVariants({ variant, size, className }), 'cursor-pointer')}\n ref={ref}\n {...props}\n />\n );\n }\n);\nButton.displayName = 'Button';\n\nexport { Button };\n","'use client';\n\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\nimport * as React from 'react';\nimport { DayPicker } from 'react-day-picker';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { buttonVariants } from '../../utils/button-variants';\n\nexport type CalendarProps = React.ComponentProps<typeof DayPicker>;\n\n/**\n * Calendar component built on react-day-picker with shadcn/ui styling.\n * Supports single date, multiple dates, and date range selection modes.\n */\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n ...props\n}: CalendarProps): React.ReactElement {\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn('relative p-3', className)}\n classNames={{\n months: 'flex flex-col sm:flex-row gap-2 px-5',\n month: 'flex flex-col gap-4',\n month_caption: 'flex justify-center pt-1 relative items-center w-full',\n caption_label: 'text-sm font-medium',\n nav: 'flex items-center gap-1',\n button_previous: cn(\n buttonVariants({ variant: 'outline' }),\n 'absolute left-1 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100'\n ),\n button_next: cn(\n buttonVariants({ variant: 'outline' }),\n 'absolute right-1 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100'\n ),\n month_grid: 'w-full border-collapse space-y-1',\n weekdays: 'flex',\n weekday: 'text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]',\n week: 'flex w-full mt-2',\n day: cn(\n 'relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-selected/15 [&:has([aria-selected].day-outside)]:bg-selected/10 [&:has([aria-selected].day-range-end)]:rounded-r-md',\n props.mode === 'range'\n ? '[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md'\n : '[&:has([aria-selected])]:rounded-md'\n ),\n day_button: cn(\n buttonVariants({ variant: 'ghost' }),\n 'h-9 w-9 p-0 font-normal aria-selected:opacity-100 rounded-none hover:rounded-none'\n ),\n range_start: 'day-range-start rounded-l-md',\n range_end: 'day-range-end rounded-r-md',\n selected:\n 'bg-selected text-selected-foreground hover:bg-selected hover:text-selected-foreground focus:bg-selected focus:text-selected-foreground',\n today: 'bg-accent text-accent-foreground',\n outside:\n 'day-outside text-muted-foreground opacity-50 aria-selected:bg-selected/10 aria-selected:text-muted-foreground aria-selected:opacity-30',\n disabled: 'text-muted-foreground opacity-50',\n range_middle: 'aria-selected:bg-selected/15 aria-selected:text-foreground',\n hidden: 'invisible',\n ...classNames,\n }}\n components={{\n Chevron: ({ orientation }) => {\n const Icon = orientation === 'left' ? ChevronLeft : ChevronRight;\n return <Icon className=\"h-4 w-4\" />;\n },\n }}\n {...props}\n />\n );\n}\nCalendar.displayName = 'Calendar';\n\nexport { Calendar };\n","import { JSX } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\n/** Card container component with rounded borders. */\nfunction Card({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card\"\n className={cn('bg-card text-card-foreground flex flex-col rounded-xl border', className)}\n {...props}\n />\n );\n}\n\n/** Card header section for title and description. Provides top padding for the card. */\nfunction CardHeader({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-header\"\n className={cn('flex flex-col gap-1.5 px-6 pt-6', className)}\n {...props}\n />\n );\n}\n\n/** Card title with semibold styling. */\nfunction CardTitle({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-title\"\n className={cn('leading-none font-semibold', className)}\n {...props}\n />\n );\n}\n\n/** Card description with muted text styling. */\nfunction CardDescription({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-description\"\n className={cn('text-muted-foreground text-sm', className)}\n {...props}\n />\n );\n}\n\n/** Card content area with horizontal padding, top spacing, and bottom padding. */\nfunction CardContent({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return <div data-slot=\"card-content\" className={cn('px-6 pt-4 pb-6', className)} {...props} />;\n}\n\n/** Card footer with flex alignment for actions, top spacing, and bottom padding. */\nfunction CardFooter({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn('flex items-center px-6 pt-4 pb-6', className)}\n {...props}\n />\n );\n}\n\nexport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };\n","import * as CheckboxPrimitive from '@radix-ui/react-checkbox';\nimport { CheckIcon } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\n/** Checkbox component wrapping Radix UI Checkbox primitive. */\nfunction Checkbox({\n className,\n ...props\n}: React.ComponentProps<typeof CheckboxPrimitive.Root>): React.ReactElement {\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n 'border-input data-[state=checked]:bg-selected data-[state=checked]:text-selected-foreground data-[state=checked]:border-selected focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"flex items-center justify-center text-current transition-none\"\n >\n <CheckIcon data-slot=\"checkbox-indicator-icon\" className=\"size-3.5\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n );\n}\n\nexport { Checkbox };\n","'use client';\n\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst Popover = PopoverPrimitive.Root;\n\nconst PopoverTrigger = PopoverPrimitive.Trigger;\n\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 w-72 rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md outline-none',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2',\n 'data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };\n","'use client';\n\nimport { format } from 'date-fns';\nimport { Calendar as CalendarIcon } from 'lucide-react';\nimport type { DateRange } from 'react-day-picker';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Button } from './button';\nimport { Calendar } from './calendar';\nimport { Popover, PopoverContent, PopoverTrigger } from './popover';\n\n/**\n * Props for the DateRangePicker component.\n */\nexport interface DateRangePickerProps {\n /** The selected date range */\n value?: DateRange;\n /** Callback when the date range changes */\n onChange?: (range: DateRange | undefined) => void;\n /** Placeholder text when no date is selected */\n placeholder?: string;\n /** Additional CSS classes */\n className?: string;\n /** Whether the picker is disabled */\n disabled?: boolean;\n /** Number of months to display (default: 2) */\n numberOfMonths?: number;\n /** Alignment of the popover */\n align?: 'start' | 'center' | 'end';\n}\n\n/**\n * DateRangePicker component for selecting a date range.\n * Uses react-day-picker with Radix Popover for a shadcn-styled date range selection.\n *\n * @example\n * ```tsx\n * const [dateRange, setDateRange] = useState<DateRange | undefined>();\n *\n * <DateRangePicker\n * value={dateRange}\n * onChange={setDateRange}\n * placeholder=\"Select date range\"\n * />\n * ```\n */\nfunction DateRangePicker({\n value,\n onChange,\n placeholder = 'Pick a date range',\n className,\n disabled = false,\n numberOfMonths = 2,\n align = 'start',\n}: DateRangePickerProps): React.ReactElement {\n return (\n <div className={cn('grid gap-2', className)}>\n <Popover>\n <PopoverTrigger asChild>\n <Button\n id=\"date-range\"\n variant=\"outline\"\n disabled={disabled}\n className={cn(\n 'w-[280px] justify-start text-left font-normal',\n !value && 'text-muted-foreground'\n )}\n >\n <CalendarIcon className=\"mr-2 h-4 w-4\" />\n {value?.from ? (\n value.to ? (\n <>\n {format(value.from, 'LLL dd, y')} - {format(value.to, 'LLL dd, y')}\n </>\n ) : (\n format(value.from, 'LLL dd, y')\n )\n ) : (\n <span>{placeholder}</span>\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align={align}>\n <Calendar\n autoFocus\n mode=\"range\"\n defaultMonth={value?.from}\n selected={value}\n onSelect={onChange}\n numberOfMonths={numberOfMonths}\n />\n </PopoverContent>\n </Popover>\n </div>\n );\n}\nDateRangePicker.displayName = 'DateRangePicker';\n\nexport { DateRangePicker };\n\n// Re-export DateRange type for convenience\nexport type { DateRange };\n","import * as DialogPrimitive from '@radix-ui/react-dialog';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst Dialog = DialogPrimitive.Root;\n\nconst DialogTrigger = DialogPrimitive.Trigger;\n\nconst DialogPortal = DialogPrimitive.Portal;\n\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80',\n className\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n 'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 flex flex-col w-full max-w-lg translate-x-[-50%] translate-y-[-50%] border shadow-lg duration-200 sm:rounded-lg max-h-[90vh]',\n className\n )}\n {...props}\n >\n <DialogPrimitive.Close className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none z-10\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-x\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n <div className=\"overflow-y-auto p-6 flex flex-col gap-4\">{children}</div>\n </DialogPrimitive.Content>\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element => (\n <div className={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)} {...props} />\n);\nDialogHeader.displayName = 'DialogHeader';\n\nconst DialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element => (\n <div\n className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}\n {...props}\n />\n);\nDialogFooter.displayName = 'DialogFooter';\n\nconst DialogTitle = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn('text-lg leading-none font-semibold tracking-tight', className)}\n {...props}\n />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n className={cn('text-muted-foreground text-sm', className)}\n {...props}\n />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","'use client';\n\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { Check, ChevronRight, Circle } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst DropdownMenu = DropdownMenuPrimitive.Root;\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group;\n\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal;\n\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub;\n\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <DropdownMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n 'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent',\n inset && 'pl-8',\n className\n )}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto h-4 w-4\" />\n </DropdownMenuPrimitive.SubTrigger>\n));\nDropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;\n\nconst DropdownMenuSubContent = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n));\nDropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;\n\nconst DropdownMenuContent = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nconst DropdownMenuItem = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n inset && 'pl-8',\n className\n )}\n {...props}\n />\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n));\nDropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Circle className=\"h-2 w-2 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n));\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;\n\nconst DropdownMenuLabel = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', className)}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-muted', className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nconst DropdownMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>): React.ReactNode => {\n return (\n <span className={cn('ml-auto text-xs tracking-widest opacity-60', className)} {...props} />\n );\n};\nDropdownMenuShortcut.displayName = 'DropdownMenuShortcut';\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuGroup,\n DropdownMenuPortal,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuRadioGroup,\n};\n","import { Check, ChevronDown } from 'lucide-react';\nimport * as React from 'react';\n\nimport type { Ecosystem } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '.';\n\nexport interface EcosystemDropdownOption {\n value: Ecosystem;\n label: string;\n enabled: boolean;\n disabledLabel?: string;\n}\n\nexport interface EcosystemDropdownProps {\n options: EcosystemDropdownOption[];\n value: Ecosystem | null;\n onValueChange: (ecosystem: Ecosystem) => void;\n getEcosystemIcon?: (ecosystem: Ecosystem) => React.ReactNode;\n disabled?: boolean;\n className?: string;\n placeholder?: string;\n 'aria-labelledby'?: string;\n}\n\n/** Simple dropdown selector for choosing a blockchain ecosystem. */\nexport function EcosystemDropdown({\n options,\n value,\n onValueChange,\n getEcosystemIcon,\n disabled = false,\n className,\n placeholder = 'Select blockchain...',\n 'aria-labelledby': ariaLabelledby,\n}: EcosystemDropdownProps): React.ReactElement {\n const [open, setOpen] = React.useState(false);\n const selectedOption = options.find((o) => o.value === value);\n\n return (\n <DropdownMenu open={open} onOpenChange={setOpen}>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n aria-labelledby={ariaLabelledby}\n disabled={disabled}\n className={cn('w-full justify-between', className)}\n >\n <span className=\"flex items-center gap-2 truncate\">\n {selectedOption ? (\n <>\n {getEcosystemIcon?.(selectedOption.value)}\n <span className=\"truncate\">{selectedOption.label}</span>\n </>\n ) : (\n <span className=\"text-muted-foreground\">{placeholder}</span>\n )}\n </span>\n <ChevronDown className=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-[--radix-dropdown-menu-trigger-width] min-w-[200px]\"\n align=\"start\"\n >\n {options.map((option) => (\n <DropdownMenuItem\n key={option.value}\n disabled={!option.enabled}\n onSelect={() => {\n onValueChange(option.value);\n setOpen(false);\n }}\n className=\"gap-2\"\n >\n {getEcosystemIcon?.(option.value)}\n <span className=\"flex-1 truncate\">{option.label}</span>\n {!option.enabled && option.disabledLabel && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{option.disabledLabel}</span>\n )}\n {value === option.value && <Check className=\"h-4 w-4 shrink-0 opacity-100\" />}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","import React from 'react';\n\nexport interface MidnightIconProps {\n size?: number;\n className?: string;\n variant?: 'mono' | 'branded';\n}\n\n/**\n * MidnightIcon - SVG icon for the Midnight blockchain\n * Inline SVG to ensure it renders correctly when this package is consumed as a library\n */\nexport function MidnightIcon({\n size = 16,\n className = '',\n variant: _variant,\n}: MidnightIconProps): React.ReactElement {\n // variant is accepted for API consistency but not used as MidnightIcon is always branded\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 789.37 789.37\"\n width={size}\n height={size}\n className={className}\n aria-hidden=\"true\"\n >\n <path\n d=\"m394.69,0C176.71,0,0,176.71,0,394.69s176.71,394.69,394.69,394.69,394.69-176.71,394.69-394.69S612.67,0,394.69,0Zm0,716.6c-177.5,0-321.91-144.41-321.91-321.91S217.18,72.78,394.69,72.78s321.91,144.41,321.91,321.91-144.41,321.91-321.91,321.91Z\"\n fill=\"currentColor\"\n />\n <rect x=\"357.64\" y=\"357.64\" width=\"74.09\" height=\"74.09\" fill=\"currentColor\" />\n <rect x=\"357.64\" y=\"240.66\" width=\"74.09\" height=\"74.09\" fill=\"currentColor\" />\n <rect x=\"357.64\" y=\"123.69\" width=\"74.09\" height=\"74.09\" fill=\"currentColor\" />\n </svg>\n );\n}\n","import React from 'react';\n\nimport type { EcosystemMetadata } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { MidnightIcon } from '../icons/MidnightIcon';\n\nexport interface EcosystemIconProps {\n ecosystem: Pick<EcosystemMetadata, 'id' | 'iconComponent'>;\n /** Text used to derive the initial letter when no icon is available */\n fallbackLabel?: string;\n className?: string;\n size?: number;\n variant?: 'mono' | 'branded';\n}\n\n/** Displays the appropriate icon for a blockchain ecosystem. */\nexport function EcosystemIcon({\n ecosystem,\n fallbackLabel,\n className,\n size = 16,\n variant = 'branded',\n}: EcosystemIconProps): React.ReactElement {\n if (ecosystem.id === 'midnight') {\n return <MidnightIcon size={size} variant={variant} className={cn('shrink-0', className)} />;\n }\n\n if (ecosystem.iconComponent) {\n return (\n <ecosystem.iconComponent\n size={size}\n variant={variant}\n className={cn('shrink-0', className)}\n />\n );\n }\n\n const initial = (fallbackLabel ?? ecosystem.id).charAt(0).toUpperCase();\n\n return (\n <div\n className={cn(\n 'bg-muted text-muted-foreground shrink-0 rounded-full flex items-center justify-center font-medium',\n className\n )}\n style={{ width: size, height: size, fontSize: size * 0.5 }}\n role=\"img\"\n aria-label={fallbackLabel ?? ecosystem.id}\n >\n {initial}\n </div>\n );\n}\n","import { FileText } from 'lucide-react';\nimport React from 'react';\n\nexport interface EmptyStateProps {\n /**\n * The icon to display - can be a React component or SVG path\n */\n icon?: React.ReactNode;\n\n /**\n * Main heading text\n */\n title: string;\n\n /**\n * Descriptive text explaining the empty state\n */\n description: string;\n\n /**\n * Additional CSS classes for the container\n */\n className?: string;\n\n /**\n * Size variant for the empty state\n * @default 'default'\n */\n size?: 'small' | 'default' | 'large';\n}\n\n/**\n * Reusable empty state component for showing helpful messages when content is not available\n */\nexport function EmptyState({\n icon,\n title,\n description,\n className = '',\n size = 'default',\n}: EmptyStateProps): React.ReactElement {\n // Default icon using lucide-react\n const defaultIcon = <FileText className=\"h-6 w-6 text-muted-foreground\" />;\n\n // Size-based styling\n const sizeClasses = {\n small: {\n container: 'py-6',\n iconContainer: 'p-2 mb-2',\n title: 'text-base font-medium mb-1',\n description: 'text-xs max-w-sm',\n },\n default: {\n container: 'py-12',\n iconContainer: 'p-3 mb-4',\n title: 'text-lg font-medium mb-2',\n description: 'text-sm max-w-md',\n },\n large: {\n container: 'py-16',\n iconContainer: 'p-4 mb-6',\n title: 'text-xl font-medium mb-3',\n description: 'text-base max-w-lg',\n },\n };\n\n const styles = sizeClasses[size];\n\n return (\n <div\n className={`flex flex-col items-center justify-center text-center ${styles.container} ${className}`}\n >\n <div className={`rounded-full bg-muted ${styles.iconContainer}`}>{icon || defaultIcon}</div>\n <h3 className={`${styles.title}`}>{title}</h3>\n <p className={`text-muted-foreground ${styles.description}`}>{description}</p>\n </div>\n );\n}\n","import { ExternalLinkIcon } from 'lucide-react';\nimport React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\n// TODO: Add props\n// interface ExternalLinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n// // No additional props needed for basic functionality\n// }\n\n// export const ExternalLink = React.forwardRef<HTMLAnchorElement, ExternalLinkProps>(\nexport const ExternalLink = React.forwardRef<\n HTMLAnchorElement,\n React.AnchorHTMLAttributes<HTMLAnchorElement>\n>(({ children, className, ...props }, ref) => {\n return (\n <a\n ref={ref}\n className={cn(\n 'inline-flex items-center gap-1 text-primary underline-offset-4 hover:underline',\n className\n )}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n {...props}\n >\n {children}\n <ExternalLinkIcon className=\"h-3 w-3 ml-1\" /> {/* Adjust size/margin as needed */}\n </a>\n );\n});\n\nExternalLink.displayName = 'ExternalLink';\n","import { JSX } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\n/**\n * Props for the Footer component\n */\nexport interface FooterProps {\n /**\n * Company or organization name for the copyright notice\n * @default 'OpenZeppelin'\n */\n companyName?: string;\n\n /**\n * Copyright year to display\n * @default Current year\n */\n copyrightYear?: number;\n\n /**\n * URL for the privacy policy link\n * @default 'https://www.openzeppelin.com/privacy'\n */\n privacyPolicyUrl?: string;\n\n /**\n * Text for the privacy policy link\n * @default 'Privacy Policy'\n */\n privacyPolicyText?: string;\n\n /**\n * URL for the terms of service link\n * @default 'https://www.openzeppelin.com/tos'\n */\n termsOfServiceUrl?: string;\n\n /**\n * Text for the terms of service link\n * @default 'Terms of Service'\n */\n termsOfServiceText?: string;\n\n /**\n * Whether to show the privacy policy link\n * @default true\n */\n showPrivacyPolicy?: boolean;\n\n /**\n * Whether to show the terms of service link\n * @default true\n */\n showTermsOfService?: boolean;\n\n /**\n * Additional CSS classes for the footer container\n */\n className?: string;\n}\n\n/**\n * Application footer component with customizable legal links and branding.\n *\n * This component provides a consistent footer layout with customizable:\n * - Company name and copyright year\n * - Privacy policy and terms of service links and text\n * - Optional visibility controls for legal links\n * - Custom styling support\n */\nexport const Footer = ({\n companyName = 'OpenZeppelin',\n copyrightYear = new Date().getFullYear(),\n privacyPolicyUrl = 'https://www.openzeppelin.com/privacy',\n privacyPolicyText = 'Privacy Policy',\n termsOfServiceUrl = 'https://www.openzeppelin.com/tos',\n termsOfServiceText = 'Terms of Service',\n showPrivacyPolicy = true,\n showTermsOfService = true,\n className,\n}: FooterProps = {}): JSX.Element => {\n const hasLegalLinks = showPrivacyPolicy || showTermsOfService;\n\n return (\n <footer className={cn('border-t bg-background border-[#F5F5F5]', className)}>\n <div className=\"px-6 py-4 sm:h-12\">\n <div className=\"text-sm text-muted-foreground flex flex-col items-center gap-2 sm:flex-row sm:items-center sm:justify-between\">\n <span>\n © {copyrightYear} {companyName}\n </span>\n {hasLegalLinks && (\n <div className=\"flex flex-col items-center gap-2 sm:flex-row sm:gap-4\">\n {showPrivacyPolicy && (\n <a\n href={privacyPolicyUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"hover:text-foreground transition-colors\"\n >\n {privacyPolicyText}\n </a>\n )}\n {showTermsOfService && (\n <a\n href={termsOfServiceUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"hover:text-foreground transition-colors\"\n >\n {termsOfServiceText}\n </a>\n )}\n </div>\n )}\n </div>\n </div>\n </footer>\n );\n};\n","import * as LabelPrimitive from '@radix-ui/react-label';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\ntype LabelProps = React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>;\n/**\n * Label component for form fields, following shadcn/ui styling\n */\nconst Label = React.forwardRef<HTMLLabelElement, LabelProps>(({ className, ...props }, ref) => {\n return (\n <LabelPrimitive.Root\n ref={ref}\n data-slot=\"label\"\n className={cn('text-sm leading-none font-medium', className)}\n {...props}\n />\n );\n});\n\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label };\n","import * as React from 'react';\nimport type { FieldError, FieldPath, FieldValues, UseFormReturn } from 'react-hook-form';\nimport { Controller, FormProvider, useFormContext } from 'react-hook-form';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Label } from './label';\n\n/**\n * Context provider for the form\n */\nconst Form = <TFieldValues extends FieldValues = FieldValues, TContext = unknown>({\n ...props\n}: React.ComponentProps<typeof FormProvider<TFieldValues, TContext>>): React.ReactElement => {\n return <FormProvider {...props} />;\n};\n\n/**\n * Props for form field components\n */\ninterface FormFieldContextValue<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> {\n name: TName;\n}\n\n/**\n * Context for form field state\n */\nconst FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);\n\n/**\n * Get form field context\n */\nconst useFormField = (): {\n id: string;\n name: string;\n formItemId: string;\n formDescriptionId: string;\n formMessageId: string;\n error?: FieldError;\n} => {\n const fieldContext = React.useContext(FormFieldContext);\n const itemContext = React.useContext(FormItemContext);\n const { getFieldState, formState } = useFormContext();\n\n const fieldState = getFieldState(fieldContext.name, formState);\n\n if (!fieldContext) {\n throw new Error('useFormField should be used within <FormField>');\n }\n\n const { id } = itemContext;\n\n return {\n id,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n error: fieldState.error as FieldError | undefined,\n };\n};\n\n/**\n * Form field component\n */\nconst FormField = <\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n ...props\n}: ControllerProps<TFieldValues, TName>): React.ReactElement => {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n );\n};\n\n/**\n * Context for form item state\n */\ninterface FormItemContextValue {\n id: string;\n}\n\nconst FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);\n\n/**\n * Form item component\n */\nconst FormItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const id = React.useId();\n\n return (\n <FormItemContext.Provider value={{ id }}>\n <div\n ref={ref}\n data-slot=\"form-item\"\n className={cn('flex flex-col gap-2', className)}\n {...props}\n />\n </FormItemContext.Provider>\n );\n }\n);\nFormItem.displayName = 'FormItem';\n\n/**\n * Form label component\n */\nconst FormLabel = React.forwardRef<HTMLLabelElement, React.ComponentPropsWithoutRef<typeof Label>>(\n ({ className, ...props }, ref) => {\n const { error, formItemId } = useFormField();\n\n return (\n <Label\n ref={ref}\n className={error ? cn('text-destructive', className) : className}\n htmlFor={formItemId}\n {...props}\n />\n );\n }\n);\nFormLabel.displayName = 'FormLabel';\n\n/**\n * Form control component\n */\nconst FormControl = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ ...props }, ref) => {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField();\n\n return (\n <div\n ref={ref}\n id={formItemId}\n aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}\n aria-invalid={!!error}\n {...props}\n />\n );\n }\n);\nFormControl.displayName = 'FormControl';\n\n/**\n * Form description component\n */\nconst FormDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => {\n const { formDescriptionId } = useFormField();\n\n return (\n <p\n ref={ref}\n id={formDescriptionId}\n data-slot=\"form-description\"\n className={cn('text-muted-foreground text-sm', className)}\n {...props}\n />\n );\n});\nFormDescription.displayName = 'FormDescription';\n\n/**\n * Form error message component\n */\nconst FormMessage = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, children, ...props }, ref) => {\n const { error, formMessageId } = useFormField();\n const body = error ? String(error?.message) : children;\n\n if (!body) {\n return null;\n }\n\n return (\n <p\n ref={ref}\n id={formMessageId}\n data-slot=\"form-message\"\n className={cn('text-destructive text-sm font-medium', className)}\n {...props}\n >\n {body}\n </p>\n );\n});\nFormMessage.displayName = 'FormMessage';\n\n/**\n * Types for form controller props\n */\ntype ControllerProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> = {\n name: TName;\n control?: UseFormReturn<TFieldValues>['control'];\n render: (props: {\n field: {\n value: unknown;\n onChange: (...event: unknown[]) => void;\n onBlur: () => void;\n name: TName;\n ref: React.RefCallback<HTMLInputElement>;\n };\n fieldState: {\n invalid: boolean;\n isTouched: boolean;\n isDirty: boolean;\n error?: unknown;\n };\n formState: UseFormReturn<TFieldValues>['formState'];\n }) => React.ReactElement;\n};\n\nexport { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage };\n","import { Menu } from 'lucide-react';\nimport React from 'react';\n\nexport interface HeaderProps {\n title?: string;\n /** Open the mobile sidebar */\n onOpenSidebar?: () => void;\n /** Content to display on the right side of the header */\n rightContent?: React.ReactNode;\n}\n\nexport const Header = ({ title, onOpenSidebar, rightContent }: HeaderProps): React.ReactElement => {\n return (\n <header className=\"border-b border-[#F5F5F5] bg-background\">\n <div className=\"flex h-16 items-center px-3 sm:px-4 md:px-5 min-w-0\">\n {/* Mobile menu button */}\n <button\n type=\"button\"\n aria-label=\"Open menu\"\n onClick={onOpenSidebar}\n className=\"mr-2 sm:mr-3 inline-flex items-center justify-center rounded-md p-2 text-foreground hover:bg-muted focus:outline-none focus:ring-2 focus:ring-primary xl:hidden\"\n >\n <Menu className=\"size-5\" />\n </button>\n {/* Left side - Title (conditional) */}\n {title && (\n <div className=\"flex items-center min-w-0\">\n <h1 className=\"truncate max-w-[50vw] text-base font-semibold text-foreground\">\n {title}\n </h1>\n </div>\n )}\n\n {/* Right side - Wallet Connection or other content */}\n <div className=\"ml-auto flex items-center\">{rightContent}</div>\n </div>\n </header>\n );\n};\n","import * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\n/**\n * Input component that follows shadcn/ui styling and accessibility patterns\n */\nexport type InputProps = React.InputHTMLAttributes<HTMLInputElement>;\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n 'border-input bg-background ring-offset-background focus-visible:ring-ring placeholder:text-muted-foreground h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n ref={ref}\n {...props}\n />\n );\n }\n);\n\nInput.displayName = 'Input';\n\nexport { Input };\n","import { Slot, Slottable } from '@radix-ui/react-slot';\nimport { type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { buttonVariants } from '../../utils/button-variants';\n\n/**\n * Loading spinner component\n */\nconst Spinner = (): React.ReactElement => (\n <svg\n className=\"mr-2 h-4 w-4 animate-spin\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n);\n\nexport interface LoadingButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n loading?: boolean;\n}\n\nconst LoadingButton = React.forwardRef<HTMLButtonElement, LoadingButtonProps>(\n (\n { className, loading = false, children, disabled, variant, size, asChild = false, ...props },\n ref\n ) => {\n const Comp = asChild ? Slot : 'button';\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant || 'default'}\n data-size={size || 'default'}\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n disabled={loading || disabled}\n {...props}\n >\n {loading && <Spinner />}\n <Slottable>{children}</Slottable>\n </Comp>\n );\n }\n);\nLoadingButton.displayName = 'LoadingButton';\n\nexport { LoadingButton };\n","import React from 'react';\n\nimport type { NetworkConfig } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { MidnightIcon } from '../icons/MidnightIcon';\n\nexport interface NetworkIconProps {\n network: Pick<NetworkConfig, 'ecosystem' | 'iconComponent'>;\n className?: string;\n size?: number;\n variant?: 'mono' | 'branded';\n}\n\n/** Displays the appropriate icon for a blockchain network. */\nexport function NetworkIcon({\n network,\n className,\n size = 16,\n variant = 'branded',\n}: NetworkIconProps): React.ReactElement {\n if (network.ecosystem === 'midnight') {\n return <MidnightIcon size={size} variant={variant} className={cn('shrink-0', className)} />;\n }\n\n if (network.iconComponent) {\n return (\n <network.iconComponent size={size} variant={variant} className={cn('shrink-0', className)} />\n );\n }\n\n return (\n <div\n className={cn('bg-muted shrink-0 rounded-full', className)}\n style={{ width: size, height: size }}\n aria-hidden=\"true\"\n />\n );\n}\n","import { Check, ChevronDown, Search } from 'lucide-react';\nimport * as React from 'react';\n\nimport type { NetworkType } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Input,\n} from '.';\n\ninterface NetworkSelectorBaseProps<T> {\n networks: T[];\n getNetworkLabel: (network: T) => string;\n getNetworkIcon?: (network: T) => React.ReactNode;\n getNetworkType?: (network: T) => NetworkType | undefined;\n getNetworkId: (network: T) => string;\n groupByEcosystem?: boolean;\n getEcosystem?: (network: T) => string;\n filterNetwork?: (network: T, query: string) => boolean;\n /** When true, the network cannot be selected */\n isNetworkDisabled?: (network: T) => boolean;\n /** Optional label for disabled networks (e.g. \"Self-host required\") */\n getNetworkDisabledLabel?: (network: T) => string | undefined;\n className?: string;\n placeholder?: string;\n}\n\ninterface SingleSelectProps<T> {\n multiple?: false;\n selectedNetwork: T | null;\n onSelectNetwork: (network: T) => void;\n selectedNetworkIds?: never;\n onSelectionChange?: never;\n renderTrigger?: never;\n}\n\ninterface MultiSelectProps<_T> {\n multiple: true;\n selectedNetworkIds: string[];\n onSelectionChange: (ids: string[]) => void;\n /** Override the default trigger button with a custom element. */\n renderTrigger?: (props: { selectedCount: number; open: boolean }) => React.ReactNode;\n selectedNetwork?: never;\n onSelectNetwork?: never;\n}\n\nexport type NetworkSelectorProps<T> = NetworkSelectorBaseProps<T> &\n (SingleSelectProps<T> | MultiSelectProps<T>);\n\n/** Searchable dropdown selector for blockchain networks with optional grouping and multi-select. */\nexport function NetworkSelector<T>({\n networks,\n getNetworkLabel,\n getNetworkIcon,\n getNetworkType,\n getNetworkId,\n groupByEcosystem = false,\n getEcosystem,\n filterNetwork,\n isNetworkDisabled,\n getNetworkDisabledLabel,\n className,\n placeholder = 'Select Network',\n ...modeProps\n}: NetworkSelectorProps<T>): React.ReactElement {\n const [open, setOpen] = React.useState(false);\n const [searchQuery, setSearchQuery] = React.useState('');\n\n const isMultiple = modeProps.multiple === true;\n\n const selectedNetworkIds = isMultiple ? modeProps.selectedNetworkIds : undefined;\n const onSelectionChange = isMultiple ? modeProps.onSelectionChange : undefined;\n const selectedNetwork = !isMultiple ? modeProps.selectedNetwork : undefined;\n const onSelectNetwork = !isMultiple ? modeProps.onSelectNetwork : undefined;\n\n const filteredNetworks = React.useMemo(() => {\n if (!searchQuery) return networks;\n if (filterNetwork) return networks.filter((n) => filterNetwork(n, searchQuery));\n return networks.filter((n) =>\n getNetworkLabel(n).toLowerCase().includes(searchQuery.toLowerCase())\n );\n }, [networks, searchQuery, filterNetwork, getNetworkLabel]);\n\n const groupedNetworks = React.useMemo(() => {\n if (!groupByEcosystem || !getEcosystem) {\n return { All: filteredNetworks };\n }\n return filteredNetworks.reduce(\n (acc, network) => {\n const ecosystem = getEcosystem(network);\n if (!acc[ecosystem]) {\n acc[ecosystem] = [];\n }\n acc[ecosystem].push(network);\n return acc;\n },\n {} as Record<string, T[]>\n );\n }, [filteredNetworks, groupByEcosystem, getEcosystem]);\n\n const isSelected = React.useCallback(\n (network: T): boolean => {\n if (isMultiple && selectedNetworkIds) {\n return selectedNetworkIds.includes(getNetworkId(network));\n }\n return selectedNetwork ? getNetworkId(selectedNetwork) === getNetworkId(network) : false;\n },\n [isMultiple, selectedNetworkIds, selectedNetwork, getNetworkId]\n );\n\n const handleSelect = React.useCallback(\n (network: T) => {\n if (isNetworkDisabled?.(network)) {\n return;\n }\n\n if (isMultiple && selectedNetworkIds && onSelectionChange) {\n const id = getNetworkId(network);\n const next = selectedNetworkIds.includes(id)\n ? selectedNetworkIds.filter((x) => x !== id)\n : [...selectedNetworkIds, id];\n onSelectionChange(next);\n } else if (onSelectNetwork) {\n onSelectNetwork(network);\n setOpen(false);\n }\n },\n [\n isMultiple,\n selectedNetworkIds,\n onSelectionChange,\n onSelectNetwork,\n getNetworkId,\n isNetworkDisabled,\n ]\n );\n\n const handleClearAll = React.useCallback(() => {\n if (isMultiple && onSelectionChange) {\n onSelectionChange([]);\n }\n }, [isMultiple, onSelectionChange]);\n\n const selectedCount = selectedNetworkIds?.length ?? 0;\n const renderTrigger = isMultiple ? modeProps.renderTrigger : undefined;\n\n const triggerContent = (() => {\n if (isMultiple && renderTrigger) {\n return renderTrigger({ selectedCount, open });\n }\n\n if (isMultiple) {\n return (\n <Button\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n className={cn('w-full justify-between', className)}\n >\n <span className=\"truncate text-muted-foreground\">\n {selectedCount > 0\n ? `${selectedCount} network${selectedCount > 1 ? 's' : ''} selected`\n : placeholder}\n </span>\n <ChevronDown className=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n );\n }\n\n return (\n <Button\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n className={cn('w-full justify-between', className)}\n >\n <span className=\"flex items-center gap-2 truncate\">\n {selectedNetwork ? (\n <>\n {getNetworkIcon?.(selectedNetwork)}\n <span className=\"truncate\">{getNetworkLabel(selectedNetwork)}</span>\n {getNetworkType && (\n <span className=\"shrink-0 rounded-sm bg-muted px-1.5 py-0.5 text-[10px] font-medium uppercase text-muted-foreground\">\n {getNetworkType(selectedNetwork)}\n </span>\n )}\n </>\n ) : (\n <span className=\"text-muted-foreground\">{placeholder}</span>\n )}\n </span>\n <ChevronDown className=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n );\n })();\n\n return (\n <DropdownMenu open={open} onOpenChange={setOpen}>\n <DropdownMenuTrigger asChild>{triggerContent}</DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-[--radix-dropdown-menu-trigger-width] min-w-[240px] p-0\"\n align=\"start\"\n >\n <div className=\"flex items-center border-b px-3\">\n <Search className=\"mr-2 h-4 w-4 shrink-0 opacity-50\" />\n <Input\n placeholder=\"Search network...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' && e.key !== 'Enter') {\n e.stopPropagation();\n }\n }}\n className=\"h-9 w-full border-0 bg-transparent p-0 placeholder:text-muted-foreground focus-visible:ring-0 focus-visible:ring-offset-0\"\n aria-label=\"Search networks\"\n />\n </div>\n <div className=\"max-h-[300px] overflow-y-auto p-1\">\n {isMultiple && selectedCount > 0 && (\n <>\n <div className=\"flex items-center justify-between px-2 py-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n {selectedCount} selected\n </span>\n <button\n onClick={handleClearAll}\n className=\"text-xs text-muted-foreground hover:text-foreground\"\n >\n Clear all\n </button>\n </div>\n <DropdownMenuSeparator />\n </>\n )}\n\n {Object.entries(groupedNetworks).length === 0 ? (\n <div className=\"py-6 text-center text-sm text-muted-foreground\">No network found.</div>\n ) : (\n Object.entries(groupedNetworks).map(([group, groupNetworks], index) => (\n <React.Fragment key={group}>\n {groupByEcosystem && (\n <DropdownMenuLabel className=\"text-xs font-medium text-muted-foreground\">\n {group}\n </DropdownMenuLabel>\n )}\n <DropdownMenuGroup>\n {groupNetworks.map((network) => {\n const disabled = isNetworkDisabled?.(network) ?? false;\n const disabledLabel = disabled ? getNetworkDisabledLabel?.(network) : undefined;\n\n return (\n <DropdownMenuItem\n key={getNetworkId(network)}\n disabled={disabled}\n onSelect={(e) => {\n if (disabled) {\n e.preventDefault();\n return;\n }\n if (isMultiple) e.preventDefault();\n handleSelect(network);\n }}\n className={cn('gap-2', disabled && 'cursor-not-allowed opacity-60')}\n >\n {isMultiple ? (\n <div\n className={cn(\n 'flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border transition-colors',\n isSelected(network)\n ? 'border-selected bg-selected text-selected-foreground'\n : 'border-input bg-background',\n disabled && 'opacity-50'\n )}\n >\n {isSelected(network) && <Check className=\"h-3 w-3\" />}\n </div>\n ) : null}\n {getNetworkIcon?.(network)}\n <div className=\"flex flex-1 items-center gap-2 min-w-0\">\n <span className=\"truncate\">{getNetworkLabel(network)}</span>\n {getNetworkType && (\n <span className=\"shrink-0 rounded-sm bg-muted px-1.5 py-0.5 text-[10px] font-medium uppercase text-muted-foreground\">\n {getNetworkType(network)}\n </span>\n )}\n {disabledLabel ? (\n <span className=\"shrink-0 rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground\">\n {disabledLabel}\n </span>\n ) : null}\n </div>\n {!isMultiple && isSelected(network) && (\n <Check className=\"h-4 w-4 text-selected opacity-100\" />\n )}\n </DropdownMenuItem>\n );\n })}\n </DropdownMenuGroup>\n {index < Object.keys(groupedNetworks).length - 1 && <DropdownMenuSeparator />}\n </React.Fragment>\n ))\n )}\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","import React from 'react';\n\nimport type { NetworkConfig } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { NetworkIcon } from './network-icon';\n\ninterface NetworkStatusBadgeProps {\n network: NetworkConfig | null;\n className?: string;\n}\n\n// Define constants for consistency\nconst ICON_SIZE = 16;\n\n/**\n * NetworkStatusBadge - Displays network information in a compact badge format\n * Shows the network icon, ecosystem, and name with dashed borders for testnet/devnet\n */\nexport function NetworkStatusBadge({\n network,\n className,\n}: NetworkStatusBadgeProps): React.ReactElement | null {\n if (!network) return null;\n\n const isTestnetLike = network.type === 'testnet' || network.type === 'devnet';\n\n return (\n <div\n className={cn(\n 'inline-flex items-center gap-2 rounded-full bg-muted px-3 py-2',\n isTestnetLike ? 'border-2 border-dashed border-muted-foreground/40' : 'border-0',\n className\n )}\n >\n {/* Network icon */}\n <NetworkIcon network={network} size={ICON_SIZE} />\n\n {/* Combined ecosystem + network name */}\n <div className=\"flex items-baseline gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground uppercase\">\n {network.ecosystem}\n </span>\n <span className=\"text-xs font-medium\">{network.name}</span>\n </div>\n </div>\n );\n}\n","import { MoreHorizontal } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '.';\n\n/** Single action item within an OverflowMenu dropdown. */\nexport interface OverflowMenuItem {\n id: string;\n label: string;\n icon?: React.ReactNode;\n destructive?: boolean;\n disabled?: boolean;\n onSelect: () => void;\n}\n\n/** Props for the OverflowMenu component. */\nexport interface OverflowMenuProps {\n items: OverflowMenuItem[];\n /** Align dropdown relative to trigger. @default \"end\" */\n align?: 'start' | 'center' | 'end';\n /** Additional classes on the trigger button. */\n className?: string;\n /** Accessible label for the trigger button. @default \"More actions\" */\n 'aria-label'?: string;\n}\n\n/** Compact \"...\" dropdown menu for secondary actions. */\nexport function OverflowMenu({\n items,\n align = 'end',\n className,\n 'aria-label': ariaLabel = 'More actions',\n}: OverflowMenuProps) {\n if (items.length === 0) return null;\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className={cn('h-8 w-8', className)}\n aria-label={ariaLabel}\n >\n <MoreHorizontal className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align={align} className=\"min-w-[140px]\">\n {items.map((item, index) => (\n <React.Fragment key={item.id}>\n {item.destructive && index > 0 && <DropdownMenuSeparator />}\n <DropdownMenuItem\n onClick={item.onSelect}\n disabled={item.disabled}\n className={cn(item.destructive && 'text-destructive focus:text-destructive')}\n >\n {item.icon}\n {item.label}\n </DropdownMenuItem>\n </React.Fragment>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","import * as ProgressPrimitive from '@radix-ui/react-progress';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst Progress = React.forwardRef<\n React.ElementRef<typeof ProgressPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n>(({ className, value, ...props }, ref) => (\n <ProgressPrimitive.Root\n ref={ref}\n className={cn(\n 'relative h-2 w-full overflow-hidden rounded-full bg-gray-100 dark:bg-gray-800',\n className\n )}\n {...props}\n >\n <ProgressPrimitive.Indicator\n className=\"bg-primary h-full w-full flex-1 transition-all\"\n style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\n />\n </ProgressPrimitive.Root>\n));\nProgress.displayName = ProgressPrimitive.Root.displayName;\n\nexport { Progress };\n","import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';\nimport { Circle } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst RadioGroup = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>\n>(({ className, ...props }, ref) => {\n return (\n <RadioGroupPrimitive.Root\n className={cn('flex flex-col space-y-2', className)}\n data-slot=\"radiogroup\"\n {...props}\n ref={ref}\n />\n );\n});\nRadioGroup.displayName = RadioGroupPrimitive.Root.displayName;\n\nconst RadioGroupItem = React.forwardRef<\n HTMLButtonElement,\n React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>\n>(({ className, ...props }, ref) => {\n return (\n <RadioGroupPrimitive.Item\n ref={ref}\n className={cn(\n 'border-input bg-background text-selected h-4 w-4 rounded-full border shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator className=\"flex items-center justify-center\">\n <Circle className=\"h-2.5 w-2.5 fill-current text-current\" />\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n );\n});\nRadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;\n\nexport { RadioGroup, RadioGroupItem };\n","import * as SelectPrimitive from '@radix-ui/react-select';\nimport { Check, ChevronDown, ChevronUp } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst Select = SelectPrimitive.Root;\n\nconst SelectGroup = SelectPrimitive.Group;\n\nconst SelectValue = SelectPrimitive.Value;\n\nconst SelectTrigger = React.forwardRef<\n HTMLButtonElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger\n ref={ref}\n data-slot=\"select-trigger\"\n className={cn(\n 'border-input bg-background placeholder:text-muted-foreground flex h-10 w-full items-center justify-between rounded-md border px-3 py-2 text-sm focus:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDown className=\"h-4 w-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n));\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName;\n\nconst SelectScrollUpButton = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n data-slot=\"select-scroll-button\"\n className={className}\n {...props}\n >\n <ChevronUp className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollUpButton>\n));\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;\n\nconst SelectScrollDownButton = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n data-slot=\"select-scroll-button\"\n className={className}\n {...props}\n >\n <ChevronDown className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollDownButton>\n));\nSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;\n\nconst SelectContent = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = 'popper', ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n data-slot=\"select-content\"\n className={cn(\n 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-96 w-[var(--radix-select-trigger-width)] overflow-hidden rounded-md border shadow-md',\n position === 'popper' &&\n 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n className\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n 'p-1',\n position === 'popper' &&\n 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\nSelectContent.displayName = SelectPrimitive.Content.displayName;\n\nconst SelectLabel = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n data-slot=\"select-label\"\n className={cn('py-1.5 pr-2 pl-8 text-sm font-semibold', className)}\n {...props}\n />\n));\nSelectLabel.displayName = SelectPrimitive.Label.displayName;\n\nconst SelectItem = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n data-slot=\"select-item\"\n className={cn(\n 'hover:bg-accent relative flex w-full cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors duration-150 outline-none select-none focus:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span\n data-slot=\"select-item-indicator\"\n className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\"\n >\n <SelectPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n));\nSelectItem.displayName = SelectPrimitive.Item.displayName;\n\nconst SelectSeparator = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n data-slot=\"select-separator\"\n className={cn('bg-muted -mx-1 my-1 h-px', className)}\n {...props}\n />\n));\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName;\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n};\n","import React, { ReactNode } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport interface SidebarButtonProps {\n icon?: ReactNode;\n children: ReactNode;\n onClick?: () => void;\n size?: 'default' | 'small';\n badge?: string;\n disabled?: boolean;\n isSelected?: boolean;\n /** When provided, renders as an anchor element instead of a button */\n href?: string;\n target?: React.HTMLAttributeAnchorTarget;\n rel?: string;\n className?: string;\n}\n\n/**\n * A styled button component for sidebar actions with consistent styling.\n * Can render as a button or anchor element depending on whether href is provided.\n */\nexport function SidebarButton({\n icon,\n children,\n onClick,\n size = 'default',\n badge,\n disabled = false,\n isSelected = false,\n href,\n target,\n rel,\n className,\n}: SidebarButtonProps): React.ReactElement {\n const minHeight = size === 'small' ? 'min-h-10' : 'min-h-11';\n\n const commonClass = cn(\n 'group relative flex flex-wrap items-center gap-x-2 gap-y-0.5 px-3 py-2 rounded-lg font-semibold text-sm transition-colors',\n badge ? 'justify-between' : 'justify-start',\n disabled\n ? 'text-muted-foreground/60 cursor-not-allowed'\n : isSelected\n ? 'text-selected bg-selected/10'\n : 'text-muted-foreground hover:text-foreground cursor-pointer hover:before:content-[\"\"] hover:before:absolute hover:before:inset-x-0 hover:before:top-1 hover:before:bottom-1 hover:before:bg-muted/80 hover:before:rounded-lg hover:before:-z-10',\n minHeight,\n className\n );\n\n const content = (\n <>\n <div className=\"flex items-center gap-2\">\n {icon}\n {children}\n </div>\n {badge && (\n <span className=\"text-xs px-2 py-0.5 bg-muted text-muted-foreground rounded-full font-medium\">\n {badge}\n </span>\n )}\n </>\n );\n\n if (href) {\n return (\n <a href={href} target={target} rel={rel} className={commonClass} onClick={onClick}>\n {content}\n </a>\n );\n }\n\n return (\n <button className={commonClass} onClick={disabled ? undefined : onClick} disabled={disabled}>\n {content}\n </button>\n );\n}\n","import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';\nimport { ChevronRight } from 'lucide-react';\nimport React, { ReactNode, useState } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport interface SidebarGroupProps {\n /** Title displayed in the collapsible trigger */\n title: string;\n /** Optional icon displayed before the title */\n icon?: ReactNode;\n /** Content to render when expanded */\n children: ReactNode;\n /** Whether the group is open by default */\n defaultOpen?: boolean;\n /** Controlled open state */\n open?: boolean;\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Additional CSS classes for the container */\n className?: string;\n /** Additional CSS classes for the trigger */\n triggerClassName?: string;\n /** Additional CSS classes for the content wrapper */\n contentClassName?: string;\n}\n\n/**\n * A collapsible group component for organizing sidebar navigation items.\n * Supports both controlled and uncontrolled modes.\n */\nexport function SidebarGroup({\n title,\n icon,\n children,\n defaultOpen = false,\n open: controlledOpen,\n onOpenChange,\n className,\n triggerClassName,\n contentClassName,\n}: SidebarGroupProps): React.ReactElement {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : uncontrolledOpen;\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (!isControlled) {\n setUncontrolledOpen(nextOpen);\n }\n onOpenChange?.(nextOpen);\n };\n\n return (\n <CollapsiblePrimitive.Root\n open={isOpen}\n onOpenChange={handleOpenChange}\n className={cn('w-full', className)}\n >\n <CollapsiblePrimitive.Trigger\n className={cn(\n 'group flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-semibold',\n 'text-muted-foreground transition-colors hover:text-foreground',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n triggerClassName\n )}\n >\n <ChevronRight\n className={cn('size-4 shrink-0 transition-transform duration-200', isOpen && 'rotate-90')}\n />\n {icon && <span className=\"shrink-0\">{icon}</span>}\n <span className=\"flex-1 text-left\">{title}</span>\n </CollapsiblePrimitive.Trigger>\n\n <CollapsiblePrimitive.Content\n className={cn(\n 'overflow-hidden transition-all duration-200 ease-in-out',\n 'data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down',\n contentClassName\n )}\n >\n <div className=\"py-1 pl-4\">{children}</div>\n </CollapsiblePrimitive.Content>\n </CollapsiblePrimitive.Root>\n );\n}\n","import React, { ReactNode } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport interface SidebarLayoutProps {\n /** Content for the sidebar header (e.g., logo) */\n header?: ReactNode;\n /** Content to be displayed below the header but above the scrollable area */\n subHeader?: ReactNode;\n /** Main scrollable content area */\n children: ReactNode;\n /** Content for the fixed footer (e.g., nav icons) */\n footer?: ReactNode;\n /** Additional CSS classes for the sidebar container */\n className?: string;\n /** Width of the sidebar (default: 289px) */\n width?: number | string;\n /** Background color/class for the sidebar */\n background?: string;\n /** Controls visibility in mobile slide-over */\n mobileOpen?: boolean;\n /** Close handler for mobile slide-over */\n onMobileOpenChange?: (open: boolean) => void;\n /** Aria label for mobile dialog */\n mobileAriaLabel?: string;\n}\n\n/**\n * A flexible sidebar layout component with desktop sidebar and mobile slide-over.\n * Provides slots for header, scrollable content, and footer.\n */\nexport function SidebarLayout({\n header,\n subHeader,\n children,\n footer,\n className,\n width = 289,\n background = 'bg-[rgba(245,245,245,0.31)]',\n mobileOpen,\n onMobileOpenChange,\n mobileAriaLabel = 'Menu',\n}: SidebarLayoutProps): React.ReactElement {\n const widthStyle = typeof width === 'number' ? `${width}px` : width;\n\n return (\n <>\n {/* Desktop Sidebar */}\n <div\n className={cn(\n 'fixed left-0 top-0 z-40 h-full hidden xl:flex xl:flex-col',\n background,\n className\n )}\n style={{ width: widthStyle }}\n >\n {/* Fixed Header */}\n {header && <div className=\"shrink-0 px-8 pt-12\">{header}</div>}\n\n {/* Fixed SubHeader */}\n {subHeader && <div className=\"shrink-0 px-8 mt-6\">{subHeader}</div>}\n\n {/* Scrollable Content Area */}\n <div className=\"flex-1 overflow-y-auto px-8 pb-24\">{children}</div>\n\n {/* Fixed Footer */}\n {footer && <div className=\"pointer-events-auto sticky bottom-0 px-8 py-4\">{footer}</div>}\n </div>\n\n {/* Spacer to push content (desktop only) */}\n <div className=\"hidden xl:block\" style={{ width: widthStyle }} />\n\n {/* Mobile slide-over */}\n {typeof mobileOpen === 'boolean' && onMobileOpenChange && (\n <div\n className={cn(\n 'xl:hidden fixed inset-0 z-50',\n mobileOpen ? 'pointer-events-auto' : 'pointer-events-none'\n )}\n aria-hidden={!mobileOpen}\n >\n {/* Backdrop */}\n <div\n className={cn(\n 'absolute inset-0 bg-black/40 transition-opacity',\n mobileOpen ? 'opacity-100' : 'opacity-0'\n )}\n onClick={() => onMobileOpenChange(false)}\n />\n {/* Panel */}\n <div\n className={cn(\n 'absolute left-0 top-0 h-full w-[85%] max-w-[320px] bg-[rgba(245,245,245,0.98)] shadow-xl transition-transform',\n mobileOpen ? 'translate-x-0' : '-translate-x-full'\n )}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={mobileAriaLabel}\n >\n <div className=\"flex h-full flex-col\">\n {/* Mobile Header */}\n {header && <div className=\"shrink-0 px-6 pt-10 pb-4\">{header}</div>}\n\n {/* Mobile SubHeader */}\n {subHeader && <div className=\"shrink-0 px-6 pb-4\">{subHeader}</div>}\n\n {/* Mobile Scrollable Content */}\n <div className=\"flex-1 overflow-y-auto px-6 pb-20\">{children}</div>\n\n {/* Mobile Footer */}\n {footer && <div className=\"px-6 py-4\">{footer}</div>}\n </div>\n </div>\n </div>\n )}\n </>\n );\n}\n","import React, { ReactNode } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport interface SidebarSectionProps {\n /** Optional section title displayed above the content */\n title?: string;\n /** Content to render within the section */\n children: ReactNode;\n /** Additional CSS classes */\n className?: string;\n /** CSS classes for the title element */\n titleClassName?: string;\n /** Whether this section should grow to fill available space */\n grow?: boolean;\n}\n\n/**\n * A generic sidebar section wrapper with optional title.\n * Used to group related sidebar items together.\n */\nexport function SidebarSection({\n title,\n children,\n className,\n titleClassName,\n grow = false,\n}: SidebarSectionProps): React.ReactElement {\n return (\n <div className={cn('flex flex-col w-full', grow && 'flex-1', className)}>\n {title && (\n <div className={cn('text-[#5e5e5e] text-xs font-semibold leading-4 mb-1', titleClassName)}>\n {title}\n </div>\n )}\n <div className={cn('flex flex-col', grow && 'flex-1 overflow-hidden')}>{children}</div>\n </div>\n );\n}\n","import * as TabsPrimitive from '@radix-ui/react-tabs';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\n/** Tabs container component wrapping Radix UI Tabs Root. */\nfunction Tabs({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Root>): React.ReactElement {\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n className={cn('flex w-full max-w-full min-w-0 flex-col gap-2 overflow-x-hidden', className)}\n {...props}\n />\n );\n}\n\n/** Tabs list component containing tab triggers. */\nfunction TabsList({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.List>): React.ReactElement {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n className={cn(\n 'bg-muted text-muted-foreground flex h-9 w-full max-w-full min-w-0 items-center justify-start rounded-lg p-1 overflow-x-auto overflow-y-hidden flex-nowrap overscroll-x-contain [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden sm:overflow-visible',\n className\n )}\n {...props}\n />\n );\n}\n\n/** Individual tab trigger button. */\nfunction TabsTrigger({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Trigger>): React.ReactElement {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n \"data-[state=active]:bg-background data-[state=active]:text-selected focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring inline-flex flex-1 items-center justify-center gap-1.5 rounded-md px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\n/** Tab content panel displayed when its trigger is active. */\nfunction TabsContent({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Content>): React.ReactElement {\n return (\n <TabsPrimitive.Content\n data-slot=\"tabs-content\"\n className={cn('flex-1 outline-none', className)}\n {...props}\n />\n );\n}\n\nexport { Tabs, TabsContent, TabsList, TabsTrigger };\n","import * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, ...props }, ref) => {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n 'border-input bg-background ring-offset-background focus-visible:ring-ring placeholder:text-muted-foreground aria-invalid:ring-destructive/20 aria-invalid:border-destructive dark:aria-invalid:ring-destructive/40 min-h-16 w-full rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n ref={ref}\n {...props}\n />\n );\n }\n);\nTextarea.displayName = 'Textarea';\n\nexport { Textarea };\n","import { FileText } from 'lucide-react';\nimport React from 'react';\n\nimport { truncateMiddle } from '@openzeppelin/ui-utils';\n\nimport { Button } from './button';\n\ninterface ViewContractStateButtonProps {\n contractAddress: string | null;\n onToggle: () => void;\n}\n\n/**\n * ViewContractStateButton - A button to toggle the contract state widget\n * Shows the contract address in a truncated format\n */\nexport function ViewContractStateButton({\n contractAddress,\n onToggle,\n}: ViewContractStateButtonProps): React.ReactElement | null {\n if (!contractAddress) return null;\n\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"px-3 py-2 h-auto gap-2 items-start justify-start sm:items-center\"\n onClick={onToggle}\n title=\"Show Contract State\"\n >\n <FileText size={16} className=\"shrink-0 self-center\" />\n <span className=\"flex flex-col sm:flex-row sm:items-center text-left leading-tight\">\n <span className=\"text-sm font-medium\">View Contract State</span>\n <span className=\"text-xs text-muted-foreground sm:ml-1\">\n ({truncateMiddle(contractAddress)})\n </span>\n </span>\n </Button>\n );\n}\n","import { AlertCircle, Check, Pencil } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport type StepStatus = 'pending' | 'completed' | 'skipped';\n\nexport type StepVisualState = 'completed' | 'current' | 'visited' | 'invalid' | 'upcoming';\n\nexport interface WizardStepDef {\n id: string;\n title: string;\n status?: StepStatus;\n /** When true the step is highlighted with an error indicator. */\n isInvalid?: boolean;\n}\n\nexport interface WizardStepperProps {\n steps: WizardStepDef[];\n currentStepIndex: number;\n /** Index of the furthest step the user has reached. Steps up to this index stay clickable. */\n furthestStepIndex?: number;\n onStepClick?: (index: number) => void;\n variant?: 'vertical' | 'horizontal';\n /** When true all steps are clickable regardless of their state (used by scrollable layout). */\n freeNavigation?: boolean;\n className?: string;\n}\n\nfunction resolveState(\n step: WizardStepDef,\n index: number,\n currentStepIndex: number,\n furthestStepIndex: number\n): StepVisualState {\n if (step.status === 'completed' || step.status === 'skipped') return 'completed';\n if (index === currentStepIndex) return 'current';\n if (step.isInvalid && (index < currentStepIndex || index <= furthestStepIndex)) return 'invalid';\n if (index < currentStepIndex) return 'completed';\n if (index <= furthestStepIndex) return 'visited';\n return 'upcoming';\n}\n\nfunction canClick(state: StepVisualState, freeNavigation = false): boolean {\n if (freeNavigation) return true;\n return state !== 'upcoming';\n}\n\nfunction StepCircle({ state, index }: { state: StepVisualState; index: number }) {\n return (\n <span\n className={cn(\n 'flex size-6 shrink-0 items-center justify-center rounded-full text-xs font-semibold transition-all',\n state === 'completed' && 'bg-selected text-selected-foreground',\n state === 'current' && 'bg-selected text-selected-foreground ring-2 ring-selected/30',\n state === 'visited' && 'bg-selected/10 text-selected ring-1 ring-selected/40',\n state === 'invalid' && 'bg-destructive/10 text-destructive ring-1 ring-destructive/40',\n state === 'upcoming' && 'bg-muted text-muted-foreground'\n )}\n >\n {state === 'completed' ? (\n <Check className=\"size-3.5\" />\n ) : state === 'visited' ? (\n <Pencil className=\"size-3\" />\n ) : state === 'invalid' ? (\n <AlertCircle className=\"size-3.5\" />\n ) : (\n index + 1\n )}\n </span>\n );\n}\n\nfunction StepLabel({\n title,\n state,\n isSkipped,\n}: {\n title: string;\n state: StepVisualState;\n isSkipped: boolean;\n}) {\n return (\n <div className=\"min-w-0 flex-1\">\n <span\n className={cn(\n 'text-sm font-medium transition-colors',\n state === 'current' && 'text-selected',\n state === 'completed' && 'text-foreground',\n state === 'visited' && 'text-selected',\n state === 'invalid' && 'text-destructive',\n state === 'upcoming' && 'text-muted-foreground'\n )}\n >\n {title}\n </span>\n {isSkipped && <span className=\"mt-0.5 block text-[11px] text-muted-foreground\">Skipped</span>}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Vertical variant — card-wrapped sidebar\n// ---------------------------------------------------------------------------\n\nfunction VerticalStepper({\n steps,\n currentStepIndex,\n furthestStepIndex = currentStepIndex,\n onStepClick,\n freeNavigation,\n className,\n}: WizardStepperProps) {\n return (\n <nav\n aria-label=\"Wizard steps\"\n className={cn('rounded-2xl border border-border bg-card p-6', className)}\n >\n <div className=\"flex flex-col gap-1\">\n {steps.map((step, index) => {\n const state = resolveState(step, index, currentStepIndex, furthestStepIndex);\n const clickable = canClick(state, freeNavigation) && !!onStepClick;\n\n return (\n <button\n key={step.id}\n type=\"button\"\n onClick={() => clickable && onStepClick?.(index)}\n disabled={!clickable}\n className={cn(\n 'flex items-center gap-3 rounded-xl border border-transparent px-3 py-3 text-left transition-all duration-150',\n clickable ? 'cursor-pointer' : 'cursor-not-allowed opacity-50',\n state === 'current' && 'border-selected/40 bg-selected/5',\n state === 'completed' && 'bg-card hover:bg-muted/40',\n state === 'visited' && 'bg-card hover:bg-selected/5',\n state === 'invalid' &&\n 'border-destructive/40 bg-destructive/5 hover:bg-destructive/10',\n state === 'upcoming' && 'bg-card'\n )}\n aria-current={state === 'current' ? 'step' : undefined}\n >\n <StepCircle state={state} index={index} />\n <StepLabel title={step.title} state={state} isSkipped={step.status === 'skipped'} />\n </button>\n );\n })}\n </div>\n </nav>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Horizontal variant — card-wrapped top bar with connector lines\n// ---------------------------------------------------------------------------\n\nfunction HorizontalStepper({\n steps,\n currentStepIndex,\n furthestStepIndex = currentStepIndex,\n onStepClick,\n freeNavigation,\n className,\n}: WizardStepperProps) {\n return (\n <nav\n aria-label=\"Wizard steps\"\n className={cn('rounded-2xl border border-border bg-card p-6', className)}\n >\n <div className=\"flex w-full items-center\">\n {steps.map((step, index) => {\n const state = resolveState(step, index, currentStepIndex, furthestStepIndex);\n const clickable = canClick(state, freeNavigation) && !!onStepClick;\n const isLast = index === steps.length - 1;\n\n return (\n <React.Fragment key={step.id}>\n <button\n type=\"button\"\n onClick={() => clickable && onStepClick?.(index)}\n disabled={!clickable}\n className={cn(\n 'flex items-center gap-2 rounded-xl border border-transparent px-3 py-2 text-left transition-all duration-150',\n clickable ? 'cursor-pointer' : 'cursor-not-allowed opacity-50',\n state === 'current' && 'border-selected/40 bg-selected/5',\n state === 'completed' && 'bg-card hover:bg-muted/40',\n state === 'visited' && 'bg-card hover:bg-selected/5',\n state === 'invalid' &&\n 'border-destructive/40 bg-destructive/5 hover:bg-destructive/10',\n state === 'upcoming' && 'bg-card'\n )}\n aria-current={state === 'current' ? 'step' : undefined}\n aria-label={`Step ${index + 1}: ${step.title}`}\n >\n <StepCircle state={state} index={index} />\n <div className=\"hidden sm:block\">\n <StepLabel\n title={step.title}\n state={state}\n isSkipped={step.status === 'skipped'}\n />\n </div>\n </button>\n\n {!isLast && (\n <div\n className={cn(\n 'mx-1 h-px flex-1 transition-colors sm:mx-2',\n index < currentStepIndex ? 'bg-selected' : 'bg-border'\n )}\n />\n )}\n </React.Fragment>\n );\n })}\n </div>\n </nav>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Public component\n// ---------------------------------------------------------------------------\n\n/**\n * A stepper component for navigating through a series of steps.\n *\n * @param props - The props for the WizardStepper component.\n * @returns A React node representing the stepper component.\n */\nexport function WizardStepper(props: WizardStepperProps): ReactNode {\n const { variant = 'horizontal', ...rest } = props;\n return variant === 'vertical' ? (\n <VerticalStepper {...rest} variant={variant} />\n ) : (\n <HorizontalStepper {...rest} variant={variant} />\n );\n}\n","import { ChevronLeft, ChevronRight, X } from 'lucide-react';\nimport type { ReactNode } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Button } from '../button';\n\nexport interface WizardNavigationProps {\n isFirstStep: boolean;\n isLastStep: boolean;\n canProceed?: boolean;\n onPrevious: () => void;\n onNext: () => void;\n onCancel?: () => void;\n /** Extra actions rendered between Cancel/Previous and Next (e.g. Show Code) */\n extraActions?: ReactNode;\n nextLabel?: string;\n lastStepLabel?: string;\n /**\n * Optional secondary action on the **last step** only, shown to the left of the\n * primary control with a less prominent (outline) style. Omitted when either\n * `lastStepSecondaryLabel` or `onLastStepSecondary` is missing.\n */\n onLastStepSecondary?: () => void;\n lastStepSecondaryLabel?: string;\n lastStepSecondaryDisabled?: boolean;\n /**\n * When `false` on the last step, the primary Next/Finish button is omitted\n * (e.g. when the step body provides its own primary action).\n * @default true\n */\n showLastStepPrimary?: boolean;\n className?: string;\n}\n\n/**\n * A navigation component for the wizard.\n *\n * @param props - The props for the WizardNavigation component.\n * @returns A React node representing the navigation component.\n */\nexport function WizardNavigation({\n isFirstStep,\n isLastStep,\n canProceed = true,\n onPrevious,\n onNext,\n onCancel,\n extraActions,\n nextLabel = 'Next',\n lastStepLabel = 'Finish',\n onLastStepSecondary,\n lastStepSecondaryLabel,\n lastStepSecondaryDisabled,\n showLastStepPrimary = true,\n className,\n}: WizardNavigationProps) {\n const showPrimary = !isLastStep || showLastStepPrimary;\n const showSecondary =\n isLastStep &&\n lastStepSecondaryLabel != null &&\n lastStepSecondaryLabel !== '' &&\n onLastStepSecondary != null;\n\n return (\n <div className={cn('flex items-center justify-between', className)}>\n <div className=\"flex gap-2\">\n {onCancel && (\n <Button type=\"button\" variant=\"outline\" onClick={onCancel} className=\"gap-2\">\n <X className=\"size-4\" />\n Cancel\n </Button>\n )}\n {!isFirstStep && (\n <Button type=\"button\" variant=\"outline\" onClick={onPrevious} className=\"gap-2\">\n <ChevronLeft className=\"size-4\" />\n Previous\n </Button>\n )}\n </div>\n\n <div className=\"flex gap-2\">\n {extraActions}\n {showSecondary && (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onLastStepSecondary}\n disabled={lastStepSecondaryDisabled ?? false}\n className=\"gap-2\"\n >\n {lastStepSecondaryLabel}\n </Button>\n )}\n {showPrimary && (\n <Button type=\"button\" onClick={onNext} disabled={!canProceed} className=\"gap-2\">\n {isLastStep ? lastStepLabel : nextLabel}\n {!isLastStep && <ChevronRight className=\"size-4\" />}\n </Button>\n )}\n </div>\n </div>\n );\n}\n","import { useCallback, useEffect, useRef, useState, type RefObject } from 'react';\n\ninterface StepWithId {\n id: string;\n}\n\ninterface UseScrollableWizardStepTrackingOptions<TStep extends StepWithId> {\n steps: TStep[];\n currentStepIndex: number;\n onStepChange: (index: number) => void;\n scrollRef: RefObject<HTMLDivElement | null>;\n sectionId: (stepId: string) => string;\n /**\n * Pixels to keep between the container top and the scrolled-to section.\n * Defaults to 32 (matches the `p-8` padding on the scroll column).\n */\n scrollPadding?: number;\n}\n\n/**\n * Clamp a step index into the valid range for the current wizard.\n */\nexport function getSafeStepIndex(stepCount: number, currentStepIndex: number) {\n if (stepCount === 0) return 0;\n\n return Math.max(0, Math.min(currentStepIndex, stepCount - 1));\n}\n\n/**\n * Track the highest step reached unless a controlled value is provided.\n */\nexport function useFurthestStepIndex(\n currentStepIndex: number,\n controlledFurthestStepIndex?: number\n) {\n const [internalFurthestStepIndex, setInternalFurthestStepIndex] = useState(currentStepIndex);\n\n useEffect(() => {\n setInternalFurthestStepIndex((prev) => Math.max(prev, currentStepIndex));\n }, [currentStepIndex]);\n\n return controlledFurthestStepIndex ?? internalFurthestStepIndex;\n}\n\n/**\n * Keep the scrollable wizard's active and visited step state in sync with scrolling and clicks.\n */\nexport function useScrollableWizardStepTracking<TStep extends StepWithId>({\n steps,\n currentStepIndex,\n onStepChange,\n scrollRef,\n sectionId,\n scrollPadding = SCROLL_PADDING_PX,\n}: UseScrollableWizardStepTrackingOptions<TStep>) {\n const safeIndex = getSafeStepIndex(steps.length, currentStepIndex);\n const initialIndexRef = useRef(safeIndex);\n const rafRef = useRef<number | null>(null);\n const manualSelectionIndexRef = useRef<number | null>(null);\n\n // Keep a ref to the latest steps/sectionId/onStepChange so the scroll\n // handler always uses fresh values without being a dependency.\n const stepsRef = useRef(steps);\n const sectionIdRef = useRef(sectionId);\n const onStepChangeRef = useRef(onStepChange);\n const scrollPaddingRef = useRef(scrollPadding);\n useEffect(() => {\n stepsRef.current = steps;\n sectionIdRef.current = sectionId;\n onStepChangeRef.current = onStepChange;\n scrollPaddingRef.current = scrollPadding;\n });\n\n const [activeIndex, setActiveIndex] = useState(initialIndexRef.current);\n const activeIndexRef = useRef(initialIndexRef.current);\n const [furthestStepIndex, setFurthestStepIndex] = useState(initialIndexRef.current);\n\n // Ref flag used to suppress the onStepChange call from the initial mount\n // scroll evaluation, preventing a React render-order violation where an\n // external store update fires during the commit phase of a sibling component.\n // Using a ref (rather than a local variable) ensures the flag is reliably\n // set before the RAF callback executes, even in environments where the RAF\n // fires synchronously or immediately after scheduling.\n const isMountedRef = useRef(false);\n\n const clearManualSelection = useCallback(() => {\n manualSelectionIndexRef.current = null;\n }, []);\n\n // Wire up scroll tracking once, against the stable scrollRef.\n // Steps/sectionId changes are consumed via refs so this effect never\n // re-runs (and never inadvertently clears the manual selection lock).\n useEffect(() => {\n const container = scrollRef.current;\n if (!container) return;\n const ownerDocument = container.ownerDocument;\n\n isMountedRef.current = false;\n // Gate used inside the first RAF callback to flip isMountedRef only after\n // the initial scroll evaluation completes — ensuring onStepChange is never\n // called during the React commit phase on mount.\n let didCompleteInitialRaf = false;\n\n const releaseManualSelectionOnUserScroll = () => {\n clearManualSelection();\n };\n const handleKeyDown = (event: KeyboardEvent) => {\n if (isScrollableNavigationKey(event)) {\n clearManualSelection();\n }\n };\n\n const handleScroll = () => {\n if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);\n\n rafRef.current = requestAnimationFrame(() => {\n const currentSteps = stepsRef.current;\n const currentSectionId = sectionIdRef.current;\n const currentOnStepChange = onStepChangeRef.current;\n\n if (currentSteps.length === 0) return;\n\n const manualSelectionIndex = manualSelectionIndexRef.current;\n const naturalState = resolveScrollableActiveIndex(\n container,\n currentSteps,\n currentSectionId\n );\n const naturalActiveIndex = naturalState.activeIndex;\n const newActiveIndex = manualSelectionIndex ?? naturalActiveIndex;\n const shouldCommitFurthestStepIndex =\n manualSelectionIndex !== null ? true : naturalState.commitFurthestStepIndex;\n\n const prevActiveIndex = activeIndexRef.current;\n if (prevActiveIndex !== newActiveIndex) {\n activeIndexRef.current = newActiveIndex;\n setActiveIndex(newActiveIndex);\n // Only notify the parent once the initial mount RAF has completed so\n // we don't call setState on a sibling component during React's commit\n // phase. isMountedRef is set to true at the end of the first RAF run.\n if (isMountedRef.current) {\n lastEmittedIndexRef.current = newActiveIndex;\n currentOnStepChange(newActiveIndex);\n }\n } else {\n setActiveIndex(newActiveIndex);\n }\n if (shouldCommitFurthestStepIndex) {\n setFurthestStepIndex((prev) => Math.max(prev, newActiveIndex));\n }\n rafRef.current = null;\n\n // Mark mounted at the very end of the first RAF so subsequent scroll\n // events (and the RAF callbacks they schedule) can call onStepChange.\n if (!didCompleteInitialRaf) {\n didCompleteInitialRaf = true;\n isMountedRef.current = true;\n }\n });\n };\n\n container.addEventListener('wheel', releaseManualSelectionOnUserScroll, { passive: true });\n container.addEventListener('touchmove', releaseManualSelectionOnUserScroll, { passive: true });\n // pointerdown covers scrollbar drag and other pointer-based scrolling that\n // does not fire wheel or touchmove events.\n container.addEventListener('pointerdown', releaseManualSelectionOnUserScroll);\n ownerDocument.addEventListener('keydown', handleKeyDown);\n container.addEventListener('scroll', handleScroll, { passive: true });\n handleScroll();\n\n return () => {\n isMountedRef.current = false;\n container.removeEventListener('wheel', releaseManualSelectionOnUserScroll);\n container.removeEventListener('touchmove', releaseManualSelectionOnUserScroll);\n container.removeEventListener('pointerdown', releaseManualSelectionOnUserScroll);\n ownerDocument.removeEventListener('keydown', handleKeyDown);\n container.removeEventListener('scroll', handleScroll);\n if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);\n };\n // Intentionally only re-run when the scroll container itself changes.\n // steps/sectionId/onStepChange are consumed via refs above.\n }, [clearManualSelection, scrollRef]);\n\n // Tracks the last index this hook reported to the parent via onStepChange.\n // Used to distinguish external prop changes (true programmatic navigation)\n // from echoes of our own scroll-driven updates flowing back as props.\n const lastEmittedIndexRef = useRef(safeIndex);\n\n // Sync activeIndex and scroll position when currentStepIndex is changed\n // externally (e.g. programmatic navigation from outside the scrollable layout).\n // We skip the sync when currentStepIndex simply echoes the value we last\n // emitted ourselves — otherwise scroll-driven onStepChange calls would\n // create a feedback loop that bounces the scroll position back to the\n // previously active section.\n useEffect(() => {\n const newSafeIndex = getSafeStepIndex(stepsRef.current.length, currentStepIndex);\n\n // Echo of our own last emission — not an external command, ignore.\n if (newSafeIndex === lastEmittedIndexRef.current) return;\n\n // External navigation: adopt the new index and scroll to it.\n lastEmittedIndexRef.current = newSafeIndex;\n activeIndexRef.current = newSafeIndex;\n setActiveIndex(newSafeIndex);\n setFurthestStepIndex((prev) => Math.max(prev, newSafeIndex));\n\n const step = stepsRef.current[newSafeIndex];\n if (!step) return;\n const sectionElement = scrollRef.current?.querySelector<HTMLElement>(\n `#${CSS.escape(sectionIdRef.current(step.id))}`\n );\n if (scrollRef.current && sectionElement)\n scrollSectionIntoView(scrollRef.current, sectionElement, scrollPaddingRef.current);\n }, [currentStepIndex, scrollRef]);\n\n const scrollToSection = useCallback(\n (index: number) => {\n const step = stepsRef.current[index];\n if (!step) return;\n\n manualSelectionIndexRef.current = index;\n activeIndexRef.current = index;\n lastEmittedIndexRef.current = index;\n setActiveIndex(index);\n setFurthestStepIndex((prev) => Math.max(prev, index));\n onStepChangeRef.current(index);\n\n const container = scrollRef.current;\n const sectionElement = container?.querySelector<HTMLElement>(\n `#${CSS.escape(sectionIdRef.current(step.id))}`\n );\n if (container && sectionElement)\n scrollSectionIntoView(container, sectionElement, scrollPaddingRef.current);\n },\n [scrollRef]\n );\n\n return {\n activeIndex,\n furthestStepIndex,\n scrollToSection,\n };\n}\n\nfunction resolveScrollableActiveIndex<TStep extends StepWithId>(\n container: HTMLDivElement,\n steps: TStep[],\n sectionId: (stepId: string) => string\n) {\n if (steps.length === 0) {\n return {\n activeIndex: 0,\n commitFurthestStepIndex: false,\n };\n }\n\n const containerRect = container.getBoundingClientRect();\n const anchorY = containerRect.top + Math.min(containerRect.height * 0.35, 220);\n const isScrollable = container.scrollHeight > container.clientHeight + 1;\n const isAtBottom =\n isScrollable && container.scrollTop + container.clientHeight >= container.scrollHeight - 1;\n const isNearBottom =\n isScrollable && container.scrollTop + container.clientHeight >= container.scrollHeight - 4;\n\n if (isAtBottom) {\n return {\n activeIndex: steps.length - 1,\n commitFurthestStepIndex: false,\n };\n }\n\n let activeIndex = 0;\n let highestScore = Number.NEGATIVE_INFINITY;\n for (let i = 0; i < steps.length; i++) {\n const sectionMetrics = getSectionMetrics(container, steps[i].id, sectionId, containerRect);\n if (!sectionMetrics) continue;\n\n const score = scoreScrollableStep({\n stepIndex: i,\n stepCount: steps.length,\n containerRect,\n anchorY,\n isNearBottom,\n ...sectionMetrics,\n });\n\n if (score >= highestScore) {\n highestScore = score;\n activeIndex = i;\n }\n }\n\n return {\n activeIndex,\n commitFurthestStepIndex: true,\n };\n}\n\n// Matches the p-8 (32px) padding on the scrollable content column so that\n// auto-scrolled sections align flush with the sidebar card's top border.\nconst SCROLL_PADDING_PX = 32;\n\nfunction getSectionElement(\n container: HTMLDivElement,\n stepId: string,\n sectionId: (stepId: string) => string\n) {\n return container.querySelector<HTMLElement>(`#${CSS.escape(sectionId(stepId))}`);\n}\n\nfunction scrollSectionIntoView(\n container: HTMLDivElement,\n sectionElement: HTMLElement,\n padding: number\n) {\n const elementTop = sectionElement.getBoundingClientRect().top;\n const containerTop = container.getBoundingClientRect().top;\n const targetScrollTop = container.scrollTop + (elementTop - containerTop) - padding;\n container.scrollTo({\n top: targetScrollTop,\n behavior: 'smooth',\n });\n}\n\nfunction getSectionMetrics(\n container: HTMLDivElement,\n stepId: string,\n sectionId: (stepId: string) => string,\n containerRect: DOMRect\n) {\n const sectionElement = getSectionElement(container, stepId, sectionId);\n if (!sectionElement) return null;\n\n const sectionRect = sectionElement.getBoundingClientRect();\n\n return {\n sectionRect,\n visibleHeight: getVisibleHeight(containerRect, sectionRect),\n };\n}\n\nfunction getVisibleHeight(containerRect: DOMRect, sectionRect: DOMRect) {\n return Math.max(\n 0,\n Math.min(sectionRect.bottom, containerRect.bottom) -\n Math.max(sectionRect.top, containerRect.top)\n );\n}\n\nfunction scoreScrollableStep({\n stepIndex,\n stepCount,\n containerRect,\n sectionRect,\n visibleHeight,\n anchorY,\n isNearBottom,\n}: {\n stepIndex: number;\n stepCount: number;\n containerRect: DOMRect;\n sectionRect: DOMRect;\n visibleHeight: number;\n anchorY: number;\n isNearBottom: boolean;\n}) {\n const isVisible = visibleHeight > 0;\n const focusBandTop = containerRect.top + Math.min(containerRect.height * 0.2, 140);\n const focusBandBottom = containerRect.top + Math.min(containerRect.height * 0.55, 360);\n const focusBandOverlap = getBandOverlapHeight(sectionRect, focusBandTop, focusBandBottom);\n const distanceToFocusBand =\n focusBandOverlap > 0\n ? 0\n : Math.min(\n Math.abs(sectionRect.top - focusBandBottom),\n Math.abs(sectionRect.bottom - focusBandTop)\n );\n const isLastStep = stepIndex === stepCount - 1;\n const lastStepProminent =\n isLastStep &&\n visibleHeight >= Math.min(sectionRect.height, containerRect.height) * 0.25 &&\n sectionRect.top <= containerRect.top + containerRect.height * 0.65;\n\n let score = isVisible ? visibleHeight : Number.NEGATIVE_INFINITY;\n\n if (focusBandOverlap > 0) score += 12_000 + focusBandOverlap * 25;\n if (sectionRect.top <= anchorY) score += 250;\n score += Math.max(0, 1_000 - distanceToFocusBand);\n\n if (isNearBottom && lastStepProminent && isVisible) score += 15_000;\n\n return score;\n}\n\nfunction getBandOverlapHeight(sectionRect: DOMRect, bandTop: number, bandBottom: number) {\n return Math.max(0, Math.min(sectionRect.bottom, bandBottom) - Math.max(sectionRect.top, bandTop));\n}\n\nfunction isScrollableNavigationKey(event: KeyboardEvent) {\n if (event.metaKey || event.ctrlKey || event.altKey) return false;\n\n return ['ArrowDown', 'ArrowUp', 'PageDown', 'PageUp', 'Home', 'End', ' '].includes(event.key);\n}\n","import { useCallback, useId, useLayoutEffect, useRef, type ReactNode } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Button } from '../button';\nimport { getSafeStepIndex, useFurthestStepIndex, useScrollableWizardStepTracking } from './hooks';\nimport { WizardNavigation } from './WizardNavigation';\nimport type { StepStatus, WizardStepDef } from './WizardStepper';\nimport { WizardStepper } from './WizardStepper';\n\nexport type { StepStatus, WizardStepDef };\n\nexport interface WizardStepConfig extends WizardStepDef {\n component: ReactNode;\n isValid?: boolean;\n}\n\nexport interface WizardLayoutProps {\n steps: WizardStepConfig[];\n currentStepIndex: number;\n onStepChange: (index: number) => void;\n /**\n * Called when the user completes the wizard from the **scrollable** layout footer\n * (when that footer is shown), or as a fallback when the last step is confirmed\n * in **paged** layouts — see `onLastStepPrimary`.\n */\n onComplete?: () => void;\n /**\n * Called when the user activates the primary control on the **last step** of a\n * **paged** layout (`vertical` / `horizontal`). When omitted, `onComplete` is\n * invoked instead for that interaction.\n */\n onLastStepPrimary?: () => void;\n onCancel?: () => void;\n /** Label for the primary control on non-final steps. @default \"Next\" */\n nextLabel?: string;\n /** Label for the primary control on the last step of paged layouts. @default \"Finish\" */\n lastStepLabel?: string;\n /**\n * Optional secondary control on the **last step** of **paged** layouts only.\n * Rendered to the left of the primary action with an outline style. Both\n * `lastStepSecondaryLabel` and `onLastStepSecondary` must be set for it to appear.\n */\n onLastStepSecondary?: () => void;\n lastStepSecondaryLabel?: string;\n lastStepSecondaryDisabled?: boolean;\n /**\n * When true, the primary Next/Finish control is omitted on the last step of\n * **paged** layouts. Use when the step content provides its own primary action.\n * @default false\n */\n hideLastStepPrimary?: boolean;\n /**\n * When true, the optional footer button at the bottom of the **scrollable**\n * layout is omitted (even if `onComplete` is set).\n * @default false\n */\n hideScrollableCompleteButton?: boolean;\n /** Label for the scrollable layout footer button. @default \"Finish\" */\n scrollableCompleteLabel?: string;\n /**\n * Optional secondary footer button for the **scrollable** layout (outline style),\n * to the left of the complete button. Both `scrollableSecondaryLabel` and\n * `onScrollableSecondary` must be set for it to appear.\n */\n onScrollableSecondary?: () => void;\n scrollableSecondaryLabel?: string;\n scrollableSecondaryDisabled?: boolean;\n /**\n * - `'vertical'` — Vertical sidebar stepper, one step visible at a time (paged).\n * - `'horizontal'` — Horizontal top stepper, one step visible at a time (paged).\n * - `'scrollable'` — Vertical sidebar stepper, all steps on a single scrollable page.\n */\n variant?: 'vertical' | 'horizontal' | 'scrollable';\n /**\n * Optional override for the highest step index reached in paged variants.\n * When omitted, the layout tracks this internally.\n */\n furthestStepIndex?: number;\n /** Extra actions for the bottom navigation bar (paged variants only). */\n navActions?: ReactNode;\n /** Header content rendered above the step content (e.g. title, breadcrumbs). */\n header?: ReactNode;\n /**\n * Pixels of spacing preserved between the container top and an auto-scrolled\n * section heading (`scrollable` variant only). Defaults to 32 (matches `p-8`).\n */\n scrollPadding?: number;\n className?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Paged layout (vertical & horizontal stepper)\n// ---------------------------------------------------------------------------\n\nfunction PagedLayout({\n steps,\n currentStepIndex,\n furthestStepIndex: furthestStepIndexProp,\n onStepChange,\n onComplete,\n onLastStepPrimary,\n onCancel,\n nextLabel,\n lastStepLabel,\n onLastStepSecondary,\n lastStepSecondaryLabel,\n lastStepSecondaryDisabled,\n hideLastStepPrimary,\n navActions,\n header,\n variant,\n className,\n}: WizardLayoutProps & { variant: 'vertical' | 'horizontal' }) {\n const safeIndex = getSafeStepIndex(steps.length, currentStepIndex);\n const resolvedFurthestStepIndex = useFurthestStepIndex(safeIndex, furthestStepIndexProp);\n const stepBodyScrollRef = useRef<HTMLDivElement>(null);\n\n // Paged variants use an inner `overflow-y-auto` body; the document does not scroll.\n // When the user changes steps, reset that panel to the top so the new step starts at the beginning.\n useLayoutEffect(() => {\n const el = stepBodyScrollRef.current;\n if (!el) return;\n el.scrollTop = 0;\n }, [safeIndex]);\n\n if (steps.length === 0) return null;\n\n const isFirstStep = safeIndex === 0;\n const isLastStep = safeIndex === steps.length - 1;\n const currentStep = steps[safeIndex];\n const canProceed = currentStep?.isValid !== false;\n\n const handleNext = () => {\n if (isLastStep) {\n if (onLastStepPrimary) {\n onLastStepPrimary();\n } else {\n onComplete?.();\n }\n return;\n }\n onStepChange(safeIndex + 1);\n };\n\n const handlePrevious = () => {\n if (!isFirstStep) onStepChange(safeIndex - 1);\n };\n\n const stepDefs = toStepDefs(steps, safeIndex);\n\n const navigation = (\n <WizardNavigation\n isFirstStep={isFirstStep}\n isLastStep={isLastStep}\n canProceed={canProceed}\n onPrevious={handlePrevious}\n onNext={handleNext}\n onCancel={onCancel}\n extraActions={navActions}\n nextLabel={nextLabel}\n lastStepLabel={lastStepLabel}\n onLastStepSecondary={onLastStepSecondary}\n lastStepSecondaryLabel={lastStepSecondaryLabel}\n lastStepSecondaryDisabled={lastStepSecondaryDisabled}\n showLastStepPrimary={!hideLastStepPrimary}\n />\n );\n\n const footer = (\n <div className=\"shrink-0 border-t border-border bg-background px-8 py-4\">\n <div className=\"mx-auto max-w-5xl\">{navigation}</div>\n </div>\n );\n\n if (variant === 'vertical') {\n return (\n <div className={cn('flex h-full gap-6', className)}>\n <div className=\"w-[220px] shrink-0 py-6 pl-6\">\n <WizardStepper\n variant=\"vertical\"\n steps={stepDefs}\n currentStepIndex={safeIndex}\n furthestStepIndex={resolvedFurthestStepIndex}\n onStepClick={onStepChange}\n className=\"h-full\"\n />\n </div>\n\n <div className=\"flex min-w-0 flex-1 flex-col overflow-hidden\">\n <div ref={stepBodyScrollRef} className=\"flex-1 overflow-y-auto p-8\">\n <div className=\"mx-auto max-w-5xl\">\n {header}\n {currentStep?.component}\n </div>\n </div>\n {footer}\n </div>\n </div>\n );\n }\n\n return (\n <div className={cn('flex h-full flex-col', className)}>\n <div className=\"shrink-0 p-6 pb-0\">\n <WizardStepper\n variant=\"horizontal\"\n steps={stepDefs}\n currentStepIndex={safeIndex}\n furthestStepIndex={resolvedFurthestStepIndex}\n onStepClick={onStepChange}\n />\n </div>\n\n <div className=\"flex min-w-0 flex-1 flex-col overflow-hidden\">\n <div ref={stepBodyScrollRef} className=\"flex-1 overflow-y-auto p-8\">\n <div className=\"mx-auto max-w-5xl\">\n {header}\n {currentStep?.component}\n </div>\n </div>\n {footer}\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Scrollable layout — all sections on one page, scroll-tracked stepper\n// ---------------------------------------------------------------------------\n\nfunction ScrollableLayout({\n steps,\n currentStepIndex,\n onStepChange,\n header,\n onComplete,\n hideScrollableCompleteButton,\n scrollableCompleteLabel,\n onScrollableSecondary,\n scrollableSecondaryLabel,\n scrollableSecondaryDisabled,\n scrollPadding,\n className,\n}: Pick<\n WizardLayoutProps,\n | 'steps'\n | 'currentStepIndex'\n | 'onStepChange'\n | 'header'\n | 'onComplete'\n | 'hideScrollableCompleteButton'\n | 'scrollableCompleteLabel'\n | 'onScrollableSecondary'\n | 'scrollableSecondaryLabel'\n | 'scrollableSecondaryDisabled'\n | 'scrollPadding'\n | 'className'\n>) {\n const instanceId = useId();\n const scrollRef = useRef<HTMLDivElement>(null);\n const sectionId = useCallback(\n (stepId: string) => `wizard-section-${instanceId}-${stepId}`,\n [instanceId]\n );\n const { activeIndex, furthestStepIndex, scrollToSection } = useScrollableWizardStepTracking({\n steps,\n currentStepIndex,\n onStepChange,\n scrollRef,\n sectionId,\n scrollPadding,\n });\n\n if (steps.length === 0) return null;\n\n const stepDefs = toStepDefs(steps, activeIndex);\n\n const showScrollableSecondary =\n onScrollableSecondary != null &&\n scrollableSecondaryLabel != null &&\n scrollableSecondaryLabel !== '';\n const showScrollablePrimary = onComplete != null && !hideScrollableCompleteButton;\n const showScrollableFooter = showScrollableSecondary || showScrollablePrimary;\n\n return (\n <div className={cn('flex h-full gap-6', className)}>\n <div className=\"w-[220px] shrink-0 py-6 pl-6\">\n <WizardStepper\n variant=\"vertical\"\n steps={stepDefs}\n currentStepIndex={activeIndex}\n furthestStepIndex={furthestStepIndex}\n onStepClick={scrollToSection}\n freeNavigation\n className=\"h-full\"\n />\n </div>\n\n <div ref={scrollRef} className=\"flex min-w-0 flex-1 flex-col overflow-y-auto p-8\">\n {header}\n <div className=\"space-y-12\">\n {steps.map((step) => (\n <section key={step.id} id={sectionId(step.id)}>\n {step.component}\n </section>\n ))}\n </div>\n\n {showScrollableFooter && (\n <div className=\"flex justify-end gap-2 pt-8\">\n {showScrollableSecondary && (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onScrollableSecondary}\n disabled={scrollableSecondaryDisabled ?? false}\n >\n {scrollableSecondaryLabel}\n </Button>\n )}\n {showScrollablePrimary && (\n <Button type=\"button\" onClick={onComplete}>\n {scrollableCompleteLabel ?? 'Finish'}\n </Button>\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction toStepDefs(steps: WizardStepConfig[], currentStepIndex: number): WizardStepDef[] {\n return steps.map((s, i) => {\n // isInvalid on WizardStepDef takes explicit precedence; isValid on\n // WizardStepConfig is the convenience shorthand when not set.\n const isInvalid = s.isInvalid ?? s.isValid === false;\n // Don't auto-assign 'completed' for invalid past steps — resolveState\n // needs to see isInvalid=true to render the error indicator instead.\n const status = s.status ?? (i < currentStepIndex && !isInvalid ? 'completed' : 'pending');\n return { id: s.id, title: s.title, status, isInvalid };\n });\n}\n\n// ---------------------------------------------------------------------------\n// Public component\n// ---------------------------------------------------------------------------\n\n/**\n * A layout component for the wizard.\n *\n * @param props - The props for the WizardLayout component.\n * @returns A React node representing the layout component.\n */\nexport function WizardLayout(props: WizardLayoutProps) {\n const { variant = 'horizontal', ...rest } = props;\n\n if (variant === 'scrollable') {\n return (\n <ScrollableLayout\n steps={rest.steps}\n currentStepIndex={rest.currentStepIndex}\n onStepChange={rest.onStepChange}\n header={rest.header}\n onComplete={rest.onComplete}\n hideScrollableCompleteButton={rest.hideScrollableCompleteButton}\n scrollableCompleteLabel={rest.scrollableCompleteLabel}\n onScrollableSecondary={rest.onScrollableSecondary}\n scrollableSecondaryLabel={rest.scrollableSecondaryLabel}\n scrollableSecondaryDisabled={rest.scrollableSecondaryDisabled}\n scrollPadding={rest.scrollPadding}\n className={rest.className}\n />\n );\n }\n\n return <PagedLayout {...rest} variant={variant} />;\n}\n","import { createContext } from 'react';\n\nimport type { AddressSuggestionResolver } from '@openzeppelin/ui-types';\n\n/**\n * @internal Shared context instance consumed by both AddressField and\n * AddressSuggestionProvider. Kept in its own file so component files export\n * only components (required by React Fast Refresh).\n */\nexport const AddressSuggestionContext = createContext<AddressSuggestionResolver | null>(null);\n","/**\n * Accessibility utilities for form field components\n */\n\n/**\n * Default aria-describedby ID generator based on field ID\n */\nexport function getDescribedById(\n id: string,\n type: 'error' | 'description' | 'counter' = 'error'\n): string {\n return `${id}-${type}`;\n}\n\n/**\n * Interface for accessibility attributes to be applied to form fields\n */\nexport interface AccessibilityProps {\n /**\n * ARIA attributes for accessibility\n */\n 'aria-invalid'?: boolean;\n 'aria-required'?: boolean;\n 'aria-describedby'?: string;\n 'aria-errormessage'?: string;\n 'aria-labelledby'?: string;\n\n /**\n * Indicates if the input is required\n */\n required?: boolean;\n\n /**\n * Indicates if the input is disabled\n */\n disabled?: boolean;\n\n /**\n * Indicates if the input is readonly\n */\n readOnly?: boolean;\n\n /**\n * Tab index for keyboard navigation\n * Use 0 for normal tab order\n * Use -1 to remove from tab order\n */\n tabIndex?: number;\n}\n\n/**\n * Generates accessibility attributes for form fields\n */\nexport function getAccessibilityProps({\n id,\n hasError = false,\n isRequired = false,\n isDisabled = false,\n isReadOnly = false,\n hasHelperText = false,\n hasCharacterCounter = false,\n}: {\n id: string;\n hasError?: boolean;\n isRequired?: boolean;\n isDisabled?: boolean;\n isReadOnly?: boolean;\n hasHelperText?: boolean;\n hasCharacterCounter?: boolean;\n}): AccessibilityProps {\n // Build aria-describedby referencing multiple elements if needed\n const describedByIds: string[] = [];\n\n if (hasError) {\n describedByIds.push(getDescribedById(id, 'error'));\n }\n\n if (hasHelperText) {\n describedByIds.push(getDescribedById(id, 'description'));\n }\n\n if (hasCharacterCounter) {\n describedByIds.push(getDescribedById(id, 'counter'));\n }\n\n return {\n 'aria-invalid': hasError,\n 'aria-required': isRequired,\n 'aria-describedby': describedByIds.length > 0 ? describedByIds.join(' ') : undefined,\n 'aria-errormessage': hasError ? getDescribedById(id, 'error') : undefined,\n required: isRequired,\n disabled: isDisabled,\n readOnly: isReadOnly,\n tabIndex: isDisabled ? -1 : 0,\n };\n}\n\n/**\n * Utility function to handle keyboard events for interactive elements\n * Helps ensure keyboard users can interact with form controls\n */\nexport function handleKeyboardEvent(\n event: React.KeyboardEvent,\n handlers: {\n onEnter?: () => void;\n onSpace?: () => void;\n onEscape?: () => void;\n onArrowUp?: () => void;\n onArrowDown?: () => void;\n onArrowLeft?: () => void;\n onArrowRight?: () => void;\n onTab?: () => void;\n }\n): void {\n switch (event.key) {\n case 'Enter':\n if (handlers.onEnter) {\n event.preventDefault();\n handlers.onEnter();\n }\n break;\n case ' ':\n if (handlers.onSpace) {\n event.preventDefault();\n handlers.onSpace();\n }\n break;\n case 'Escape':\n if (handlers.onEscape) {\n event.preventDefault();\n handlers.onEscape();\n }\n break;\n case 'ArrowUp':\n if (handlers.onArrowUp) {\n event.preventDefault();\n handlers.onArrowUp();\n }\n break;\n case 'ArrowDown':\n if (handlers.onArrowDown) {\n event.preventDefault();\n handlers.onArrowDown();\n }\n break;\n case 'ArrowLeft':\n if (handlers.onArrowLeft) {\n event.preventDefault();\n handlers.onArrowLeft();\n }\n break;\n case 'ArrowRight':\n if (handlers.onArrowRight) {\n event.preventDefault();\n handlers.onArrowRight();\n }\n break;\n case 'Tab':\n if (handlers.onTab) {\n event.preventDefault();\n handlers.onTab();\n }\n break;\n default:\n break;\n }\n}\n\n/**\n * Field focus management utility\n * For managing focus within a field group or complex form component\n */\nexport function createFocusManager(): {\n focusFirstElement: (container: HTMLElement | null) => void;\n focusElementById: (id: string) => void;\n trapFocus: (event: KeyboardEvent, container: HTMLElement | null) => void;\n} {\n return {\n /**\n * Focus the first focusable element within a container\n */\n focusFirstElement(container: HTMLElement | null): void {\n if (!container) return;\n\n const focusable = container.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n );\n\n if (focusable.length > 0) {\n focusable[0].focus();\n }\n },\n\n /**\n * Focus a specific element by ID\n */\n focusElementById(id: string): void {\n const element = document.getElementById(id);\n if (element) {\n element.focus();\n }\n },\n\n /**\n * Trap focus within a container (for modals, dropdowns, etc.)\n */\n trapFocus(event: KeyboardEvent, container: HTMLElement | null): void {\n if (!container || event.key !== 'Tab') return;\n\n const focusable = Array.from(\n container.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n )\n );\n\n if (focusable.length === 0) return;\n\n const firstElement = focusable[0];\n const lastElement = focusable[focusable.length - 1];\n\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n } else if (!event.shiftKey && document.activeElement === lastElement) {\n event.preventDefault();\n firstElement.focus();\n }\n },\n };\n}\n\n/**\n * Provides a handler for Escape key to clear input fields\n *\n * @param onChange - Function to call when value changes\n * @param value - Current value of the input\n * @returns A function to handle the Escape key press\n */\nexport function handleEscapeKey(\n onChange: (value: string) => void,\n value: unknown\n): (e: React.KeyboardEvent) => void {\n return (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n\n // Only reset if there's a value to clear\n if (value) {\n onChange('');\n } else {\n // If already empty, blur the field\n (e.target as HTMLElement).blur();\n }\n }\n };\n}\n\n/**\n * Provides a handler for Space/Enter keys for toggle components (checkboxes, switches)\n *\n * @param onChange - Function to call when value changes\n * @param value - Current value of the input\n * @returns A function to handle the Space/Enter key press\n */\nexport function handleToggleKeys(\n onChange: (value: boolean) => void,\n value: boolean\n): (e: React.KeyboardEvent) => void {\n return (e: React.KeyboardEvent) => {\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n onChange(!value);\n }\n };\n}\n\n/**\n * Provides a handler for arrow keys for numeric inputs\n *\n * @param onChange - Function to call when value changes\n * @param value - Current numeric value\n * @param step - Step amount for increments/decrements\n * @param min - Minimum allowed value (optional)\n * @param max - Maximum allowed value (optional)\n * @returns A function to handle arrow key presses\n */\nexport function handleNumericKeys(\n onChange: (value: number) => void,\n value: number,\n step: number = 1,\n min?: number,\n max?: number\n): (e: React.KeyboardEvent) => void {\n return (e: React.KeyboardEvent) => {\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n const direction = e.key === 'ArrowUp' ? 1 : -1;\n let newValue = typeof value === 'number' ? value + step * direction : 0;\n\n // Apply min/max constraints if provided\n if (typeof min === 'number') newValue = Math.max(min, newValue);\n if (typeof max === 'number') newValue = Math.min(max, newValue);\n\n onChange(newValue);\n }\n };\n}\n","/**\n * Layout utility functions for form components\n */\n\n/**\n * Helper function to get width classes based on the field width\n */\nexport function getWidthClasses(width: 'full' | 'half' | 'third'): string {\n switch (width) {\n case 'half':\n return 'form-field-half';\n case 'third':\n return 'form-field-third';\n case 'full':\n default:\n return 'form-field-full';\n }\n}\n","import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { Controller, FieldValues, useWatch } from 'react-hook-form';\n\nimport type { AddressingCapability, AddressSuggestion } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { AddressSuggestionContext } from './address-suggestion/context';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n validateField,\n} from './utils';\n\nconst DEBOUNCE_MS = 200;\nconst MAX_SUGGESTIONS = 5;\n\ninterface AddressFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n addressing?: AddressingCapability;\n\n /**\n * Explicit suggestion list. When provided, overrides context-based resolution.\n * Pass `false` to disable suggestions entirely (even when a context provider is mounted).\n *\n * Note: context-resolved suggestions are automatically capped at\n * `MAX_SUGGESTIONS` (5) entries, while explicitly passed arrays are\n * rendered as-is — callers should pre-slice if needed.\n */\n suggestions?: AddressSuggestion[] | false;\n\n /**\n * Called when the user selects a suggestion. Receives the selected suggestion\n * so callers can perform additional side-effects beyond filling the field value.\n */\n onSuggestionSelect?: (suggestion: AddressSuggestion) => void;\n}\n\n/**\n * Address input field component specifically designed for blockchain addresses via React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like AddressField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles blockchain address-specific rendering and validation using the passed addressing capability\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Blockchain address validation through the provided addressing capability\n * - Automatic error handling and reporting\n * - Chain-agnostic design (validation handled by capabilities)\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation\n *\n * Autocomplete suggestions can be provided in two ways:\n *\n * 1. **Context-based (zero-config)**: Mount an `AddressSuggestionProvider` in the\n * component tree. Every `AddressField` below it automatically resolves suggestions.\n *\n * 2. **Prop-based (explicit)**: Pass `suggestions` directly. This overrides context.\n * Pass `suggestions={false}` to opt out when a provider is mounted.\n *\n * The suggestion dropdown includes built-in debouncing, keyboard navigation (Arrow keys,\n * Enter, Escape), click-outside dismissal, and ARIA listbox semantics.\n */\nexport function AddressField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n addressing,\n readOnly,\n suggestions: suggestionsProp,\n onSuggestionSelect,\n}: AddressFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n const contextResolver = useContext(AddressSuggestionContext);\n const containerRef = useRef<HTMLDivElement>(null);\n const lastSetValueRef = useRef<string>('');\n\n const [inputValue, setInputValue] = useState('');\n const [debouncedQuery, setDebouncedQuery] = useState('');\n const [showSuggestions, setShowSuggestions] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n\n const watchedFieldValue = useWatch({ control, name }) as string | undefined;\n\n useEffect(() => {\n const currentFieldValue = watchedFieldValue ?? '';\n if (currentFieldValue !== lastSetValueRef.current) {\n lastSetValueRef.current = currentFieldValue;\n setInputValue(currentFieldValue);\n }\n }, [watchedFieldValue]);\n\n useEffect(() => {\n if (!inputValue.trim()) {\n setDebouncedQuery('');\n return;\n }\n const timer = setTimeout(() => setDebouncedQuery(inputValue), DEBOUNCE_MS);\n return () => clearTimeout(timer);\n }, [inputValue]);\n\n const suggestionsDisabled = suggestionsProp === false;\n\n const resolvedSuggestions = useMemo<AddressSuggestion[]>(() => {\n if (suggestionsDisabled) return [];\n if (Array.isArray(suggestionsProp)) return suggestionsProp;\n if (!contextResolver || !debouncedQuery.trim()) return [];\n return contextResolver.resolveSuggestions(debouncedQuery).slice(0, MAX_SUGGESTIONS);\n }, [suggestionsDisabled, suggestionsProp, contextResolver, debouncedQuery]);\n\n const hasSuggestions = showSuggestions && resolvedSuggestions.length > 0;\n\n useEffect(() => {\n let active = true;\n const handleClickOutside = (e: MouseEvent) => {\n if (active && containerRef.current && !containerRef.current.contains(e.target as Node)) {\n setShowSuggestions(false);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => {\n active = false;\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, []);\n\n const handleSuggestionKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (!hasSuggestions) return;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setHighlightedIndex((prev) => (prev < resolvedSuggestions.length - 1 ? prev + 1 : 0));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setHighlightedIndex((prev) => (prev > 0 ? prev - 1 : resolvedSuggestions.length - 1));\n }\n },\n [hasSuggestions, resolvedSuggestions.length]\n );\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Check required field explicitly first\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Perform standard validations (min, max, pattern, etc.) if they exist\n // Using the existing validateField utility for this part\n const standardValidationResult = validateField(value, validation);\n if (standardValidationResult !== true) {\n return standardValidationResult;\n }\n\n // Perform capability-specific address validation if addressing exists\n if (addressing && typeof value === 'string') {\n if (!addressing.isValidAddress(value)) {\n return 'Invalid address format for the selected chain';\n }\n }\n\n // If all checks pass\n return true;\n },\n }}\n disabled={readOnly}\n render={({ fieldState: { error, isTouched }, field }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Safely extract the pattern error message. The `pattern` validation rule can be either a\n // RegExp object or an object with a `value` (RegExp) and a `message` (string). This\n // type guard ensures we only try to access `.message` on the correct object type.\n const patternErrorMessage =\n validation?.pattern &&\n typeof validation.pattern === 'object' &&\n 'message' in validation.pattern\n ? (validation.pattern.message as string)\n : undefined;\n\n // Handle input change with validation\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const value = e.target.value;\n field.onChange(value);\n lastSetValueRef.current = value;\n setInputValue(value);\n setShowSuggestions(value.length > 0);\n setHighlightedIndex(-1);\n };\n\n const applySuggestion = (suggestion: AddressSuggestion): void => {\n field.onChange(suggestion.value);\n onSuggestionSelect?.(suggestion);\n lastSetValueRef.current = suggestion.value;\n setInputValue(suggestion.value);\n setShowSuggestions(false);\n setHighlightedIndex(-1);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n if (hasSuggestions && e.key === 'Enter' && highlightedIndex >= 0) {\n e.preventDefault();\n applySuggestion(resolvedSuggestions[highlightedIndex]);\n return;\n }\n\n if (e.key === 'Escape') {\n if (hasSuggestions) {\n setShowSuggestions(false);\n return;\n }\n handleEscapeKey(field.onChange, field.value)(e);\n }\n };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <div ref={containerRef} className=\"relative\" onKeyDown={handleSuggestionKeyDown}>\n <Input\n {...field}\n id={id}\n placeholder={placeholder || '0x...'}\n className={validationClasses}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n value={field.value ?? ''}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n aria-expanded={hasSuggestions}\n aria-autocomplete={suggestionsDisabled ? undefined : 'list'}\n aria-controls={hasSuggestions ? `${id}-suggestions` : undefined}\n aria-activedescendant={\n hasSuggestions && highlightedIndex >= 0\n ? `${id}-suggestion-${highlightedIndex}`\n : undefined\n }\n disabled={readOnly}\n />\n\n {hasSuggestions && (\n <div\n id={`${id}-suggestions`}\n className={cn(\n 'absolute z-50 mt-1 w-full rounded-md border border-border bg-popover shadow-md',\n 'max-h-48 overflow-auto'\n )}\n role=\"listbox\"\n >\n {resolvedSuggestions.map((s, i) => (\n <button\n key={`${s.value}-${s.description ?? i}`}\n id={`${id}-suggestion-${i}`}\n type=\"button\"\n role=\"option\"\n aria-selected={i === highlightedIndex}\n className={cn(\n 'flex w-full flex-col px-3 py-2 text-left text-sm',\n 'hover:bg-selected/10',\n i === highlightedIndex && 'bg-selected/10'\n )}\n onMouseDown={(e) => {\n e.preventDefault();\n applySuggestion(s);\n }}\n onMouseEnter={() => setHighlightedIndex(i)}\n >\n <span className=\"font-medium\">{s.label}</span>\n <span className=\"truncate font-mono text-xs text-muted-foreground\">\n {s.value}\n </span>\n </button>\n ))}\n </div>\n )}\n </div>\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message || patternErrorMessage : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nAddressField.displayName = 'AddressField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Label } from '../ui/label';\nimport { Textarea } from '../ui/textarea';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n} from './utils';\n\n/**\n * TextAreaField component properties\n */\nexport interface TextAreaFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Number of rows for the textarea\n */\n rows?: number;\n\n /**\n * Maximum characters allowed in textarea\n */\n maxLength?: number;\n\n /**\n * Custom validation function for textarea values\n */\n validateTextArea?: (value: string) => boolean | string;\n}\n\n/**\n * Multi-line text input field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles textarea-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Resizable multi-line text input\n * - Character limit support\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation with Escape to clear\n */\nexport function TextAreaField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n rows = 4,\n maxLength,\n validateTextArea,\n readOnly,\n}: TextAreaFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Run custom validation if provided\n if (validateTextArea && value) {\n const validation = validateTextArea(value);\n if (validation !== true && typeof validation === 'string') {\n return validation;\n }\n }\n\n // Check maximum length\n if (maxLength && typeof value === 'string' && value.length > maxLength) {\n return `Maximum length is ${maxLength} characters`;\n }\n\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <Textarea\n {...field}\n id={id}\n placeholder={placeholder}\n rows={rows}\n maxLength={maxLength}\n className={validationClasses}\n value={field.value ?? ''}\n disabled={readOnly}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n onKeyDown={handleEscapeKey((value) => {\n if (typeof field.onChange === 'function') {\n field.onChange(value);\n }\n }, field.value)}\n />\n\n {/* Display character count if maxLength is provided */}\n {maxLength && typeof field.value === 'string' && (\n <div className=\"text-muted-foreground text-right text-xs\">\n {field.value.length}/{maxLength}\n </div>\n )}\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nTextAreaField.displayName = 'TextAreaField';\n","import type { AddressCandidateClassification } from '@openzeppelin/ui-utils';\n\n/**\n * Localizable UI strings for {@link AddressListField} built-in chrome\n * (buttons, previews, bulk-add feedback). Domain copy such as placeholders and\n * format hints are passed as component props instead.\n */\nexport interface AddressListFieldLabels {\n addSingleAddress: string;\n invalidSingleAddress: string;\n enableBulkEntry: string;\n enableSingleEntry: string;\n addAddresses: string;\n addAddressCount: (count: number) => string;\n invalidPrefix: string;\n invalidMore: (extraCount: number) => string;\n maxItemsReached: (maxItems: number) => string;\n addressesAdded: (count: number) => string;\n removeAddress: (index: number) => string;\n previewReadyToAdd: (count: number) => string;\n previewInvalid: (count: number) => string;\n previewAlreadyListed: (count: number) => string;\n previewDuplicateInPaste: (count: number) => string;\n bulkNothingAdded: string;\n bulkAdded: (count: number) => string;\n bulkInvalidFormats: (count: number) => string;\n bulkAlreadyListed: (count: number) => string;\n bulkDuplicatesInPaste: (count: number) => string;\n}\n\n/** Default English labels for {@link AddressListField}. */\nexport const DEFAULT_ADDRESS_LIST_FIELD_LABELS: AddressListFieldLabels = {\n addSingleAddress: 'Add',\n invalidSingleAddress: 'Enter a valid address',\n enableBulkEntry: 'Bulk paste',\n enableSingleEntry: 'Single entry',\n addAddresses: 'Add addresses',\n addAddressCount: (count) => `Add ${count} address${count === 1 ? '' : 'es'}`,\n invalidPrefix: 'Invalid:',\n invalidMore: (extraCount) => `(+${extraCount} more)`,\n maxItemsReached: (maxItems) => `Maximum of ${maxItems} addresses reached.`,\n addressesAdded: (count) => `${count} address${count === 1 ? '' : 'es'} added`,\n removeAddress: (index) => `Remove address ${index + 1}`,\n previewReadyToAdd: (count) => `${count} ready to add`,\n previewInvalid: (count) => `${count} invalid`,\n previewAlreadyListed: (count) => `${count} already listed`,\n previewDuplicateInPaste: (count) => `${count} duplicate in paste`,\n bulkNothingAdded: 'No addresses were added. Check formatting and try again.',\n bulkAdded: (count) => `Added ${count} address${count === 1 ? '' : 'es'}`,\n bulkInvalidFormats: (count) => `${count} invalid format${count === 1 ? '' : 's'}`,\n bulkAlreadyListed: (count) => `${count} already listed`,\n bulkDuplicatesInPaste: (count) => `${count} duplicate${count === 1 ? '' : 's'} in paste`,\n};\n\n/** Merges {@link DEFAULT_ADDRESS_LIST_FIELD_LABELS} with optional overrides. */\nexport function resolveAddressListFieldLabels(\n overrides?: Partial<AddressListFieldLabels>\n): AddressListFieldLabels {\n return { ...DEFAULT_ADDRESS_LIST_FIELD_LABELS, ...overrides };\n}\n\n/** Builds the inline helper preview shown while the user types in the draft textarea. */\nexport function buildAddressListPreviewSummary(\n classification: AddressCandidateClassification | null,\n labels: AddressListFieldLabels\n): string | null {\n if (!classification) return null;\n\n const skipped =\n classification.invalid.length +\n classification.alreadyListed.length +\n classification.duplicatesInInput.length;\n if (classification.accepted.length === 0 && skipped === 0) return null;\n\n const parts: string[] = [];\n if (classification.accepted.length > 0) {\n parts.push(labels.previewReadyToAdd(classification.accepted.length));\n }\n if (classification.invalid.length > 0) {\n parts.push(labels.previewInvalid(classification.invalid.length));\n }\n if (classification.alreadyListed.length > 0) {\n parts.push(labels.previewAlreadyListed(classification.alreadyListed.length));\n }\n if (classification.duplicatesInInput.length > 0) {\n parts.push(labels.previewDuplicateInPaste(classification.duplicatesInInput.length));\n }\n return parts.join(' · ');\n}\n\n/** Formats post-add feedback after the user commits parsed addresses to the list. */\nexport function formatAddressBulkSummary(\n classification: AddressCandidateClassification,\n addedCount: number,\n labels: AddressListFieldLabels\n): string | null {\n if (addedCount === 0 && classification.accepted.length === 0) {\n const skipped =\n classification.invalid.length +\n classification.alreadyListed.length +\n classification.duplicatesInInput.length;\n if (skipped === 0) return null;\n return labels.bulkNothingAdded;\n }\n\n const parts: string[] = [];\n if (addedCount > 0) {\n parts.push(labels.bulkAdded(addedCount));\n }\n if (classification.invalid.length > 0) {\n parts.push(labels.bulkInvalidFormats(classification.invalid.length));\n }\n if (classification.alreadyListed.length > 0) {\n parts.push(labels.bulkAlreadyListed(classification.alreadyListed.length));\n }\n if (classification.duplicatesInInput.length > 0) {\n parts.push(labels.bulkDuplicatesInPaste(classification.duplicatesInInput.length));\n }\n\n if (parts.length === 0) return null;\n\n return parts.join('. ') + '.';\n}\n","import { Info, Plus } from 'lucide-react';\nimport { useCallback, useMemo, useState, type ReactNode } from 'react';\nimport { useForm } from 'react-hook-form';\n\nimport type { AddressingCapability } from '@openzeppelin/ui-types';\nimport { classifyAddressCandidates, parseDelimitedAddressInput } from '@openzeppelin/ui-utils';\n\nimport { Button } from '../../ui/button';\nimport { TextAreaField } from '../TextAreaField';\nimport {\n buildAddressListPreviewSummary,\n formatAddressBulkSummary,\n type AddressListFieldLabels,\n} from './labels';\n\ninterface AddressListBulkDraftForm {\n input: string;\n}\n\nexport interface AddressListBulkEntryProps {\n fieldId: string;\n value: readonly string[];\n onAdd: (addresses: string[]) => void;\n placeholder: string;\n formatHint: string;\n addressing?: AddressingCapability;\n maxItems?: number;\n disabled?: boolean;\n maxInvalidPreview?: number;\n labels: AddressListFieldLabels;\n /** Entry-mode toggle rendered flush to the textarea's right edge. */\n modeToggle?: ReactNode;\n}\n\n/** Bulk paste entry — info callout, textarea, and add action in a compact stack. */\nexport function AddressListBulkEntry({\n fieldId,\n value,\n onAdd,\n placeholder,\n formatHint,\n addressing,\n maxItems,\n disabled = false,\n maxInvalidPreview = 3,\n labels,\n modeToggle,\n}: AddressListBulkEntryProps) {\n const atLimit = maxItems != null && value.length >= maxItems;\n const inputDisabled = disabled || atLimit;\n const [feedback, setFeedback] = useState<string | null>(null);\n\n const { control, reset, watch } = useForm<AddressListBulkDraftForm>({\n defaultValues: { input: '' },\n mode: 'onChange',\n });\n\n const rawInput = watch('input');\n const classification = useMemo(() => {\n if (!rawInput.trim()) return null;\n return classifyAddressCandidates(\n parseDelimitedAddressInput(rawInput),\n value,\n addressing,\n maxItems\n );\n }, [rawInput, value, addressing, maxItems]);\n\n const previewSummary = useMemo(\n () => buildAddressListPreviewSummary(classification, labels),\n [classification, labels]\n );\n\n const statusMessage = rawInput.trim() ? (previewSummary ?? undefined) : (feedback ?? undefined);\n\n const handleAdd = useCallback(() => {\n if (!classification || classification.accepted.length === 0 || atLimit) return;\n onAdd(classification.accepted);\n reset({ input: '' });\n setFeedback(formatAddressBulkSummary(classification, classification.accepted.length, labels));\n }, [classification, atLimit, onAdd, reset, labels]);\n\n const acceptedCount = classification?.accepted.length ?? 0;\n const addButtonLabel =\n acceptedCount > 0 ? labels.addAddressCount(acceptedCount) : labels.addAddresses;\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-start gap-2 rounded-lg border border-border/70 bg-muted/30 px-3 py-2.5\">\n <Info className=\"mt-0.5 size-4 shrink-0 text-muted-foreground\" />\n <p className=\"text-xs leading-relaxed text-muted-foreground\">{formatHint}</p>\n </div>\n\n <div>\n <div className=\"relative\">\n <TextAreaField\n id={`address-list-bulk-${fieldId}`}\n name=\"input\"\n label=\"\"\n placeholder={placeholder}\n helperText={statusMessage}\n control={control}\n rows={4}\n validation={{ required: false }}\n readOnly={inputDisabled}\n />\n </div>\n {modeToggle ? <div className=\"flex justify-end pr-2\">{modeToggle}</div> : null}\n </div>\n\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <div className=\"min-w-0 flex-1\">\n {classification && classification.invalid.length > 0 ? (\n <p className=\"text-xs text-destructive\">\n {labels.invalidPrefix} {classification.invalid.slice(0, maxInvalidPreview).join(', ')}\n {classification.invalid.length > maxInvalidPreview\n ? ` ${labels.invalidMore(classification.invalid.length - maxInvalidPreview)}`\n : ''}\n </p>\n ) : null}\n {atLimit && maxItems != null ? (\n <p className=\"text-xs text-muted-foreground\">{labels.maxItemsReached(maxItems)}</p>\n ) : null}\n </div>\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"shrink-0\"\n disabled={inputDisabled || acceptedCount === 0}\n onClick={() => handleAdd()}\n >\n <Plus className=\"mr-1 size-4\" />\n {addButtonLabel}\n </Button>\n </div>\n </div>\n );\n}\n","import { X } from 'lucide-react';\n\nimport { AddressDisplay } from '../../ui/address-display';\nimport { Button } from '../../ui/button';\nimport type { AddressListFieldLabels } from './labels';\n\nexport interface AddressListEntriesProps {\n value: readonly string[];\n getExplorerUrl?: (address: string) => string | null | undefined;\n disabled?: boolean;\n labels: AddressListFieldLabels;\n onRemove: (index: number) => void;\n}\n\n/** Renders committed addresses with remove actions. Shared by single and bulk entry modes. */\nexport function AddressListEntries({\n value,\n getExplorerUrl,\n disabled = false,\n labels,\n onRemove,\n}: AddressListEntriesProps) {\n if (value.length === 0) return null;\n\n return (\n <div className=\"space-y-1\">\n <p className=\"text-xs text-muted-foreground\">{labels.addressesAdded(value.length)}</p>\n <div className=\"max-h-44 space-y-1 overflow-y-auto rounded-md border border-border/70 p-1\">\n {value.map((address, index) => (\n <div\n key={`${address}-${index}`}\n className=\"flex items-center justify-between rounded bg-muted p-2\"\n >\n <AddressDisplay\n address={address}\n variant=\"inline\"\n truncateWhenLabeled\n showCopyButton\n explorerUrl={getExplorerUrl?.(address) ?? undefined}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"size-7 shrink-0 p-0 text-muted-foreground hover:text-destructive\"\n onClick={() => onRemove(index)}\n disabled={disabled}\n aria-label={labels.removeAddress(index)}\n >\n <X className=\"size-3.5\" />\n </Button>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { Plus } from 'lucide-react';\nimport { useCallback, useMemo, type ReactNode } from 'react';\nimport { useForm, useWatch } from 'react-hook-form';\n\nimport type { AddressingCapability } from '@openzeppelin/ui-types';\n\nimport { Button } from '../../ui/button';\nimport { AddressField } from '../AddressField';\nimport type { AddressListFieldLabels } from './labels';\n\ninterface AddressListSingleDraftForm {\n draft: string;\n}\n\nexport interface AddressListSingleEntryProps {\n fieldId: string;\n value: readonly string[];\n onAdd: (address: string) => void;\n placeholder: string;\n addressing?: AddressingCapability;\n maxItems?: number;\n disabled?: boolean;\n labels: AddressListFieldLabels;\n /** Entry-mode toggle rendered flush to the input's right edge. */\n modeToggle?: ReactNode;\n}\n\n/** Single-address entry — inline {@link AddressField} with an Add button (address-book aware). */\nexport function AddressListSingleEntry({\n fieldId,\n value,\n onAdd,\n placeholder,\n addressing,\n maxItems,\n disabled = false,\n labels,\n modeToggle,\n}: AddressListSingleEntryProps) {\n const atLimit = maxItems != null && value.length >= maxItems;\n const inputDisabled = disabled || atLimit;\n\n const { control, reset, getValues, handleSubmit } = useForm<AddressListSingleDraftForm>({\n defaultValues: { draft: '' },\n mode: 'onChange',\n });\n\n const draft = useWatch({ control, name: 'draft' });\n const trimmedDraft = (draft ?? '').trim();\n\n const validationState = useMemo(() => {\n if (!trimmedDraft) return { canAdd: false, showInvalid: false };\n if (value.includes(trimmedDraft)) return { canAdd: false, showInvalid: false };\n if (atLimit) return { canAdd: false, showInvalid: false };\n if (addressing && !addressing.isValidAddress(trimmedDraft)) {\n return { canAdd: false, showInvalid: true };\n }\n return { canAdd: true, showInvalid: false };\n }, [trimmedDraft, value, atLimit, addressing]);\n\n const submitAdd = useCallback(() => {\n if (!validationState.canAdd) return;\n onAdd(getValues('draft').trim());\n reset({ draft: '' });\n }, [validationState.canAdd, onAdd, getValues, reset]);\n\n return (\n <div className=\"space-y-1\">\n <div className=\"flex items-start gap-2\">\n <div className=\"min-w-0 flex-1\">\n <AddressField\n id={`address-list-single-${fieldId}`}\n name=\"draft\"\n label=\"\"\n placeholder={placeholder}\n helperText={validationState.showInvalid ? labels.invalidSingleAddress : undefined}\n control={control}\n addressing={addressing}\n validation={{ required: false }}\n readOnly={inputDisabled}\n />\n {modeToggle ? <div className=\"-mt-px flex justify-end pr-2\">{modeToggle}</div> : null}\n </div>\n <Button\n type=\"button\"\n className=\"h-10 shrink-0\"\n disabled={inputDisabled || !validationState.canAdd}\n onClick={handleSubmit(submitAdd)}\n >\n <Plus className=\"mr-1 size-4\" />\n {labels.addSingleAddress}\n </Button>\n </div>\n\n {atLimit && maxItems != null && (\n <p className=\"text-xs text-muted-foreground\">{labels.maxItemsReached(maxItems)}</p>\n )}\n </div>\n );\n}\n","import { ClipboardPaste, PencilLine } from 'lucide-react';\nimport { useCallback, useId, useMemo, useState } from 'react';\n\nimport type { AddressingCapability } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Label } from '../../ui/label';\nimport { AddressListBulkEntry } from './AddressListBulkEntry';\nimport { AddressListEntries } from './AddressListEntries';\nimport { AddressListSingleEntry } from './AddressListSingleEntry';\nimport { resolveAddressListFieldLabels, type AddressListFieldLabels } from './labels';\n\nexport type AddressListEntryMode = 'single' | 'bulk';\n\n/**\n * AddressListField component properties.\n *\n * Uses a controlled `value` / `onChange` API for the committed address list.\n * Entry defaults to single-address mode ({@link AddressField} with address-book\n * suggestions); users can toggle to bulk paste mode — never both at once.\n */\nexport interface AddressListFieldProps {\n /** Committed addresses currently shown in the list. */\n value: readonly string[];\n /** Called when addresses are added or removed. */\n onChange: (addresses: string[]) => void;\n /** Placeholder for single-address entry (default mode). */\n placeholder: string;\n /** Placeholder for bulk paste. Defaults to {@link placeholder}. */\n bulkPlaceholder?: string;\n /** Shown in bulk mode only — delimiter and validation guidance. */\n formatHint: string;\n /** When provided, each candidate is validated via {@link AddressingCapability.isValidAddress}. */\n addressing?: AddressingCapability;\n /** Optional explorer URL resolver passed through to {@link AddressDisplay}. */\n getExplorerUrl?: (address: string) => string | null | undefined;\n /** Optional field label rendered above the active entry control. */\n label?: string;\n /** Optional domain-specific helper shown below the header row. */\n helperText?: string;\n /** Maximum number of addresses allowed in {@link value}. */\n maxItems?: number;\n /** Disables entry and remove actions. */\n disabled?: boolean;\n /** Maximum invalid entries shown inline before truncating with a count suffix (bulk mode). */\n maxInvalidPreview?: number;\n className?: string;\n /** Entry mode shown on mount. Defaults to `'single'`. */\n defaultEntryMode?: AddressListEntryMode;\n /**\n * Whether users can switch between single and bulk entry. Defaults to `true`.\n * Set to `false` to hide the toggle and lock the field to {@link defaultEntryMode}.\n */\n allowModeToggle?: boolean;\n /** Optional UI labels to override {@link DEFAULT_ADDRESS_LIST_FIELD_LABELS}. */\n labels?: Partial<AddressListFieldLabels>;\n}\n\n/**\n * Multi-address list field with single-entry default and optional bulk paste.\n */\nexport function AddressListField({\n value,\n onChange,\n placeholder,\n bulkPlaceholder,\n formatHint,\n addressing,\n getExplorerUrl,\n label,\n helperText,\n maxItems,\n disabled = false,\n maxInvalidPreview = 3,\n className,\n defaultEntryMode = 'single',\n allowModeToggle = true,\n labels: labelOverrides,\n}: AddressListFieldProps) {\n const fieldId = useId();\n const labels = useMemo(() => resolveAddressListFieldLabels(labelOverrides), [labelOverrides]);\n const [entryMode, setEntryMode] = useState<AddressListEntryMode>(defaultEntryMode);\n const resolvedBulkPlaceholder = bulkPlaceholder ?? placeholder;\n\n const handleRemove = useCallback(\n (index: number) => {\n onChange(value.filter((_, currentIndex) => currentIndex !== index));\n },\n [onChange, value]\n );\n\n const handleAddSingle = useCallback(\n (address: string) => {\n onChange([...value, address]);\n },\n [onChange, value]\n );\n\n const handleAddBulk = useCallback(\n (addresses: string[]) => {\n onChange([...value, ...addresses]);\n },\n [onChange, value]\n );\n\n const switchToBulk = useCallback(() => setEntryMode('bulk'), []);\n const switchToSingle = useCallback(() => setEntryMode('single'), []);\n\n const toggleClassName =\n 'inline-flex items-center gap-1 rounded-b-md rounded-t-none border border-t-0 border-input bg-muted/40 px-2 py-1 text-xs font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground';\n const modeToggle = !allowModeToggle ? undefined : entryMode === 'single' ? (\n <button type=\"button\" onClick={switchToBulk} className={toggleClassName}>\n <ClipboardPaste className=\"size-3\" />\n {labels.enableBulkEntry}\n </button>\n ) : (\n <button type=\"button\" onClick={switchToSingle} className={toggleClassName}>\n <PencilLine className=\"size-3\" />\n {labels.enableSingleEntry}\n </button>\n );\n\n return (\n <div className={cn('space-y-3', className)}>\n {label ? <Label className=\"text-sm font-medium leading-none\">{label}</Label> : null}\n {helperText && entryMode === 'single' ? (\n <p className=\"text-sm leading-relaxed text-muted-foreground\">{helperText}</p>\n ) : null}\n\n {entryMode === 'single' ? (\n <AddressListSingleEntry\n fieldId={fieldId}\n value={value}\n onAdd={handleAddSingle}\n placeholder={placeholder}\n addressing={addressing}\n maxItems={maxItems}\n disabled={disabled}\n labels={labels}\n modeToggle={modeToggle}\n />\n ) : (\n <AddressListBulkEntry\n fieldId={fieldId}\n value={value}\n onAdd={handleAddBulk}\n placeholder={resolvedBulkPlaceholder}\n formatHint={formatHint}\n addressing={addressing}\n maxItems={maxItems}\n disabled={disabled}\n maxInvalidPreview={maxInvalidPreview}\n labels={labels}\n modeToggle={modeToggle}\n />\n )}\n\n <AddressListEntries\n value={value}\n getExplorerUrl={getExplorerUrl}\n disabled={disabled}\n labels={labels}\n onRemove={handleRemove}\n />\n </div>\n );\n}\n","/**\n * Address Suggestion Context\n *\n * Provides a React context for resolving address autocomplete suggestions.\n * When an `AddressSuggestionProvider` is mounted, every `AddressField`\n * in the subtree automatically renders a suggestion dropdown as the user types.\n *\n * @example\n * ```tsx\n * import { AddressSuggestionProvider } from '@openzeppelin/ui-components';\n * import { useAliasSuggestionResolver } from '@openzeppelin/ui-storage';\n *\n * function App() {\n * const resolver = useAliasSuggestionResolver(db);\n * return (\n * <AddressSuggestionProvider {...resolver}>\n * <MyApp />\n * </AddressSuggestionProvider>\n * );\n * }\n * ```\n */\nimport * as React from 'react';\n\nimport type { AddressSuggestionResolver } from '@openzeppelin/ui-types';\n\nimport { AddressSuggestionContext } from './context';\n\n/**\n * Props for `AddressSuggestionProvider`.\n *\n * Accepts the same shape as `AddressSuggestionResolver` so the provider can be\n * spread directly from a resolver hook: `<AddressSuggestionProvider {...resolver}>`.\n */\nexport interface AddressSuggestionProviderProps extends AddressSuggestionResolver {\n children: React.ReactNode;\n}\n\n/**\n * Provides address suggestion resolution to all `AddressField` instances in the\n * subtree. Wrap your application (or a subsection) with this provider and\n * supply a `resolveSuggestions` function.\n *\n * @param props - Resolver function and children\n *\n * @example\n * ```tsx\n * <AddressSuggestionProvider\n * resolveSuggestions={(query, networkId) => filterAliases(query, networkId)}\n * >\n * <App />\n * </AddressSuggestionProvider>\n * ```\n */\nexport function AddressSuggestionProvider({\n children,\n resolveSuggestions,\n}: AddressSuggestionProviderProps): React.ReactElement {\n const value = React.useMemo<AddressSuggestionResolver>(\n () => ({ resolveSuggestions }),\n [resolveSuggestions]\n );\n\n return (\n <AddressSuggestionContext.Provider value={value}>{children}</AddressSuggestionContext.Provider>\n );\n}\n","/**\n * Convenience hook that resolves suggestions for a query string using the\n * nearest `AddressSuggestionProvider`. Returns an empty array when no provider\n * is mounted or when the query is empty.\n *\n * @param query - Current input value to match against\n * @param networkId - Optional network identifier for scoping results\n * @returns Object containing the resolved suggestions array\n *\n * @example\n * ```tsx\n * function MyField({ query }: { query: string }) {\n * const { suggestions } = useAddressSuggestions(query, 'ethereum-mainnet');\n * return (\n * <ul>\n * {suggestions.map(s => <li key={s.value}>{s.label}</li>)}\n * </ul>\n * );\n * }\n * ```\n */\nimport * as React from 'react';\n\nimport type { AddressSuggestion } from '@openzeppelin/ui-types';\n\nimport { AddressSuggestionContext } from './context';\n\n/**\n * Return type for the `useAddressSuggestions` convenience hook.\n */\nexport interface UseAddressSuggestionsResult {\n /** Resolved suggestions for the current query */\n suggestions: AddressSuggestion[];\n}\n\n/** Resolves address suggestions from the nearest `AddressSuggestionProvider`. */\nexport function useAddressSuggestions(\n query: string,\n networkId?: string\n): UseAddressSuggestionsResult {\n const resolver = React.useContext(AddressSuggestionContext);\n\n const suggestions = React.useMemo(() => {\n if (!resolver || !query.trim()) return [];\n return resolver.resolveSuggestions(query, networkId);\n }, [resolver, query, networkId]);\n\n return { suggestions };\n}\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n handleNumericKeys,\n} from './utils';\n\n/**\n * AmountField component properties\n */\nexport interface AmountFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Minimum value validation\n */\n min?: number;\n\n /**\n * Maximum value validation\n */\n max?: number;\n\n /**\n * Step value for increment/decrement\n */\n step?: number;\n\n /**\n * Number of decimal places to allow\n */\n decimals?: number;\n\n /**\n * Currency/token symbol to display\n */\n symbol?: string;\n\n /**\n * Position of the symbol (before or after the amount)\n */\n symbolPosition?: 'prefix' | 'suffix';\n\n /**\n * Custom validation function for amount values\n */\n validateAmount?: (value: number) => boolean | string;\n}\n\n/**\n * Amount input field component specifically designed for currency/token amounts with React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles amount-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Support for currency/token symbols\n * - Numeric-specific validations (min, max, decimals)\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation with arrow keys for numeric increment/decrement\n */\nexport function AmountField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n min,\n max,\n step = 0.01,\n decimals = 2,\n symbol = '',\n symbolPosition = 'suffix',\n validateAmount,\n}: AmountFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Formatter for displaying currency/token values\n const formatCurrency = (value: string | number): string => {\n if (value === '' || value === undefined || value === null) return '';\n\n const numValue = typeof value === 'string' ? parseFloat(value) : value;\n if (isNaN(numValue)) return '';\n\n return numValue.toFixed(decimals);\n };\n\n // Parse string input to number\n const parseAmount = (value: string): number => {\n const parsed = parseFloat(value);\n return isNaN(parsed) ? 0 : parsed;\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Convert to number for validation\n const numValue = typeof value === 'string' ? parseFloat(value) : value;\n\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '' || isNaN(numValue)) {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Validate min/max constraints\n if (min !== undefined && numValue < min) {\n return `Value must be at least ${min}`;\n }\n\n if (max !== undefined && numValue > max) {\n return `Value must be at most ${max}`;\n }\n\n // Run custom validation if provided\n if (validateAmount && !isNaN(numValue)) {\n const validation = validateAmount(numValue);\n if (validation !== true && typeof validation === 'string') {\n return validation;\n }\n }\n\n return true;\n },\n }}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error?.message;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n // Format display value\n const displayValue = field.value !== undefined && field.value !== null ? field.value : '';\n\n return (\n <>\n <div className=\"relative\">\n {symbol && symbolPosition === 'prefix' && (\n <span className=\"absolute top-1/2 left-3 -translate-y-1/2 text-gray-500\">\n {symbol}\n </span>\n )}\n\n <Input\n {...field}\n id={id}\n type=\"text\"\n inputMode=\"decimal\"\n placeholder={placeholder}\n value={displayValue}\n className={`${validationClasses} ${\n symbol && symbolPosition === 'prefix' ? 'pl-8' : ''\n } ${symbol && symbolPosition === 'suffix' ? 'pr-8' : ''}`}\n data-slot=\"input\"\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n onChange={(e) => {\n // Allow numeric values and decimal point\n const value = e.target.value;\n if (value === '' || /^-?\\d*\\.?\\d*$/.test(value)) {\n field.onChange(value);\n }\n }}\n onBlur={(e) => {\n // Format on blur\n if (e.target.value) {\n const parsed = parseFloat(e.target.value);\n if (!isNaN(parsed)) {\n field.onChange(formatCurrency(parsed));\n }\n }\n if (field.onBlur) {\n field.onBlur();\n }\n }}\n onKeyDown={(e) => {\n // Handle Escape key\n if (e.key === 'Escape') {\n handleEscapeKey((value) => {\n field.onChange(value === '' ? null : value);\n }, field.value)(e);\n return;\n }\n\n // Handle arrow keys for increment/decrement\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n handleNumericKeys(\n (newValue) => {\n field.onChange(formatCurrency(newValue));\n },\n parseAmount(field.value || ''),\n step,\n min,\n max\n )(e);\n }\n }}\n />\n\n {symbol && symbolPosition === 'suffix' && (\n <span className=\"absolute top-1/2 right-3 -translate-y-1/2 text-gray-500\">\n {symbol}\n </span>\n )}\n </div>\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nAmountField.displayName = 'AmountField';\n","import { GripVertical, Plus, X } from 'lucide-react';\nimport React from 'react';\nimport { Controller, FieldValues, useFieldArray, useFormContext, useWatch } from 'react-hook-form';\n\nimport type { FormFieldType } from '@openzeppelin/ui-types';\n\nimport { Button } from '../ui/button';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage, getAccessibilityProps } from './utils';\n\n/**\n * ArrayField component properties\n */\nexport interface ArrayFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * The type of elements in the array (e.g., 'text', 'number', 'blockchain-address')\n */\n elementType?: FormFieldType['type']; // TODO: Consider if a more specific subset of FieldType is relevant here if this component only renders simple types directly.\n\n /**\n * Minimum number of array elements\n */\n minItems?: number;\n\n /**\n * Maximum number of array elements\n */\n maxItems?: number;\n\n /**\n * Base configuration for array element fields.\n * This allows specifying common properties like placeholder, helperText, or specific validation\n * for each element in the array.\n */\n // TODO: Refine elementFieldConfig type. `id` and `name` are derived internally.\n // Consider a type like `Omit<Partial<FormFieldType>, 'id' | 'name'> & { defaultValue?: unknown }`\n // to allow specifying a more complex default value for appended items.\n elementFieldConfig?: Partial<FormFieldType>;\n\n /**\n * Render function for array elements.\n * This is crucial for rendering complex elements or integrating custom field components.\n */\n // TODO: Explore a fallback rendering mechanism if `renderElement` is not provided,\n // especially if `elementType` is a known simple type (e.g., 'text', 'number').\n // This could make the component more self-contained for basic array types.\n renderElement?: (field: FormFieldType, index: number) => React.ReactNode;\n}\n\n/**\n * Array input field component specifically designed for React Hook Form integration.\n *\n * This component provides a dynamic interface for managing array inputs with:\n * - Add/remove functionality for array items\n * - Validation for array length constraints\n * - Integration with existing field components for array elements\n * - Full accessibility support\n *\n * The component reuses existing field components (TextField, NumberField, etc.)\n * for individual array elements, maintaining consistency across the form system.\n *\n * Why the extra guards and synchronization exist (post-mortem/rationale):\n * - In certain runtime states (StrictMode double-invocation, preview remounts, state rehydration\n * from storage), React Hook Form's useFieldArray may not synchronously reflect an `append()`\n * or `remove()` call in the immediately subsequent read (e.g., reading `fields.length` or\n * `getValues(name)` right after the call). This resulted in newly added items (especially\n * falsy defaults like 0/false) appearing briefly and then disappearing, or remove operations\n * not updating the UI.\n * - To make array operations deterministic and resilient across flows (preview form with\n * FormProvider and the wizard's \"Use Hardcoded Value\" without a provider), we:\n * 1) Read a stable snapshot of the array value BEFORE `append()` and, if the immediate\n * post-append read doesn't reflect the addition, we coerce the state to\n * \"previousSnapshot + newValue\" via `setValue` (when context exists) or `replace`.\n * 2) Avoid `remove()` race conditions by always computing the new array via filter and\n * applying it with `replace`, which proved to be the most consistent across contexts.\n * 3) Keep `fields` in sync with the watched array value using a guarded `replace` in an effect.\n * A ref flag (`isReplacingRef`) prevents infinite loops when we ourselves are driving\n * the `replace`.\n * 4) Use optional chaining for form context (`formContext?.control`, `formContext?.getValues`,\n * `formContext?.setValue`) so the component works with either an inherited FormProvider or\n * an explicit `control` prop.\n * 5) Use `queueMicrotask` to reset the guard flag after our `replace` has been scheduled,\n * avoiding an extra timer tick while ensuring the effect observes the final state.\n *\n * Guarantees:\n * - Operations are idempotent: the fallback only runs when the immediate read does not reflect\n * the intended state, so we don't double-append/remove.\n * - Works both with and without FormProvider (preview vs wizard) due to context-agnostic state\n * reads and `replace` fallback.\n */\nexport function ArrayField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n elementType = 'text',\n minItems = 0,\n maxItems,\n elementFieldConfig,\n renderElement,\n readOnly,\n}: ArrayFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Get form context for nested field registration (may be absent in some builder flows)\n const formContext = useFormContext();\n\n // Use useFieldArray for dynamic array management\n const { fields, append, replace } = useFieldArray({\n control: control || formContext?.control,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n name: name as any, // Type assertion needed due to generic constraints\n // TODO: Investigate if stricter typing for `name` can be achieved to avoid `as any`\n // with react-hook-form's useFieldArray and deeply nested field names.\n });\n\n // Watch current array value in a context-agnostic way (works with provided control)\n const rawWatchedArray = useWatch({ control: control || formContext?.control, name }) as\n | unknown[]\n | undefined;\n const watchedArrayValue = React.useMemo<unknown[]>(() => {\n return Array.isArray(rawWatchedArray) ? rawWatchedArray : [];\n }, [rawWatchedArray]);\n\n // Ensure field array is synchronized with current value length on mount/reset\n // Keep field array synchronized with watched values, but prevent infinite loops\n const isReplacingRef = React.useRef(false);\n React.useEffect(() => {\n if (isReplacingRef.current) {\n // Skip sync if we're in the middle of a replace operation\n return;\n }\n\n if (Array.isArray(watchedArrayValue) && fields.length !== watchedArrayValue.length) {\n isReplacingRef.current = true;\n replace(watchedArrayValue as unknown as never);\n\n // Reset the flag in a microtask to allow the replace to complete without a timer tick\n queueMicrotask(() => {\n isReplacingRef.current = false;\n });\n }\n }, [fields.length, watchedArrayValue, replace]);\n\n // Note: Structural changes are observed via useWatch and the sync effect above; no additional tracking needed here.\n\n // Handle removing an array item with fallback for stale reads\n const handleRemoveItem = (index: number): void => {\n const valuesBeforeRemove = Array.isArray(watchedArrayValue)\n ? (watchedArrayValue as unknown[])\n : ([] as unknown[]);\n\n // Always use the fallback approach for remove to ensure consistency\n const updatedArray = valuesBeforeRemove.filter((_, i) => i !== index);\n\n // Set flag to prevent sync loop during manual replace\n isReplacingRef.current = true;\n replace(updatedArray as unknown as never);\n\n // Reset flag after operation\n queueMicrotask(() => {\n isReplacingRef.current = false;\n });\n };\n\n // Handle adding new array item\n const handleAddItem = (): void => {\n // Determine default value based on element type\n // TODO: Enhance default value generation.\n // 1. Allow `elementFieldConfig.defaultValue` to override this basic logic.\n // 2. For 'object' or 'array-object' elementType (if supported directly later),\n // this would need to be more sophisticated (e.g., an empty object/array).\n // 3. Consider a more generic `getDefaultValueByFieldType` utility if not already used/available.\n const defaultValue =\n elementFieldConfig?.defaultValue !== undefined\n ? elementFieldConfig.defaultValue\n : elementType === 'number' || elementType === 'amount'\n ? 0\n : elementType === 'checkbox'\n ? false\n : ''; // Default for text, address, etc.\n\n // Background and rationale:\n // In certain runtime states (e.g., preview remounts, incidental resets, StrictMode double-invocations),\n // an immediate read right after useFieldArray.append(...) can be stale and still reflect the\n // pre-append array. This manifested as a user-visible bug where adding an item (notably value 0)\n // either did nothing or briefly appeared and then disappeared.\n //\n // To make the operation deterministic, we snapshot the array BEFORE calling append and then\n // verify that the length actually increased. If not, we force-set the array using the snapshot\n // plus the new value. This is safe and idempotent because it only runs when the immediate read\n // did not reflect the append; it does not double-append.\n\n // Set flag to prevent sync interference during add operation\n isReplacingRef.current = true;\n\n const fieldsBeforeAppend = fields.length;\n const valuesBeforeAppend = Array.isArray(watchedArrayValue)\n ? (watchedArrayValue as unknown[])\n : ([] as unknown[]);\n\n append(defaultValue as FieldValues[typeof name]);\n\n // Verify append actually reflected in form state; if not, force set\n const afterAppendFieldsCount =\n (formContext?.getValues?.(name) as unknown[] | undefined)?.length ?? fields.length;\n\n // Fallback: if the immediate read did not reflect the append, coerce to\n // \"previous snapshot + new value\" so the UI consistently renders the new item.\n if (afterAppendFieldsCount <= fieldsBeforeAppend) {\n const baseArray = Array.isArray(valuesBeforeAppend)\n ? (valuesBeforeAppend as unknown[])\n : ([] as unknown[]);\n const coercedArray = [...baseArray, defaultValue] as unknown[];\n\n if (formContext?.setValue) {\n formContext.setValue(name as never, coercedArray as never, {\n shouldDirty: true,\n shouldTouch: true,\n });\n } else {\n // No form context (e.g., builder hardcoded flow). Use useFieldArray.replace to force state.\n replace(coercedArray as unknown as never);\n }\n }\n\n // Reset flag after operation completes\n queueMicrotask(() => {\n isReplacingRef.current = false;\n });\n };\n\n // Check if we can add more items\n const canAddMore = !maxItems || fields.length < maxItems;\n\n // Check if we can remove items\n const canRemove = fields.length > minItems;\n\n // TODO: For future enhancement, consider adding drag-and-drop reordering functionality for array items.\n // The GripVertical icon hints at this, but implementation would require additional libraries/logic.\n\n return (\n <Controller\n control={control || formContext?.control}\n name={name}\n rules={{\n // TODO: Consider if custom validation functions passed via `validation.validate` prop\n // should also be callable here, in addition to these built-in length checks.\n validate: (value) => {\n // Validate array constraints\n if (validation?.required && (!Array.isArray(value) || value.length === 0)) {\n return 'At least one item is required';\n }\n\n if (minItems && Array.isArray(value) && value.length < minItems) {\n return `Minimum ${minItems} item${minItems > 1 ? 's' : ''} required`;\n }\n\n if (maxItems && Array.isArray(value) && value.length > maxItems) {\n return `Maximum ${maxItems} item${maxItems > 1 ? 's' : ''} allowed`;\n }\n\n return true;\n },\n }}\n render={({ fieldState: { error } }) => {\n const hasError = !!error;\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n // TODO: Review aria-controls/aria-labelledby for the \"Add Item\" button and the list of items for improved accessibility.\n\n return (\n <div\n className={`flex flex-col gap-4 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n >\n {/* Label */}\n {label && (\n <div className=\"flex items-center justify-between\">\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n </div>\n )}\n\n {/* Array items */}\n <div className=\"space-y-3\">\n {fields.length === 0 ? (\n <div className=\"text-muted-foreground text-sm py-4 text-center border border-dashed rounded-md\">\n No items added yet. Click “Add Item” to begin.\n </div>\n ) : (\n fields.map((field, index) => {\n // Create field configuration for array element\n // Spread elementFieldConfig first to preserve all properties (including enumMetadata, components)\n const elementField: FormFieldType = {\n ...elementFieldConfig, // Include all props from config (enumMetadata, components, etc.)\n id: field.id, // Use RHF field.id for stable, unique keys per item\n name: `${name}.${index}`, // RHF name for the element\n label: elementFieldConfig?.label || '', // Label for the element's field (can be empty if not desired)\n type: elementFieldConfig?.type || elementType, // Prefer elementFieldConfig.type if available\n validation: elementFieldConfig?.validation || {},\n placeholder: elementFieldConfig?.placeholder,\n helperText: elementFieldConfig?.helperText,\n width: 'full', // Typically, elements take full width within their row\n readOnly: elementFieldConfig?.readOnly ?? readOnly, // Inherit readOnly from parent\n };\n\n return (\n <div key={field.id} className=\"flex gap-2 items-center\">\n <div className=\"flex items-center\">\n {/* TODO: The GripVertical icon is purely visual currently.\n If drag-and-drop is implemented, this would be the drag handle.\n Ensure it has appropriate ARIA attributes if it becomes interactive. */}\n <GripVertical className=\"size-4 text-muted-foreground\" />\n </div>\n <div className=\"flex-1\">\n {renderElement ? (\n renderElement(elementField, index)\n ) : (\n // This fallback is okay, but a more robust solution might attempt to\n // render a default UI field based on `elementType` if it's a known simple type.\n <div className=\"text-sm text-muted-foreground\">\n Field type “{elementType}” requires a render function\n </div>\n )}\n </div>\n {!readOnly && canRemove && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => handleRemoveItem(index)}\n className=\"size-8 p-0\"\n aria-label={`Remove item ${index + 1}`}\n >\n <X className=\"size-4\" />\n </Button>\n )}\n </div>\n );\n })\n )}\n </div>\n\n {/* Add Item button */}\n {!readOnly && canAddMore && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={handleAddItem}\n className=\"gap-1 w-full sm:w-auto\"\n // TODO: Add aria-live region or other announcement for screen readers when an item is added/removed.\n >\n <Plus className=\"size-3\" />\n Add Item\n </Button>\n )}\n\n {/* Helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Error message */}\n <ErrorMessage error={error} id={errorId} />\n </div>\n );\n }}\n />\n );\n}\n\n// Set display name for debugging\nArrayField.displayName = 'ArrayField';\n","import { ChevronDown, ChevronRight, GripVertical, Plus, X } from 'lucide-react';\nimport React from 'react';\nimport { Controller, FieldValues, useFieldArray, useFormContext, useWatch } from 'react-hook-form';\n\nimport type {\n ContractSchema,\n FormFieldType,\n FunctionParameter,\n TypeMappingCapability,\n} from '@openzeppelin/ui-types';\n\nimport { Button } from '../ui/button';\nimport { Card } from '../ui/card';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage, getAccessibilityProps } from './utils';\n\n/**\n * ArrayObjectField component properties\n */\nexport interface ArrayObjectFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * The components/properties of each object in the array.\n * Defines the schema for the nested fields within each object item.\n */\n components?: FunctionParameter[]; // TODO: As above, review type for `components`.\n\n /**\n * Minimum number of array elements\n */\n minItems?: number;\n\n /**\n * Maximum number of array elements\n */\n maxItems?: number;\n\n /**\n * Render function for object properties.\n * This function is responsible for rendering each individual property\n * of an object within an array item.\n */\n // TODO: Explore a fallback rendering mechanism if `renderProperty` is not provided,\n // for known simple property types.\n renderProperty?: (\n field: FormFieldType,\n itemIndex: number,\n propertyName: string\n ) => React.ReactNode;\n\n /**\n * Whether items should be collapsible.\n * Useful for managing UI complexity when objects have many properties.\n */\n collapsible?: boolean;\n\n /**\n * Whether items should start collapsed.\n */\n defaultCollapsed?: boolean;\n\n /**\n * The type-mapping capability for chain-specific field generation.\n * Essential for correctly determining field types for object properties.\n */\n typeMapping?: TypeMappingCapability;\n\n /**\n * Optional contract schema to enrich nested field generation.\n */\n contractSchema?: ContractSchema;\n}\n\n/**\n * Array of objects input field component specifically designed for React Hook Form integration.\n *\n * This component provides a dynamic interface for managing arrays of composite objects with:\n * - Add/remove functionality for array items\n * - Structured rendering of object properties within each array item\n * - Collapsible items for better UX with complex objects\n * - Validation for array constraints and object properties (though individual property validation is largely via rendered component)\n * - Full accessibility support\n *\n * The component combines the functionality of ArrayField and ObjectField to handle\n * complex nested data structures commonly found in blockchain contracts.\n */\nexport function ArrayObjectField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n components = [],\n minItems = 0,\n maxItems,\n renderProperty,\n collapsible = true,\n defaultCollapsed = false,\n readOnly,\n typeMapping,\n contractSchema,\n}: ArrayObjectFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Get form context for nested field registration\n const formContext = useFormContext();\n const effectiveControl = control || formContext.control;\n\n // Use useFieldArray for dynamic array management\n const { fields, append, remove } = useFieldArray({\n control: effectiveControl,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n name: name as any, // Type assertion needed due to generic constraints\n // TODO: Investigate if stricter typing for `name` can be achieved here.\n });\n\n // Track collapsed state for each item\n const [collapsedItems, setCollapsedItems] = React.useState<Record<string, boolean>>(() => {\n // TODO: Initialize collapsedItems based on `fields` from useFieldArray if `defaultCollapsed`\n // needs to apply to dynamically added items after initial render.\n // Current initialization only covers items present on first render.\n // This might require a useEffect hook that syncs with `fields`.\n const initial: Record<string, boolean> = {};\n fields.forEach((field) => {\n initial[field.id] = defaultCollapsed;\n });\n return initial;\n });\n\n // Handle adding new array item\n const handleAddItem = (): void => {\n // Create default object based on components\n const defaultObject: Record<string, unknown> = {};\n components.forEach((component) => {\n // TODO: This default value logic is extensive.\n // 1. Consider moving to a utility function `generateDefaultObject(components: FunctionParameter[]): Record<string, unknown>`.\n // 2. For nested 'tuple' (objects), recursively call this utility to generate deeply nested default structures.\n // Currently, `defaultObject[component.name] = {};` is a shallow empty object.\n // 3. Ensure consistency with any default value generation used elsewhere (e.g., in FormGenerator or core).\n if (component.type.includes('bool')) {\n defaultObject[component.name] = false;\n } else if (component.type.includes('int') || component.type.includes('uint')) {\n defaultObject[component.name] = 0; // Or perhaps '' to align with NumberField's initial controlled state?\n } else if (component.type.includes('[]')) {\n // Array types\n defaultObject[component.name] = [];\n } else if (component.type.startsWith('tuple')) {\n // Object/tuple types\n defaultObject[component.name] = {}; // TODO: Recursive default generation for nested tuples.\n } else {\n // Default for string and other types\n defaultObject[component.name] = '';\n }\n });\n\n // TODO: RHF's `append` type for nested field arrays is complex. `defaultObject` is Record<string, unknown>.\n // Casting to `any` here is a pragmatic approach if precisely matching RHF's expected generic type\n // (e.g., FieldArray<TFieldValues, TFieldName>[number]) proves too difficult for this dynamically built object.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n append(defaultObject as any);\n };\n\n // Toggle collapsed state for an item\n const toggleCollapsed = (fieldId: string): void => {\n setCollapsedItems((prev) => ({\n ...prev,\n [fieldId]: !prev[fieldId],\n }));\n };\n\n // Check if we can add more items\n const canAddMore = !maxItems || fields.length < maxItems;\n\n // Check if we can remove items\n const canRemove = fields.length > minItems;\n\n // TODO: For future enhancement, consider drag-and-drop reordering for array items.\n // TODO: Performance for very large arrays of complex objects. Virtualization might be needed.\n\n return (\n <Controller\n control={effectiveControl}\n name={name}\n rules={{\n // TODO: Similar to ArrayField, consider integration of custom validation functions.\n validate: (value) => {\n if (validation?.required && (!value || !Array.isArray(value) || value.length === 0)) {\n return 'At least one item is required';\n }\n if (minItems && Array.isArray(value) && value.length < minItems) {\n return `Minimum ${minItems} item${minItems > 1 ? 's' : ''} required`;\n }\n if (maxItems && Array.isArray(value) && value.length > maxItems) {\n return `Maximum ${maxItems} item${maxItems > 1 ? 's' : ''} allowed`;\n }\n return true;\n },\n }}\n render={({ fieldState: { error } }) => {\n const hasError = !!error;\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n // TODO: Review aria-controls/aria-labelledby for the \"Add Item\" button and the list of items.\n\n return (\n <div\n className={`flex flex-col gap-4 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n >\n {label && (\n <div className=\"flex items-center justify-between\">\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n </div>\n )}\n\n <div className=\"space-y-3\">\n {fields.length === 0 ? (\n <div className=\"text-muted-foreground text-sm py-4 text-center border border-dashed rounded-md\">\n No items added yet. Click “Add Item” to begin.\n </div>\n ) : (\n fields.map((field, index) => {\n const isCollapsed = collapsedItems[field.id] ?? defaultCollapsed;\n\n return (\n <Card key={field.id} className=\"p-4\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-center gap-2 flex-1\">\n {/* TODO: Aria attributes for GripVertical if it becomes interactive (drag handle). */}\n <GripVertical className=\"size-4 text-muted-foreground\" />\n {collapsible && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => toggleCollapsed(field.id)}\n className=\"p-0 h-auto\"\n aria-label={isCollapsed ? 'Expand item' : 'Collapse item'}\n // TODO: Add aria-expanded={!isCollapsed} and aria-controls={`item-content-${field.id}`}\n >\n {isCollapsed ? (\n <ChevronRight className=\"h-4 w-4\" />\n ) : (\n <ChevronDown className=\"h-4 w-4\" />\n )}\n </Button>\n )}\n {isCollapsed && (\n <div className=\"flex items-center gap-4 text-sm text-muted-foreground ml-2\">\n <CollapsedSummary\n name={name}\n index={index}\n components={components}\n control={effectiveControl}\n />\n </div>\n )}\n </div>\n {!readOnly && canRemove && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => remove(index)}\n aria-label={`Remove item ${index + 1}`}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n\n {!isCollapsed && (\n <div className=\"space-y-4 mt-4\">\n {((): React.ReactNode[] => {\n return components.map((component) => {\n // Generate field using the type-mapping capability to preserve nested metadata.\n if (!typeMapping) {\n throw new Error(\n `ArrayObjectField: No typeMapping capability provided for field generation. Cannot generate field for \"${component.name}\"`\n );\n }\n\n const generatedField = typeMapping.generateDefaultField(\n component,\n contractSchema\n );\n\n // Override with array object-specific configuration\n const propertyField: FormFieldType = {\n ...generatedField, // Include elementType and other capability-specific properties\n id: `${id}-${index}-${component.name}`,\n name: `${name}.${index}.${component.name}`,\n label: component.displayName || component.name,\n validation: {\n ...generatedField.validation, // Preserve validation from type mapping (includes min/max bounds)\n required: validation?.required, // Override required from parent\n },\n placeholder: `Enter ${component.displayName || component.name}`,\n helperText:\n component.description ||\n (generatedField.type === 'number' ? 'Numbers only' : undefined),\n width: 'full',\n readOnly,\n // Pass components for nested objects\n ...(component.components && {\n components: component.components,\n }),\n // TODO: Consider passing nested capability requirements down explicitly if needed.\n };\n\n return (\n <div key={component.name}>\n {renderProperty ? (\n renderProperty(propertyField, index, component.name)\n ) : (\n <div className=\"text-sm text-muted-foreground\">\n Property “{component.name}” requires a render\n function\n </div>\n )}\n </div>\n );\n });\n })()}\n </div>\n )}\n </Card>\n );\n })\n )}\n </div>\n\n {/* Add Item button */}\n {!readOnly && canAddMore && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={handleAddItem}\n className=\"gap-1 w-full sm:w-auto\"\n >\n {/* TODO: Add aria-live region or other announcement for item add/remove. */}\n <Plus className=\"h-3 w-3\" />\n Add Item\n </Button>\n )}\n\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n <ErrorMessage error={error} id={errorId} />\n </div>\n );\n }}\n />\n );\n}\n\n/**\n * Component to display collapsed item summary\n * TODO: This component is quite specific to ArrayObjectField.\n * If similar summaries are needed elsewhere, consider making it more generic\n * or moving it to a shared utils/components location.\n */\nfunction CollapsedSummary({\n name,\n index,\n components,\n control,\n}: {\n name: string;\n index: number;\n components: FunctionParameter[];\n control: FieldValues['control']; // TODO: useFormContext<TFieldValues>['control'] for better type safety if possible\n}): React.ReactElement {\n // Watch all values for this item\n // TODO: `useWatch` can be performance-intensive if the object is large and updates frequently.\n // If performance issues arise, consider optimizing what's watched or how often.\n const itemValues = useWatch({\n control,\n name: `${name}.${index}`, // Watch the entire object at this index\n });\n\n const summaryItems = components\n .slice(0, 3)\n .map((component) => {\n const fieldValue = itemValues?.[component.name];\n const displayValue =\n fieldValue !== undefined && fieldValue !== '' && fieldValue !== 0 && fieldValue !== false\n ? String(fieldValue).length > 20\n ? `${String(fieldValue).substring(0, 20)}...`\n : String(fieldValue)\n : null;\n\n return displayValue ? (\n <span key={component.name} className=\"flex items-center gap-1\">\n <span className=\"font-medium\">{component.displayName || component.name}:</span>\n <span className=\"text-foreground\">{displayValue}</span>\n </span>\n ) : null;\n })\n .filter(Boolean);\n\n const isEmpty =\n !itemValues ||\n Object.values(itemValues).every(\n (value) => value === undefined || value === '' || value === 0 || value === false\n );\n\n if (isEmpty && summaryItems.length === 0) {\n // Ensure we don't show \"Empty item\" if summaryItems has content\n return <span className=\"italic\">Empty item</span>;\n }\n\n return (\n <>\n {summaryItems.length > 0 ? (\n summaryItems\n ) : (\n <span className=\"italic\">Item has values (not shown in summary)</span>\n )}\n {/* TODO: The \"+ X more\" count should be accurate based on total properties vs. shown in summary.\n If summaryItems is empty but the item is not (due to values not fitting summary criteria),\n this count might be misleading.\n Consider `components.length - (actually displayed count in summaryItems)`\n */}\n {components.length > 3 &&\n summaryItems.length < components.length && ( // Only show \"more\" if not all are summarized or could be summarized\n <span className=\"text-xs\">+{components.length - summaryItems.length} more</span>\n )}\n </>\n );\n}\n\n// Set display name for debugging\nArrayObjectField.displayName = 'ArrayObjectField';\n","import { type ForwardedRef, type ReactElement, type ReactNode } from 'react';\nimport type { Control, FieldPath, FieldValues } from 'react-hook-form';\n\nimport { type FieldValidation } from '@openzeppelin/ui-types';\n\nimport { getWidthClasses } from './utils/layout';\n\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '../ui/form';\n\n/**\n * Base props shared by all field components\n *\n * @template TFieldValues The field values type from React Hook Form\n */\nexport interface BaseFieldProps<TFieldValues extends FieldValues = FieldValues> {\n /**\n * Unique identifier for the field\n */\n id: string;\n\n /**\n * Label text to display\n */\n label: string;\n\n /**\n * Placeholder text when empty\n */\n placeholder?: string;\n\n /**\n * Helper text to display below the field\n */\n helperText?: string;\n\n /**\n * Field width for layout\n */\n width?: 'full' | 'half' | 'third';\n\n /**\n * Validation rules for the field\n */\n validation?: FieldValidation;\n\n /**\n * Form control from React Hook Form\n */\n control: Control<TFieldValues>;\n\n /**\n * Field name in the form\n */\n name: FieldPath<TFieldValues>;\n\n /**\n * Whether the field should be displayed as read-only/disabled.\n * @default false\n */\n readOnly?: boolean;\n}\n\n/**\n * BaseField component to provide a consistent layout for form fields\n *\n * @important This component is the foundation of the app rendering architecture and should\n * ONLY be used by field-specific components within the system, not as a standalone component.\n *\n * Architecture role:\n * 1. Provides a consistent layout structure for all field types\n * 2. Handles integration with React Hook Form through the FormField component\n * 3. Manages common rendering aspects like labels, error messages, and help text\n * 4. Delegates actual input rendering to field-specific components via renderInput\n *\n * Field component hierarchy:\n * - TransactionForm (top-level renderer)\n * - DynamicFormField (field type selector)\n * - Specific field components (TextField, NumberField, etc.)\n * - BaseField (common field structure - this component)\n * - Actual input element rendered by renderInput\n *\n * This component should only be extended by field-specific components like\n * TextField, NumberField, and AddressField - it is not meant for direct use in forms.\n */\nexport function BaseField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n renderInput,\n}: BaseFieldProps<TFieldValues> & {\n renderInput: (\n field: Record<string, unknown>,\n props: { id: string; ref?: ForwardedRef<HTMLElement> }\n ) => ReactNode;\n ref?: ForwardedRef<HTMLElement>;\n}): ReactElement {\n return (\n <FormField\n control={control}\n name={name}\n render={({ field }) => (\n <FormItem className={getWidthClasses(width)}>\n <FormLabel htmlFor={id}>{label}</FormLabel>\n <FormControl>{renderInput(field, { id })}</FormControl>\n {helperText && <FormDescription id={`${id}-description`}>{helperText}</FormDescription>}\n <FormMessage id={`${id}-error`} />\n </FormItem>\n )}\n />\n );\n}\n\n// Set displayName properly\nBaseField.displayName = 'BaseField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n INTEGER_HTML_PATTERN,\n INTEGER_INPUT_PATTERN,\n INTEGER_PATTERN,\n validateField,\n} from './utils';\n\n/**\n * BigIntField component properties\n */\nexport interface BigIntFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Custom validation function for big integer string values\n */\n validateBigInt?: (value: string) => boolean | string;\n}\n\n/**\n * Big integer input field component for large numbers beyond JavaScript's Number precision.\n *\n * This component is designed for blockchain integer types like uint128, uint256, int128, int256\n * that can hold values larger than JavaScript's Number.MAX_SAFE_INTEGER (2^53 - 1).\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects BigIntField for large integer types\n * 4. This component handles string-based integer input with validation\n * 5. Adapters convert the string to BigInt when submitting transactions\n *\n * The component includes:\n * - Integer-only validation (no decimals allowed)\n * - String-based storage to avoid JavaScript Number precision issues\n * - Integration with React Hook Form\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation\n */\nexport function BigIntField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n validateBigInt,\n readOnly,\n}: BigIntFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Ensure validation includes integer-only pattern\n // This will be handled by validateField utility, avoiding duplication\n const enhancedValidation = {\n ...validation,\n pattern: validation?.pattern || INTEGER_PATTERN,\n };\n\n // Validation function for big integer strings\n const validateBigIntValue = (value: string): string | true => {\n // Run standard validation with integer pattern (includes pattern validation)\n const standardValidation = validateField(value, enhancedValidation);\n if (standardValidation !== true) return standardValidation as string;\n\n // Run custom validator if provided\n if (validateBigInt) {\n const customValidation = validateBigInt(value);\n if (customValidation !== true && typeof customValidation === 'string') {\n return customValidation;\n }\n }\n\n return true;\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Skip validation if empty and check required separately\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Handle incomplete inputs\n if (value === '-') {\n return 'Please enter a complete number';\n }\n\n // For string values, validate as big integer\n if (typeof value === 'string') {\n return validateBigIntValue(value);\n }\n\n // Convert numbers to strings (in case value is accidentally a number)\n if (typeof value === 'number') {\n return validateBigIntValue(value.toString());\n }\n\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Handle input change\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const rawValue = e.target.value;\n\n // Allow empty string\n if (rawValue === '') {\n field.onChange('');\n return;\n }\n\n // Allow standalone minus sign for negative numbers\n if (rawValue === '-') {\n field.onChange(rawValue);\n return;\n }\n\n // Check if the input is a valid integer format\n // Allow only digits and optional leading minus sign (using input pattern)\n if (INTEGER_INPUT_PATTERN.test(rawValue)) {\n field.onChange(rawValue);\n }\n // If invalid format, don't update (prevents non-numeric input)\n };\n\n // Handle keyboard events\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n // Allow only numeric characters, backspace, delete, tab, escape, enter, arrows, hyphen\n const allowedKeys = [\n '0',\n '1',\n '2',\n '3',\n '4',\n '5',\n '6',\n '7',\n '8',\n '9',\n 'Backspace',\n 'Delete',\n 'Tab',\n 'Escape',\n 'Enter',\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n '-',\n ];\n\n // Allow Ctrl/Cmd+A, C, V, X, Z for common editing operations\n if (\n (e.ctrlKey || e.metaKey) &&\n ['a', 'c', 'v', 'x', 'z'].includes(e.key.toLowerCase())\n ) {\n return;\n }\n\n if (!allowedKeys.includes(e.key) && !e.ctrlKey && !e.metaKey) {\n e.preventDefault();\n }\n\n // Handle escape key to clear input\n if (e.key === 'Escape') {\n handleEscapeKey(field.onChange, field.value)(e);\n return;\n }\n };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <Input\n {...field}\n value={field.value ?? ''}\n id={id}\n placeholder={placeholder || 'Enter integer value'}\n type=\"text\"\n className={validationClasses}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n onChange={handleInputChange}\n inputMode=\"numeric\"\n pattern={INTEGER_HTML_PATTERN}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n disabled={readOnly}\n />\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nBigIntField.displayName = 'BigIntField';\n","import React from 'react';\nimport { Controller, FieldPath, FieldValues, PathValue } from 'react-hook-form';\n\nimport { Checkbox } from '../ui/checkbox';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleToggleKeys,\n validateField,\n} from './utils';\n\n/**\n * BooleanField component properties\n */\nexport interface BooleanFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Custom validation function for boolean values\n */\n validateBoolean?: (value: boolean) => boolean | string;\n}\n\n/**\n * Boolean input field component (checkbox) specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like BooleanField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles boolean-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Checkbox-specific behavior\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation with Space/Enter for toggling\n */\nexport function BooleanField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n validateBoolean,\n readOnly,\n}: BooleanFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Function to validate boolean values\n const validateBooleanValue = (value: boolean): string | true => {\n // Run standard validation first\n const standardValidation = validateField(value, validation);\n if (standardValidation !== true) return standardValidation as string;\n\n // Then run custom validator if provided\n if (validateBoolean) {\n const customValidation = validateBoolean(value);\n if (customValidation !== true && typeof customValidation === 'string') {\n return customValidation;\n }\n }\n\n return true;\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n <Controller\n control={control}\n name={name}\n defaultValue={false as PathValue<TFieldValues, FieldPath<TFieldValues>>}\n rules={{\n validate: (value) => {\n // Handle required validation specifically\n if (value === undefined || value === null) {\n return validation?.required ? 'This field is required' : true;\n }\n\n // For boolean values\n if (typeof value === 'boolean') {\n // If required, it means a boolean value (true or false) must be present.\n // The check for undefined/null above handles the case where it's not set.\n // So, if it's a boolean (true or false), it passes the required check here.\n return validateBooleanValue(value);\n }\n\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Handle checkbox change with validation\n const handleCheckedChange = (checked: boolean | 'indeterminate'): void => {\n const value = checked === true;\n field.onChange(value);\n\n // Trigger validation if required and unchecked\n if (isRequired && !value) {\n setTimeout(() => field.onBlur(), 0);\n }\n };\n\n // Add keyboard accessibility for toggle\n const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>): void => {\n handleToggleKeys(field.onChange, !!field.value)(e);\n\n // Trigger validation for required fields\n if (e.key === ' ' || e.key === 'Enter') {\n if (isRequired) {\n setTimeout(() => field.onBlur(), 0);\n }\n }\n };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n isDisabled: readOnly,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <div className=\"flex items-center space-x-2\">\n <Checkbox\n {...field}\n id={id}\n checked={!!field.value}\n onCheckedChange={handleCheckedChange}\n className={validationClasses}\n onKeyDown={handleKeyDown}\n disabled={readOnly}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n />\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n </div>\n\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground pl-6 text-sm\">\n {helperText}\n </div>\n )}\n\n <ErrorMessage error={error} id={errorId} className=\"pl-6\" />\n </>\n );\n }}\n />\n </div>\n );\n}\n\nBooleanField.displayName = 'BooleanField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { validateBytesSimple } from '@openzeppelin/ui-utils';\n\nimport { Label } from '../ui/label';\nimport { Textarea } from '../ui/textarea';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n} from './utils';\n\n/**\n * BytesField component properties\n */\nexport interface BytesFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Number of rows for the textarea\n */\n rows?: number;\n\n /**\n * Maximum length in bytes (not characters)\n */\n maxBytes?: number;\n\n /**\n * Exact length in bytes required (for fixed-size types like bytes32)\n * When set, the value must be exactly this many bytes.\n * Takes precedence over maxBytes.\n */\n exactBytes?: number;\n\n /**\n * Whether to accept hex, base64, or both formats\n */\n acceptedFormats?: 'hex' | 'base64' | 'both';\n\n /**\n * Whether to automatically add/remove 0x prefix for hex values\n */\n autoPrefix?: boolean;\n\n /**\n * Whether to allow 0x prefix in hex input (defaults to true)\n */\n allowHexPrefix?: boolean;\n}\n\n/**\n * Specialized input field for bytes data with built-in hex/base64 validation.\n *\n * This component provides proper validation for blockchain bytes data including:\n * - Hex encoding validation (with optional 0x prefix support)\n * - Base64 encoding validation\n * - Byte length validation\n * - Format detection and conversion\n *\n * Key props for EVM compatibility:\n * - `allowHexPrefix`: Whether to accept 0x prefixed input (defaults to true)\n * - `autoPrefix`: Whether to automatically add 0x prefixes (defaults to false)\n *\n * These are separate concerns - you can accept 0x input without auto-adding prefixes.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects BytesField for 'bytes' field types\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles bytes-specific validation and formatting\n */\nexport function BytesField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n placeholder = 'Enter hex or base64 encoded bytes',\n rows = 3,\n maxBytes,\n exactBytes,\n acceptedFormats = 'both',\n autoPrefix = false,\n allowHexPrefix = true,\n readOnly,\n}: BytesFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n /**\n * Validates bytes input format and encoding using validator.js\n */\n const validateBytesField = (value: string): boolean | string => {\n return validateBytesSimple(value, {\n acceptedFormats,\n maxBytes,\n exactBytes,\n allowHexPrefix, // Allow prefix based on explicit prop (defaults to true)\n });\n };\n\n /**\n * Formats the input value (adds 0x prefix if needed)\n */\n const formatValue = (value: string): string => {\n if (!value || !autoPrefix) return value;\n\n const cleanValue = value.trim().replace(/\\s+/g, '');\n const withoutPrefix = cleanValue.startsWith('0x') ? cleanValue.slice(2) : cleanValue;\n\n // Only add prefix for valid hex that doesn't already have it\n if (withoutPrefix && /^[0-9a-fA-F]*$/.test(withoutPrefix) && withoutPrefix.length % 2 === 0) {\n return cleanValue.startsWith('0x') ? cleanValue : `0x${cleanValue}`;\n }\n\n return cleanValue;\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n disabled={readOnly}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Run bytes-specific validation using validator.js\n return validateBytesField(value);\n },\n }}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && (isTouched || validation?.required);\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n isDisabled: readOnly,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <Textarea\n id={id}\n name={field.name}\n ref={field.ref}\n placeholder={placeholder}\n rows={rows}\n className={validationClasses}\n disabled={readOnly}\n value={field.value ?? ''}\n onChange={(e) => {\n // Only update value without formatting for better performance\n field.onChange(e.target.value);\n }}\n onBlur={(e) => {\n // Apply formatting on blur when user finishes typing\n const formatted = formatValue(e.target.value);\n field.onChange(formatted);\n // Register field as touched with React Hook Form\n field.onBlur();\n }}\n onKeyDown={handleEscapeKey(field.onChange, field.value)}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`.trim()}\n />\n\n {/* Display helper text with format hint */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n <div className=\"text-xs text-muted-foreground mt-1\">\n {acceptedFormats === 'hex' && 'Hex format (e.g., 48656c6c6f or 0x48656c6c6f)'}\n {acceptedFormats === 'base64' && 'Base64 format (e.g., SGVsbG8=)'}\n {acceptedFormats === 'both' &&\n 'Hex (e.g., 48656c6c6f) or Base64 (e.g., SGVsbG8=) format'}\n {exactBytes && ` • Exactly ${exactBytes} bytes (${exactBytes * 2} hex chars)`}\n {!exactBytes && maxBytes && ` • Max ${maxBytes} bytes`}\n </div>\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nBytesField.displayName = 'BytesField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n validateField,\n} from './utils';\n\n/**\n * DateTimeField component properties\n */\nexport interface DateTimeFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Placeholder text displayed when the field is empty\n */\n placeholder?: string;\n\n /**\n * If true, clears the field when user clicks Escape; otherwise just blurs\n */\n clearOnEscape?: boolean;\n}\n\n/**\n * Datetime-local input field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like DateTimeField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles date-time specific rendering, conversion, and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Conversion between input value (YYYY-MM-DDTHH:mm) and ISO 8601 strings (toISOString)\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation with Escape-to-clear behavior\n */\nexport function DateTimeField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n readOnly,\n clearOnEscape = true,\n}: DateTimeFieldProps<TFieldValues>): React.ReactElement {\n /**\n * TODO: Replace native datetime-local input with a styled popover-based\n * calendar/time picker (Radix Popover + Select) to match the design system.\n * Maintain ISO 8601 value semantics and provide a mobile fallback to native input.\n */\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Validate ISO 8601 string or empty according to validation rules\n const validateDateValue = (value: string): string | true => {\n const validationResult = validateField(value, validation);\n return validationResult === true ? true : (validationResult as string);\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n if (typeof value === 'string') {\n return validateDateValue(value);\n }\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const raw = e.target.value; // YYYY-MM-DDTHH:mm or ''\n if (!raw) {\n field.onChange('');\n return;\n }\n // Preserve the exact local selection instead of converting to UTC.\n // Store as ISO-like local string with timezone offset maintained by parsing components.\n const [datePart, timePart] = raw.split('T');\n const [year, month, day] = datePart.split('-').map((s) => Number(s));\n const [hours, minutes] = timePart.split(':').map((s) => Number(s));\n const localDate = new Date(year, month - 1, day, hours, minutes, 0, 0);\n // Serialize back to local YYYY-MM-DDTHH:mm string so the value remains what the user picked\n const pad = (n: number): string => String(n).padStart(2, '0');\n const serialized = `${localDate.getFullYear()}-${pad(localDate.getMonth() + 1)}-${pad(localDate.getDate())}T${pad(localDate.getHours())}:${pad(localDate.getMinutes())}`;\n field.onChange(serialized);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n if (e.key === 'Escape') {\n if (clearOnEscape) {\n handleEscapeKey(field.onChange as (v: string) => void, field.value)(e);\n } else {\n (e.target as HTMLElement).blur();\n }\n }\n };\n\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n isDisabled: !!readOnly,\n });\n\n const formatDateTimeLocal = (val: unknown): string => {\n if (!val) return '';\n try {\n const d = new Date(val as string);\n if (isNaN(d.getTime())) return '';\n const pad = (n: number): string => String(n).padStart(2, '0');\n const year = d.getFullYear();\n const month = pad(d.getMonth() + 1);\n const day = pad(d.getDate());\n const hours = pad(d.getHours());\n const minutes = pad(d.getMinutes());\n // Return a local datetime string for the input value to avoid timezone shifts\n return `${year}-${month}-${day}T${hours}:${minutes}`;\n } catch {\n return '';\n }\n };\n\n const inputValue: string = formatDateTimeLocal(field.value);\n\n return (\n <>\n <Input\n {...field}\n id={id}\n placeholder={placeholder}\n className={validationClasses}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n value={inputValue}\n type=\"datetime-local\"\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n disabled={readOnly}\n />\n\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\nDateTimeField.displayName = 'DateTimeField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport type { EnumValue, FormFieldType, FunctionParameter } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select';\nimport { Textarea } from '../ui/textarea';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n validateField,\n} from './utils';\n\n/**\n * Enum variant definition\n */\nexport interface EnumVariant {\n /** Name of the variant (e.g., 'One', 'Two', 'Three') */\n name: string;\n /** Type of variant: 'void' for unit variants, 'tuple' for variants with payload, 'integer' for numeric enums */\n type: 'void' | 'tuple' | 'integer';\n /** For tuple variants: array of payload type names (e.g., ['U32', 'ScString']) */\n payloadTypes?: string[];\n /** Optional nested component definitions for tuple payload entries */\n payloadComponents?: (FunctionParameter[] | undefined)[];\n /** For integer variants: the numeric value */\n value?: number;\n /** Flag indicating if this variant has a single Tuple payload (for serialization) */\n isSingleTuplePayload?: boolean;\n}\n\n/**\n * Enum metadata extracted from contract spec\n */\nexport interface EnumMetadata {\n /** Name of the enum type */\n name: string;\n /** Array of variants in the enum */\n variants: EnumVariant[];\n /** True if all variants are unit variants (no payloads), suitable for simple select/radio */\n isUnitOnly: boolean;\n}\n\n/**\n * Enum field value structure for blockchain enum types\n */\nexport type EnumFieldValue = EnumValue;\n\n/**\n * EnumField component properties\n */\nexport interface EnumFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Enum metadata containing variant information\n */\n enumMetadata?: EnumMetadata;\n\n /**\n * Custom validation function for enum values\n */\n validateEnum?: (value: EnumFieldValue) => boolean | string;\n\n /**\n * Render function for payload input fields.\n * This allows the parent component to provide appropriate field components\n * based on the payload type, maintaining separation of concerns.\n */\n renderPayloadField?: (field: FormFieldType, payloadIndex: number) => React.ReactNode;\n}\n\n/**\n * Composite enum field component for blockchain enum types.\n *\n * This component handles both unit enums (simple variants) and tagged enums (variants with payloads).\n * For unit enums, it renders as a simple select dropdown.\n * For tagged enums, it renders a variant picker plus conditional input fields for payload data.\n *\n * The value format is designed to be chain-agnostic:\n * - Unit variants: { tag: \"VariantName\" }\n * - Tuple variants: { tag: \"VariantName\", values: [...] }\n */\nexport function EnumField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder = 'Select variant',\n helperText,\n control,\n name,\n width = 'full',\n validation,\n enumMetadata,\n validateEnum,\n renderPayloadField,\n readOnly,\n}: EnumFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Use consistent width classes\n const widthClass = width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3';\n\n // If no enum metadata or empty variants, fallback to a simple text input with helper text\n if (!enumMetadata || enumMetadata.variants.length === 0) {\n return (\n <div className={cn('flex flex-col gap-2', widthClass)}>\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n disabled={readOnly}\n rules={{\n validate: (value) => {\n // Use standard validation first\n const standardValidation = validateField(value, validation);\n if (standardValidation !== true) {\n return standardValidation;\n }\n\n // If it's a string, try to validate it as JSON\n if (typeof value === 'string') {\n try {\n const parsed = JSON.parse(value);\n // Check if it has the required 'tag' property\n if (!parsed.tag) {\n return 'JSON must have a \"tag\" property specifying the enum variant';\n }\n } catch {\n return 'Invalid JSON format. Please enter valid JSON like {\"tag\":\"VariantName\"}';\n }\n }\n\n // If it's an object, check if it has the required 'tag' property\n if (typeof value === 'object' && value !== null) {\n if (!('tag' in value)) {\n return 'Enum value must have a \"tag\" property specifying the variant';\n }\n }\n\n return true;\n },\n }}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <div className=\"space-y-2\">\n <div className=\"p-3 border border-border rounded-md bg-muted\">\n <p className=\"text-sm text-muted-foreground\">\n Enum metadata not available. Please enter the value in JSON format.\n </p>\n <p className=\"text-xs text-muted-foreground mt-1\">\n Example: {`{\"tag\":\"One\"}`} or {`{\"tag\":\"Two\",\"values\":[42]}`}\n </p>\n </div>\n\n <Textarea\n id={id}\n {...accessibilityProps}\n className={cn('min-h-[80px]', validationClasses)}\n placeholder={`{\"tag\":\"One\"} or {\"tag\":\"Two\",\"values\":[42]}`}\n value={\n typeof field.value === 'string'\n ? field.value\n : JSON.stringify(field.value || {})\n }\n onChange={(e) => {\n try {\n // Try to parse as JSON, if successful store as object\n const parsed = JSON.parse(e.target.value);\n field.onChange(parsed);\n } catch {\n // If parsing fails, store as string (user is still typing)\n field.onChange(e.target.value);\n }\n }}\n onBlur={field.onBlur}\n name={field.name}\n disabled={readOnly}\n />\n </div>\n\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n <ErrorMessage error={error} id={errorId} />\n </>\n );\n }}\n />\n </div>\n );\n }\n\n return (\n <div className={cn('flex flex-col gap-2', widthClass)}>\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n disabled={readOnly}\n rules={{\n validate: (value) => {\n // Use standard validation first\n const standardValidation = validateField(value, validation);\n if (standardValidation !== true) {\n return standardValidation;\n }\n\n // Handle enum-specific validation\n if (!value || !value.tag) {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Run custom validation if provided\n if (validateEnum && value) {\n const customValidation = validateEnum(value);\n if (customValidation !== true && typeof customValidation === 'string') {\n return customValidation;\n }\n }\n\n return true;\n },\n }}\n render={({ field, fieldState: { error } }) => {\n const hasError = !!error;\n const currentValue: EnumFieldValue = field.value || { tag: '' };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n // Handle variant selection\n const handleVariantChange = (selectedTag: string): void => {\n const selectedVariant = enumMetadata.variants.find((v) => v.name === selectedTag);\n if (!selectedVariant) return;\n\n if (selectedVariant.type === 'void' || selectedVariant.type === 'integer') {\n // Unit variant - just set the tag\n field.onChange({ tag: selectedTag });\n } else {\n // Tuple variant - initialize with empty values (chain-agnostic)\n const initialValues = new Array(selectedVariant.payloadTypes?.length || 0).fill('');\n\n field.onChange({\n tag: selectedTag,\n values: initialValues,\n });\n }\n };\n\n // Handle payload value changes for tuple variants (chain-agnostic)\n const handlePayloadChange = (index: number, value: string): void => {\n const newValues = [...(currentValue.values || [])];\n // Simple chain-agnostic structure - just store the raw values\n newValues[index] = value;\n const newEnumValue = { ...currentValue, values: newValues };\n field.onChange(newEnumValue);\n };\n\n const selectedVariant = enumMetadata.variants.find((v) => v.name === currentValue.tag);\n\n return (\n <>\n {/* Variant Picker */}\n <Select\n value={currentValue.tag}\n onValueChange={handleVariantChange}\n disabled={readOnly}\n >\n <SelectTrigger id={id} {...accessibilityProps}>\n <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n <SelectContent>\n {enumMetadata.variants.map((variant) => (\n <SelectItem key={variant.name} value={variant.name}>\n {variant.name}\n {variant.type === 'integer' && variant.value !== undefined && (\n <span className=\"text-muted-foreground ml-2\">({variant.value})</span>\n )}\n {variant.type === 'tuple' && variant.payloadTypes && (\n <span className=\"text-muted-foreground ml-2\">\n ({variant.payloadTypes.join(', ')})\n </span>\n )}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n {/* Conditional Payload Inputs for Tuple Variants */}\n {selectedVariant &&\n selectedVariant.type === 'tuple' &&\n selectedVariant.payloadTypes && (\n <div className=\"ml-4 space-y-2 border-l-2 border-border pl-4\">\n <p className=\"text-sm text-muted-foreground\">\n Enter values for {selectedVariant.name}:\n </p>\n {selectedVariant.payloadTypes.map((payloadType, index) => {\n // Create field configuration for payload input\n const payloadField: FormFieldType = {\n id: `${id}-payload-${index}`,\n name: `${name}.values.${index}`,\n label: payloadType,\n type: 'text' as FormFieldType['type'],\n validation: {},\n placeholder: `Enter ${payloadType} value`,\n helperText: undefined,\n width: 'full',\n originalParameterType: payloadType,\n readOnly: readOnly, // Inherit readOnly state from parent\n ...(selectedVariant.payloadComponents?.[index] && {\n components: selectedVariant.payloadComponents[index],\n }),\n };\n\n return (\n <div key={index} className=\"flex flex-col gap-1\">\n {renderPayloadField ? (\n renderPayloadField(payloadField, index)\n ) : (\n // Fallback to basic input if no render function provided\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor={`${id}-payload-${index}`} className=\"text-sm\">\n {payloadType}\n </Label>\n <Input\n id={`${id}-payload-${index}`}\n type=\"text\"\n placeholder={`Enter ${payloadType} value`}\n value={(currentValue.values?.[index] as string) || ''}\n onChange={(e) => handlePayloadChange(index, e.target.value)}\n disabled={readOnly}\n />\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage error={error} id={errorId} />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nEnumField.displayName = 'EnumField';\n","import { AlertCircle, CheckCircle2, File as FileIcon, Upload, X } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Button } from '../ui/button';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage, getAccessibilityProps, validateField } from './utils';\n\n/**\n * FileUploadField component properties\n */\nexport interface FileUploadFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Accepted file types (e.g., \".zip,.tar.gz\")\n */\n accept?: string;\n /**\n * Maximum file size in bytes\n */\n maxSize?: number;\n /**\n * Whether to convert the file to base64 string\n */\n convertToBase64?: boolean;\n}\n\n/**\n * File upload field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like FileUploadField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles file upload-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - File type and size validation\n * - Optional conversion to base64 for storage\n * - Visual feedback for selected files\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation\n */\n/**\n * Format bytes to human-readable size\n */\nfunction formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;\n}\n\n/** File upload field component with drag-and-drop support. */\nexport function FileUploadField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder = 'Drop your file here or click to browse',\n helperText,\n control,\n name,\n width = 'full',\n validation,\n readOnly,\n accept,\n maxSize,\n convertToBase64 = false,\n}: FileUploadFieldProps<TFieldValues>): React.ReactElement {\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [fileName, setFileName] = useState<string>('');\n const [fileSize, setFileSize] = useState<number>(0);\n const [isProcessing, setIsProcessing] = useState(false);\n const [isDragOver, setIsDragOver] = useState(false);\n const [uploadStatus, setUploadStatus] = useState<'idle' | 'success' | 'error'>('idle');\n\n const handleFileToBase64 = (file: File): Promise<string> => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (): void => {\n if (typeof reader.result === 'string') {\n // Remove data URL prefix to get just base64\n const parts = reader.result.split(',');\n if (parts.length !== 2) {\n reject(new Error('Invalid data URL format'));\n return;\n }\n const base64 = parts[1];\n resolve(base64);\n } else {\n reject(new Error('Failed to convert file to base64'));\n }\n };\n reader.onerror = (): void => {\n reject(reader.error);\n };\n reader.readAsDataURL(file);\n });\n };\n\n const handleFileChange = async (\n file: File | null,\n onChange: (value: string | File) => void\n ): Promise<void> => {\n if (!file) {\n setFileName('');\n setFileSize(0);\n setUploadStatus('idle');\n onChange('');\n return;\n }\n\n // Validate file size\n if (maxSize && file.size > maxSize) {\n const maxSizeMB = (maxSize / (1024 * 1024)).toFixed(2);\n onChange('');\n setFileName('');\n setFileSize(0);\n setUploadStatus('error');\n // This will trigger validation error through React Hook Form\n throw new Error(`File size exceeds ${maxSizeMB} MB limit`);\n }\n\n setFileName(file.name);\n setFileSize(file.size);\n setUploadStatus('idle');\n\n // Immediately set the File object so required-field checks pass\n // and upstream loaders can proceed without waiting for conversion.\n onChange(file);\n\n // If base64 conversion is requested, convert in background and\n // replace the value once ready (keeps UI responsive and avoids\n // triggering preflight missing-field errors).\n if (!convertToBase64) {\n setUploadStatus('success');\n return;\n }\n\n setIsProcessing(true);\n\n try {\n const base64 = await handleFileToBase64(file);\n onChange(base64);\n setUploadStatus('success');\n } catch {\n onChange('');\n setFileName('');\n setFileSize(0);\n setUploadStatus('error');\n } finally {\n setIsProcessing(false);\n }\n };\n\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>): void => {\n e.preventDefault();\n e.stopPropagation();\n if (!readOnly && !isProcessing) {\n setIsDragOver(true);\n }\n };\n\n const handleDragLeave = (e: React.DragEvent<HTMLDivElement>): void => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n };\n\n const handleDrop = (\n e: React.DragEvent<HTMLDivElement>,\n onChange: (value: string | File) => void\n ): void => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n\n if (readOnly || isProcessing) return;\n\n const file = e.dataTransfer.files?.[0] || null;\n if (file) {\n handleFileChange(file, onChange);\n }\n };\n\n const clearFile = (onChange: (value: string | File) => void): void => {\n if (fileInputRef.current) {\n fileInputRef.current.value = '';\n }\n setFileName('');\n setFileSize(0);\n setUploadStatus('idle');\n onChange('');\n };\n\n return (\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n if (!value) return validateField(value, validation);\n\n // Additional file-specific validations\n if (\n maxSize &&\n value &&\n typeof value === 'object' &&\n 'size' in value &&\n value.size > maxSize\n ) {\n const maxSizeMB = (maxSize / (1024 * 1024)).toFixed(2);\n return `File size must be less than ${maxSizeMB} MB`;\n }\n\n return validateField(value, validation);\n },\n }}\n disabled={readOnly}\n render={({ field: { onChange, onBlur }, fieldState: { error } }) => {\n const fieldId = `${id}-field`;\n const errorId = `${fieldId}-error`;\n const hasError = !!error;\n const widthClass = width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3';\n\n // Build helper text with file requirements\n const requirementsText = [];\n if (accept) {\n const types = accept\n .split(',')\n .map((t) => t.trim())\n .join(', ');\n requirementsText.push(`Accepted types: ${types}`);\n }\n if (maxSize) {\n requirementsText.push(`Max size: ${formatFileSize(maxSize)}`);\n }\n const fullHelperText = helperText || requirementsText.join(' • ');\n\n return (\n <div className={`flex flex-col gap-2 ${widthClass}`}>\n <Label htmlFor={fieldId}>\n {label}\n {validation?.required && <span className=\"text-red-500 ml-1\">*</span>}\n </Label>\n\n {/* Hidden file input */}\n <input\n ref={fileInputRef}\n id={fieldId}\n type=\"file\"\n accept={accept}\n disabled={readOnly || isProcessing}\n onBlur={onBlur}\n onChange={(e) => {\n const file = e.target.files?.[0] || null;\n handleFileChange(file, onChange);\n }}\n className=\"hidden\"\n {...getAccessibilityProps({\n id: fieldId,\n hasError,\n isRequired: validation?.required,\n isDisabled: readOnly || isProcessing,\n })}\n />\n\n {/* Drop zone / Upload area */}\n <div\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={(e) => handleDrop(e, onChange)}\n onClick={() => {\n if (!readOnly && !isProcessing && !fileName) {\n fileInputRef.current?.click();\n }\n }}\n className={`\n relative rounded-lg border-2 border-dashed transition-all duration-200\n ${\n isDragOver\n ? 'border-selected bg-selected/5'\n : hasError\n ? 'border-destructive bg-destructive/5'\n : fileName\n ? 'border-border bg-muted/30'\n : 'border-border bg-background hover:border-selected/50 hover:bg-muted/50'\n }\n ${readOnly || isProcessing ? 'cursor-not-allowed opacity-60' : fileName ? 'cursor-default' : 'cursor-pointer'}\n p-6\n `}\n >\n {!fileName ? (\n // Empty state - show upload prompt\n <div className=\"flex flex-col items-center justify-center gap-3 text-center\">\n <div\n className={`rounded-full p-3 transition-colors ${\n isDragOver ? 'bg-selected/10' : 'bg-muted'\n }`}\n >\n <Upload\n className={`h-8 w-8 transition-colors ${\n isDragOver ? 'text-selected' : 'text-muted-foreground'\n }`}\n />\n </div>\n <div className=\"space-y-1\">\n <p className=\"text-sm font-medium\">\n {isDragOver ? 'Drop file here' : placeholder}\n </p>\n {fullHelperText && !isDragOver && (\n <p className=\"text-xs text-muted-foreground\">{fullHelperText}</p>\n )}\n </div>\n </div>\n ) : (\n // File selected state\n <div className=\"flex items-start gap-4\">\n <div\n className={`rounded-lg p-2 ${\n uploadStatus === 'success'\n ? 'bg-success/10'\n : uploadStatus === 'error'\n ? 'bg-destructive/10'\n : 'bg-muted'\n }`}\n >\n <FileIcon\n className={`h-8 w-8 ${\n uploadStatus === 'success'\n ? 'text-success'\n : uploadStatus === 'error'\n ? 'text-destructive'\n : 'text-muted-foreground'\n }`}\n />\n </div>\n <div className=\"flex-1 min-w-0 space-y-1\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium truncate\">{fileName}</p>\n <p className=\"text-xs text-muted-foreground\">\n {formatFileSize(fileSize)}\n {isProcessing && ' • Processing...'}\n </p>\n </div>\n <div className=\"flex items-center gap-2 shrink-0\">\n {uploadStatus === 'success' && !isProcessing && (\n <CheckCircle2 className=\"h-5 w-5 text-success\" />\n )}\n {uploadStatus === 'error' && (\n <AlertCircle className=\"h-5 w-5 text-destructive\" />\n )}\n {!readOnly && !isProcessing && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation();\n clearFile(onChange);\n }}\n className=\"h-8 w-8 p-0\"\n >\n <X className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n </div>\n {!isProcessing && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={readOnly}\n onClick={(e) => {\n e.stopPropagation();\n fileInputRef.current?.click();\n }}\n className=\"mt-2\"\n >\n Change file\n </Button>\n )}\n </div>\n </div>\n )}\n </div>\n\n <ErrorMessage error={error} id={errorId} />\n </div>\n );\n }}\n />\n );\n}\n","import { Plus, X } from 'lucide-react';\nimport React from 'react';\nimport { Controller, FieldValues, useFieldArray, useFormContext, useWatch } from 'react-hook-form';\n\nimport type { FormFieldType } from '@openzeppelin/ui-types';\nimport { getDefaultValueForType } from '@openzeppelin/ui-utils';\n\nimport { Button } from '../../ui/button';\nimport { Label } from '../../ui/label';\nimport { BaseFieldProps } from '../BaseField';\nimport { ErrorMessage, getAccessibilityProps } from '../utils';\nimport {\n computeChildTouched,\n MapEntryRow,\n useDuplicateKeyIndexes,\n useMapFieldSync,\n validateMapStructure,\n} from './index';\n\n/**\n * Helper function to format a label with an optional type hint\n */\nfunction formatLabeledType(baseLabel: string, typeHint?: string): string {\n if (!typeHint) {\n return baseLabel;\n }\n return `${baseLabel} (${typeHint})`;\n}\n\n/**\n * Helper function to create a default map entry with appropriate default values for key and value types\n */\nfunction createDefaultEntry(mapMetadata?: MapFieldProps['mapMetadata']): {\n key: unknown;\n value: unknown;\n} {\n return {\n key: mapMetadata?.keyFieldConfig?.type\n ? getDefaultValueForType(mapMetadata.keyFieldConfig.type)\n : '',\n value: mapMetadata?.valueFieldConfig?.type\n ? getDefaultValueForType(mapMetadata.valueFieldConfig.type)\n : '',\n };\n}\n\n/**\n * MapField component properties\n */\nexport interface MapFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Map metadata containing key and value type information\n */\n mapMetadata?: {\n keyType?: string;\n valueType?: string;\n keyFieldConfig?: Partial<FormFieldType>;\n valueFieldConfig?: Partial<FormFieldType>;\n };\n\n /**\n * Minimum number of map entries\n */\n minItems?: number;\n\n /**\n * Render function for map keys.\n * This allows the parent component to provide appropriate field components\n * based on the key type, maintaining separation of concerns.\n */\n renderKeyField?: (field: FormFieldType, entryIndex: number) => React.ReactNode;\n\n /**\n * Render function for map values.\n * This allows the parent component to provide appropriate field components\n * based on the value type, maintaining separation of concerns.\n */\n renderValueField?: (field: FormFieldType, entryIndex: number) => React.ReactNode;\n}\n\n/**\n * Map (key-value dictionary) input field component specifically designed for React Hook Form integration.\n *\n * This component provides a dynamic interface for managing map/dictionary inputs with:\n * - Add/remove functionality for key-value pairs\n * - Validation for map size constraints\n * - Integration with existing field components for keys and values\n * - Chain-agnostic data format (array of {key, value} objects)\n * - Full accessibility support\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like MapField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles map-specific rendering and validation\n *\n * The component stores data in a chain-agnostic format as an array of {key, value} objects.\n * The adapter is responsible for converting this to the chain-specific format (e.g., SorobanMapEntry[])\n * when submitting to the blockchain.\n */\nexport function MapField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n mapMetadata,\n minItems = 0,\n renderKeyField,\n renderValueField,\n readOnly,\n}: MapFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Get form context for field array operations\n const formContext = useFormContext();\n const effectiveControl = control || formContext.control;\n\n // Use field array for dynamic key-value pairs\n const { fields, append, remove, replace } = useFieldArray({\n control: effectiveControl,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n name: name as any, // Type assertion needed due to generic constraints\n });\n\n // Watch the map field value for duplicate key checking and initialization\n const watchedValue = useWatch({\n control: effectiveControl,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n name: name as any, // Type assertion needed due to generic constraints\n });\n const watchedValueKey = React.useMemo(() => JSON.stringify(watchedValue), [watchedValue]);\n\n // Keep field array synchronized with watched values\n const isReplacingRef = useMapFieldSync(watchedValue, fields.length, replace);\n\n /*\n * Keep the parent MapField error in sync without calling trigger:\n * - If any child has an error and the parent is required -> set a parent error\n * - Else use the structural validation result\n * This avoids re-entrancy loops that can happen when calling trigger during Preview.\n */\n React.useEffect(() => {\n if (!formContext) return;\n if (isReplacingRef.current) return;\n\n const mapArray = Array.isArray(watchedValue)\n ? (watchedValue as Array<{ key?: unknown; value?: unknown }>)\n : [];\n\n let childHasError = false;\n for (let i = 0; i < mapArray.length; i++) {\n const keyPath = `${name}.${i}.key`;\n const valuePath = `${name}.${i}.value`;\n const keyError = (formContext.formState.errors as Record<string, { message?: string }>)[\n keyPath\n ]?.message;\n const valueError = (formContext.formState.errors as Record<string, { message?: string }>)[\n valuePath\n ]?.message;\n if (keyError || valueError) {\n childHasError = true;\n break;\n }\n }\n\n const structural = validateMapStructure({\n value: watchedValue,\n required: !!validation?.required,\n minItems,\n });\n\n let nextMessage: string | undefined;\n if (childHasError && validation?.required) {\n nextMessage = 'This field is required';\n } else if (structural !== true) {\n nextMessage = structural;\n }\n\n const currentMessage = ((formContext.formState.errors as Record<string, { message?: string }>)[\n name as string\n ]?.message || undefined) as string | undefined;\n\n if (nextMessage && nextMessage !== currentMessage) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n formContext.setError(name as any, { type: 'manual', message: nextMessage });\n } else if (!nextMessage && currentMessage) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n formContext.clearErrors(name as any);\n }\n }, [\n formContext,\n name,\n watchedValue,\n watchedValueKey,\n validation?.required,\n minItems,\n isReplacingRef,\n ]);\n\n const duplicateKeyIndexes = useDuplicateKeyIndexes(watchedValue);\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={effectiveControl}\n name={name}\n disabled={readOnly}\n rules={{\n validate: (value) =>\n validateMapStructure({ value, required: !!validation?.required, minItems }),\n }}\n render={({ fieldState: { error, isTouched } }) => {\n // Check if any child fields have been touched to correctly determine\n // when to show the parent validation message.\n const anyChildTouched = computeChildTouched(formContext, name, watchedValue);\n const effectivelyTouched = isTouched || anyChildTouched;\n const hasError = !!error?.message;\n\n // Determine if the error message should be shown.\n // For required fields, we want to show the error immediately if the field is invalid.\n // For other fields, we only show it after the user has interacted with the component.\n const shouldShowError = hasError && (effectivelyTouched || isRequired);\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n // Add new map item\n const handleAddEntry = (): void => {\n // Set flag to prevent sync interference during add operation\n isReplacingRef.current = true;\n append(createDefaultEntry(mapMetadata) as FieldValues[typeof name]);\n\n // Reset flag after operation\n queueMicrotask(() => {\n isReplacingRef.current = false;\n });\n };\n\n // Remove map item\n const handleRemoveEntry = (index: number): void => {\n if (fields.length > minItems) {\n // Set flag to prevent sync interference during remove operation\n isReplacingRef.current = true;\n remove(index);\n\n // Reset flag after operation\n queueMicrotask(() => {\n isReplacingRef.current = false;\n });\n }\n };\n\n return (\n <>\n <div\n className=\"space-y-3\"\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`.trim()}\n >\n {fields.length === 0 ? (\n <div className=\"text-muted-foreground text-sm p-4 border border-dashed border-border rounded-md text-center\">\n No items added yet. Click “Add Item” to begin.\n </div>\n ) : (\n fields.map((field, index) => {\n // Create field configurations for key and value, following ArrayField pattern\n const isDuplicateKey = duplicateKeyIndexes.has(index);\n\n const keyField: FormFieldType = {\n ...mapMetadata?.keyFieldConfig,\n id: `${id}-key-${index}`,\n name: `${name}.${index}.key`,\n label: formatLabeledType(\n 'Key',\n mapMetadata?.keyFieldConfig?.originalParameterType || mapMetadata?.keyType\n ),\n type: mapMetadata?.keyFieldConfig?.type || 'text',\n validation: { required: true, ...mapMetadata?.keyFieldConfig?.validation },\n placeholder: mapMetadata?.keyFieldConfig?.placeholder || 'Enter key',\n width: 'full',\n readOnly: readOnly,\n originalParameterType: mapMetadata?.keyFieldConfig?.originalParameterType,\n };\n\n const valueField: FormFieldType = {\n ...mapMetadata?.valueFieldConfig,\n id: `${id}-value-${index}`,\n name: `${name}.${index}.value`,\n label: formatLabeledType(\n 'Value',\n mapMetadata?.valueFieldConfig?.originalParameterType ||\n mapMetadata?.valueType\n ),\n type: mapMetadata?.valueFieldConfig?.type || 'text',\n validation: { required: true, ...mapMetadata?.valueFieldConfig?.validation },\n placeholder: mapMetadata?.valueFieldConfig?.placeholder || 'Enter value',\n width: 'full',\n readOnly: readOnly,\n originalParameterType: mapMetadata?.valueFieldConfig?.originalParameterType,\n };\n\n return (\n <div\n key={field.id}\n className=\"flex items-start gap-2 p-3 border border-border rounded-md bg-background\"\n >\n <MapEntryRow\n keyField={keyField}\n valueField={valueField}\n isDuplicateKey={isDuplicateKey}\n renderKeyField={renderKeyField}\n renderValueField={renderValueField}\n index={index}\n />\n\n {!readOnly && fields.length > minItems && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => handleRemoveEntry(index)}\n className=\"size-8 p-0\"\n aria-label={`Remove item ${index + 1}`}\n >\n <X className=\"size-4\" />\n </Button>\n )}\n </div>\n );\n })\n )}\n\n {/* Add Item Button */}\n {!readOnly && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full\"\n onClick={handleAddEntry}\n >\n <Plus className=\"h-4 w-4 mr-2\" />\n Add Item\n </Button>\n )}\n </div>\n\n {/* Helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Error message */}\n <ErrorMessage\n message={shouldShowError ? error?.message : undefined}\n error={error}\n id={errorId}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nMapField.displayName = 'MapField';\n","import React from 'react';\n\nimport type { FormFieldType } from '@openzeppelin/ui-types';\n\ninterface Props {\n keyField: FormFieldType;\n valueField: FormFieldType;\n isDuplicateKey: boolean;\n renderKeyField?: (field: FormFieldType, entryIndex: number) => React.ReactNode;\n renderValueField?: (field: FormFieldType, entryIndex: number) => React.ReactNode;\n index: number;\n}\n\n/** Renders a single key-value entry row in a map field. */\nexport function MapEntryRow({\n keyField,\n valueField,\n isDuplicateKey,\n renderKeyField,\n renderValueField,\n index,\n}: Props): React.ReactElement {\n return (\n <div className=\"flex-1 grid grid-cols-1 gap-2 md:grid-cols-2\">\n <div className=\"flex flex-col gap-1\">\n {renderKeyField ? (\n <>\n {renderKeyField(keyField, index)}\n {isDuplicateKey && (\n <div className=\"text-destructive mt-1 text-sm\" role=\"alert\">\n Duplicate keys are not allowed\n </div>\n )}\n </>\n ) : (\n <div className=\"text-sm text-muted-foreground p-2 border border-dashed border-border rounded\">\n Key field type “{keyField.type}” requires a render function\n </div>\n )}\n </div>\n\n <div className=\"flex flex-col gap-1 md:items-center md:justify-center\">\n {renderValueField ? (\n renderValueField(valueField, index)\n ) : (\n <div className=\"text-sm text-muted-foreground p-2 border border-dashed border-border rounded\">\n Value field type “{valueField.type}” requires a render function\n </div>\n )}\n </div>\n </div>\n );\n}\n","import { UseFormReturn } from 'react-hook-form';\n\n/** Computes whether any child field in a map has been touched. */\nexport function computeChildTouched(\n formContext: UseFormReturn | undefined,\n name: string,\n watchedValue: unknown\n): boolean {\n const mapArray = Array.isArray(watchedValue)\n ? (watchedValue as Array<{ key?: unknown; value?: unknown }>)\n : [];\n if (!formContext || mapArray.length === 0) return false;\n\n for (let i = 0; i < mapArray.length; i++) {\n const keyPath = `${name}.${i}.key` as const;\n const valuePath = `${name}.${i}.value` as const;\n const keyState = formContext.getFieldState(keyPath, formContext.formState);\n const valueState = formContext.getFieldState(valuePath, formContext.formState);\n if (keyState.isTouched || valueState.isTouched) return true;\n }\n return false;\n}\n","import React from 'react';\n\n/** Hook that returns indexes of map entries with duplicate keys. */\nexport function useDuplicateKeyIndexes(watchedValue: unknown): Set<number> {\n return React.useMemo(() => {\n const duplicates = new Set<number>();\n if (!Array.isArray(watchedValue)) return duplicates;\n\n const keyCounts = new Map<string, number[]>();\n watchedValue.forEach((item: { key?: unknown }, index: number) => {\n const key = item?.key;\n if (key !== undefined && key !== null && key !== '') {\n const keyStr = String(key);\n if (!keyCounts.has(keyStr)) keyCounts.set(keyStr, []);\n keyCounts.get(keyStr)!.push(index);\n }\n });\n\n for (const [, indexes] of keyCounts) {\n if (indexes.length > 1) {\n indexes.forEach((i) => duplicates.add(i));\n }\n }\n return duplicates;\n }, [watchedValue]);\n}\n","import React from 'react';\n\n/**\n * Keeps a field array synchronized with a watched value's length using replace,\n * while preventing infinite loops via a guard ref.\n */\nexport function useMapFieldSync<TReplaceValue>(\n watchedValue: unknown,\n fieldsLength: number,\n replace: (value: TReplaceValue) => void\n): ReturnType<typeof React.useRef<boolean>> {\n const isReplacingRef = React.useRef(false);\n\n React.useEffect(() => {\n if (isReplacingRef.current) return;\n\n if (Array.isArray(watchedValue) && fieldsLength !== watchedValue.length) {\n isReplacingRef.current = true;\n replace(watchedValue as TReplaceValue);\n queueMicrotask(() => {\n isReplacingRef.current = false;\n });\n }\n }, [fieldsLength, watchedValue, replace]);\n\n return isReplacingRef;\n}\n","import { isMapEntryArray, MapEntry } from '@openzeppelin/ui-types';\n\nimport { validateMapEntries } from '../../utils/validation';\n\ninterface ValidateArgs {\n value: unknown;\n required: boolean;\n minItems?: number;\n}\n\n/** Validates a map field's structure including duplicates and required entries. */\nexport function validateMapStructure({ value, required, minItems }: ValidateArgs): string | true {\n // Validate that the value is actually an array of MapEntry objects\n if (!isMapEntryArray(value)) {\n if (required) return 'This field is required';\n return true;\n }\n\n const mapArray: MapEntry[] = value;\n\n const duplicateError = validateMapEntries(mapArray);\n if (duplicateError) return duplicateError;\n\n const hasPartial = mapArray.some((entry: MapEntry) => {\n const key = entry.key;\n const val = entry.value;\n const keyEmpty = key === '' || key == null;\n const valEmpty = val === '' || val == null;\n return (keyEmpty && !valEmpty) || (!keyEmpty && valEmpty);\n });\n if (hasPartial) return 'All key-value pairs must be completed';\n\n const validEntries = mapArray.filter((entry: MapEntry) => {\n const key = entry.key;\n const val = entry.value;\n return key !== '' && key != null && val !== '' && val != null;\n });\n\n if (required && validEntries.length === 0) return 'This field is required';\n\n if (minItems && validEntries.length < minItems) {\n return `At least ${minItems} item${minItems > 1 ? 's' : ''} required`;\n }\n\n return true;\n}\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n validateField,\n} from './utils';\n\n/**\n * NumberField component properties\n */\nexport interface NumberFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Minimum value validation\n */\n min?: number;\n\n /**\n * Maximum value validation\n */\n max?: number;\n\n /**\n * Step value for increment/decrement\n */\n step?: number;\n\n /**\n * Custom validation function for number values\n */\n validateNumber?: (value: number) => boolean | string;\n}\n\n/**\n * Number input field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like NumberField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles number-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Numeric-specific validations (min, max, step)\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation with arrow keys for numeric increment/decrement\n */\nexport function NumberField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n min,\n max,\n step = 1,\n validateNumber,\n readOnly,\n}: NumberFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Create merged validation that includes min/max from props\n const mergedValidation = {\n ...validation,\n min: validation?.min !== undefined ? validation.min : min,\n max: validation?.max !== undefined ? validation.max : max,\n };\n\n // Regular expressions for number validation\n const NUMBER_REGEX = {\n // Allow optional minus sign, digits, optional decimal point, more digits\n VALID_FORMAT: /^-?\\d*\\.?\\d*$/,\n // Complete number (more strict than the format check)\n COMPLETE_NUMBER: /^-?\\d+\\.?\\d*$/,\n };\n\n // Common validation for numeric values\n const validateNumericValue = (value: number): string | true => {\n // Run standard validation\n const standardValidation = validateField(value, mergedValidation);\n if (standardValidation !== true) return standardValidation as string;\n\n // Run custom validator if provided\n if (validateNumber) {\n const customValidation = validateNumber(value);\n if (customValidation !== true && typeof customValidation === 'string') {\n return customValidation;\n }\n }\n\n return true;\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Skip validation if empty and check required separately\n if (value === undefined || value === null || value === '') {\n return mergedValidation?.required ? 'This field is required' : true;\n }\n\n // Handle incomplete number inputs\n if (value === '-') {\n return 'Please enter a complete number';\n }\n\n // Handle decimal point at the end\n if (typeof value === 'string' && value.endsWith('.')) {\n return 'Please enter a complete decimal number';\n }\n\n // For string values that passed our format check but aren't complete numbers\n if (typeof value === 'string') {\n // Parse the validated string to a number\n const parsedNum = parseFloat(value);\n if (isNaN(parsedNum)) {\n return 'Invalid number'; // Explicitly return error for NaN\n }\n return validateNumericValue(parsedNum);\n }\n\n // For already numeric values\n if (typeof value === 'number') {\n return validateNumericValue(value);\n }\n\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Handle input change\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const rawValue = e.target.value;\n\n // Check if the input matches our valid number format\n const isValidNumberFormat = NUMBER_REGEX.VALID_FORMAT.test(rawValue);\n\n if (!isValidNumberFormat && rawValue !== '') {\n // Don't update the field value for invalid formats\n // This prevents entering invalid characters\n return;\n }\n\n // For valid format or empty string\n if (rawValue === '') {\n // Empty value\n field.onChange('');\n } else if (rawValue === '-') {\n // Allow standalone minus for user to continue typing\n field.onChange(rawValue);\n } else if (rawValue.endsWith('.')) {\n // Allow numbers ending with decimal point for user to continue typing\n field.onChange(rawValue);\n } else {\n // Convert to number for valid numeric values\n const numValue = parseFloat(rawValue);\n field.onChange(isNaN(numValue) ? rawValue : numValue);\n }\n\n // Note: Validation happens naturally when user leaves the field\n // No need to trigger it programmatically on every change\n };\n\n // Handle keyboard events\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n // Allow only numeric characters, backspace, delete, tab, escape, enter, arrows, period, hyphen\n // This is a basic filter; more complex scenarios might need a more robust solution\n const allowedKeys = [\n '0',\n '1',\n '2',\n '3',\n '4',\n '5',\n '6',\n '7',\n '8',\n '9',\n 'Backspace',\n 'Delete',\n 'Tab',\n 'Escape',\n 'Enter',\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n '.',\n '-',\n ];\n\n // Allow Ctrl/Cmd+A, C, V, X, Z for common editing operations\n if (\n (e.ctrlKey || e.metaKey) &&\n ['a', 'c', 'v', 'x', 'z'].includes(e.key.toLowerCase())\n ) {\n return;\n }\n\n if (!allowedKeys.includes(e.key) && !e.ctrlKey && !e.metaKey) {\n e.preventDefault();\n }\n\n // Handle escape key to clear input\n if (e.key === 'Escape') {\n handleEscapeKey(field.onChange, field.value)(e);\n return;\n }\n\n // Handle arrow keys for increment/decrement\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault(); // Prevent default browser behavior\n\n // Get current value as number or default to 0\n let currentValue = 0;\n if (typeof field.value === 'number') {\n currentValue = field.value;\n } else if (\n typeof field.value === 'string' &&\n NUMBER_REGEX.COMPLETE_NUMBER.test(field.value)\n ) {\n currentValue = parseFloat(field.value);\n }\n\n // Calculate new value based on step, respecting min/max\n const increment = e.key === 'ArrowUp' ? step : -step;\n const newValue = Math.min(\n max !== undefined ? max : Infinity,\n Math.max(min !== undefined ? min : -Infinity, currentValue + increment)\n );\n\n // Update the field\n field.onChange(newValue);\n // Note: Validation happens naturally, no need to trigger it programmatically\n }\n };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <Input\n {...field}\n value={field.value ?? ''}\n id={id}\n placeholder={placeholder}\n type=\"text\"\n min={min}\n max={max}\n step={step}\n className={validationClasses}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n onChange={handleInputChange}\n inputMode=\"decimal\"\n pattern=\"-?[0-9]*\\.?[0-9]*\"\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n disabled={readOnly}\n />\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nNumberField.displayName = 'NumberField';\n","import React from 'react';\nimport { Control, Controller, FieldValues, useFormContext } from 'react-hook-form';\n\nimport type {\n ContractSchema,\n FormFieldType,\n FunctionParameter,\n TypeMappingCapability,\n} from '@openzeppelin/ui-types';\n\n// TODO: Consider if FunctionParameter is the most appropriate type for `components` here,\n// or if a UI-specific version of a component/property definition would be more robust.\n\nimport { Card } from '../ui/card';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage, getAccessibilityProps } from './utils';\n\n/**\n * ObjectField component properties\n */\nexport interface ObjectFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * The components/properties of the object.\n * These define the schema for the nested fields within the object.\n */\n components?: FunctionParameter[]; // TODO: As above, review type for `components`.\n\n /**\n * Render function for object properties.\n * This is crucial for rendering complex properties or integrating custom field components.\n */\n // TODO: Explore a fallback rendering mechanism if `renderProperty` is not provided,\n // especially for known simple property types (e.g., 'text', 'number').\n // This could make the component more self-contained for basic object structures.\n renderProperty?: (field: FormFieldType, propertyName: string) => React.ReactNode;\n\n /**\n * Whether to show the object in a card container.\n * Useful for visually grouping object properties.\n */\n // TODO: Consider more advanced layout options beyond a simple card,\n // e.g., tabs, accordions for very complex objects, or grid layouts.\n showCard?: boolean;\n\n /**\n * The type-mapping capability for chain-specific field generation.\n * Essential for correctly determining field types for object properties.\n */\n typeMapping?: TypeMappingCapability;\n\n /**\n * Optional contract schema for nested metadata (structs/enums).\n */\n contractSchema?: ContractSchema;\n}\n\n/**\n * Object (composite/nested) input field component specifically designed for React Hook Form integration.\n *\n * This component provides a structured interface for managing object inputs with:\n * - Nested field rendering based on object components\n * - Validation for required properties (currently, the object itself can be required)\n * - Integration with existing field components for object properties\n * - Full accessibility support\n *\n * The component reuses existing field components for individual properties,\n * maintaining consistency across the form system while supporting complex nested structures.\n */\nexport function ObjectField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n components = [],\n renderProperty,\n showCard = true,\n readOnly,\n typeMapping,\n contractSchema,\n}: ObjectFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Get form context for nested field registration\n const formContext = useFormContext();\n const effectiveControl = control || formContext.control;\n\n // TODO: Consider performance implications for very large/deeply nested objects.\n // For extremely complex objects, virtualization or other rendering strategies might be needed.\n\n return (\n <Controller\n control={effectiveControl as Control<FieldValues>}\n name={name}\n rules={{\n // TODO: Expand validation capabilities for objects.\n // Current validation only checks if the object itself is required.\n // Future: Allow schema-level validation for individual properties within the object,\n // or a custom validate function that receives the whole object value.\n validate: (value) => {\n // Validate object constraints\n if (\n validation?.required &&\n (!value || typeof value !== 'object' || Array.isArray(value))\n ) {\n return 'This field is required';\n }\n\n // Additional object validation can be added here (e.g., based on `components` schema)\n return true;\n },\n }}\n render={({ fieldState: { error } }) => {\n const hasError = !!error;\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n const content = (\n <>\n {/* Object properties */}\n <div className=\"space-y-4\">\n {components.length === 0 ? (\n <div className=\"text-muted-foreground text-sm\">\n No properties defined for this object\n </div>\n ) : (\n components.map((component) => {\n // Generate field using the type-mapping capability to preserve nested array/object metadata.\n if (!typeMapping) {\n throw new Error(\n `ObjectField: No typeMapping capability provided for field generation. Cannot generate field for \"${component.name}\"`\n );\n }\n\n const generatedField = typeMapping.generateDefaultField(\n component,\n contractSchema\n );\n\n // Override with object-specific configuration\n const propertyField: FormFieldType = {\n ...generatedField, // Include elementType and other capability-specific properties\n id: `${id}-${component.name}`,\n name: `${name}.${component.name}`,\n label: component.displayName || component.name,\n // Validation merging precedence:\n // 1. Spread generatedField.validation (adapter-provided bounds, etc.)\n // 2. Override 'required' from parent validation if specified\n // This preserves min/max bounds while allowing parent to control required state\n validation: {\n ...generatedField.validation, // Preserve validation from type mapping (includes min/max bounds)\n required: validation?.required, // Override required from parent\n },\n placeholder: `Enter ${component.displayName || component.name}`,\n helperText:\n component.description ||\n (generatedField.type === 'number' ? 'Numbers only' : undefined),\n width: 'full',\n readOnly,\n // Pass components for nested objects (tuples within a struct)\n ...(component.components && {\n components: component.components,\n }),\n };\n\n return (\n <div key={component.name}>\n {renderProperty ? (\n renderProperty(propertyField, component.name)\n ) : (\n // This fallback is okay, but a more robust solution might attempt to\n // render a default UI field based on `propertyField.type` if it's a known simple type.\n <div className=\"text-sm text-muted-foreground\">\n Property “{component.name}” requires a render function\n </div>\n )}\n </div>\n );\n })\n )}\n </div>\n\n {/* Helper text for the entire object */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm mt-2\">\n {helperText}\n </div>\n )}\n\n {/* Error message for the entire object */}\n <ErrorMessage error={error} id={errorId} />\n </>\n );\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n >\n {/* Label for the entire object */}\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n {/* TODO: Conditional rendering of Card based on `showCard` and `components.length`.\n Perhaps don't render a card if there are no components or if showCard is false.\n Currently, an empty card might be rendered if components is empty but showCard is true. */}\n {showCard ? <Card className=\"p-4\">{content}</Card> : content}\n </div>\n );\n }}\n />\n );\n}\n\n// Set display name for debugging\nObjectField.displayName = 'ObjectField';\n","import { Eye, EyeOff } from 'lucide-react';\nimport React, { useState } from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n validateField,\n} from './utils';\n\n/**\n * PasswordField component properties\n */\nexport interface PasswordFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Placeholder text displayed when the field is empty\n */\n placeholder?: string;\n\n /**\n * Whether to show the password visibility toggle button\n * @default true\n */\n showToggle?: boolean;\n}\n\n/**\n * Password input field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like PasswordField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles password-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Password visibility toggle functionality\n * - Password-specific validations (minLength, maxLength, pattern)\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation\n */\nexport function PasswordField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n readOnly,\n showToggle = true,\n}: PasswordFieldProps<TFieldValues>): React.ReactElement {\n const [showPassword, setShowPassword] = useState(false);\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Function for validating password values\n const validatePasswordValue = (value: string): string | true => {\n const validationResult = validateField(value, validation);\n return validationResult === true ? true : (validationResult as string);\n };\n\n // Toggle password visibility\n const togglePasswordVisibility = (): void => {\n setShowPassword((prev) => !prev);\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Validate password values\n if (typeof value === 'string') {\n return validatePasswordValue(value);\n }\n\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Handle input change with validation for required fields\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const value = e.target.value;\n field.onChange(value);\n\n // Trigger validation if the field is required and empty\n if (isRequired && value === '') {\n setTimeout(() => field.onBlur(), 0);\n }\n };\n\n // Handle keyboard events\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n if (e.key === 'Escape') {\n handleEscapeKey(field.onChange, field.value)(e);\n\n // If required, trigger validation after clearing\n if (isRequired) {\n setTimeout(() => field.onBlur(), 0);\n }\n }\n };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <div className=\"relative\">\n <Input\n {...field}\n id={id}\n type={showPassword ? 'text' : 'password'}\n placeholder={placeholder}\n className={`${validationClasses} ${showToggle ? 'pr-10' : ''}`}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n value={field.value ?? ''}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n disabled={readOnly}\n />\n {showToggle && !readOnly && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent\"\n onClick={togglePasswordVisibility}\n aria-label={showPassword ? 'Hide password' : 'Show password'}\n >\n {showPassword ? (\n <EyeOff className=\"h-4 w-4 text-muted-foreground\" />\n ) : (\n <Eye className=\"h-4 w-4 text-muted-foreground\" />\n )}\n </Button>\n )}\n </div>\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nPasswordField.displayName = 'PasswordField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage, getAccessibilityProps } from './utils';\n\n/**\n * Option item for radio fields\n */\nexport interface RadioOption {\n /**\n * Value to be submitted with the form\n */\n value: string;\n\n /**\n * Display label for the option\n */\n label: string;\n\n /**\n * Whether this option is disabled\n */\n disabled?: boolean;\n}\n\n/**\n * RadioField component properties\n */\nexport interface RadioFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Available options for selection\n */\n options?: RadioOption[];\n\n /**\n * Direction of radio options layout\n */\n layout?: 'horizontal' | 'vertical';\n\n /**\n * Custom validation function for radio values\n */\n validateRadio?: (value: string) => boolean | string;\n}\n\n/**\n * Radio button field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles radio-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Customizable options list\n * - Horizontal or vertical layout options\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n */\nexport function RadioField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n options = [],\n layout = 'vertical',\n validateRadio,\n}: RadioFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n const radioGroupId = `${id}-group`;\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={radioGroupId} className=\"text-sm font-medium\">\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Run custom validation if provided\n if (validateRadio && value) {\n const validation = validateRadio(value);\n if (validation !== true && typeof validation === 'string') {\n return validation;\n }\n }\n\n return true;\n },\n }}\n render={({ field, fieldState: { error } }) => {\n const hasError = !!error;\n\n // Group accessibility attributes\n const groupAccessibilityProps = getAccessibilityProps({\n id: radioGroupId,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <div\n id={radioGroupId}\n role=\"radiogroup\"\n className={`flex ${layout === 'vertical' ? 'flex-col gap-3' : 'flex-row flex-wrap gap-4'}`}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n {...groupAccessibilityProps}\n >\n {options.map((option, index) => {\n const optionId = `${id}-option-${index}`;\n const isSelected = field.value === option.value;\n const isDisabled = option.disabled;\n\n return (\n <label\n key={option.value}\n htmlFor={optionId}\n className={`group relative flex cursor-pointer items-center gap-2 rounded-lg px-3 py-2 transition-all duration-150 ${\n isDisabled ? 'cursor-not-allowed opacity-50' : 'hover:bg-muted/50'\n } ${isSelected && !hasError ? 'bg-selected/5' : ''}`}\n >\n <input\n type=\"radio\"\n id={optionId}\n value={option.value}\n disabled={isDisabled}\n checked={isSelected}\n onChange={() => field.onChange(option.value)}\n className=\"sr-only\"\n aria-describedby={hasError ? errorId : undefined}\n />\n\n {/* Custom Radio Button */}\n <div className=\"relative flex size-4 items-center justify-center\">\n <div\n className={`absolute size-4 rounded-full border-2 transition-all duration-150 ${\n isSelected\n ? hasError\n ? 'border-destructive bg-destructive/10'\n : 'border-selected bg-selected/10'\n : hasError\n ? 'border-destructive/50'\n : 'border-muted-foreground/40 group-hover:border-muted-foreground/60'\n } ${!isDisabled && 'group-hover:scale-105'}`}\n />\n\n {/* Inner dot for selected state */}\n <div\n className={`absolute size-1.5 rounded-full transition-all duration-150 ${\n isSelected\n ? hasError\n ? 'bg-destructive scale-100 opacity-100'\n : 'bg-selected scale-100 opacity-100'\n : 'scale-0 opacity-0'\n }`}\n />\n </div>\n\n {/* Label text */}\n <span\n className={`text-sm transition-colors duration-150 ${\n isDisabled\n ? 'text-muted-foreground'\n : isSelected\n ? hasError\n ? 'text-destructive font-medium'\n : 'text-foreground font-medium'\n : 'text-foreground'\n }`}\n >\n {option.label}\n </span>\n\n {/* Focus ring */}\n <div\n className={`absolute -inset-1 rounded-lg ring-2 ring-selected ring-offset-2 ring-offset-background transition-opacity duration-150 ${\n isSelected && !isDisabled\n ? 'opacity-0 focus-within:opacity-100'\n : 'opacity-0'\n }`}\n />\n </label>\n );\n })}\n </div>\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-sm text-muted-foreground\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage error={error} id={errorId} />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nRadioField.displayName = 'RadioField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Label } from '../ui/label';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage } from './utils';\n\n/**\n * Option item for select fields\n */\nexport interface SelectOption {\n /**\n * Value to be submitted with the form\n */\n value: string;\n\n /**\n * Display label for the option\n */\n label: string;\n\n /**\n * Whether this option is disabled\n */\n disabled?: boolean;\n}\n\n/**\n * SelectField component properties\n */\nexport interface SelectFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Available options for selection\n */\n options?: SelectOption[];\n\n /**\n * Custom validation function for select values\n */\n validateSelect?: (value: string) => boolean | string;\n\n /**\n * Optional default value used when the field has no value yet\n */\n defaultValue?: string;\n}\n\n/**\n * Select dropdown field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles radio-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Customizable options list\n * - Horizontal or vertical layout options\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n */\nexport function SelectField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder = 'Select an option',\n helperText,\n control,\n name,\n width = 'full',\n validation,\n options = [],\n validateSelect,\n defaultValue,\n}: SelectFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Determine width values\n const widthPercentage = width === 'full' ? '100%' : width === 'half' ? '50%' : '33.333%';\n const widthClass = width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3';\n\n return (\n <div className={cn('flex flex-col gap-2', widthClass)} style={{ width: widthPercentage }}>\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n defaultValue={defaultValue as unknown as undefined}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Run custom validation if provided\n if (validateSelect && value) {\n const validation = validateSelect(value);\n if (validation !== true && typeof validation === 'string') {\n return validation;\n }\n }\n\n return true;\n },\n }}\n render={({ field, fieldState: { error } }) => {\n const hasError = !!error;\n\n // Get accessibility attributes\n const accessibilityAttrs = {\n 'aria-invalid': hasError,\n 'aria-required': isRequired,\n 'aria-describedby':\n `${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`.trim(),\n };\n\n // Ensure we properly handle the onValueChange event\n const handleValueChange = (newValue: string): void => {\n field.onChange(newValue);\n };\n\n return (\n <>\n <Select\n defaultValue={field.value}\n onValueChange={handleValueChange}\n value={field.value}\n >\n <SelectTrigger id={id} {...accessibilityAttrs}>\n <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n <SelectContent\n // Ensure dropdown width matches trigger width\n style={{\n width: 'var(--radix-select-trigger-width)',\n maxWidth: 'var(--radix-select-trigger-width)',\n }}\n >\n {options.length === 0 ? (\n <div className=\"px-2 py-1.5 text-sm text-muted-foreground\">\n No options available\n </div>\n ) : (\n options.map((option) => (\n <SelectItem\n key={option.value}\n value={option.value}\n disabled={option.disabled}\n >\n {option.label}\n </SelectItem>\n ))\n )}\n </SelectContent>\n </Select>\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage error={error} id={errorId} />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nSelectField.displayName = 'SelectField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Label } from '../ui/label';\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n} from '../ui/select';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage } from './utils';\n\n/**\n * Option item for select fields with visual indicators\n */\nexport interface GroupedSelectOption {\n /**\n * Value to be submitted with the form\n */\n value: string;\n\n /**\n * Display label for the option\n */\n label: string;\n\n /**\n * Whether this option is disabled\n */\n disabled?: boolean;\n\n /**\n * Custom CSS class to apply to the option\n */\n className?: string;\n}\n\n/**\n * Option group structure\n */\nexport interface OptionGroup {\n /**\n * Group label to display\n */\n label: string;\n\n /**\n * Options within this group\n */\n options: GroupedSelectOption[];\n}\n\n/**\n * SelectGroupedField component properties\n */\nexport interface SelectGroupedFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Available option groups for selection\n */\n groups?: OptionGroup[];\n\n /**\n * Custom validation function for select values\n */\n validateSelect?: (value: string) => boolean | string;\n}\n\n/**\n * Select dropdown field component with grouped options specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles radio-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Customizable options list\n * - Horizontal or vertical layout options\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n */\nexport function SelectGroupedField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder = 'Select an option',\n helperText,\n control,\n name,\n width = 'full',\n validation,\n groups = [],\n validateSelect,\n}: SelectGroupedFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Determine width values\n const widthPercentage = width === 'full' ? '100%' : width === 'half' ? '50%' : '33.333%';\n const widthClass = width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3';\n\n return (\n <div className={cn('flex flex-col gap-2', widthClass)} style={{ width: widthPercentage }}>\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Run custom validation if provided\n if (validateSelect && value) {\n const validation = validateSelect(value);\n if (validation !== true && typeof validation === 'string') {\n return validation;\n }\n }\n\n return true;\n },\n }}\n render={({ field, fieldState: { error } }) => {\n const hasError = !!error;\n\n // Get accessibility attributes\n const accessibilityAttrs = {\n 'aria-invalid': hasError,\n 'aria-required': isRequired,\n 'aria-describedby':\n `${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`.trim(),\n };\n\n // Ensure we properly handle the onValueChange event\n const handleValueChange = (newValue: string): void => {\n field.onChange(newValue);\n };\n\n return (\n <>\n <Select\n defaultValue={field.value}\n onValueChange={handleValueChange}\n value={field.value}\n >\n <SelectTrigger id={id} {...accessibilityAttrs}>\n <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n <SelectContent\n // Ensure dropdown width matches trigger width\n style={{\n width: 'var(--radix-select-trigger-width)',\n maxWidth: 'var(--radix-select-trigger-width)',\n }}\n >\n {groups.map((group, groupIndex) => (\n <React.Fragment key={`group-${groupIndex}`}>\n {groupIndex > 0 && <SelectSeparator />}\n <SelectGroup>\n <SelectLabel>{group.label}</SelectLabel>\n {group.options.map((option) => (\n <SelectItem\n key={option.value}\n value={option.value}\n disabled={option.disabled}\n className={cn(option.className, option.disabled && 'opacity-50')}\n >\n <span>{option.label}</span>\n </SelectItem>\n ))}\n </SelectGroup>\n </React.Fragment>\n ))}\n </SelectContent>\n </Select>\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage error={error} id={errorId} />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nSelectGroupedField.displayName = 'SelectGroupedField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n validateField,\n} from './utils';\n\n/**\n * TextField component properties\n */\nexport interface TextFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Placeholder text displayed when the field is empty\n */\n placeholder?: string;\n}\n\n/**\n * Text input field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like TextField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles text-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Text-specific validations (minLength, maxLength, pattern)\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation\n */\nexport function TextField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n readOnly,\n}: TextFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Function for validating text values\n const validateTextValue = (value: string): string | true => {\n const validationResult = validateField(value, validation);\n return validationResult === true ? true : (validationResult as string);\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Validate text values\n if (typeof value === 'string') {\n return validateTextValue(value);\n }\n\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Handle input change with validation for required fields\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const value = e.target.value;\n field.onChange(value);\n // Note: Validation happens naturally when user leaves the field\n // No need to trigger it programmatically on every change\n };\n\n // Handle keyboard events\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n if (e.key === 'Escape') {\n handleEscapeKey(field.onChange, field.value)(e);\n // Note: Validation happens naturally when user leaves the field\n // No need to trigger it programmatically\n }\n };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <Input\n {...field}\n id={id}\n placeholder={placeholder}\n className={validationClasses}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n value={field.value ?? ''}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n disabled={readOnly}\n />\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nTextField.displayName = 'TextField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { getInvalidUrlMessage, isValidUrl } from '@openzeppelin/ui-utils';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n validateField,\n} from './utils';\n\n/**\n * URL input field component specifically designed for React Hook Form integration.\n */\nexport function UrlField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n readOnly,\n}: BaseFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Check required field explicitly first\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Perform standard validations (min, max, pattern, etc.) if they exist\n const standardValidationResult = validateField(value, validation);\n if (standardValidationResult !== true) {\n return standardValidationResult;\n }\n\n // Perform URL-specific validation using the shared validator\n if (typeof value === 'string' && value && !isValidUrl(value)) {\n return getInvalidUrlMessage();\n }\n\n // If all checks pass\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Handle input change with validation\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const value = e.target.value;\n field.onChange(value);\n\n // Trigger validation if the field is required and empty\n if (isRequired && value === '') {\n setTimeout(() => field.onBlur(), 0);\n }\n };\n\n // Add keyboard accessibility for clearing the field with Escape\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n if (e.key === 'Escape') {\n handleEscapeKey(field.onChange, field.value)(e);\n\n // If required, trigger validation after clearing\n if (isRequired) {\n setTimeout(() => field.onBlur(), 0);\n }\n }\n };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <Input\n {...field}\n id={id}\n type=\"url\"\n placeholder={placeholder || 'https://example.com'}\n className={validationClasses}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n value={field.value ?? ''}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n disabled={readOnly}\n />\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\nUrlField.displayName = 'UrlField';\n","import {\n AlertCircle,\n CheckCircle,\n DollarSign,\n Hash,\n Info,\n Loader2,\n Network,\n Timer,\n} from 'lucide-react';\nimport React from 'react';\n\nimport type { RelayerDetails, RelayerDetailsRich } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { AddressDisplay } from '../ui/address-display';\n\nexport interface RelayerDetailsCardProps {\n details: RelayerDetails;\n enhancedDetails?: RelayerDetailsRich | null;\n loading?: boolean;\n className?: string;\n /** Optional UI labels to override default copy */\n labels?: Partial<{\n detailsTitle: string;\n active: string;\n paused: string;\n systemDisabled: string;\n network: string;\n relayerId: string;\n balance: string;\n nonce: string;\n pending: string;\n lastTransaction: string;\n }>;\n}\n\nexport const RelayerDetailsCard: React.FC<RelayerDetailsCardProps> = ({\n details,\n enhancedDetails,\n loading = false,\n className,\n labels,\n}) => {\n const displayDetails = enhancedDetails || details;\n\n const l = {\n detailsTitle: labels?.detailsTitle || 'Relayer Details',\n active: labels?.active || 'Active',\n paused: labels?.paused || 'Paused',\n systemDisabled: labels?.systemDisabled || 'System Disabled',\n network: labels?.network || 'Network',\n relayerId: labels?.relayerId || 'Relayer ID',\n balance: labels?.balance || 'Balance',\n nonce: labels?.nonce || 'Nonce',\n pending: labels?.pending || 'Pending Transactions',\n lastTransaction: labels?.lastTransaction || 'Last Transaction',\n } as const;\n\n // Format timestamp for display\n const formatTimestamp = (timestamp: string): string => {\n try {\n const date = new Date(timestamp);\n return date.toLocaleString();\n } catch {\n return timestamp;\n }\n };\n\n return (\n <div\n className={cn(\n 'flex flex-col sm:flex-row sm:items-start space-y-3 sm:space-y-0 sm:space-x-3 p-3 bg-slate-50 rounded-md',\n className\n )}\n >\n <Info className=\"size-5 text-primary mt-0.5 flex-shrink-0 hidden sm:block\" />\n <div className=\"space-y-3 flex-1 min-w-0\">\n <div>\n <h4 className=\"text-sm font-medium mb-2\">{l.detailsTitle}</h4>\n\n {/* Relayer Name and Status */}\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-2 space-y-1 sm:space-y-0\">\n <p className=\"text-sm font-medium text-foreground truncate\">{displayDetails.name}</p>\n <span\n className={cn(\n 'inline-flex items-center px-2 py-1 rounded-full text-xs font-medium self-start',\n displayDetails.paused || enhancedDetails?.systemDisabled\n ? 'bg-red-100 text-red-800'\n : 'bg-green-100 text-green-800'\n )}\n >\n {displayDetails.paused || enhancedDetails?.systemDisabled ? (\n <>\n <AlertCircle className=\"size-3 mr-1\" />\n {enhancedDetails?.systemDisabled ? l.systemDisabled : l.paused}\n </>\n ) : (\n <>\n <CheckCircle className=\"size-3 mr-1\" />\n {l.active}\n </>\n )}\n </span>\n </div>\n\n {/* Relayer Address */}\n <div className=\"mb-3\">\n <AddressDisplay\n className=\"w-full sm:w-auto\"\n address={displayDetails.address}\n truncate={true}\n startChars={6}\n endChars={4}\n showCopyButton\n />\n </div>\n\n {/* Additional Details */}\n <div className=\"space-y-1 pt-2 border-t border-slate-200\">\n <div className=\"flex items-center gap-2\">\n <Network className=\"size-3.5 text-muted-foreground flex-shrink-0\" />\n <p className=\"text-xs text-muted-foreground truncate\">\n <span className=\"font-medium\">{l.network}:</span> {displayDetails.network}\n </p>\n </div>\n\n <div className=\"flex items-start gap-2\">\n <Hash className=\"size-3.5 text-muted-foreground flex-shrink-0 mt-0.5\" />\n <div className=\"text-xs text-muted-foreground min-w-0 flex-1\">\n <span className=\"font-medium\">{l.relayerId}:</span>{' '}\n <code className=\"font-mono text-xs bg-slate-100 px-1 py-0.5 rounded break-all\">\n {displayDetails.relayerId}\n </code>\n </div>\n </div>\n </div>\n\n {/* Enhanced Details Section */}\n {loading && (\n <div className=\"mt-3 flex items-center gap-2 text-xs text-muted-foreground\">\n <Loader2 className=\"size-3 animate-spin\" />\n Loading additional details...\n </div>\n )}\n\n {!loading && enhancedDetails && (\n <div className=\"mt-3 pt-3 border-t border-slate-200 space-y-2\">\n {/* Balance */}\n {enhancedDetails.balance && (\n <div className=\"flex items-center gap-2 text-xs\">\n <DollarSign className=\"size-3.5 text-muted-foreground flex-shrink-0\" />\n <div className=\"text-muted-foreground min-w-0 flex-1\">\n <span className=\"font-medium\">{l.balance}:</span>{' '}\n <span className=\"break-all\">{enhancedDetails.balance}</span>\n </div>\n </div>\n )}\n\n {/* Nonce */}\n {enhancedDetails.nonce && (\n <div className=\"flex items-center gap-2 text-xs\">\n <Hash className=\"size-3.5 text-muted-foreground flex-shrink-0\" />\n <span className=\"text-muted-foreground\">\n <span className=\"font-medium\">{l.nonce}:</span> {enhancedDetails.nonce}\n </span>\n </div>\n )}\n\n {/* Pending Transactions */}\n {enhancedDetails.pendingTransactionsCount !== undefined && (\n <div className=\"flex items-center gap-2 text-xs\">\n <Timer className=\"size-3.5 text-muted-foreground flex-shrink-0\" />\n <span className=\"text-muted-foreground\">\n <span className=\"font-medium\">{l.pending}:</span>{' '}\n {enhancedDetails.pendingTransactionsCount}\n </span>\n </div>\n )}\n\n {/* Last Transaction */}\n {enhancedDetails.lastConfirmedTransactionTimestamp && (\n <div className=\"flex items-start gap-2 text-xs\">\n <CheckCircle className=\"size-3.5 text-muted-foreground mt-0.5 flex-shrink-0\" />\n <div className=\"text-muted-foreground min-w-0 flex-1\">\n <span className=\"font-medium\">{l.lastTransaction}:</span>\n <br />\n <span className=\"text-xs break-words\">\n {formatTimestamp(enhancedDetails.lastConfirmedTransactionTimestamp)}\n </span>\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Warning if relayer is paused or system disabled */}\n {(displayDetails.paused || enhancedDetails?.systemDisabled) && (\n <div className=\"bg-red-50 border border-red-200 rounded-md p-2\">\n <p className=\"text-xs text-red-700 flex items-start gap-1\">\n <AlertCircle className=\"size-3 mt-0.5 flex-shrink-0\" />\n <span className=\"min-w-0 flex-1\">\n {enhancedDetails?.systemDisabled\n ? 'This relayer has been disabled by the system and cannot process transactions.'\n : 'This relayer is currently paused and cannot process transactions.'}\n </span>\n </p>\n </div>\n )}\n </div>\n </div>\n );\n};\n","import { createContext } from 'react';\n\nimport type { NetworkErrorContextValue } from './useNetworkErrors';\n\nexport const NetworkErrorContext = createContext<NetworkErrorContextValue | undefined>(undefined);\n","'use client';\n\nimport { toast } from 'sonner';\nimport { useCallback, useMemo, useRef, useState } from 'react';\n\nimport { NetworkErrorContext } from './NetworkErrorContext';\nimport type { NetworkError, NetworkErrorType } from './useNetworkErrors';\n\ninterface NetworkErrorNotificationProviderProps {\n children: React.ReactNode;\n}\n\n/** Provider component for managing and displaying network error notifications. */\nexport function NetworkErrorNotificationProvider({\n children,\n}: NetworkErrorNotificationProviderProps): React.ReactNode {\n const [errors, setErrors] = useState<NetworkError[]>([]);\n const [openNetworkSettingsHandler, setOpenNetworkSettingsHandler] = useState<\n ((networkId: string) => void) | undefined\n >();\n const errorDedupeRef = useRef<Map<string, number>>(new Map());\n\n const reportNetworkError = useCallback(\n (type: NetworkErrorType, networkId: string, networkName: string, message: string) => {\n // Create a unique key for deduplication\n const dedupeKey = `${type}-${networkId}-${message}`;\n const now = Date.now();\n const lastReported = errorDedupeRef.current.get(dedupeKey);\n\n // Dedupe errors that occur within 5 seconds\n if (lastReported && now - lastReported < 5000) {\n return;\n }\n\n errorDedupeRef.current.set(dedupeKey, now);\n\n const error: NetworkError = {\n id: `${type}-${networkId}-${now}`,\n type,\n networkId,\n networkName,\n message,\n timestamp: now,\n };\n\n setErrors((prev) => {\n const newErrors = [...prev, error];\n return newErrors;\n });\n\n // Show toast notification with action button\n const typeLabel = type === 'rpc' ? 'RPC' : 'Explorer';\n toast.error(`${typeLabel} Error - ${networkName}`, {\n description: message,\n duration: 10000, // Show for 10 seconds\n action: openNetworkSettingsHandler\n ? {\n label: 'Configure',\n onClick: (): void => {\n openNetworkSettingsHandler(networkId);\n },\n }\n : undefined,\n });\n\n // Auto-remove error after 1 minute\n setTimeout(() => {\n setErrors((prev) => prev.filter((e) => e.id !== error.id));\n errorDedupeRef.current.delete(dedupeKey);\n }, 60000);\n },\n [openNetworkSettingsHandler]\n );\n\n const clearError = useCallback((id: string) => {\n setErrors((prev) => prev.filter((e) => e.id !== id));\n }, []);\n\n const clearAllErrors = useCallback(() => {\n setErrors([]);\n errorDedupeRef.current.clear();\n }, []);\n\n const stableSetHandler = useCallback((handler: (networkId: string) => void) => {\n setOpenNetworkSettingsHandler(() => handler);\n }, []);\n\n const value = useMemo(\n () => ({\n errors,\n reportNetworkError,\n clearError,\n clearAllErrors,\n onOpenNetworkSettings: openNetworkSettingsHandler,\n setOpenNetworkSettingsHandler: stableSetHandler,\n }),\n [\n errors,\n reportNetworkError,\n clearError,\n clearAllErrors,\n openNetworkSettingsHandler,\n stableSetHandler,\n ]\n );\n\n return <NetworkErrorContext.Provider value={value}>{children}</NetworkErrorContext.Provider>;\n}\n","'use client';\n\nimport { useCallback, useContext } from 'react';\n\nimport type { RuntimeCapability } from '@openzeppelin/ui-types';\n\nimport { NetworkErrorContext } from './NetworkErrorContext';\n\nexport type NetworkErrorType = 'rpc' | 'explorer';\n\nexport interface NetworkError {\n id: string;\n type: NetworkErrorType;\n networkId: string;\n networkName: string;\n message: string;\n timestamp: number;\n}\n\nexport interface NetworkErrorContextValue {\n errors: NetworkError[];\n reportNetworkError: (\n type: NetworkErrorType,\n networkId: string,\n networkName: string,\n message: string\n ) => void;\n clearError: (id: string) => void;\n clearAllErrors: () => void;\n onOpenNetworkSettings?: (networkId: string) => void;\n setOpenNetworkSettingsHandler: (handler: (networkId: string) => void) => void;\n}\n\n/** Hook to access network error reporting and management functions. */\nexport function useNetworkErrors(): NetworkErrorContextValue {\n const context = useContext(NetworkErrorContext);\n if (!context) {\n throw new Error('useNetworkErrors must be used within NetworkErrorNotificationProvider');\n }\n return context;\n}\n\n/**\n * Hook for reporting network errors for a specific runtime-bound capability\n */\nexport function useNetworkErrorReporter(capability: RuntimeCapability | null): {\n reportRpcError: (message: string) => void;\n reportExplorerError: (message: string) => void;\n} {\n const { reportNetworkError } = useNetworkErrors();\n\n const reportRpcError = useCallback(\n (message: string) => {\n if (!capability) return;\n reportNetworkError(\n 'rpc',\n capability.networkConfig.id,\n capability.networkConfig.name,\n message\n );\n },\n [capability, reportNetworkError]\n );\n\n const reportExplorerError = useCallback(\n (message: string) => {\n if (!capability) return;\n reportNetworkError(\n 'explorer',\n capability.networkConfig.id,\n capability.networkConfig.name,\n message\n );\n },\n [capability, reportNetworkError]\n );\n\n return {\n reportRpcError,\n reportExplorerError,\n };\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\n\nimport type { RuntimeCapability } from '@openzeppelin/ui-types';\n\nimport { useNetworkErrors } from './useNetworkErrors';\n\n/**\n * Creates an adapter proxy that intercepts and reports network errors\n */\nexport function useNetworkErrorAwareAdapter<T extends RuntimeCapability>(\n capability: T | null\n): T | null {\n const { reportNetworkError } = useNetworkErrors();\n const wrappedCapabilityRef = useRef<T | null>(null);\n\n useEffect(() => {\n if (!capability) {\n wrappedCapabilityRef.current = null;\n return;\n }\n\n // Create a proxy that wraps the runtime capability to intercept errors\n const wrappedCapability = new Proxy(capability, {\n get(target, prop, receiver): unknown {\n const value = Reflect.get(target, prop, receiver);\n\n // Wrap async methods that might throw network errors\n if (\n typeof value === 'function' &&\n (prop === 'queryViewFunction' || prop === 'loadContract')\n ) {\n return async (...args: unknown[]) => {\n try {\n return await value.apply(target, args);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n\n // Check if it's an RPC error\n if (\n errorMessage.toLowerCase().includes('rpc') ||\n errorMessage.toLowerCase().includes('network') ||\n errorMessage.toLowerCase().includes('timeout') ||\n errorMessage.toLowerCase().includes('fetch') ||\n errorMessage.toLowerCase().includes('connection')\n ) {\n reportNetworkError(\n 'rpc',\n target.networkConfig.id,\n target.networkConfig.name,\n errorMessage\n );\n }\n\n // Check if it's an explorer error\n if (\n errorMessage.toLowerCase().includes('explorer') ||\n errorMessage.toLowerCase().includes('etherscan') ||\n errorMessage.toLowerCase().includes('api key') ||\n errorMessage.toLowerCase().includes('abi') ||\n errorMessage.toLowerCase().includes('verified')\n ) {\n reportNetworkError(\n 'explorer',\n target.networkConfig.id,\n target.networkConfig.name,\n errorMessage\n );\n }\n\n // Re-throw the error to maintain normal error handling\n throw error;\n }\n };\n }\n\n return value;\n },\n }) as T;\n\n wrappedCapabilityRef.current = wrappedCapability;\n }, [capability, reportNetworkError]);\n\n return wrappedCapabilityRef.current;\n}\n","'use client';\n\nimport { CloudOff, Settings } from 'lucide-react';\nimport { useContext } from 'react';\n\nimport type { NetworkConfig } from '@openzeppelin/ui-types';\nimport { getServiceDisplayName } from '@openzeppelin/ui-utils';\n\nimport { Alert, AlertDescription, AlertTitle } from '../ui/alert';\nimport { Button } from '../ui/button';\nimport { NetworkErrorContext } from './NetworkErrorContext';\n\nexport interface NetworkServiceErrorBannerProps {\n /** The network configuration for which the service connection failed */\n networkConfig: NetworkConfig;\n /** The type of service that failed (e.g., 'rpc', 'explorer', 'indexer') */\n serviceType: string;\n /** Optional custom error message to display */\n errorMessage?: string;\n /** Optional custom title override */\n title?: string;\n /** Optional custom description to show below the error message */\n description?: string;\n /**\n * Optional callback to open network settings dialog.\n * If not provided, will try to use the context from NetworkErrorNotificationProvider.\n * If neither is available, the settings button will not be rendered.\n */\n onOpenNetworkSettings?: (networkId: string) => void;\n}\n\n/**\n * User-friendly banner displayed when a network service connection fails.\n * Works with any service type (RPC, Explorer, Indexer, etc.) and provides\n * a clear explanation of the issue with a call-to-action to open the\n * network settings dialog where users can configure an alternative endpoint.\n *\n * This component can be used with or without the NetworkErrorNotificationProvider:\n * - With provider: The settings handler is obtained from context\n * - Without provider: Pass onOpenNetworkSettings prop directly, or the button won't render\n */\nexport function NetworkServiceErrorBanner({\n networkConfig,\n serviceType,\n errorMessage,\n title,\n description,\n onOpenNetworkSettings: onOpenNetworkSettingsProp,\n}: NetworkServiceErrorBannerProps): React.ReactNode {\n // Try to get handler from context (won't throw if not in provider)\n const context = useContext(NetworkErrorContext);\n const onOpenNetworkSettings = onOpenNetworkSettingsProp ?? context?.onOpenNetworkSettings;\n\n const handleOpenSettings = (): void => {\n onOpenNetworkSettings?.(networkConfig.id);\n };\n\n const serviceName = getServiceDisplayName(serviceType);\n const defaultTitle = `Unable to Connect to ${networkConfig.name}`;\n const defaultDescription = onOpenNetworkSettings\n ? `This could be due to network congestion, rate limiting, or the service being temporarily down. You can configure a custom ${serviceName.toLowerCase()} endpoint in the network settings.`\n : `This could be due to network congestion, rate limiting, or the service being temporarily down.`;\n\n return (\n <Alert variant=\"destructive\" className=\"border-red-500/50 bg-red-50 dark:bg-red-950/20\">\n <CloudOff className=\"h-4 w-4 text-red-600 dark:text-red-400\" />\n <AlertTitle className=\"text-red-900 dark:text-red-100\">{title || defaultTitle}</AlertTitle>\n <AlertDescription className=\"text-red-800 dark:text-red-200\">\n <p className=\"mb-2\">\n {errorMessage ||\n `The ${serviceName.toLowerCase()} for ${networkConfig.name} is currently unavailable or not responding.`}\n </p>\n <p className=\"text-sm mb-3\">{description || defaultDescription}</p>\n {onOpenNetworkSettings && (\n <Button\n onClick={handleOpenSettings}\n variant=\"default\"\n size=\"sm\"\n className=\"bg-red-600 hover:bg-red-700 text-white dark:bg-red-500 dark:hover:bg-red-600\"\n >\n <Settings className=\"mr-2 h-4 w-4\" />\n Configure {serviceName} Settings\n </Button>\n )}\n </AlertDescription>\n </Alert>\n );\n}\n","import { Info } from 'lucide-react';\nimport type React from 'react';\n\nimport {\n getHostedNetworkAvailabilityNoticeCopy,\n isNetworkAvailabilityPolicyActive,\n} from '@openzeppelin/ui-utils';\n\nimport { Alert, AlertDescription, AlertTitle } from '../ui/alert';\n\nexport interface NetworkAvailabilityNoticeProps {\n /** Display name of the hosting app, e.g. \"UI Builder\" */\n appName: string;\n /** GitHub repository URL for self-hosting instructions */\n selfHostRepoUrl: string;\n className?: string;\n}\n\n/**\n * Banner shown when the deployment disables mainnet or specific network IDs.\n * Hidden when no network availability policy is active.\n */\nexport function NetworkAvailabilityNotice({\n appName,\n selfHostRepoUrl,\n className,\n}: NetworkAvailabilityNoticeProps): React.ReactElement | null {\n if (!isNetworkAvailabilityPolicyActive()) {\n return null;\n }\n\n const { title, descriptionBeforeLink, descriptionLinkLabel } =\n getHostedNetworkAvailabilityNoticeCopy(appName);\n\n return (\n <Alert className={className}>\n <Info className=\"h-4 w-4\" />\n <AlertTitle>{title}</AlertTitle>\n <AlertDescription>\n {descriptionBeforeLink}\n <a\n href={selfHostRepoUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"font-medium underline underline-offset-4 hover:text-foreground\"\n >\n {descriptionLinkLabel}\n </a>\n .\n </AlertDescription>\n </Alert>\n );\n}\n","import { useTheme } from 'next-themes';\nimport { Toaster as Sonner, ToasterProps } from 'sonner';\nimport { JSX } from 'react';\n\nconst Toaster = ({ ...props }: ToasterProps): JSX.Element => {\n const { theme = 'system' } = useTheme();\n\n return (\n <Sonner\n theme={theme as ToasterProps['theme']}\n className=\"toaster group\"\n toastOptions={{\n classNames: {\n toast:\n 'group toast group-[.toaster]:bg-gray-900 group-[.toaster]:text-gray-50 group-[.toaster]:border-gray-800 group-[.toaster]:shadow-lg',\n description: 'group-[.toast]:text-gray-400',\n actionButton:\n 'group-[.toast]:bg-white group-[.toast]:text-gray-900 group-[.toast]:hover:bg-gray-100 group-[.toast]:font-medium group-[.toast]:border-0',\n cancelButton:\n 'group-[.toast]:bg-gray-800 group-[.toast]:text-gray-300 group-[.toast]:hover:bg-gray-700',\n error:\n 'group-[.toast]:!bg-red-950 group-[.toast]:!text-red-50 group-[.toast]:!border-red-900',\n },\n }}\n {...props}\n />\n );\n};\n\nexport { Toaster };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,MAAa;;;;ACMb,MAAM,0DAA4B,IAAI;CACpC,UAAU,EACR,SAAS;EACP,SAAS;EACT,MAAM;EACP,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CAAC;AAEF,MAAM,6DACJ,2GACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,MAAM;EACP,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACF;AAED,MAAM,6DACJ,kLACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,MAAM;EACP,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACF;AAED,MAAM,kEAAoC,IAAI;CAC5C,UAAU,EACR,SAAS;EACP,SAAS;EACT,MAAM;EACP,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CAAC;AAIF,MAAM,0BAA0BA,MAAM,cAAgC,UAAU;AAUhF,MAAM,YAAYA,MAAM,YACrB,EAAE,UAAU,WAAW,GAAG,SAAS,QAClC,2CAAC,wBAAwB;CAAS,OAAO;WACvC,2CAACC,0BAAmB;EAAU;EAAK,GAAI;GAAS;EACf,CAEtC;AACD,UAAU,cAAc;AAMxB,MAAM,gBAAgBD,MAAM,YACzB,EAAE,WAAW,SAAS,aAAa,GAAG,SAAS,QAAQ;CACtD,MAAM,iBAAiBA,MAAM,WAAW,wBAAwB;CAChE,MAAM,UAAU,eAAe;AAE/B,QACE,2CAACC,0BAAmB;EACb;EACL,0CAAc,sBAAsB,EAAE,SAAS,CAAC,EAAE,UAAU;EAC5D,GAAI;GACJ;EAGP;AACD,cAAc,cAAc;AAM5B,MAAM,mBAAmBD,MAAM,YAC5B,EAAE,WAAW,UAAU,SAAS,aAAa,GAAG,SAAS,QAAQ;CAChE,MAAM,iBAAiBA,MAAM,WAAW,wBAAwB;CAChE,MAAM,UAAU,eAAe;AAE/B,QACE,2CAACC,0BAAmB;EAAO,WAAU;YACnC,4CAACA,0BAAmB;GACb;GACL,0CAAc,yBAAyB,EAAE,SAAS,CAAC,EAAE,UAAU;GAC/D,GAAI;cAEH,UACD,2CAACC,4BAAY,WAAU,uDAAuD;IACnD;GACH;EAGjC;AACD,iBAAiB,cAAc;AAM/B,MAAM,mBAAmBF,MAAM,YAC5B,EAAE,WAAW,UAAU,SAAS,aAAa,GAAG,SAAS,QAAQ;CAChE,MAAM,iBAAiBA,MAAM,WAAW,wBAAwB;CAChE,MAAM,UAAU,eAAe;AAE/B,QACE,2CAACC,0BAAmB;EACb;EACL,0CAAc,yBAAyB,EAAE,SAAS,CAAC,EAAE,UAAU;EAC/D,GAAI;YAEJ,2CAAC;GAAI,0CAAc,8BAA8B,EAAE,SAAS,CAAC,CAAC;GAAG;IAAe;GACrD;EAGlC;AACD,iBAAiB,cAAc;;;;AC9I/B,MAAM,kBAAkBE,wBAAiB;AAEzC,MAAM,UAAUA,wBAAiB;AAEjC,MAAM,iBAAiBA,wBAAiB;AAExC,MAAM,iBAAiBC,MAAM,YAG1B,EAAE,WAAW,aAAa,GAAG,GAAG,SAAS,QAC1C,2CAACD,wBAAiB,oBAChB,2CAACA,wBAAiB;CACX;CACO;CACZ,0CACE,gXACA,UACD;CACD,GAAI;EACJ,GACsB,CAC1B;AACF,eAAe,cAAcA,wBAAiB,QAAQ;;;;;;;;;AClBtD,MAAa,+CAAiE,KAAK;;;;;;;;ACGnF,SAAS,kBAA2B;AAClC,QAAOE,MAAM,qBACXA,MAAM,aAAa,kBAAkB;AACnC,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,YAChE,cAAmB;EAErB,MAAM,KAAK,OAAO,WAAW,iBAAiB;AAC9C,KAAG,iBAAiB,UAAU,cAAc;AAC5C,eAAmB,GAAG,oBAAoB,UAAU,cAAc;IACjE,EAAE,CAAC,QAEJ,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,cAC1D,OAAO,WAAW,iBAAiB,CAAC,UACpC,YACA,KACP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkKH,SAAgB,eAAe,EAC7B,SACA,UAAU,cACV,sBAAsB,OACtB,oBAAoB,OACpB,aAAa,GACb,WAAW,GACX,iBAAiB,OACjB,wBAAwB,OACxB,aACA,OAAO,WACP,aAAa,iBACb,WACA,eAAe,OACf,cAAc,OACd,UAAU,QACV,WACA,gBACA,gBACA,cACA,cACA,SACA,GAAG,SACuC;CAC1C,MAAM,CAAC,QAAQ,aAAaA,MAAM,SAAS,MAAM;CACjD,MAAM,CAAC,WAAW,gBAAgBA,MAAM,SAAS,MAAM;CACvD,MAAM,iBAAiBA,MAAM,OAAsB,KAAK;CACxD,MAAM,eAAe,iBAAiB;CAEtC,MAAM,WAAWA,MAAM,WAAW,oBAAoB;CAEtD,MAAM,gBAAgB,eAClB,SACC,aAAa,UAAU,aAAa,SAAS,UAAU;CAE5D,MAAM,oBACJ,iBAAiB,SAAY,eAAe,sBAAsB,QAAQ,cAAc,GAAG;CAE7F,MAAM,qBAAqBA,MAAM,kBAAkB;AACjD,YAAU,cAAc,SAAS,UAAU;IAC1C;EAAC;EAAU;EAAS;EAAU,CAAC;CAElC,MAAM,cAAc,eAChB,SACC,oBAAoB,UAAU,cAAc,qBAAqB;CAEtE,MAAM,gBAAgB,qBAAqB,qBAAqB,CAAC;CACjE,MAAM,kBAAkB,CAAC,qBAAsB,iBAAiB;CAChE,MAAM,iBAAiB,kBAAkB,qDAAyB,SAAS,YAAY,SAAS;CAEhG,MAAM,sDACJ,CAAC,mBAAmB,aACnB,mBAAmB,CAAC,sBAAsB,YAC5C;CAED,MAAM,6BAA6B,iBAAiB,CAAC,eAAe,mBAAmB;CAEvF,MAAM,sBAAsB,MAAgD;AAC1E,MAAI,iBAAiB,aACnB,cAAa,KAAK;AAEpB,mBAAiB,EAAE;AACnB,iBAAe,EAAiD;;CAGlE,MAAM,sBAAsB,MAAgD;AAC1E,MAAI,iBAAiB,aACnB,cAAa,MAAM;AAErB,mBAAiB,EAAE;AACnB,iBAAe,EAAiD;;CAGlE,MAAM,yBAAyB,MAA8C;AAC3E,MAAI,iBAAiB,CAAC,aACpB,eAAc,SAAS,CAAC,KAAK;AAE/B,YAAU,EAAE;;CAGd,MAAM,cAAc,MAA8B;AAChD,IAAE,iBAAiB;AACnB,YAAU,UAAU,UAAU,QAAQ;AACtC,YAAU,KAAK;AAEf,MAAI,eAAe,QACjB,QAAO,aAAa,eAAe,QAAQ;AAE7C,iBAAe,UAAU,OAAO,iBAAiB;AAC/C,aAAU,MAAM;AAChB,kBAAe,UAAU;KACxB,IAAK;;AAGV,OAAM,gBAAgB;AACpB,eAAmB;AACjB,OAAI,eAAe,QACjB,QAAO,aAAa,eAAe,QAAQ;;IAG9C,EAAE,CAAC;CAEN,MAAM,SAAS,YAAY;CAE3B,MAAM,gBACJ;EACG,kBACC,2CAAC;GACC,MAAK;GACL,SAAS;GACT,0CACE,2BACA,CAAC,UAAU,wBACX,wBACI,2KACA,2BACL;GACD,cAAY,SAAS,WAAW;aAE/B,SACC,2CAACC,sBAAM,WAAU,iCAAiC,GAElD,2CAACC,qBAAK,WAAU,gBAAgB;IAE3B;EAGV,eACC,2CAAC;GACC,MAAM;GACN,QAAO;GACP,KAAI;GACJ,UAAU,MAAM;AACd,MAAE,iBAAiB;;GAErB,WAAU;GACV,cAAW;aAEX,2CAACC,6BAAa,WAAU,gBAAgB;IACtC;EAGL,eACC,2CAAC;GACC,MAAK;GACL,UAAU,MAAM;AACd,MAAE,iBAAiB;AACnB,iBAAa;;GAEf,WAAU;GACV,cAAW;aAEX,2CAACC,uBAAO,WAAU,gBAAgB;IAC3B;KAEV;CAGL,MAAM,oBAAoB,eAAe;CAEzC,MAAM,mBAAmB,YAAoD;AAC3E,MAAI,CAAC,kBAAmB,QAAO;AAC/B,SACE,2CAAC;GAAgB,eAAe;aAC9B,4CAAC,sBACC,2CAAC;IAAe;cAAS;KAAyB,EAClD,2CAAC;IAAe,WAAU;cAAqB;KAAyB,IAChE;IACM;;AAItB,KAAI,cACF,QAAO,gBACL,4CAAC;EACC,0CACE,iDACA,UAAU,qCACV,0BACA,4BACA,UACD;EACD,gBAAgB;EAChB,gBAAgB;EAChB,SAAS;EACT,GAAI;aAEJ,2CAAC;GAAK,WAAU;aACb;IACI,EACP,4CAAC;GAAI,WAAU;cACb,2CAAC;IAAK,WAAW;cAAuB;KAAsB,EAC7D;IACG;GACF,CACP;AAGH,QAAO,gBACL,4CAAC;EACC,0CACE,qDACA,UAAU,qCACV,oCACA,4BACA,UACD;EACD,gBAAgB;EAChB,gBAAgB;EAChB,SAAS;EACT,GAAI;aAEJ,2CAAC;GAAK,WAAW;aAAuB;IAAsB,EAC7D;GACG,CACP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACzVH,SAAgB,qBAAqB,EACnC,UACA,cACA,eACgD;CAChD,MAAM,QAAQC,MAAM,eACX;EAAE;EAAc;EAAa,GACpC,CAAC,cAAc,YAAY,CAC5B;AAED,QAAO,2CAAC,oBAAoB;EAAgB;EAAQ;GAAwC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC/B9F,SAAgB,gBAAgB,SAAiB,WAA2C;CAC1F,MAAM,WAAWC,MAAM,WAAW,oBAAoB;CAEtD,MAAM,QAAQ,UAAU,aAAa,SAAS,UAAU;CAExD,MAAM,SAASA,MAAM,kBAAkB;AACrC,YAAU,cAAc,SAAS,UAAU;IAC1C;EAAC;EAAU;EAAS;EAAU,CAAC;AAElC,QAAO;EAAE;EAAO,QAAQ,UAAU,cAAc,SAAS;EAAW;;;;;AC1CtE,MAAM,kDACJ,6JACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,aACE;EACF,SAAS;EACV,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACF;AAED,MAAM,QAAQC,MAAM,YAGjB,EAAE,WAAW,SAAS,GAAG,SAAS,QACnC,2CAAC;CAAS;CAAK,MAAK;CAAQ,0CAAc,cAAc,EAAE,SAAS,CAAC,EAAE,UAAU;CAAE,GAAI;EAAS,CAC/F;AACF,MAAM,cAAc;AAEpB,MAAM,aAAaA,MAAM,YACtB,EAAE,WAAW,GAAG,SAAS,QACxB,2CAAC;CACM;CACL,0CAAc,gDAAgD,UAAU;CACxE,GAAI;EACJ,CAEL;AACD,WAAW,cAAc;AAEzB,MAAM,mBAAmBA,MAAM,YAG5B,EAAE,WAAW,GAAG,SAAS,QAC1B,2CAAC;CAAS;CAAK,0CAAc,iCAAiC,UAAU;CAAE,GAAI;EAAS,CACvF;AACF,iBAAiB,cAAc;;;;ACO/B,MAAM,gBAGF;CACF,MAAM;EACJ,WAAW;EACX,MAAM;EACN,OAAO;EACP,MAAM;EACP;CACD,SAAS;EACP,WAAW;EACX,MAAM;EACN,OAAO;EACP,MAAM;EACP;CACD,SAAS;EACP,WAAW;EACX,MAAM;EACN,OAAO;EACP,MAAM;EACP;CACD,OAAO;EACL,WAAW;EACX,MAAM;EACN,OAAO;EACP,MAAM;EACP;CACD,SAAS;EACP,WAAW;EACX,MAAM;EACN,OAAO;EACP,MAAM;EACP;CACF;AAED,MAAM,aAGF;CACF,SAAS;EACP,WAAW;EACX,KAAK;EACL,OAAO;EACP,MAAM;EACN,aAAa;EACd;CACD,SAAS;EACP,WAAW;EACX,KAAK;EACL,OAAO;EACP,MAAM;EACN,aAAa;EACd;CACF;;;;;AAMD,MAAa,SAASC,MAAM,YAExB,EACE,WACA,UAAU,QACV,OAAO,WACP,OACA,UACA,cAAc,MACd,WACA,QAEF,QACG;CACH,MAAM,SAAS,cAAc;CAC7B,MAAM,SAAS,WAAW;AAE1B,QACE,2CAAC;EACM;EACL,MAAK;EACL,0CAAc,qBAAqB,OAAO,WAAW,OAAO,WAAW,UAAU;YAEjF,4CAAC;GAAI,0CAAc,QAAQ,OAAO,IAAI;;IACnC,QAAQ,2CAAC;KAAI,0CAAc,mBAAmB,OAAO,KAAK;eAAG;MAAW;IACzE,4CAAC;KAAI,WAAU;gBACZ,SAAS,2CAAC;MAAG,0CAAc,OAAO,OAAO,OAAO,MAAM;gBAAG;OAAW,EACrE,2CAAC;MAAI,0CAAc,OAAO,MAAM,OAAO,KAAK;MAAG;OAAe;MAC1D;IACL,eACC,2CAAC;KACC,MAAK;KACL,SAAS;KACT,0CAAc,0DAA0D,OAAO,KAAK;KACpF,cAAW;eAEX,2CAACC,kBAAE,WAAW,OAAO,cAAe;MAC7B;;IAEP;GACF;EAGX;AACD,OAAO,cAAc;;;;AC5JrB,MAAa,mDACX,wQACA;CACE,UAAU;EACR,SAAS;GACP,SAAS;GACT,aAAa;GACb,SACE;GACF,WAAW;GACX,OAAO;GACP,MAAM;GACP;EACD,MAAM;GACJ,SAAS;GACT,IAAI;GACJ,IAAI;GACJ,MAAM;GACP;EACF;CACD,iBAAiB;EACf,SAAS;EACT,MAAM;EACP;CACF,CACF;;;;ACbD,MAAM,SAASC,MAAM,YAClB,EAAE,WAAW,SAAS,MAAM,UAAU,OAAO,GAAG,SAAS,QAAQ;AAEhE,QACE,2CAFW,UAAUC,4BAAO;EAG1B,aAAU;EACV,gBAAc,WAAW;EACzB,aAAW,QAAQ;EACnB,0CAAc,eAAe;GAAE;GAAS;GAAM;GAAW,CAAC,EAAE,iBAAiB;EACxE;EACL,GAAI;GACJ;EAGP;AACD,OAAO,cAAc;;;;;;;;ACbrB,SAAS,SAAS,EAChB,WACA,YACA,kBAAkB,MAClB,GAAG,SACiC;AACpC,QACE,2CAACC;EACkB;EACjB,0CAAc,gBAAgB,UAAU;EACxC,YAAY;GACV,QAAQ;GACR,OAAO;GACP,eAAe;GACf,eAAe;GACf,KAAK;GACL,gDACE,eAAe,EAAE,SAAS,WAAW,CAAC,EACtC,0EACD;GACD,4CACE,eAAe,EAAE,SAAS,WAAW,CAAC,EACtC,2EACD;GACD,YAAY;GACZ,UAAU;GACV,SAAS;GACT,MAAM;GACN,oCACE,4NACA,MAAM,SAAS,UACX,yKACA,sCACL;GACD,2CACE,eAAe,EAAE,SAAS,SAAS,CAAC,EACpC,oFACD;GACD,aAAa;GACb,WAAW;GACX,UACE;GACF,OAAO;GACP,SACE;GACF,UAAU;GACV,cAAc;GACd,QAAQ;GACR,GAAG;GACJ;EACD,YAAY,EACV,UAAU,EAAE,kBAAkB;AAE5B,UAAO,2CADM,gBAAgB,SAASC,2BAAcC,6BACvC,WAAU,YAAY;KAEtC;EACD,GAAI;GACJ;;AAGN,SAAS,cAAc;;;;;ACvEvB,SAAS,KAAK,EAAE,WAAW,GAAG,SAAmD;AAC/E,QACE,2CAAC;EACC,aAAU;EACV,0CAAc,gEAAgE,UAAU;EACxF,GAAI;GACJ;;;AAKN,SAAS,WAAW,EAAE,WAAW,GAAG,SAAmD;AACrF,QACE,2CAAC;EACC,aAAU;EACV,0CAAc,mCAAmC,UAAU;EAC3D,GAAI;GACJ;;;AAKN,SAAS,UAAU,EAAE,WAAW,GAAG,SAAmD;AACpF,QACE,2CAAC;EACC,aAAU;EACV,0CAAc,8BAA8B,UAAU;EACtD,GAAI;GACJ;;;AAKN,SAAS,gBAAgB,EAAE,WAAW,GAAG,SAAmD;AAC1F,QACE,2CAAC;EACC,aAAU;EACV,0CAAc,iCAAiC,UAAU;EACzD,GAAI;GACJ;;;AAKN,SAAS,YAAY,EAAE,WAAW,GAAG,SAAmD;AACtF,QAAO,2CAAC;EAAI,aAAU;EAAe,0CAAc,kBAAkB,UAAU;EAAE,GAAI;GAAS;;;AAIhG,SAAS,WAAW,EAAE,WAAW,GAAG,SAAmD;AACrF,QACE,2CAAC;EACC,aAAU;EACV,0CAAc,oCAAoC,UAAU;EAC5D,GAAI;GACJ;;;;;;ACrDN,SAAS,SAAS,EAChB,WACA,GAAG,SACuE;AAC1E,QACE,2CAACC,yBAAkB;EACjB,aAAU;EACV,0CACE,ubACA,UACD;EACD,GAAI;YAEJ,2CAACA,yBAAkB;GACjB,aAAU;GACV,WAAU;aAEV,2CAACC;IAAU,aAAU;IAA0B,WAAU;KAAa;IAC1C;GACP;;;;;ACnB7B,MAAM,UAAUC,wBAAiB;AAEjC,MAAM,iBAAiBA,wBAAiB;AAExC,MAAM,gBAAgBA,wBAAiB;AAEvC,MAAM,iBAAiBC,MAAM,YAG1B,EAAE,WAAW,QAAQ,UAAU,aAAa,GAAG,GAAG,SAAS,QAC5D,2CAACD,wBAAiB,oBAChB,2CAACA,wBAAiB;CACX;CACE;CACK;CACZ,0CACE,2GACA,gEACA,8DACA,gEACA,iFACA,iFACA,UACD;CACD,GAAI;EACJ,GACsB,CAC1B;AACF,eAAe,cAAcA,wBAAiB,QAAQ;;;;;;;;;;;;;;;;;;;ACYtD,SAAS,gBAAgB,EACvB,OACA,UACA,cAAc,qBACd,WACA,WAAW,OACX,iBAAiB,GACjB,QAAQ,WACmC;AAC3C,QACE,2CAAC;EAAI,0CAAc,cAAc,UAAU;YACzC,4CAAC,sBACC,2CAAC;GAAe;aACd,4CAAC;IACC,IAAG;IACH,SAAQ;IACE;IACV,0CACE,iDACA,CAAC,SAAS,wBACX;eAED,2CAACE,yBAAa,WAAU,iBAAiB,EACxC,OAAO,OACN,MAAM,KACJ;0BACU,MAAM,MAAM,YAAY;KAAC;0BAAW,MAAM,IAAI,YAAY;QACjE,wBAEI,MAAM,MAAM,YAAY,GAGjC,2CAAC,oBAAM,cAAmB;KAErB;IACM,EACjB,2CAAC;GAAe,WAAU;GAAoB;aAC5C,2CAAC;IACC;IACA,MAAK;IACL,cAAc,OAAO;IACrB,UAAU;IACV,UAAU;IACM;KAChB;IACa,IACT;GACN;;AAGV,gBAAgB,cAAc;;;;AC5F9B,MAAM,SAASC,uBAAgB;AAE/B,MAAM,gBAAgBA,uBAAgB;AAEtC,MAAM,eAAeA,uBAAgB;AAErC,MAAM,cAAcA,uBAAgB;AAEpC,MAAM,gBAAgBC,MAAM,YAGzB,EAAE,WAAW,GAAG,SAAS,QAC1B,2CAACD,uBAAgB;CACV;CACL,0CACE,0JACA,UACD;CACD,GAAI;EACJ,CACF;AACF,cAAc,cAAcA,uBAAgB,QAAQ;AAEpD,MAAM,gBAAgBC,MAAM,YAGzB,EAAE,WAAW,UAAU,GAAG,SAAS,QACpC,4CAAC,2BACC,2CAAC,kBAAgB,EACjB,4CAACD,uBAAgB;CACV;CACL,0CACE,mWACA,UACD;CACD,GAAI;YAEJ,4CAACA,uBAAgB;EAAM,WAAU;aAC/B,4CAAC;GACC,OAAM;GACN,OAAM;GACN,QAAO;GACP,SAAQ;GACR,MAAK;GACL,QAAO;GACP,aAAY;GACZ,eAAc;GACd,gBAAe;GACf,WAAU;cAEV,2CAAC,UAAK,GAAE,eAAe,EACvB,2CAAC,UAAK,GAAE,eAAe;IACnB,EACN,2CAAC;GAAK,WAAU;aAAU;IAAY;GAChB,EACxB,2CAAC;EAAI,WAAU;EAA2C;GAAe;EACjD,IACb,CACf;AACF,cAAc,cAAcA,uBAAgB,QAAQ;AAEpD,MAAM,gBAAgB,EACpB,WACA,GAAG,YAEH,2CAAC;CAAI,0CAAc,sDAAsD,UAAU;CAAE,GAAI;EAAS;AAEpG,aAAa,cAAc;AAE3B,MAAM,gBAAgB,EACpB,WACA,GAAG,YAEH,2CAAC;CACC,0CAAc,iEAAiE,UAAU;CACzF,GAAI;EACJ;AAEJ,aAAa,cAAc;AAE3B,MAAM,cAAcC,MAAM,YAGvB,EAAE,WAAW,GAAG,SAAS,QAC1B,2CAACD,uBAAgB;CACV;CACL,0CAAc,qDAAqD,UAAU;CAC7E,GAAI;EACJ,CACF;AACF,YAAY,cAAcA,uBAAgB,MAAM;AAEhD,MAAM,oBAAoBC,MAAM,YAG7B,EAAE,WAAW,GAAG,SAAS,QAC1B,2CAACD,uBAAgB;CACV;CACL,0CAAc,iCAAiC,UAAU;CACzD,GAAI;EACJ,CACF;AACF,kBAAkB,cAAcA,uBAAgB,YAAY;;;;ACnG5D,MAAM,eAAeE,8BAAsB;AAE3C,MAAM,sBAAsBA,8BAAsB;AAElD,MAAM,oBAAoBA,8BAAsB;AAEhD,MAAM,qBAAqBA,8BAAsB;AAEjD,MAAM,kBAAkBA,8BAAsB;AAE9C,MAAM,yBAAyBA,8BAAsB;AAErD,MAAM,yBAAyBC,MAAM,YAKlC,EAAE,WAAW,OAAO,UAAU,GAAG,SAAS,QAC3C,4CAACD,8BAAsB;CAChB;CACL,0CACE,wIACA,SAAS,QACT,UACD;CACD,GAAI;YAEH,UACD,2CAACE,6BAAa,WAAU,oBAAoB;EACX,CACnC;AACF,uBAAuB,cAAcF,8BAAsB,WAAW;AAEtE,MAAM,yBAAyBC,MAAM,YAGlC,EAAE,WAAW,GAAG,SAAS,QAC1B,2CAACD,8BAAsB;CAChB;CACL,0CACE,ybACA,UACD;CACD,GAAI;EACJ,CACF;AACF,uBAAuB,cAAcA,8BAAsB,WAAW;AAEtE,MAAM,sBAAsBC,MAAM,YAG/B,EAAE,WAAW,aAAa,GAAG,GAAG,SAAS,QAC1C,2CAACD,8BAAsB,oBACrB,2CAACA,8BAAsB;CAChB;CACO;CACZ,0CACE,ybACA,UACD;CACD,GAAI;EACJ,GAC2B,CAC/B;AACF,oBAAoB,cAAcA,8BAAsB,QAAQ;AAEhE,MAAM,mBAAmBC,MAAM,YAK5B,EAAE,WAAW,OAAO,GAAG,SAAS,QACjC,2CAACD,8BAAsB;CAChB;CACL,0CACE,mOACA,SAAS,QACT,UACD;CACD,GAAI;EACJ,CACF;AACF,iBAAiB,cAAcA,8BAAsB,KAAK;AAE1D,MAAM,2BAA2BC,MAAM,YAGpC,EAAE,WAAW,UAAU,SAAS,GAAG,SAAS,QAC7C,4CAACD,8BAAsB;CAChB;CACL,0CACE,wOACA,UACD;CACQ;CACT,GAAI;YAEJ,2CAAC;EAAK,WAAU;YACd,2CAACA,8BAAsB,2BACrB,2CAACG,sBAAM,WAAU,YAAY,GACO;GACjC,EACN;EACkC,CACrC;AACF,yBAAyB,cAAcH,8BAAsB,aAAa;AAE1E,MAAM,wBAAwBC,MAAM,YAGjC,EAAE,WAAW,UAAU,GAAG,SAAS,QACpC,4CAACD,8BAAsB;CAChB;CACL,0CACE,wOACA,UACD;CACD,GAAI;YAEJ,2CAAC;EAAK,WAAU;YACd,2CAACA,8BAAsB,2BACrB,2CAACI,uBAAO,WAAU,yBAAyB,GACP;GACjC,EACN;EAC+B,CAClC;AACF,sBAAsB,cAAcJ,8BAAsB,UAAU;AAEpE,MAAM,oBAAoBC,MAAM,YAK7B,EAAE,WAAW,OAAO,GAAG,SAAS,QACjC,2CAACD,8BAAsB;CAChB;CACL,0CAAc,qCAAqC,SAAS,QAAQ,UAAU;CAC9E,GAAI;EACJ,CACF;AACF,kBAAkB,cAAcA,8BAAsB,MAAM;AAE5D,MAAM,wBAAwBC,MAAM,YAGjC,EAAE,WAAW,GAAG,SAAS,QAC1B,2CAACD,8BAAsB;CAChB;CACL,0CAAc,4BAA4B,UAAU;CACpD,GAAI;EACJ,CACF;AACF,sBAAsB,cAAcA,8BAAsB,UAAU;AAEpE,MAAM,wBAAwB,EAC5B,WACA,GAAG,YACyD;AAC5D,QACE,2CAAC;EAAK,0CAAc,8CAA8C,UAAU;EAAE,GAAI;GAAS;;AAG/F,qBAAqB,cAAc;;;;;AC1InC,SAAgB,kBAAkB,EAChC,SACA,OACA,eACA,kBACA,WAAW,OACX,WACA,cAAc,wBACd,mBAAmB,kBAC0B;CAC7C,MAAM,CAAC,MAAM,WAAWK,MAAM,SAAS,MAAM;CAC7C,MAAM,iBAAiB,QAAQ,MAAM,MAAM,EAAE,UAAU,MAAM;AAE7D,QACE,4CAAC;EAAmB;EAAM,cAAc;aACtC,2CAAC;GAAoB;aACnB,4CAAC;IACC,SAAQ;IACR,MAAK;IACL,iBAAe;IACf,mBAAiB;IACP;IACV,0CAAc,0BAA0B,UAAU;eAElD,2CAAC;KAAK,WAAU;eACb,iBACC,qFACG,mBAAmB,eAAe,MAAM,EACzC,2CAAC;MAAK,WAAU;gBAAY,eAAe;OAAa,IACvD,GAEH,2CAAC;MAAK,WAAU;gBAAyB;OAAmB;MAEzD,EACP,2CAACC,4BAAY,WAAU,qCAAqC;KACrD;IACW,EACtB,2CAAC;GACC,WAAU;GACV,OAAM;aAEL,QAAQ,KAAK,WACZ,4CAAC;IAEC,UAAU,CAAC,OAAO;IAClB,gBAAgB;AACd,mBAAc,OAAO,MAAM;AAC3B,aAAQ,MAAM;;IAEhB,WAAU;;KAET,mBAAmB,OAAO,MAAM;KACjC,2CAAC;MAAK,WAAU;gBAAmB,OAAO;OAAa;KACtD,CAAC,OAAO,WAAW,OAAO,iBACzB,2CAAC;MAAK,WAAU;gBAA0C,OAAO;OAAqB;KAEvF,UAAU,OAAO,SAAS,2CAACC,sBAAM,WAAU,iCAAiC;;MAbxE,OAAO,MAcK,CACnB;IACkB;GACT;;;;;;;;;ACjFnB,SAAgB,aAAa,EAC3B,OAAO,IACP,YAAY,IACZ,SAAS,YAC+B;AAExC,QACE,4CAAC;EACC,OAAM;EACN,SAAQ;EACR,OAAO;EACP,QAAQ;EACG;EACX,eAAY;;GAEZ,2CAAC;IACC,GAAE;IACF,MAAK;KACL;GACF,2CAAC;IAAK,GAAE;IAAS,GAAE;IAAS,OAAM;IAAQ,QAAO;IAAQ,MAAK;KAAiB;GAC/E,2CAAC;IAAK,GAAE;IAAS,GAAE;IAAS,OAAM;IAAQ,QAAO;IAAQ,MAAK;KAAiB;GAC/E,2CAAC;IAAK,GAAE;IAAS,GAAE;IAAS,OAAM;IAAQ,QAAO;IAAQ,MAAK;KAAiB;;GAC3E;;;;;;ACjBV,SAAgB,cAAc,EAC5B,WACA,eACA,WACA,OAAO,IACP,UAAU,aAC+B;AACzC,KAAI,UAAU,OAAO,WACnB,QAAO,2CAAC;EAAmB;EAAe;EAAS,0CAAc,YAAY,UAAU;GAAI;AAG7F,KAAI,UAAU,cACZ,QACE,2CAAC,UAAU;EACH;EACG;EACT,0CAAc,YAAY,UAAU;GACpC;CAIN,MAAM,WAAW,iBAAiB,UAAU,IAAI,OAAO,EAAE,CAAC,aAAa;AAEvE,QACE,2CAAC;EACC,0CACE,qGACA,UACD;EACD,OAAO;GAAE,OAAO;GAAM,QAAQ;GAAM,UAAU,OAAO;GAAK;EAC1D,MAAK;EACL,cAAY,iBAAiB,UAAU;YAEtC;GACG;;;;;;;;ACjBV,SAAgB,WAAW,EACzB,MACA,OACA,aACA,YAAY,IACZ,OAAO,aAC+B;CAEtC,MAAM,cAAc,2CAACC,yBAAS,WAAU,kCAAkC;CAwB1E,MAAM,SArBc;EAClB,OAAO;GACL,WAAW;GACX,eAAe;GACf,OAAO;GACP,aAAa;GACd;EACD,SAAS;GACP,WAAW;GACX,eAAe;GACf,OAAO;GACP,aAAa;GACd;EACD,OAAO;GACL,WAAW;GACX,eAAe;GACf,OAAO;GACP,aAAa;GACd;EACF,CAE0B;AAE3B,QACE,4CAAC;EACC,WAAW,yDAAyD,OAAO,UAAU,GAAG;;GAExF,2CAAC;IAAI,WAAW,yBAAyB,OAAO;cAAkB,QAAQ;KAAkB;GAC5F,2CAAC;IAAG,WAAW,GAAG,OAAO;cAAU;KAAW;GAC9C,2CAAC;IAAE,WAAW,yBAAyB,OAAO;cAAgB;KAAgB;;GAC1E;;;;;AChEV,MAAa,eAAeC,cAAM,YAG/B,EAAE,UAAU,WAAW,GAAG,SAAS,QAAQ;AAC5C,QACE,4CAAC;EACM;EACL,0CACE,kFACA,UACD;EACD,QAAO;EACP,KAAI;EACJ,GAAI;;GAEH;GACD,2CAACC,iCAAiB,WAAU,iBAAiB;;;GAC3C;EAEN;AAEF,aAAa,cAAc;;;;;;;;;;;;;ACuC3B,MAAa,UAAU,EACrB,cAAc,gBACd,iCAAgB,IAAI,MAAM,EAAC,aAAa,EACxC,mBAAmB,wCACnB,oBAAoB,kBACpB,oBAAoB,oCACpB,qBAAqB,oBACrB,oBAAoB,MACpB,qBAAqB,MACrB,cACe,EAAE,KAAkB;CACnC,MAAM,gBAAgB,qBAAqB;AAE3C,QACE,2CAAC;EAAO,0CAAc,2CAA2C,UAAU;YACzE,2CAAC;GAAI,WAAU;aACb,4CAAC;IAAI,WAAU;eACb,4CAAC;KAAK;KACD;KAAc;KAAE;QACd,EACN,iBACC,4CAAC;KAAI,WAAU;gBACZ,qBACC,2CAAC;MACC,MAAM;MACN,QAAO;MACP,KAAI;MACJ,WAAU;gBAET;OACC,EAEL,sBACC,2CAAC;MACC,MAAM;MACN,QAAO;MACP,KAAI;MACJ,WAAU;gBAET;OACC;MAEF;KAEJ;IACF;GACC;;;;;;;;AC5Gb,MAAM,QAAQC,MAAM,YAA0C,EAAE,WAAW,GAAG,SAAS,QAAQ;AAC7F,QACE,2CAACC,sBAAe;EACT;EACL,aAAU;EACV,0CAAc,oCAAoC,UAAU;EAC5D,GAAI;GACJ;EAEJ;AAEF,MAAM,cAAcA,sBAAe,KAAK;;;;;;;ACTxC,MAAM,QAA4E,EAChF,GAAG,YACwF;AAC3F,QAAO,2CAACC,gCAAa,GAAI,QAAS;;;;;AAgBpC,MAAM,mBAAmBC,MAAM,cAAqC,EAAE,CAA0B;;;;AAKhG,MAAM,qBAOD;CACH,MAAM,eAAeA,MAAM,WAAW,iBAAiB;CACvD,MAAM,cAAcA,MAAM,WAAW,gBAAgB;CACrD,MAAM,EAAE,eAAe,mDAA8B;CAErD,MAAM,aAAa,cAAc,aAAa,MAAM,UAAU;AAE9D,KAAI,CAAC,aACH,OAAM,IAAI,MAAM,iDAAiD;CAGnE,MAAM,EAAE,OAAO;AAEf,QAAO;EACL;EACA,MAAM,aAAa;EACnB,YAAY,GAAG,GAAG;EAClB,mBAAmB,GAAG,GAAG;EACzB,eAAe,GAAG,GAAG;EACrB,OAAO,WAAW;EACnB;;;;;AAMH,MAAM,aAGJ,EACA,GAAG,YAC2D;AAC9D,QACE,2CAAC,iBAAiB;EAAS,OAAO,EAAE,MAAM,MAAM,MAAM;YACpD,2CAACC,8BAAW,GAAI,QAAS;GACC;;AAWhC,MAAM,kBAAkBD,MAAM,cAAoC,EAAE,CAAyB;;;;AAK7F,MAAM,WAAWA,MAAM,YACpB,EAAE,WAAW,GAAG,SAAS,QAAQ;CAChC,MAAM,KAAKA,MAAM,OAAO;AAExB,QACE,2CAAC,gBAAgB;EAAS,OAAO,EAAE,IAAI;YACrC,2CAAC;GACM;GACL,aAAU;GACV,0CAAc,uBAAuB,UAAU;GAC/C,GAAI;IACJ;GACuB;EAGhC;AACD,SAAS,cAAc;;;;AAKvB,MAAM,YAAYA,MAAM,YACrB,EAAE,WAAW,GAAG,SAAS,QAAQ;CAChC,MAAM,EAAE,OAAO,eAAe,cAAc;AAE5C,QACE,2CAAC;EACM;EACL,WAAW,uCAAW,oBAAoB,UAAU,GAAG;EACvD,SAAS;EACT,GAAI;GACJ;EAGP;AACD,UAAU,cAAc;;;;AAKxB,MAAM,cAAcA,MAAM,YACvB,EAAE,GAAG,SAAS,QAAQ;CACrB,MAAM,EAAE,OAAO,YAAY,mBAAmB,kBAAkB,cAAc;AAE9E,QACE,2CAAC;EACM;EACL,IAAI;EACJ,oBAAkB,CAAC,QAAQ,GAAG,sBAAsB,GAAG,kBAAkB,GAAG;EAC5E,gBAAc,CAAC,CAAC;EAChB,GAAI;GACJ;EAGP;AACD,YAAY,cAAc;;;;AAK1B,MAAM,kBAAkBA,MAAM,YAG3B,EAAE,WAAW,GAAG,SAAS,QAAQ;CAClC,MAAM,EAAE,sBAAsB,cAAc;AAE5C,QACE,2CAAC;EACM;EACL,IAAI;EACJ,aAAU;EACV,0CAAc,iCAAiC,UAAU;EACzD,GAAI;GACJ;EAEJ;AACF,gBAAgB,cAAc;;;;AAK9B,MAAM,cAAcA,MAAM,YAGvB,EAAE,WAAW,UAAU,GAAG,SAAS,QAAQ;CAC5C,MAAM,EAAE,OAAO,kBAAkB,cAAc;CAC/C,MAAM,OAAO,QAAQ,OAAO,OAAO,QAAQ,GAAG;AAE9C,KAAI,CAAC,KACH,QAAO;AAGT,QACE,2CAAC;EACM;EACL,IAAI;EACJ,aAAU;EACV,0CAAc,wCAAwC,UAAU;EAChE,GAAI;YAEH;GACC;EAEN;AACF,YAAY,cAAc;;;;AC1L1B,MAAa,UAAU,EAAE,OAAO,eAAe,mBAAoD;AACjG,QACE,2CAAC;EAAO,WAAU;YAChB,4CAAC;GAAI,WAAU;;IAEb,2CAAC;KACC,MAAK;KACL,cAAW;KACX,SAAS;KACT,WAAU;eAEV,2CAACE,qBAAK,WAAU,WAAW;MACpB;IAER,SACC,2CAAC;KAAI,WAAU;eACb,2CAAC;MAAG,WAAU;gBACX;OACE;MACD;IAIR,2CAAC;KAAI,WAAU;eAA6B;MAAmB;;IAC3D;GACC;;;;;AC3Bb,MAAM,QAAQC,MAAM,YACjB,EAAE,WAAW,MAAM,GAAG,SAAS,QAAQ;AACtC,QACE,2CAAC;EACO;EACN,aAAU;EACV,0CACE,2VACA,UACD;EACI;EACL,GAAI;GACJ;EAGP;AAED,MAAM,cAAc;;;;;;;ACfpB,MAAM,gBACJ,4CAAC;CACC,WAAU;CACV,OAAM;CACN,MAAK;CACL,SAAQ;YAER,2CAAC;EACC,WAAU;EACV,IAAG;EACH,IAAG;EACH,GAAE;EACF,QAAO;EACP,aAAY;GACJ,EACV,2CAAC;EACC,WAAU;EACV,MAAK;EACL,GAAE;GACI;EACJ;AAUR,MAAM,gBAAgBC,MAAM,YAExB,EAAE,WAAW,UAAU,OAAO,UAAU,UAAU,SAAS,MAAM,UAAU,OAAO,GAAG,SACrF,QACG;AAEH,QACE,4CAFW,UAAUC,4BAAO;EAG1B,aAAU;EACV,gBAAc,WAAW;EACzB,aAAW,QAAQ;EACnB,0CAAc,eAAe;GAAE;GAAS;GAAM;GAAW,CAAC,CAAC;EACtD;EACL,UAAU,WAAW;EACrB,GAAI;aAEH,WAAW,2CAAC,YAAU,EACvB,2CAACC,kCAAW,WAAqB;GAC5B;EAGZ;AACD,cAAc,cAAc;;;;;AChD5B,SAAgB,YAAY,EAC1B,SACA,WACA,OAAO,IACP,UAAU,aAC6B;AACvC,KAAI,QAAQ,cAAc,WACxB,QAAO,2CAAC;EAAmB;EAAe;EAAS,0CAAc,YAAY,UAAU;GAAI;AAG7F,KAAI,QAAQ,cACV,QACE,2CAAC,QAAQ;EAAoB;EAAe;EAAS,0CAAc,YAAY,UAAU;GAAI;AAIjG,QACE,2CAAC;EACC,0CAAc,kCAAkC,UAAU;EAC1D,OAAO;GAAE,OAAO;GAAM,QAAQ;GAAM;EACpC,eAAY;GACZ;;;;;;ACsBN,SAAgB,gBAAmB,EACjC,UACA,iBACA,gBACA,gBACA,cACA,mBAAmB,OACnB,cACA,eACA,mBACA,yBACA,WACA,cAAc,kBACd,GAAG,aAC2C;CAC9C,MAAM,CAAC,MAAM,WAAWC,MAAM,SAAS,MAAM;CAC7C,MAAM,CAAC,aAAa,kBAAkBA,MAAM,SAAS,GAAG;CAExD,MAAM,aAAa,UAAU,aAAa;CAE1C,MAAM,qBAAqB,aAAa,UAAU,qBAAqB;CACvE,MAAM,oBAAoB,aAAa,UAAU,oBAAoB;CACrE,MAAM,kBAAkB,CAAC,aAAa,UAAU,kBAAkB;CAClE,MAAM,kBAAkB,CAAC,aAAa,UAAU,kBAAkB;CAElE,MAAM,mBAAmBA,MAAM,cAAc;AAC3C,MAAI,CAAC,YAAa,QAAO;AACzB,MAAI,cAAe,QAAO,SAAS,QAAQ,MAAM,cAAc,GAAG,YAAY,CAAC;AAC/E,SAAO,SAAS,QAAQ,MACtB,gBAAgB,EAAE,CAAC,aAAa,CAAC,SAAS,YAAY,aAAa,CAAC,CACrE;IACA;EAAC;EAAU;EAAa;EAAe;EAAgB,CAAC;CAE3D,MAAM,kBAAkBA,MAAM,cAAc;AAC1C,MAAI,CAAC,oBAAoB,CAAC,aACxB,QAAO,EAAE,KAAK,kBAAkB;AAElC,SAAO,iBAAiB,QACrB,KAAK,YAAY;GAChB,MAAM,YAAY,aAAa,QAAQ;AACvC,OAAI,CAAC,IAAI,WACP,KAAI,aAAa,EAAE;AAErB,OAAI,WAAW,KAAK,QAAQ;AAC5B,UAAO;KAET,EAAE,CACH;IACA;EAAC;EAAkB;EAAkB;EAAa,CAAC;CAEtD,MAAM,aAAaA,MAAM,aACtB,YAAwB;AACvB,MAAI,cAAc,mBAChB,QAAO,mBAAmB,SAAS,aAAa,QAAQ,CAAC;AAE3D,SAAO,kBAAkB,aAAa,gBAAgB,KAAK,aAAa,QAAQ,GAAG;IAErF;EAAC;EAAY;EAAoB;EAAiB;EAAa,CAChE;CAED,MAAM,eAAeA,MAAM,aACxB,YAAe;AACd,MAAI,oBAAoB,QAAQ,CAC9B;AAGF,MAAI,cAAc,sBAAsB,mBAAmB;GACzD,MAAM,KAAK,aAAa,QAAQ;AAIhC,qBAHa,mBAAmB,SAAS,GAAG,GACxC,mBAAmB,QAAQ,MAAM,MAAM,GAAG,GAC1C,CAAC,GAAG,oBAAoB,GAAG,CACR;aACd,iBAAiB;AAC1B,mBAAgB,QAAQ;AACxB,WAAQ,MAAM;;IAGlB;EACE;EACA;EACA;EACA;EACA;EACA;EACD,CACF;CAED,MAAM,iBAAiBA,MAAM,kBAAkB;AAC7C,MAAI,cAAc,kBAChB,mBAAkB,EAAE,CAAC;IAEtB,CAAC,YAAY,kBAAkB,CAAC;CAEnC,MAAM,gBAAgB,oBAAoB,UAAU;CACpD,MAAM,gBAAgB,aAAa,UAAU,gBAAgB;AAoD7D,QACE,4CAAC;EAAmB;EAAM,cAAc;aACtC,2CAAC;GAAoB;oBApDK;AAC5B,QAAI,cAAc,cAChB,QAAO,cAAc;KAAE;KAAe;KAAM,CAAC;AAG/C,QAAI,WACF,QACE,4CAAC;KACC,SAAQ;KACR,MAAK;KACL,iBAAe;KACf,0CAAc,0BAA0B,UAAU;gBAElD,2CAAC;MAAK,WAAU;gBACb,gBAAgB,IACb,GAAG,cAAc,UAAU,gBAAgB,IAAI,MAAM,GAAG,aACxD;OACC,EACP,2CAACC,4BAAY,WAAU,qCAAqC;MACrD;AAIb,WACE,4CAAC;KACC,SAAQ;KACR,MAAK;KACL,iBAAe;KACf,0CAAc,0BAA0B,UAAU;gBAElD,2CAAC;MAAK,WAAU;gBACb,kBACC;OACG,iBAAiB,gBAAgB;OAClC,2CAAC;QAAK,WAAU;kBAAY,gBAAgB,gBAAgB;SAAQ;OACnE,kBACC,2CAAC;QAAK,WAAU;kBACb,eAAe,gBAAgB;SAC3B;UAER,GAEH,2CAAC;OAAK,WAAU;iBAAyB;QAAmB;OAEzD,EACP,2CAACA,4BAAY,WAAU,qCAAqC;MACrD;OAET;IAImE,EACnE,4CAAC;GACC,WAAU;GACV,OAAM;cAEN,4CAAC;IAAI,WAAU;eACb,2CAACC,uBAAO,WAAU,qCAAqC,EACvD,2CAAC;KACC,aAAY;KACZ,OAAO;KACP,WAAW,MAAM,eAAe,EAAE,OAAO,MAAM;KAC/C,YAAY,MAAM;AAChB,UAAI,EAAE,QAAQ,eAAe,EAAE,QAAQ,aAAa,EAAE,QAAQ,QAC5D,GAAE,iBAAiB;;KAGvB,WAAU;KACV,cAAW;MACX;KACE,EACN,4CAAC;IAAI,WAAU;eACZ,cAAc,gBAAgB,KAC7B,qFACE,4CAAC;KAAI,WAAU;gBACb,4CAAC;MAAK,WAAU;iBACb,eAAc;OACV,EACP,2CAAC;MACC,SAAS;MACT,WAAU;gBACX;OAEQ;MACL,EACN,2CAAC,0BAAwB,IACxB,EAGJ,OAAO,QAAQ,gBAAgB,CAAC,WAAW,IAC1C,2CAAC;KAAI,WAAU;eAAiD;MAAuB,GAEvF,OAAO,QAAQ,gBAAgB,CAAC,KAAK,CAAC,OAAO,gBAAgB,UAC3D,4CAACF,MAAM;KACJ,oBACC,2CAAC;MAAkB,WAAU;gBAC1B;OACiB;KAEtB,2CAAC,+BACE,cAAc,KAAK,YAAY;MAC9B,MAAM,WAAW,oBAAoB,QAAQ,IAAI;MACjD,MAAM,gBAAgB,WAAW,0BAA0B,QAAQ,GAAG;AAEtE,aACE,4CAAC;OAEW;OACV,WAAW,MAAM;AACf,YAAI,UAAU;AACZ,WAAE,gBAAgB;AAClB;;AAEF,YAAI,WAAY,GAAE,gBAAgB;AAClC,qBAAa,QAAQ;;OAEvB,0CAAc,SAAS,YAAY,gCAAgC;;QAElE,aACC,2CAAC;SACC,0CACE,yFACA,WAAW,QAAQ,GACf,yDACA,8BACJ,YAAY,aACb;mBAEA,WAAW,QAAQ,IAAI,2CAACG,sBAAM,WAAU,YAAY;UACjD,GACJ;QACH,iBAAiB,QAAQ;QAC1B,4CAAC;SAAI,WAAU;;UACb,2CAAC;WAAK,WAAU;qBAAY,gBAAgB,QAAQ;YAAQ;UAC3D,kBACC,2CAAC;WAAK,WAAU;qBACb,eAAe,QAAQ;YACnB;UAER,gBACC,2CAAC;WAAK,WAAU;qBACb;YACI,GACL;;UACA;QACL,CAAC,cAAc,WAAW,QAAQ,IACjC,2CAACA,sBAAM,WAAU,sCAAsC;;SAxCpD,aAAa,QAAQ,CA0CT;OAErB,GACgB;KACnB,QAAQ,OAAO,KAAK,gBAAgB,CAAC,SAAS,KAAK,2CAAC,0BAAwB;SA3D1D,MA4DJ,CACjB;KAEA;IACc;GACT;;;;;AC5SnB,MAAM,YAAY;;;;;AAMlB,SAAgB,mBAAmB,EACjC,SACA,aACqD;AACrD,KAAI,CAAC,QAAS,QAAO;AAIrB,QACE,4CAAC;EACC,0CACE,kEALgB,QAAQ,SAAS,aAAa,QAAQ,SAAS,WAM/C,sDAAsD,YACtE,UACD;aAGD,2CAAC;GAAqB;GAAS,MAAM;IAAa,EAGlD,4CAAC;GAAI,WAAU;cACb,2CAAC;IAAK,WAAU;cACb,QAAQ;KACJ,EACP,2CAAC;IAAK,WAAU;cAAuB,QAAQ;KAAY;IACvD;GACF;;;;;;ACTV,SAAgB,aAAa,EAC3B,OACA,QAAQ,OACR,WACA,cAAc,YAAY,kBACN;AACpB,KAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,QACE,4CAAC,2BACC,2CAAC;EAAoB;YACnB,2CAAC;GACC,SAAQ;GACR,MAAK;GACL,0CAAc,WAAW,UAAU;GACnC,cAAY;aAEZ,2CAACC,+BAAe,WAAU,YAAY;IAC/B;GACW,EACtB,2CAAC;EAA2B;EAAO,WAAU;YAC1C,MAAM,KAAK,MAAM,UAChB,4CAACC,MAAM,uBACJ,KAAK,eAAe,QAAQ,KAAK,2CAAC,0BAAwB,EAC3D,4CAAC;GACC,SAAS,KAAK;GACd,UAAU,KAAK;GACf,0CAAc,KAAK,eAAe,0CAA0C;cAE3E,KAAK,MACL,KAAK;IACW,KATA,KAAK,GAUT,CACjB;GACkB,IACT;;;;;AClEnB,MAAM,WAAWC,MAAM,YAGpB,EAAE,WAAW,OAAO,GAAG,SAAS,QACjC,2CAACC,yBAAkB;CACZ;CACL,0CACE,iFACA,UACD;CACD,GAAI;WAEJ,2CAACA,yBAAkB;EACjB,WAAU;EACV,OAAO,EAAE,WAAW,eAAe,OAAO,SAAS,GAAG,KAAK;GAC3D;EACqB,CACzB;AACF,SAAS,cAAcA,yBAAkB,KAAK;;;;ACjB9C,MAAM,aAAaC,MAAM,YAGtB,EAAE,WAAW,GAAG,SAAS,QAAQ;AAClC,QACE,2CAACC,4BAAoB;EACnB,0CAAc,2BAA2B,UAAU;EACnD,aAAU;EACV,GAAI;EACC;GACL;EAEJ;AACF,WAAW,cAAcA,4BAAoB,KAAK;AAElD,MAAM,iBAAiBD,MAAM,YAG1B,EAAE,WAAW,GAAG,SAAS,QAAQ;AAClC,QACE,2CAACC,4BAAoB;EACd;EACL,0CACE,sMACA,UACD;EACD,GAAI;YAEJ,2CAACA,4BAAoB;GAAU,WAAU;aACvC,2CAACC,uBAAO,WAAU,0CAA0C;IAC9B;GACP;EAE7B;AACF,eAAe,cAAcD,4BAAoB,KAAK;;;;AClCtD,MAAM,SAASE,uBAAgB;AAE/B,MAAM,cAAcA,uBAAgB;AAEpC,MAAM,cAAcA,uBAAgB;AAEpC,MAAM,gBAAgBC,MAAM,YAGzB,EAAE,WAAW,UAAU,GAAG,SAAS,QACpC,4CAACD,uBAAgB;CACV;CACL,aAAU;CACV,0CACE,uTACA,UACD;CACD,GAAI;YAEH,UACD,2CAACA,uBAAgB;EAAK;YACpB,2CAACE,4BAAY,WAAU,uBAAuB;GACzB;EACC,CAC1B;AACF,cAAc,cAAcF,uBAAgB,QAAQ;AAEpD,MAAM,uBAAuBC,MAAM,YAGhC,EAAE,WAAW,GAAG,SAAS,QAC1B,2CAACD,uBAAgB;CACV;CACL,aAAU;CACC;CACX,GAAI;WAEJ,2CAACG,0BAAU,WAAU,YAAY;EACF,CACjC;AACF,qBAAqB,cAAcH,uBAAgB,eAAe;AAElE,MAAM,yBAAyBC,MAAM,YAGlC,EAAE,WAAW,GAAG,SAAS,QAC1B,2CAACD,uBAAgB;CACV;CACL,aAAU;CACC;CACX,GAAI;WAEJ,2CAACE,4BAAY,WAAU,YAAY;EACF,CACnC;AACF,uBAAuB,cAAcF,uBAAgB,iBAAiB;AAEtE,MAAM,gBAAgBC,MAAM,YAGzB,EAAE,WAAW,UAAU,WAAW,UAAU,GAAG,SAAS,QACzD,2CAACD,uBAAgB,oBACf,4CAACA,uBAAgB;CACV;CACL,aAAU;CACV,0CACE,geACA,aAAa,YACX,mIACF,UACD;CACS;CACV,GAAI;;EAEJ,2CAAC,yBAAuB;EACxB,2CAACA,uBAAgB;GACf,0CACE,OACA,aAAa,YACX,0FACH;GAEA;IACwB;EAC3B,2CAAC,2BAAyB;;EACF,GACH,CACzB;AACF,cAAc,cAAcA,uBAAgB,QAAQ;AAEpD,MAAM,cAAcC,MAAM,YAGvB,EAAE,WAAW,GAAG,SAAS,QAC1B,2CAACD,uBAAgB;CACV;CACL,aAAU;CACV,0CAAc,0CAA0C,UAAU;CAClE,GAAI;EACJ,CACF;AACF,YAAY,cAAcA,uBAAgB,MAAM;AAEhD,MAAM,aAAaC,MAAM,YAGtB,EAAE,WAAW,UAAU,GAAG,SAAS,QACpC,4CAACD,uBAAgB;CACV;CACL,aAAU;CACV,0CACE,8TACA,UACD;CACD,GAAI;YAEJ,2CAAC;EACC,aAAU;EACV,WAAU;YAEV,2CAACA,uBAAgB,2BACf,2CAACI,sBAAM,WAAU,YAAY,GACC;GAC3B,EACP,2CAACJ,uBAAgB,YAAU,WAAoC;EAC1C,CACvB;AACF,WAAW,cAAcA,uBAAgB,KAAK;AAE9C,MAAM,kBAAkBC,MAAM,YAG3B,EAAE,WAAW,GAAG,SAAS,QAC1B,2CAACD,uBAAgB;CACV;CACL,aAAU;CACV,0CAAc,4BAA4B,UAAU;CACpD,GAAI;EACJ,CACF;AACF,gBAAgB,cAAcA,uBAAgB,UAAU;;;;;;;;AC3HxD,SAAgB,cAAc,EAC5B,MACA,UACA,SACA,OAAO,WACP,OACA,WAAW,OACX,aAAa,OACb,MACA,QACA,KACA,aACyC;CAGzC,MAAM,6CACJ,6HACA,QAAQ,oBAAoB,iBAC5B,WACI,gDACA,aACE,iCACA,oPATU,SAAS,UAAU,aAAa,YAWhD,UACD;CAED,MAAM,UACJ,qFACE,4CAAC;EAAI,WAAU;aACZ,MACA;GACG,EACL,SACC,2CAAC;EAAK,WAAU;YACb;GACI,IAER;AAGL,KAAI,KACF,QACE,2CAAC;EAAQ;EAAc;EAAa;EAAK,WAAW;EAAsB;YACvE;GACC;AAIR,QACE,2CAAC;EAAO,WAAW;EAAa,SAAS,WAAW,SAAY;EAAmB;YAChF;GACM;;;;;;;;;AC5Cb,SAAgB,aAAa,EAC3B,OACA,MACA,UACA,cAAc,OACd,MAAM,gBACN,cACA,WACA,kBACA,oBACwC;CACxC,MAAM,CAAC,kBAAkB,2CAAgC,YAAY;CAErE,MAAM,eAAe,mBAAmB;CACxC,MAAM,SAAS,eAAe,iBAAiB;CAE/C,MAAM,oBAAoB,aAAsB;AAC9C,MAAI,CAAC,aACH,qBAAoB,SAAS;AAE/B,iBAAe,SAAS;;AAG1B,QACE,4CAACK,4BAAqB;EACpB,MAAM;EACN,cAAc;EACd,0CAAc,UAAU,UAAU;aAElC,4CAACA,4BAAqB;GACpB,0CACE,mFACA,iEACA,uGACA,iBACD;;IAED,2CAACC,6BACC,0CAAc,qDAAqD,UAAU,YAAY,GACzF;IACD,QAAQ,2CAAC;KAAK,WAAU;eAAY;MAAY;IACjD,2CAAC;KAAK,WAAU;eAAoB;MAAa;;IACpB,EAE/B,2CAACD,4BAAqB;GACpB,0CACE,2DACA,qFACA,iBACD;aAED,2CAAC;IAAI,WAAU;IAAa;KAAe;IACd;GACL;;;;;;;;;ACrDhC,SAAgB,cAAc,EAC5B,QACA,WACA,UACA,QACA,WACA,QAAQ,KACR,aAAa,+BACb,YACA,oBACA,kBAAkB,UACuB;CACzC,MAAM,aAAa,OAAO,UAAU,WAAW,GAAG,MAAM,MAAM;AAE9D,QACE;EAEE,4CAAC;GACC,0CACE,6DACA,YACA,UACD;GACD,OAAO,EAAE,OAAO,YAAY;;IAG3B,UAAU,2CAAC;KAAI,WAAU;eAAuB;MAAa;IAG7D,aAAa,2CAAC;KAAI,WAAU;eAAsB;MAAgB;IAGnE,2CAAC;KAAI,WAAU;KAAqC;MAAe;IAGlE,UAAU,2CAAC;KAAI,WAAU;eAAiD;MAAa;;IACpF;EAGN,2CAAC;GAAI,WAAU;GAAkB,OAAO,EAAE,OAAO,YAAY;IAAI;EAGhE,OAAO,eAAe,aAAa,sBAClC,4CAAC;GACC,0CACE,gCACA,aAAa,wBAAwB,sBACtC;GACD,eAAa,CAAC;cAGd,2CAAC;IACC,0CACE,mDACA,aAAa,gBAAgB,YAC9B;IACD,eAAe,mBAAmB,MAAM;KACxC,EAEF,2CAAC;IACC,0CACE,iHACA,aAAa,kBAAkB,oBAChC;IACD,MAAK;IACL,cAAW;IACX,cAAY;cAEZ,4CAAC;KAAI,WAAU;;MAEZ,UAAU,2CAAC;OAAI,WAAU;iBAA4B;QAAa;MAGlE,aAAa,2CAAC;OAAI,WAAU;iBAAsB;QAAgB;MAGnE,2CAAC;OAAI,WAAU;OAAqC;QAAe;MAGlE,UAAU,2CAAC;OAAI,WAAU;iBAAa;QAAa;;MAChD;KACF;IACF;KAEP;;;;;;;;;AC9FP,SAAgB,eAAe,EAC7B,OACA,UACA,WACA,gBACA,OAAO,SACmC;AAC1C,QACE,4CAAC;EAAI,0CAAc,wBAAwB,QAAQ,UAAU,UAAU;aACpE,SACC,2CAAC;GAAI,0CAAc,uDAAuD,eAAe;aACtF;IACG,EAER,2CAAC;GAAI,0CAAc,iBAAiB,QAAQ,yBAAyB;GAAG;IAAe;GACnF;;;;;;AC9BV,SAAS,KAAK,EACZ,WACA,GAAG,SACmE;AACtE,QACE,2CAACE,qBAAc;EACb,aAAU;EACV,0CAAc,mEAAmE,UAAU;EAC3F,GAAI;GACJ;;;AAKN,SAAS,SAAS,EAChB,WACA,GAAG,SACmE;AACtE,QACE,2CAACA,qBAAc;EACb,aAAU;EACV,0CACE,qRACA,UACD;EACD,GAAI;GACJ;;;AAKN,SAAS,YAAY,EACnB,WACA,GAAG,SACsE;AACzE,QACE,2CAACA,qBAAc;EACb,aAAU;EACV,0CACE,yfACA,UACD;EACD,GAAI;GACJ;;;AAKN,SAAS,YAAY,EACnB,WACA,GAAG,SACsE;AACzE,QACE,2CAACA,qBAAc;EACb,aAAU;EACV,0CAAc,uBAAuB,UAAU;EAC/C,GAAI;GACJ;;;;;ACzDN,MAAM,WAAWC,MAAM,YACpB,EAAE,WAAW,GAAG,SAAS,QAAQ;AAChC,QACE,2CAAC;EACC,aAAU;EACV,0CACE,sYACA,UACD;EACI;EACL,GAAI;GACJ;EAGP;AACD,SAAS,cAAc;;;;;;;;ACLvB,SAAgB,wBAAwB,EACtC,iBACA,YAC0D;AAC1D,KAAI,CAAC,gBAAiB,QAAO;AAE7B,QACE,4CAAC;EACC,SAAQ;EACR,MAAK;EACL,WAAU;EACV,SAAS;EACT,OAAM;aAEN,2CAACC;GAAS,MAAM;GAAI,WAAU;IAAyB,EACvD,4CAAC;GAAK,WAAU;cACd,2CAAC;IAAK,WAAU;cAAsB;KAA0B,EAChE,4CAAC;IAAK,WAAU;;KAAwC;gDACrC,gBAAgB;KAAC;;KAC7B;IACF;GACA;;;;;ACPb,SAAS,aACP,MACA,OACA,kBACA,mBACiB;AACjB,KAAI,KAAK,WAAW,eAAe,KAAK,WAAW,UAAW,QAAO;AACrE,KAAI,UAAU,iBAAkB,QAAO;AACvC,KAAI,KAAK,cAAc,QAAQ,oBAAoB,SAAS,mBAAoB,QAAO;AACvF,KAAI,QAAQ,iBAAkB,QAAO;AACrC,KAAI,SAAS,kBAAmB,QAAO;AACvC,QAAO;;AAGT,SAAS,SAAS,OAAwB,iBAAiB,OAAgB;AACzE,KAAI,eAAgB,QAAO;AAC3B,QAAO,UAAU;;AAGnB,SAAS,WAAW,EAAE,OAAO,SAAoD;AAC/E,QACE,2CAAC;EACC,0CACE,sGACA,UAAU,eAAe,wCACzB,UAAU,aAAa,gEACvB,UAAU,aAAa,wDACvB,UAAU,aAAa,iEACvB,UAAU,cAAc,iCACzB;YAEA,UAAU,cACT,2CAACC,sBAAM,WAAU,aAAa,GAC5B,UAAU,YACZ,2CAACC,uBAAO,WAAU,WAAW,GAC3B,UAAU,YACZ,2CAACC,4BAAY,WAAU,aAAa,GAEpC,QAAQ;GAEL;;AAIX,SAAS,UAAU,EACjB,OACA,OACA,aAKC;AACD,QACE,4CAAC;EAAI,WAAU;aACb,2CAAC;GACC,0CACE,yCACA,UAAU,aAAa,iBACvB,UAAU,eAAe,mBACzB,UAAU,aAAa,iBACvB,UAAU,aAAa,oBACvB,UAAU,cAAc,wBACzB;aAEA;IACI,EACN,aAAa,2CAAC;GAAK,WAAU;aAAiD;IAAc;GACzF;;AAQV,SAAS,gBAAgB,EACvB,OACA,kBACA,oBAAoB,kBACpB,aACA,gBACA,aACqB;AACrB,QACE,2CAAC;EACC,cAAW;EACX,0CAAc,gDAAgD,UAAU;YAExE,2CAAC;GAAI,WAAU;aACZ,MAAM,KAAK,MAAM,UAAU;IAC1B,MAAM,QAAQ,aAAa,MAAM,OAAO,kBAAkB,kBAAkB;IAC5E,MAAM,YAAY,SAAS,OAAO,eAAe,IAAI,CAAC,CAAC;AAEvD,WACE,4CAAC;KAEC,MAAK;KACL,eAAe,aAAa,cAAc,MAAM;KAChD,UAAU,CAAC;KACX,0CACE,gHACA,YAAY,mBAAmB,iCAC/B,UAAU,aAAa,oCACvB,UAAU,eAAe,6BACzB,UAAU,aAAa,+BACvB,UAAU,aACR,kEACF,UAAU,cAAc,UACzB;KACD,gBAAc,UAAU,YAAY,SAAS;gBAE7C,2CAAC;MAAkB;MAAc;OAAS,EAC1C,2CAAC;MAAU,OAAO,KAAK;MAAc;MAAO,WAAW,KAAK,WAAW;OAAa;OAjB/E,KAAK,GAkBH;KAEX;IACE;GACF;;AAQV,SAAS,kBAAkB,EACzB,OACA,kBACA,oBAAoB,kBACpB,aACA,gBACA,aACqB;AACrB,QACE,2CAAC;EACC,cAAW;EACX,0CAAc,gDAAgD,UAAU;YAExE,2CAAC;GAAI,WAAU;aACZ,MAAM,KAAK,MAAM,UAAU;IAC1B,MAAM,QAAQ,aAAa,MAAM,OAAO,kBAAkB,kBAAkB;IAC5E,MAAM,YAAY,SAAS,OAAO,eAAe,IAAI,CAAC,CAAC;IACvD,MAAM,SAAS,UAAU,MAAM,SAAS;AAExC,WACE,4CAACC,cAAM,uBACL,4CAAC;KACC,MAAK;KACL,eAAe,aAAa,cAAc,MAAM;KAChD,UAAU,CAAC;KACX,0CACE,gHACA,YAAY,mBAAmB,iCAC/B,UAAU,aAAa,oCACvB,UAAU,eAAe,6BACzB,UAAU,aAAa,+BACvB,UAAU,aACR,kEACF,UAAU,cAAc,UACzB;KACD,gBAAc,UAAU,YAAY,SAAS;KAC7C,cAAY,QAAQ,QAAQ,EAAE,IAAI,KAAK;gBAEvC,2CAAC;MAAkB;MAAc;OAAS,EAC1C,2CAAC;MAAI,WAAU;gBACb,2CAAC;OACC,OAAO,KAAK;OACL;OACP,WAAW,KAAK,WAAW;QAC3B;OACE;MACC,EAER,CAAC,UACA,2CAAC,SACC,0CACE,8CACA,QAAQ,mBAAmB,gBAAgB,YAC5C,GACD,KAlCe,KAAK,GAoCT;KAEnB;IACE;GACF;;;;;;;;AAcV,SAAgB,cAAc,OAAsC;CAClE,MAAM,EAAE,UAAU,cAAc,GAAG,SAAS;AAC5C,QAAO,YAAY,aACjB,2CAAC;EAAgB,GAAI;EAAe;GAAW,GAE/C,2CAAC;EAAkB,GAAI;EAAe;GAAW;;;;;;;;;;;AClMrD,SAAgB,iBAAiB,EAC/B,aACA,YACA,aAAa,MACb,YACA,QACA,UACA,cACA,YAAY,QACZ,gBAAgB,UAChB,qBACA,wBACA,2BACA,sBAAsB,MACtB,aACwB;CACxB,MAAM,cAAc,CAAC,cAAc;CACnC,MAAM,gBACJ,cACA,0BAA0B,QAC1B,2BAA2B,MAC3B,uBAAuB;AAEzB,QACE,4CAAC;EAAI,0CAAc,qCAAqC,UAAU;aAChE,4CAAC;GAAI,WAAU;cACZ,YACC,4CAAC;IAAO,MAAK;IAAS,SAAQ;IAAU,SAAS;IAAU,WAAU;eACnE,2CAACC,kBAAE,WAAU,WAAW;KAEjB,EAEV,CAAC,eACA,4CAAC;IAAO,MAAK;IAAS,SAAQ;IAAU,SAAS;IAAY,WAAU;eACrE,2CAACC,4BAAY,WAAU,WAAW;KAE3B;IAEP,EAEN,4CAAC;GAAI,WAAU;;IACZ;IACA,iBACC,2CAAC;KACC,MAAK;KACL,SAAQ;KACR,SAAS;KACT,UAAU,6BAA6B;KACvC,WAAU;eAET;MACM;IAEV,eACC,4CAAC;KAAO,MAAK;KAAS,SAAS;KAAQ,UAAU,CAAC;KAAY,WAAU;gBACrE,aAAa,gBAAgB,WAC7B,CAAC,cAAc,2CAACC,6BAAa,WAAU,WAAW;MAC5C;;IAEP;GACF;;;;;;;;AC/EV,SAAgB,iBAAiB,WAAmB,kBAA0B;AAC5E,KAAI,cAAc,EAAG,QAAO;AAE5B,QAAO,KAAK,IAAI,GAAG,KAAK,IAAI,kBAAkB,YAAY,EAAE,CAAC;;;;;AAM/D,SAAgB,qBACd,kBACA,6BACA;CACA,MAAM,CAAC,2BAA2B,oDAAyC,iBAAiB;AAE5F,4BAAgB;AACd,gCAA8B,SAAS,KAAK,IAAI,MAAM,iBAAiB,CAAC;IACvE,CAAC,iBAAiB,CAAC;AAEtB,QAAO,+BAA+B;;;;;AAMxC,SAAgB,gCAA0D,EACxE,OACA,kBACA,cACA,WACA,WACA,gBAAgB,qBACgC;CAChD,MAAM,YAAY,iBAAiB,MAAM,QAAQ,iBAAiB;CAClE,MAAM,oCAAyB,UAAU;CACzC,MAAM,2BAA+B,KAAK;CAC1C,MAAM,4CAAgD,KAAK;CAI3D,MAAM,6BAAkB,MAAM;CAC9B,MAAM,iCAAsB,UAAU;CACtC,MAAM,oCAAyB,aAAa;CAC5C,MAAM,qCAA0B,cAAc;AAC9C,4BAAgB;AACd,WAAS,UAAU;AACnB,eAAa,UAAU;AACvB,kBAAgB,UAAU;AAC1B,mBAAiB,UAAU;GAC3B;CAEF,MAAM,CAAC,aAAa,sCAA2B,gBAAgB,QAAQ;CACvE,MAAM,mCAAwB,gBAAgB,QAAQ;CACtD,MAAM,CAAC,mBAAmB,4CAAiC,gBAAgB,QAAQ;CAQnF,MAAM,iCAAsB,MAAM;CAElC,MAAM,oDAAyC;AAC7C,0BAAwB,UAAU;IACjC,EAAE,CAAC;AAKN,4BAAgB;EACd,MAAM,YAAY,UAAU;AAC5B,MAAI,CAAC,UAAW;EAChB,MAAM,gBAAgB,UAAU;AAEhC,eAAa,UAAU;EAIvB,IAAI,wBAAwB;EAE5B,MAAM,2CAA2C;AAC/C,yBAAsB;;EAExB,MAAM,iBAAiB,UAAyB;AAC9C,OAAI,0BAA0B,MAAM,CAClC,uBAAsB;;EAI1B,MAAM,qBAAqB;AACzB,OAAI,OAAO,YAAY,KAAM,sBAAqB,OAAO,QAAQ;AAEjE,UAAO,UAAU,4BAA4B;IAC3C,MAAM,eAAe,SAAS;IAC9B,MAAM,mBAAmB,aAAa;IACtC,MAAM,sBAAsB,gBAAgB;AAE5C,QAAI,aAAa,WAAW,EAAG;IAE/B,MAAM,uBAAuB,wBAAwB;IACrD,MAAM,eAAe,6BACnB,WACA,cACA,iBACD;IACD,MAAM,qBAAqB,aAAa;IACxC,MAAM,iBAAiB,wBAAwB;IAC/C,MAAM,gCACJ,yBAAyB,OAAO,OAAO,aAAa;AAGtD,QADwB,eAAe,YACf,gBAAgB;AACtC,oBAAe,UAAU;AACzB,oBAAe,eAAe;AAI9B,SAAI,aAAa,SAAS;AACxB,0BAAoB,UAAU;AAC9B,0BAAoB,eAAe;;UAGrC,gBAAe,eAAe;AAEhC,QAAI,8BACF,uBAAsB,SAAS,KAAK,IAAI,MAAM,eAAe,CAAC;AAEhE,WAAO,UAAU;AAIjB,QAAI,CAAC,uBAAuB;AAC1B,6BAAwB;AACxB,kBAAa,UAAU;;KAEzB;;AAGJ,YAAU,iBAAiB,SAAS,oCAAoC,EAAE,SAAS,MAAM,CAAC;AAC1F,YAAU,iBAAiB,aAAa,oCAAoC,EAAE,SAAS,MAAM,CAAC;AAG9F,YAAU,iBAAiB,eAAe,mCAAmC;AAC7E,gBAAc,iBAAiB,WAAW,cAAc;AACxD,YAAU,iBAAiB,UAAU,cAAc,EAAE,SAAS,MAAM,CAAC;AACrE,gBAAc;AAEd,eAAa;AACX,gBAAa,UAAU;AACvB,aAAU,oBAAoB,SAAS,mCAAmC;AAC1E,aAAU,oBAAoB,aAAa,mCAAmC;AAC9E,aAAU,oBAAoB,eAAe,mCAAmC;AAChF,iBAAc,oBAAoB,WAAW,cAAc;AAC3D,aAAU,oBAAoB,UAAU,aAAa;AACrD,OAAI,OAAO,YAAY,KAAM,sBAAqB,OAAO,QAAQ;;IAIlE,CAAC,sBAAsB,UAAU,CAAC;CAKrC,MAAM,wCAA6B,UAAU;AAQ7C,4BAAgB;EACd,MAAM,eAAe,iBAAiB,SAAS,QAAQ,QAAQ,iBAAiB;AAGhF,MAAI,iBAAiB,oBAAoB,QAAS;AAGlD,sBAAoB,UAAU;AAC9B,iBAAe,UAAU;AACzB,iBAAe,aAAa;AAC5B,wBAAsB,SAAS,KAAK,IAAI,MAAM,aAAa,CAAC;EAE5D,MAAM,OAAO,SAAS,QAAQ;AAC9B,MAAI,CAAC,KAAM;EACX,MAAM,iBAAiB,UAAU,SAAS,cACxC,IAAI,IAAI,OAAO,aAAa,QAAQ,KAAK,GAAG,CAAC,GAC9C;AACD,MAAI,UAAU,WAAW,eACvB,uBAAsB,UAAU,SAAS,gBAAgB,iBAAiB,QAAQ;IACnF,CAAC,kBAAkB,UAAU,CAAC;AAwBjC,QAAO;EACL;EACA;EACA,yCAxBC,UAAkB;GACjB,MAAM,OAAO,SAAS,QAAQ;AAC9B,OAAI,CAAC,KAAM;AAEX,2BAAwB,UAAU;AAClC,kBAAe,UAAU;AACzB,uBAAoB,UAAU;AAC9B,kBAAe,MAAM;AACrB,yBAAsB,SAAS,KAAK,IAAI,MAAM,MAAM,CAAC;AACrD,mBAAgB,QAAQ,MAAM;GAE9B,MAAM,YAAY,UAAU;GAC5B,MAAM,iBAAiB,WAAW,cAChC,IAAI,IAAI,OAAO,aAAa,QAAQ,KAAK,GAAG,CAAC,GAC9C;AACD,OAAI,aAAa,eACf,uBAAsB,WAAW,gBAAgB,iBAAiB,QAAQ;KAE9E,CAAC,UAAU,CACZ;EAMA;;AAGH,SAAS,6BACP,WACA,OACA,WACA;AACA,KAAI,MAAM,WAAW,EACnB,QAAO;EACL,aAAa;EACb,yBAAyB;EAC1B;CAGH,MAAM,gBAAgB,UAAU,uBAAuB;CACvD,MAAM,UAAU,cAAc,MAAM,KAAK,IAAI,cAAc,SAAS,KAAM,IAAI;CAC9E,MAAM,eAAe,UAAU,eAAe,UAAU,eAAe;CACvE,MAAM,aACJ,gBAAgB,UAAU,YAAY,UAAU,gBAAgB,UAAU,eAAe;CAC3F,MAAM,eACJ,gBAAgB,UAAU,YAAY,UAAU,gBAAgB,UAAU,eAAe;AAE3F,KAAI,WACF,QAAO;EACL,aAAa,MAAM,SAAS;EAC5B,yBAAyB;EAC1B;CAGH,IAAI,cAAc;CAClB,IAAI,eAAe,OAAO;AAC1B,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,iBAAiB,kBAAkB,WAAW,MAAM,GAAG,IAAI,WAAW,cAAc;AAC1F,MAAI,CAAC,eAAgB;EAErB,MAAM,QAAQ,oBAAoB;GAChC,WAAW;GACX,WAAW,MAAM;GACjB;GACA;GACA;GACA,GAAG;GACJ,CAAC;AAEF,MAAI,SAAS,cAAc;AACzB,kBAAe;AACf,iBAAc;;;AAIlB,QAAO;EACL;EACA,yBAAyB;EAC1B;;AAKH,MAAM,oBAAoB;AAE1B,SAAS,kBACP,WACA,QACA,WACA;AACA,QAAO,UAAU,cAA2B,IAAI,IAAI,OAAO,UAAU,OAAO,CAAC,GAAG;;AAGlF,SAAS,sBACP,WACA,gBACA,SACA;CACA,MAAM,aAAa,eAAe,uBAAuB,CAAC;CAC1D,MAAM,eAAe,UAAU,uBAAuB,CAAC;CACvD,MAAM,kBAAkB,UAAU,aAAa,aAAa,gBAAgB;AAC5E,WAAU,SAAS;EACjB,KAAK;EACL,UAAU;EACX,CAAC;;AAGJ,SAAS,kBACP,WACA,QACA,WACA,eACA;CACA,MAAM,iBAAiB,kBAAkB,WAAW,QAAQ,UAAU;AACtE,KAAI,CAAC,eAAgB,QAAO;CAE5B,MAAM,cAAc,eAAe,uBAAuB;AAE1D,QAAO;EACL;EACA,eAAe,iBAAiB,eAAe,YAAY;EAC5D;;AAGH,SAAS,iBAAiB,eAAwB,aAAsB;AACtE,QAAO,KAAK,IACV,GACA,KAAK,IAAI,YAAY,QAAQ,cAAc,OAAO,GAChD,KAAK,IAAI,YAAY,KAAK,cAAc,IAAI,CAC/C;;AAGH,SAAS,oBAAoB,EAC3B,WACA,WACA,eACA,aACA,eACA,SACA,gBASC;CACD,MAAM,YAAY,gBAAgB;CAClC,MAAM,eAAe,cAAc,MAAM,KAAK,IAAI,cAAc,SAAS,IAAK,IAAI;CAClF,MAAM,kBAAkB,cAAc,MAAM,KAAK,IAAI,cAAc,SAAS,KAAM,IAAI;CACtF,MAAM,mBAAmB,qBAAqB,aAAa,cAAc,gBAAgB;CACzF,MAAM,sBACJ,mBAAmB,IACf,IACA,KAAK,IACH,KAAK,IAAI,YAAY,MAAM,gBAAgB,EAC3C,KAAK,IAAI,YAAY,SAAS,aAAa,CAC5C;CAEP,MAAM,oBADa,cAAc,YAAY,KAG3C,iBAAiB,KAAK,IAAI,YAAY,QAAQ,cAAc,OAAO,GAAG,OACtE,YAAY,OAAO,cAAc,MAAM,cAAc,SAAS;CAEhE,IAAI,QAAQ,YAAY,gBAAgB,OAAO;AAE/C,KAAI,mBAAmB,EAAG,UAAS,OAAS,mBAAmB;AAC/D,KAAI,YAAY,OAAO,QAAS,UAAS;AACzC,UAAS,KAAK,IAAI,GAAG,MAAQ,oBAAoB;AAEjD,KAAI,gBAAgB,qBAAqB,UAAW,UAAS;AAE7D,QAAO;;AAGT,SAAS,qBAAqB,aAAsB,SAAiB,YAAoB;AACvF,QAAO,KAAK,IAAI,GAAG,KAAK,IAAI,YAAY,QAAQ,WAAW,GAAG,KAAK,IAAI,YAAY,KAAK,QAAQ,CAAC;;AAGnG,SAAS,0BAA0B,OAAsB;AACvD,KAAI,MAAM,WAAW,MAAM,WAAW,MAAM,OAAQ,QAAO;AAE3D,QAAO;EAAC;EAAa;EAAW;EAAY;EAAU;EAAQ;EAAO;EAAI,CAAC,SAAS,MAAM,IAAI;;;;;AClT/F,SAAS,YAAY,EACnB,OACA,kBACA,mBAAmB,uBACnB,cACA,YACA,mBACA,UACA,WACA,eACA,qBACA,wBACA,2BACA,qBACA,YACA,QACA,SACA,aAC6D;CAC7D,MAAM,YAAY,iBAAiB,MAAM,QAAQ,iBAAiB;CAClE,MAAM,4BAA4B,qBAAqB,WAAW,sBAAsB;CACxF,MAAM,sCAA2C,KAAK;AAItD,kCAAsB;EACpB,MAAM,KAAK,kBAAkB;AAC7B,MAAI,CAAC,GAAI;AACT,KAAG,YAAY;IACd,CAAC,UAAU,CAAC;AAEf,KAAI,MAAM,WAAW,EAAG,QAAO;CAE/B,MAAM,cAAc,cAAc;CAClC,MAAM,aAAa,cAAc,MAAM,SAAS;CAChD,MAAM,cAAc,MAAM;CAC1B,MAAM,aAAa,aAAa,YAAY;CAE5C,MAAM,mBAAmB;AACvB,MAAI,YAAY;AACd,OAAI,kBACF,oBAAmB;OAEnB,eAAc;AAEhB;;AAEF,eAAa,YAAY,EAAE;;CAG7B,MAAM,uBAAuB;AAC3B,MAAI,CAAC,YAAa,cAAa,YAAY,EAAE;;CAG/C,MAAM,WAAW,WAAW,OAAO,UAAU;CAoB7C,MAAM,SACJ,2CAAC;EAAI,WAAU;YACb,2CAAC;GAAI,WAAU;aAnBjB,2CAAC;IACc;IACD;IACA;IACZ,YAAY;IACZ,QAAQ;IACE;IACV,cAAc;IACH;IACI;IACM;IACG;IACG;IAC3B,qBAAqB,CAAC;KACtB;IAKqD;GACjD;AAGR,KAAI,YAAY,WACd,QACE,4CAAC;EAAI,0CAAc,qBAAqB,UAAU;aAChD,2CAAC;GAAI,WAAU;aACb,2CAAC;IACC,SAAQ;IACR,OAAO;IACP,kBAAkB;IAClB,mBAAmB;IACnB,aAAa;IACb,WAAU;KACV;IACE,EAEN,4CAAC;GAAI,WAAU;cACb,2CAAC;IAAI,KAAK;IAAmB,WAAU;cACrC,4CAAC;KAAI,WAAU;gBACZ,QACA,aAAa;MACV;KACF,EACL;IACG;GACF;AAIV,QACE,4CAAC;EAAI,0CAAc,wBAAwB,UAAU;aACnD,2CAAC;GAAI,WAAU;aACb,2CAAC;IACC,SAAQ;IACR,OAAO;IACP,kBAAkB;IAClB,mBAAmB;IACnB,aAAa;KACb;IACE,EAEN,4CAAC;GAAI,WAAU;cACb,2CAAC;IAAI,KAAK;IAAmB,WAAU;cACrC,4CAAC;KAAI,WAAU;gBACZ,QACA,aAAa;MACV;KACF,EACL;IACG;GACF;;AAQV,SAAS,iBAAiB,EACxB,OACA,kBACA,cACA,QACA,YACA,8BACA,yBACA,uBACA,0BACA,6BACA,eACA,aAeC;CACD,MAAM,+BAAoB;CAC1B,MAAM,8BAAmC,KAAK;CAC9C,MAAM,oCACH,WAAmB,kBAAkB,WAAW,GAAG,UACpD,CAAC,WAAW,CACb;CACD,MAAM,EAAE,aAAa,mBAAmB,oBAAoB,gCAAgC;EAC1F;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;AAEF,KAAI,MAAM,WAAW,EAAG,QAAO;CAE/B,MAAM,WAAW,WAAW,OAAO,YAAY;CAE/C,MAAM,0BACJ,yBAAyB,QACzB,4BAA4B,QAC5B,6BAA6B;CAC/B,MAAM,wBAAwB,cAAc,QAAQ,CAAC;CACrD,MAAM,uBAAuB,2BAA2B;AAExD,QACE,4CAAC;EAAI,0CAAc,qBAAqB,UAAU;aAChD,2CAAC;GAAI,WAAU;aACb,2CAAC;IACC,SAAQ;IACR,OAAO;IACP,kBAAkB;IACC;IACnB,aAAa;IACb;IACA,WAAU;KACV;IACE,EAEN,4CAAC;GAAI,KAAK;GAAW,WAAU;;IAC5B;IACD,2CAAC;KAAI,WAAU;eACZ,MAAM,KAAK,SACV,2CAAC;MAAsB,IAAI,UAAU,KAAK,GAAG;gBAC1C,KAAK;QADM,KAAK,GAET,CACV;MACE;IAEL,wBACC,4CAAC;KAAI,WAAU;gBACZ,2BACC,2CAAC;MACC,MAAK;MACL,SAAQ;MACR,SAAS;MACT,UAAU,+BAA+B;gBAExC;OACM,EAEV,yBACC,2CAAC;MAAO,MAAK;MAAS,SAAS;gBAC5B,2BAA2B;OACrB;MAEP;;IAEJ;GACF;;AAQV,SAAS,WAAW,OAA2B,kBAA2C;AACxF,QAAO,MAAM,KAAK,GAAG,MAAM;EAGzB,MAAM,YAAY,EAAE,aAAa,EAAE,YAAY;EAG/C,MAAM,SAAS,EAAE,WAAW,IAAI,oBAAoB,CAAC,YAAY,cAAc;AAC/E,SAAO;GAAE,IAAI,EAAE;GAAI,OAAO,EAAE;GAAO;GAAQ;GAAW;GACtD;;;;;;;;AAaJ,SAAgB,aAAa,OAA0B;CACrD,MAAM,EAAE,UAAU,cAAc,GAAG,SAAS;AAE5C,KAAI,YAAY,aACd,QACE,2CAAC;EACC,OAAO,KAAK;EACZ,kBAAkB,KAAK;EACvB,cAAc,KAAK;EACnB,QAAQ,KAAK;EACb,YAAY,KAAK;EACjB,8BAA8B,KAAK;EACnC,yBAAyB,KAAK;EAC9B,uBAAuB,KAAK;EAC5B,0BAA0B,KAAK;EAC/B,6BAA6B,KAAK;EAClC,eAAe,KAAK;EACpB,WAAW,KAAK;GAChB;AAIN,QAAO,2CAAC;EAAY,GAAI;EAAe;GAAW;;;;;;;;;;ACpXpD,MAAa,oDAA2E,KAAK;;;;;;;;;;ACF7F,SAAgB,iBACd,IACA,OAA4C,SACpC;AACR,QAAO,GAAG,GAAG,GAAG;;;;;AA0ClB,SAAgB,sBAAsB,EACpC,IACA,WAAW,OACX,aAAa,OACb,aAAa,OACb,aAAa,OACb,gBAAgB,OAChB,sBAAsB,SASD;CAErB,MAAM,iBAA2B,EAAE;AAEnC,KAAI,SACF,gBAAe,KAAK,iBAAiB,IAAI,QAAQ,CAAC;AAGpD,KAAI,cACF,gBAAe,KAAK,iBAAiB,IAAI,cAAc,CAAC;AAG1D,KAAI,oBACF,gBAAe,KAAK,iBAAiB,IAAI,UAAU,CAAC;AAGtD,QAAO;EACL,gBAAgB;EAChB,iBAAiB;EACjB,oBAAoB,eAAe,SAAS,IAAI,eAAe,KAAK,IAAI,GAAG;EAC3E,qBAAqB,WAAW,iBAAiB,IAAI,QAAQ,GAAG;EAChE,UAAU;EACV,UAAU;EACV,UAAU;EACV,UAAU,aAAa,KAAK;EAC7B;;;;;;AAOH,SAAgB,oBACd,OACA,UAUM;AACN,SAAQ,MAAM,KAAd;EACE,KAAK;AACH,OAAI,SAAS,SAAS;AACpB,UAAM,gBAAgB;AACtB,aAAS,SAAS;;AAEpB;EACF,KAAK;AACH,OAAI,SAAS,SAAS;AACpB,UAAM,gBAAgB;AACtB,aAAS,SAAS;;AAEpB;EACF,KAAK;AACH,OAAI,SAAS,UAAU;AACrB,UAAM,gBAAgB;AACtB,aAAS,UAAU;;AAErB;EACF,KAAK;AACH,OAAI,SAAS,WAAW;AACtB,UAAM,gBAAgB;AACtB,aAAS,WAAW;;AAEtB;EACF,KAAK;AACH,OAAI,SAAS,aAAa;AACxB,UAAM,gBAAgB;AACtB,aAAS,aAAa;;AAExB;EACF,KAAK;AACH,OAAI,SAAS,aAAa;AACxB,UAAM,gBAAgB;AACtB,aAAS,aAAa;;AAExB;EACF,KAAK;AACH,OAAI,SAAS,cAAc;AACzB,UAAM,gBAAgB;AACtB,aAAS,cAAc;;AAEzB;EACF,KAAK;AACH,OAAI,SAAS,OAAO;AAClB,UAAM,gBAAgB;AACtB,aAAS,OAAO;;AAElB;EACF,QACE;;;;;;;AAQN,SAAgB,qBAId;AACA,QAAO;EAIL,kBAAkB,WAAqC;AACrD,OAAI,CAAC,UAAW;GAEhB,MAAM,YAAY,UAAU,iBAC1B,6EACD;AAED,OAAI,UAAU,SAAS,EACrB,WAAU,GAAG,OAAO;;EAOxB,iBAAiB,IAAkB;GACjC,MAAM,UAAU,SAAS,eAAe,GAAG;AAC3C,OAAI,QACF,SAAQ,OAAO;;EAOnB,UAAU,OAAsB,WAAqC;AACnE,OAAI,CAAC,aAAa,MAAM,QAAQ,MAAO;GAEvC,MAAM,YAAY,MAAM,KACtB,UAAU,iBACR,6EACD,CACF;AAED,OAAI,UAAU,WAAW,EAAG;GAE5B,MAAM,eAAe,UAAU;GAC/B,MAAM,cAAc,UAAU,UAAU,SAAS;AAEjD,OAAI,MAAM,YAAY,SAAS,kBAAkB,cAAc;AAC7D,UAAM,gBAAgB;AACtB,gBAAY,OAAO;cACV,CAAC,MAAM,YAAY,SAAS,kBAAkB,aAAa;AACpE,UAAM,gBAAgB;AACtB,iBAAa,OAAO;;;EAGzB;;;;;;;;;AAUH,SAAgB,gBACd,UACA,OACkC;AAClC,SAAQ,MAA2B;AACjC,MAAI,EAAE,QAAQ,UAAU;AACtB,KAAE,gBAAgB;AAGlB,OAAI,MACF,UAAS,GAAG;OAGZ,CAAC,EAAE,OAAuB,MAAM;;;;;;;;;;;AAaxC,SAAgB,iBACd,UACA,OACkC;AAClC,SAAQ,MAA2B;AACjC,MAAI,EAAE,QAAQ,OAAO,EAAE,QAAQ,SAAS;AACtC,KAAE,gBAAgB;AAClB,YAAS,CAAC,MAAM;;;;;;;;;;;;;;AAetB,SAAgB,kBACd,UACA,OACA,OAAe,GACf,KACA,KACkC;AAClC,SAAQ,MAA2B;AACjC,MAAI,EAAE,QAAQ,aAAa,EAAE,QAAQ,aAAa;AAChD,KAAE,gBAAgB;GAClB,MAAM,YAAY,EAAE,QAAQ,YAAY,IAAI;GAC5C,IAAI,WAAW,OAAO,UAAU,WAAW,QAAQ,OAAO,YAAY;AAGtE,OAAI,OAAO,QAAQ,SAAU,YAAW,KAAK,IAAI,KAAK,SAAS;AAC/D,OAAI,OAAO,QAAQ,SAAU,YAAW,KAAK,IAAI,KAAK,SAAS;AAE/D,YAAS,SAAS;;;;;;;;;;;;;ACxSxB,SAAgB,gBAAgB,OAA0C;AACxE,SAAQ,OAAR;EACE,KAAK,OACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,KAAK;EACL,QACE,QAAO;;;;;;ACIb,MAAM,cAAc;AACpB,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDxB,SAAgB,aAA6D,EAC3E,IACA,OACA,aACA,YACA,SACA,MACA,QAAQ,QACR,YACA,YACA,UACA,aAAa,iBACb,sBACsD;CACtD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAE5B,MAAM,wCAA6B,yBAAyB;CAC5D,MAAM,iCAAsC,KAAK;CACjD,MAAM,oCAAiC,GAAG;CAE1C,MAAM,CAAC,YAAY,qCAA0B,GAAG;CAChD,MAAM,CAAC,gBAAgB,yCAA8B,GAAG;CACxD,MAAM,CAAC,iBAAiB,0CAA+B,MAAM;CAC7D,MAAM,CAAC,kBAAkB,2CAAgC,GAAG;CAE5D,MAAM,kDAA6B;EAAE;EAAS;EAAM,CAAC;AAErD,4BAAgB;EACd,MAAM,oBAAoB,qBAAqB;AAC/C,MAAI,sBAAsB,gBAAgB,SAAS;AACjD,mBAAgB,UAAU;AAC1B,iBAAc,kBAAkB;;IAEjC,CAAC,kBAAkB,CAAC;AAEvB,4BAAgB;AACd,MAAI,CAAC,WAAW,MAAM,EAAE;AACtB,qBAAkB,GAAG;AACrB;;EAEF,MAAM,QAAQ,iBAAiB,kBAAkB,WAAW,EAAE,YAAY;AAC1E,eAAa,aAAa,MAAM;IAC/B,CAAC,WAAW,CAAC;CAEhB,MAAM,sBAAsB,oBAAoB;CAEhD,MAAM,+CAAyD;AAC7D,MAAI,oBAAqB,QAAO,EAAE;AAClC,MAAI,MAAM,QAAQ,gBAAgB,CAAE,QAAO;AAC3C,MAAI,CAAC,mBAAmB,CAAC,eAAe,MAAM,CAAE,QAAO,EAAE;AACzD,SAAO,gBAAgB,mBAAmB,eAAe,CAAC,MAAM,GAAG,gBAAgB;IAClF;EAAC;EAAqB;EAAiB;EAAiB;EAAe,CAAC;CAE3E,MAAM,iBAAiB,mBAAmB,oBAAoB,SAAS;AAEvE,4BAAgB;EACd,IAAI,SAAS;EACb,MAAM,sBAAsB,MAAkB;AAC5C,OAAI,UAAU,aAAa,WAAW,CAAC,aAAa,QAAQ,SAAS,EAAE,OAAe,CACpF,oBAAmB,MAAM;;AAG7B,WAAS,iBAAiB,aAAa,mBAAmB;AAC1D,eAAa;AACX,YAAS;AACT,YAAS,oBAAoB,aAAa,mBAAmB;;IAE9D,EAAE,CAAC;CAEN,MAAM,kDACH,MAA2B;AAC1B,MAAI,CAAC,eAAgB;AAErB,MAAI,EAAE,QAAQ,aAAa;AACzB,KAAE,gBAAgB;AAClB,wBAAqB,SAAU,OAAO,oBAAoB,SAAS,IAAI,OAAO,IAAI,EAAG;aAC5E,EAAE,QAAQ,WAAW;AAC9B,KAAE,gBAAgB;AAClB,wBAAqB,SAAU,OAAO,IAAI,OAAO,IAAI,oBAAoB,SAAS,EAAG;;IAGzF,CAAC,gBAAgB,oBAAoB,OAAO,CAC7C;AAED,QACE,4CAAC;EACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;aAE5F,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACN,OAAO,EACL,WAAW,UAAU;AAEnB,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GACrD,QAAO,YAAY,WAAW,2BAA2B;IAK3D,MAAM,2BAA2BC,mCAAc,OAAO,WAAW;AACjE,QAAI,6BAA6B,KAC/B,QAAO;AAIT,QAAI,cAAc,OAAO,UAAU,UACjC;SAAI,CAAC,WAAW,eAAe,MAAM,CACnC,QAAO;;AAKX,WAAO;MAEV;GACD,UAAU;GACV,SAAS,EAAE,YAAY,EAAE,OAAO,aAAa,YAAY;IACvD,MAAM,WAAW,CAAC,CAAC;IACnB,MAAM,kBAAkB,YAAY;IACpC,MAAM,oBAAoBC,+CAA0B,OAAO,UAAU;IAKrE,MAAM,sBACJ,YAAY,WACZ,OAAO,WAAW,YAAY,YAC9B,aAAa,WAAW,UACnB,WAAW,QAAQ,UACpB;IAGN,MAAM,qBAAqB,MAAiD;KAC1E,MAAM,QAAQ,EAAE,OAAO;AACvB,WAAM,SAAS,MAAM;AACrB,qBAAgB,UAAU;AAC1B,mBAAc,MAAM;AACpB,wBAAmB,MAAM,SAAS,EAAE;AACpC,yBAAoB,GAAG;;IAGzB,MAAM,mBAAmB,eAAwC;AAC/D,WAAM,SAAS,WAAW,MAAM;AAChC,0BAAqB,WAAW;AAChC,qBAAgB,UAAU,WAAW;AACrC,mBAAc,WAAW,MAAM;AAC/B,wBAAmB,MAAM;AACzB,yBAAoB,GAAG;;IAGzB,MAAM,iBAAiB,MAAmD;AACxE,SAAI,kBAAkB,EAAE,QAAQ,WAAW,oBAAoB,GAAG;AAChE,QAAE,gBAAgB;AAClB,sBAAgB,oBAAoB,kBAAkB;AACtD;;AAGF,SAAI,EAAE,QAAQ,UAAU;AACtB,UAAI,gBAAgB;AAClB,0BAAmB,MAAM;AACzB;;AAEF,sBAAgB,MAAM,UAAU,MAAM,MAAM,CAAC,EAAE;;;IAKnD,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,eAAe,CAAC,CAAC;KAClB,CAAC;AAEF,WACE;KACE,4CAAC;MAAI,KAAK;MAAc,WAAU;MAAW,WAAW;iBACtD,2CAAC;OACC,GAAI;OACA;OACJ,aAAa,eAAe;OAC5B,WAAW;OACX,UAAU;OACV,WAAW;OACX,aAAU;OACV,OAAO,MAAM,SAAS;OACtB,GAAI;OACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;OAC7E,iBAAe;OACf,qBAAmB,sBAAsB,SAAY;OACrD,iBAAe,iBAAiB,GAAG,GAAG,gBAAgB;OACtD,yBACE,kBAAkB,oBAAoB,IAClC,GAAG,GAAG,cAAc,qBACpB;OAEN,UAAU;QACV,EAED,kBACC,2CAAC;OACC,IAAI,GAAG,GAAG;OACV,0CACE,kFACA,yBACD;OACD,MAAK;iBAEJ,oBAAoB,KAAK,GAAG,MAC3B,4CAAC;QAEC,IAAI,GAAG,GAAG,cAAc;QACxB,MAAK;QACL,MAAK;QACL,iBAAe,MAAM;QACrB,0CACE,oDACA,wBACA,MAAM,oBAAoB,iBAC3B;QACD,cAAc,MAAM;AAClB,WAAE,gBAAgB;AAClB,yBAAgB,EAAE;;QAEpB,oBAAoB,oBAAoB,EAAE;mBAE1C,2CAAC;SAAK,WAAU;mBAAe,EAAE;UAAa,EAC9C,2CAAC;SAAK,WAAU;mBACb,EAAE;UACE;UAnBF,GAAG,EAAE,MAAM,GAAG,EAAE,eAAe,IAoB7B,CACT;QACE;OAEJ;KAGL,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACC;MACQ;MACP,IAAI;MACJ,SAAS,kBAAkB,OAAO,WAAW,sBAAsB;OACnE;QACD;;IAGP;GACE;;AAKV,aAAa,cAAc;;;;;;;;;;;;;;;;;;;;;;;AC9R3B,SAAgB,cAA8D,EAC5E,IACA,OACA,aACA,YACA,SACA,MACA,QAAQ,QACR,YACA,OAAO,GACP,WACA,kBACA,YACuD;CACvD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;AAE5B,QACE,4CAAC;EACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;aAE5F,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACN,OAAO,EACL,WAAW,UAAU;AAEnB,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GACrD,QAAO,YAAY,WAAW,2BAA2B;AAI3D,QAAI,oBAAoB,OAAO;KAC7B,MAAMC,eAAa,iBAAiB,MAAM;AAC1C,SAAIA,iBAAe,QAAQ,OAAOA,iBAAe,SAC/C,QAAOA;;AAKX,QAAI,aAAa,OAAO,UAAU,YAAY,MAAM,SAAS,UAC3D,QAAO,qBAAqB,UAAU;AAGxC,WAAO;MAEV;GACD,UAAU;GACV,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,kBAAkB;IACvD,MAAM,WAAW,CAAC,CAAC;IACnB,MAAM,kBAAkB,YAAY;IACpC,MAAM,oBAAoBC,+CAA0B,OAAO,UAAU;IAGrE,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,eAAe,CAAC,CAAC;KAClB,CAAC;AAEF,WACE;KACE,2CAAC;MACC,GAAI;MACA;MACS;MACP;MACK;MACX,WAAW;MACX,OAAO,MAAM,SAAS;MACtB,UAAU;MACV,GAAI;MACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;MAC7E,WAAW,iBAAiB,UAAU;AACpC,WAAI,OAAO,MAAM,aAAa,WAC5B,OAAM,SAAS,MAAM;SAEtB,MAAM,MAAM;OACf;KAGD,aAAa,OAAO,MAAM,UAAU,YACnC,4CAAC;MAAI,WAAU;;OACZ,MAAM,MAAM;OAAO;OAAE;;OAClB;KAIP,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACC;MACQ;MACP,IAAI;MACJ,SAAS,kBAAkB,OAAO,UAAU;OAC5C;QACD;;IAGP;GACE;;AAKV,cAAc,cAAc;;;;;AC3I5B,MAAa,oCAA4D;CACvE,kBAAkB;CAClB,sBAAsB;CACtB,iBAAiB;CACjB,mBAAmB;CACnB,cAAc;CACd,kBAAkB,UAAU,OAAO,MAAM,UAAU,UAAU,IAAI,KAAK;CACtE,eAAe;CACf,cAAc,eAAe,KAAK,WAAW;CAC7C,kBAAkB,aAAa,cAAc,SAAS;CACtD,iBAAiB,UAAU,GAAG,MAAM,UAAU,UAAU,IAAI,KAAK,KAAK;CACtE,gBAAgB,UAAU,kBAAkB,QAAQ;CACpD,oBAAoB,UAAU,GAAG,MAAM;CACvC,iBAAiB,UAAU,GAAG,MAAM;CACpC,uBAAuB,UAAU,GAAG,MAAM;CAC1C,0BAA0B,UAAU,GAAG,MAAM;CAC7C,kBAAkB;CAClB,YAAY,UAAU,SAAS,MAAM,UAAU,UAAU,IAAI,KAAK;CAClE,qBAAqB,UAAU,GAAG,MAAM,iBAAiB,UAAU,IAAI,KAAK;CAC5E,oBAAoB,UAAU,GAAG,MAAM;CACvC,wBAAwB,UAAU,GAAG,MAAM,YAAY,UAAU,IAAI,KAAK,IAAI;CAC/E;;AAGD,SAAgB,8BACd,WACwB;AACxB,QAAO;EAAE,GAAG;EAAmC,GAAG;EAAW;;;AAI/D,SAAgB,+BACd,gBACA,QACe;AACf,KAAI,CAAC,eAAgB,QAAO;CAE5B,MAAM,UACJ,eAAe,QAAQ,SACvB,eAAe,cAAc,SAC7B,eAAe,kBAAkB;AACnC,KAAI,eAAe,SAAS,WAAW,KAAK,YAAY,EAAG,QAAO;CAElE,MAAM,QAAkB,EAAE;AAC1B,KAAI,eAAe,SAAS,SAAS,EACnC,OAAM,KAAK,OAAO,kBAAkB,eAAe,SAAS,OAAO,CAAC;AAEtE,KAAI,eAAe,QAAQ,SAAS,EAClC,OAAM,KAAK,OAAO,eAAe,eAAe,QAAQ,OAAO,CAAC;AAElE,KAAI,eAAe,cAAc,SAAS,EACxC,OAAM,KAAK,OAAO,qBAAqB,eAAe,cAAc,OAAO,CAAC;AAE9E,KAAI,eAAe,kBAAkB,SAAS,EAC5C,OAAM,KAAK,OAAO,wBAAwB,eAAe,kBAAkB,OAAO,CAAC;AAErF,QAAO,MAAM,KAAK,MAAM;;;AAI1B,SAAgB,yBACd,gBACA,YACA,QACe;AACf,KAAI,eAAe,KAAK,eAAe,SAAS,WAAW,GAAG;AAK5D,MAHE,eAAe,QAAQ,SACvB,eAAe,cAAc,SAC7B,eAAe,kBAAkB,WACnB,EAAG,QAAO;AAC1B,SAAO,OAAO;;CAGhB,MAAM,QAAkB,EAAE;AAC1B,KAAI,aAAa,EACf,OAAM,KAAK,OAAO,UAAU,WAAW,CAAC;AAE1C,KAAI,eAAe,QAAQ,SAAS,EAClC,OAAM,KAAK,OAAO,mBAAmB,eAAe,QAAQ,OAAO,CAAC;AAEtE,KAAI,eAAe,cAAc,SAAS,EACxC,OAAM,KAAK,OAAO,kBAAkB,eAAe,cAAc,OAAO,CAAC;AAE3E,KAAI,eAAe,kBAAkB,SAAS,EAC5C,OAAM,KAAK,OAAO,sBAAsB,eAAe,kBAAkB,OAAO,CAAC;AAGnF,KAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,QAAO,MAAM,KAAK,KAAK,GAAG;;;;;;ACtF5B,SAAgB,qBAAqB,EACnC,SACA,OACA,OACA,aACA,YACA,YACA,UACA,WAAW,OACX,oBAAoB,GACpB,QACA,cAC4B;CAC5B,MAAM,UAAU,YAAY,QAAQ,MAAM,UAAU;CACpD,MAAM,gBAAgB,YAAY;CAClC,MAAM,CAAC,UAAU,mCAAuC,KAAK;CAE7D,MAAM,EAAE,SAAS,OAAO,uCAA4C;EAClE,eAAe,EAAE,OAAO,IAAI;EAC5B,MAAM;EACP,CAAC;CAEF,MAAM,WAAW,MAAM,QAAQ;CAC/B,MAAM,0CAA+B;AACnC,MAAI,CAAC,SAAS,MAAM,CAAE,QAAO;AAC7B,sHAC6B,SAAS,EACpC,OACA,YACA,SACD;IACA;EAAC;EAAU;EAAO;EAAY;EAAS,CAAC;CAE3C,MAAM,0CACE,+BAA+B,gBAAgB,OAAO,EAC5D,CAAC,gBAAgB,OAAO,CACzB;CAED,MAAM,gBAAgB,SAAS,MAAM,GAAI,kBAAkB,SAAc,YAAY;CAErF,MAAM,yCAA8B;AAClC,MAAI,CAAC,kBAAkB,eAAe,SAAS,WAAW,KAAK,QAAS;AACxE,QAAM,eAAe,SAAS;AAC9B,QAAM,EAAE,OAAO,IAAI,CAAC;AACpB,cAAY,yBAAyB,gBAAgB,eAAe,SAAS,QAAQ,OAAO,CAAC;IAC5F;EAAC;EAAgB;EAAS;EAAO;EAAO;EAAO,CAAC;CAEnD,MAAM,gBAAgB,gBAAgB,SAAS,UAAU;CACzD,MAAM,iBACJ,gBAAgB,IAAI,OAAO,gBAAgB,cAAc,GAAG,OAAO;AAErE,QACE,4CAAC;EAAI,WAAU;;GACb,4CAAC;IAAI,WAAU;eACb,2CAACC,qBAAK,WAAU,iDAAiD,EACjE,2CAAC;KAAE,WAAU;eAAiD;MAAe;KACzE;GAEN,4CAAC,oBACC,2CAAC;IAAI,WAAU;cACb,2CAAC;KACC,IAAI,qBAAqB;KACzB,MAAK;KACL,OAAM;KACO;KACb,YAAY;KACH;KACT,MAAM;KACN,YAAY,EAAE,UAAU,OAAO;KAC/B,UAAU;MACV;KACE,EACL,aAAa,2CAAC;IAAI,WAAU;cAAyB;KAAiB,GAAG,QACtE;GAEN,4CAAC;IAAI,WAAU;eACb,4CAAC;KAAI,WAAU;gBACZ,kBAAkB,eAAe,QAAQ,SAAS,IACjD,4CAAC;MAAE,WAAU;;OACV,OAAO;OAAc;OAAE,eAAe,QAAQ,MAAM,GAAG,kBAAkB,CAAC,KAAK,KAAK;OACpF,eAAe,QAAQ,SAAS,oBAC7B,IAAI,OAAO,YAAY,eAAe,QAAQ,SAAS,kBAAkB,KACzE;;OACF,GACF,MACH,WAAW,YAAY,OACtB,2CAAC;MAAE,WAAU;gBAAiC,OAAO,gBAAgB,SAAS;OAAK,GACjF;MACA,EACN,4CAAC;KACC,MAAK;KACL,MAAK;KACL,WAAU;KACV,UAAU,iBAAiB,kBAAkB;KAC7C,eAAe,WAAW;gBAE1B,2CAACC,qBAAK,WAAU,gBAAgB,EAC/B;MACM;KACL;;GACF;;;;;;ACxHV,SAAgB,mBAAmB,EACjC,OACA,gBACA,WAAW,OACX,QACA,YAC0B;AAC1B,KAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,QACE,4CAAC;EAAI,WAAU;aACb,2CAAC;GAAE,WAAU;aAAiC,OAAO,eAAe,MAAM,OAAO;IAAK,EACtF,2CAAC;GAAI,WAAU;aACZ,MAAM,KAAK,SAAS,UACnB,4CAAC;IAEC,WAAU;eAEV,2CAAC;KACU;KACT,SAAQ;KACR;KACA;KACA,aAAa,iBAAiB,QAAQ,IAAI;MAC1C,EACF,2CAAC;KACC,MAAK;KACL,SAAQ;KACR,MAAK;KACL,WAAU;KACV,eAAe,SAAS,MAAM;KACpB;KACV,cAAY,OAAO,cAAc,MAAM;eAEvC,2CAACC,kBAAE,WAAU,aAAa;MACnB;MApBJ,GAAG,QAAQ,GAAG,QAqBf,CACN;IACE;GACF;;;;;;AC1BV,SAAgB,uBAAuB,EACrC,SACA,OACA,OACA,aACA,YACA,UACA,WAAW,OACX,QACA,cAC8B;CAC9B,MAAM,UAAU,YAAY,QAAQ,MAAM,UAAU;CACpD,MAAM,gBAAgB,YAAY;CAElC,MAAM,EAAE,SAAS,OAAO,WAAW,8CAAqD;EACtF,eAAe,EAAE,OAAO,IAAI;EAC5B,MAAM;EACP,CAAC;CAGF,MAAM,8CADiB;EAAE;EAAS,MAAM;EAAS,CAAC,IACnB,IAAI,MAAM;CAEzC,MAAM,2CAAgC;AACpC,MAAI,CAAC,aAAc,QAAO;GAAE,QAAQ;GAAO,aAAa;GAAO;AAC/D,MAAI,MAAM,SAAS,aAAa,CAAE,QAAO;GAAE,QAAQ;GAAO,aAAa;GAAO;AAC9E,MAAI,QAAS,QAAO;GAAE,QAAQ;GAAO,aAAa;GAAO;AACzD,MAAI,cAAc,CAAC,WAAW,eAAe,aAAa,CACxD,QAAO;GAAE,QAAQ;GAAO,aAAa;GAAM;AAE7C,SAAO;GAAE,QAAQ;GAAM,aAAa;GAAO;IAC1C;EAAC;EAAc;EAAO;EAAS;EAAW,CAAC;CAE9C,MAAM,yCAA8B;AAClC,MAAI,CAAC,gBAAgB,OAAQ;AAC7B,QAAM,UAAU,QAAQ,CAAC,MAAM,CAAC;AAChC,QAAM,EAAE,OAAO,IAAI,CAAC;IACnB;EAAC,gBAAgB;EAAQ;EAAO;EAAW;EAAM,CAAC;AAErD,QACE,4CAAC;EAAI,WAAU;aACb,4CAAC;GAAI,WAAU;cACb,4CAAC;IAAI,WAAU;eACb,2CAAC;KACC,IAAI,uBAAuB;KAC3B,MAAK;KACL,OAAM;KACO;KACb,YAAY,gBAAgB,cAAc,OAAO,uBAAuB;KAC/D;KACG;KACZ,YAAY,EAAE,UAAU,OAAO;KAC/B,UAAU;MACV,EACD,aAAa,2CAAC;KAAI,WAAU;eAAgC;MAAiB,GAAG;KAC7E,EACN,4CAAC;IACC,MAAK;IACL,WAAU;IACV,UAAU,iBAAiB,CAAC,gBAAgB;IAC5C,SAAS,aAAa,UAAU;eAEhC,2CAACC,qBAAK,WAAU,gBAAgB,EAC/B,OAAO;KACD;IACL,EAEL,WAAW,YAAY,QACtB,2CAAC;GAAE,WAAU;aAAiC,OAAO,gBAAgB,SAAS;IAAK;GAEjF;;;;;;;;ACpCV,SAAgB,iBAAiB,EAC/B,OACA,UACA,aACA,iBACA,YACA,YACA,gBACA,OACA,YACA,UACA,WAAW,OACX,oBAAoB,GACpB,WACA,mBAAmB,UACnB,kBAAkB,MAClB,QAAQ,kBACgB;CACxB,MAAM,4BAAiB;CACvB,MAAM,kCAAuB,8BAA8B,eAAe,EAAE,CAAC,eAAe,CAAC;CAC7F,MAAM,CAAC,WAAW,oCAA+C,iBAAiB;CAClF,MAAM,0BAA0B,mBAAmB;CAEnD,MAAM,uCACH,UAAkB;AACjB,WAAS,MAAM,QAAQ,GAAG,iBAAiB,iBAAiB,MAAM,CAAC;IAErE,CAAC,UAAU,MAAM,CAClB;CAED,MAAM,0CACH,YAAoB;AACnB,WAAS,CAAC,GAAG,OAAO,QAAQ,CAAC;IAE/B,CAAC,UAAU,MAAM,CAClB;CAED,MAAM,wCACH,cAAwB;AACvB,WAAS,CAAC,GAAG,OAAO,GAAG,UAAU,CAAC;IAEpC,CAAC,UAAU,MAAM,CAClB;CAED,MAAM,4CAAiC,aAAa,OAAO,EAAE,EAAE,CAAC;CAChE,MAAM,8CAAmC,aAAa,SAAS,EAAE,EAAE,CAAC;CAEpE,MAAM,kBACJ;CACF,MAAM,aAAa,CAAC,kBAAkB,SAAY,cAAc,WAC9D,4CAAC;EAAO,MAAK;EAAS,SAAS;EAAc,WAAW;aACtD,2CAACC,+BAAe,WAAU,WAAW,EACpC,OAAO;GACD,GAET,4CAAC;EAAO,MAAK;EAAS,SAAS;EAAgB,WAAW;aACxD,2CAACC,2BAAW,WAAU,WAAW,EAChC,OAAO;GACD;AAGX,QACE,4CAAC;EAAI,0CAAc,aAAa,UAAU;;GACvC,QAAQ,2CAAC;IAAM,WAAU;cAAoC;KAAc,GAAG;GAC9E,cAAc,cAAc,WAC3B,2CAAC;IAAE,WAAU;cAAiD;KAAe,GAC3E;GAEH,cAAc,WACb,2CAAC;IACU;IACF;IACP,OAAO;IACM;IACD;IACF;IACA;IACF;IACI;KACZ,GAEF,2CAAC;IACU;IACF;IACP,OAAO;IACP,aAAa;IACD;IACA;IACF;IACA;IACS;IACX;IACI;KACZ;GAGJ,2CAAC;IACQ;IACS;IACN;IACF;IACR,UAAU;KACV;;GACE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC9GV,SAAgB,0BAA0B,EACxC,UACA,sBACqD;CACrD,MAAM,QAAQC,MAAM,eACX,EAAE,oBAAoB,GAC7B,CAAC,mBAAmB,CACrB;AAED,QACE,2CAAC,yBAAyB;EAAgB;EAAQ;GAA6C;;;;;;;;;;;;;;;;;;;;;;;;;;;AC5BnG,SAAgB,sBACd,OACA,WAC6B;CAC7B,MAAM,WAAWC,MAAM,WAAW,yBAAyB;AAO3D,QAAO,EAAE,aALWA,MAAM,cAAc;AACtC,MAAI,CAAC,YAAY,CAAC,MAAM,MAAM,CAAE,QAAO,EAAE;AACzC,SAAO,SAAS,mBAAmB,OAAO,UAAU;IACnD;EAAC;EAAU;EAAO;EAAU,CAAC,EAEV;;;;;;;;;;;;;;;;;;;;;;;;AC2BxB,SAAgB,YAA4D,EAC1E,IACA,OACA,aACA,YACA,SACA,MACA,QAAQ,QACR,YACA,KACA,KACA,OAAO,KACP,WAAW,GACX,SAAS,IACT,iBAAiB,UACjB,kBACqD;CACrD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAG5B,MAAM,kBAAkB,UAAmC;AACzD,MAAI,UAAU,MAAM,UAAU,UAAa,UAAU,KAAM,QAAO;EAElE,MAAM,WAAW,OAAO,UAAU,WAAW,WAAW,MAAM,GAAG;AACjE,MAAI,MAAM,SAAS,CAAE,QAAO;AAE5B,SAAO,SAAS,QAAQ,SAAS;;CAInC,MAAM,eAAe,UAA0B;EAC7C,MAAM,SAAS,WAAW,MAAM;AAChC,SAAO,MAAM,OAAO,GAAG,IAAI;;AAG7B,QACE,4CAAC;EACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;aAE5F,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACN,OAAO,EACL,WAAW,UAAU;IAEnB,MAAM,WAAW,OAAO,UAAU,WAAW,WAAW,MAAM,GAAG;AAGjE,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,MAAM,MAAM,SAAS,CAC1E,QAAO,YAAY,WAAW,2BAA2B;AAI3D,QAAI,QAAQ,UAAa,WAAW,IAClC,QAAO,0BAA0B;AAGnC,QAAI,QAAQ,UAAa,WAAW,IAClC,QAAO,yBAAyB;AAIlC,QAAI,kBAAkB,CAAC,MAAM,SAAS,EAAE;KACtC,MAAMC,eAAa,eAAe,SAAS;AAC3C,SAAIA,iBAAe,QAAQ,OAAOA,iBAAe,SAC/C,QAAOA;;AAIX,WAAO;MAEV;GACD,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,kBAAkB;IACvD,MAAM,WAAW,CAAC,CAAC,OAAO;IAC1B,MAAM,kBAAkB,YAAY;IACpC,MAAM,oBAAoBC,+CAA0B,OAAO,UAAU;IAGrE,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,eAAe,CAAC,CAAC;KAClB,CAAC;IAGF,MAAM,eAAe,MAAM,UAAU,UAAa,MAAM,UAAU,OAAO,MAAM,QAAQ;AAEvF,WACE;KACE,4CAAC;MAAI,WAAU;;OACZ,UAAU,mBAAmB,YAC5B,2CAAC;QAAK,WAAU;kBACb;SACI;OAGT,2CAAC;QACC,GAAI;QACA;QACJ,MAAK;QACL,WAAU;QACG;QACb,OAAO;QACP,WAAW,GAAG,kBAAkB,GAC9B,UAAU,mBAAmB,WAAW,SAAS,GAClD,GAAG,UAAU,mBAAmB,WAAW,SAAS;QACrD,aAAU;QACV,GAAI;QACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;QAC7E,WAAW,MAAM;SAEf,MAAM,QAAQ,EAAE,OAAO;AACvB,aAAI,UAAU,MAAM,gBAAgB,KAAK,MAAM,CAC7C,OAAM,SAAS,MAAM;;QAGzB,SAAS,MAAM;AAEb,aAAI,EAAE,OAAO,OAAO;UAClB,MAAM,SAAS,WAAW,EAAE,OAAO,MAAM;AACzC,cAAI,CAAC,MAAM,OAAO,CAChB,OAAM,SAAS,eAAe,OAAO,CAAC;;AAG1C,aAAI,MAAM,OACR,OAAM,QAAQ;;QAGlB,YAAY,MAAM;AAEhB,aAAI,EAAE,QAAQ,UAAU;AACtB,2BAAiB,UAAU;AACzB,iBAAM,SAAS,UAAU,KAAK,OAAO,MAAM;aAC1C,MAAM,MAAM,CAAC,EAAE;AAClB;;AAIF,aAAI,EAAE,QAAQ,aAAa,EAAE,QAAQ,YACnC,oBACG,aAAa;AACZ,gBAAM,SAAS,eAAe,SAAS,CAAC;YAE1C,YAAY,MAAM,SAAS,GAAG,EAC9B,MACA,KACA,IACD,CAAC,EAAE;;SAGR;OAED,UAAU,mBAAmB,YAC5B,2CAAC;QAAK,WAAU;kBACb;SACI;;OAEL;KAGL,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACC;MACQ;MACP,IAAI;MACJ,SAAS,kBAAkB,OAAO,UAAU;OAC5C;QACD;;IAGP;GACE;;AAKV,YAAY,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC5K1B,SAAgB,WAA2D,EACzE,IACA,OACA,YACA,SACA,MACA,QAAQ,QACR,YACA,cAAc,QACd,WAAW,GACX,UACA,oBACA,eACA,YACoD;CACpD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAG5B,MAAM,mDAA8B;CAGpC,MAAM,EAAE,QAAQ,QAAQ,+CAA0B;EAChD,SAAS,WAAW,aAAa;EAE3B;EAGP,CAAC;CAGF,MAAM,gDAA2B;EAAE,SAAS,WAAW,aAAa;EAAS;EAAM,CAAC;CAGpF,MAAM,oBAAoBC,cAAM,cAAyB;AACvD,SAAO,MAAM,QAAQ,gBAAgB,GAAG,kBAAkB,EAAE;IAC3D,CAAC,gBAAgB,CAAC;CAIrB,MAAM,iBAAiBA,cAAM,OAAO,MAAM;AAC1C,eAAM,gBAAgB;AACpB,MAAI,eAAe,QAEjB;AAGF,MAAI,MAAM,QAAQ,kBAAkB,IAAI,OAAO,WAAW,kBAAkB,QAAQ;AAClF,kBAAe,UAAU;AACzB,WAAQ,kBAAsC;AAG9C,wBAAqB;AACnB,mBAAe,UAAU;KACzB;;IAEH;EAAC,OAAO;EAAQ;EAAmB;EAAQ,CAAC;CAK/C,MAAM,oBAAoB,UAAwB;EAMhD,MAAM,gBALqB,MAAM,QAAQ,kBAAkB,GACtD,oBACA,EAAE,EAGiC,QAAQ,GAAG,MAAM,MAAM,MAAM;AAGrE,iBAAe,UAAU;AACzB,UAAQ,aAAiC;AAGzC,uBAAqB;AACnB,kBAAe,UAAU;IACzB;;CAIJ,MAAM,sBAA4B;EAOhC,MAAM,eACJ,oBAAoB,iBAAiB,SACjC,mBAAmB,eACnB,gBAAgB,YAAY,gBAAgB,WAC1C,IACA,gBAAgB,aACd,QACA;AAcV,iBAAe,UAAU;EAEzB,MAAM,qBAAqB,OAAO;EAClC,MAAM,qBAAqB,MAAM,QAAQ,kBAAkB,GACtD,oBACA,EAAE;AAEP,SAAO,aAAyC;AAQhD,QAJG,aAAa,YAAY,KAAK,GAA4B,UAAU,OAAO,WAIhD,oBAAoB;GAIhD,MAAM,eAAe,CAAC,GAHJ,MAAM,QAAQ,mBAAmB,GAC9C,qBACA,EAAE,EAC6B,aAAa;AAEjD,OAAI,aAAa,SACf,aAAY,SAAS,MAAe,cAAuB;IACzD,aAAa;IACb,aAAa;IACd,CAAC;OAGF,SAAQ,aAAiC;;AAK7C,uBAAqB;AACnB,kBAAe,UAAU;IACzB;;CAIJ,MAAM,aAAa,CAAC,YAAY,OAAO,SAAS;CAGhD,MAAM,YAAY,OAAO,SAAS;AAKlC,QACE,2CAACC;EACC,SAAS,WAAW,aAAa;EAC3B;EACN,OAAO,EAGL,WAAW,UAAU;AAEnB,OAAI,YAAY,aAAa,CAAC,MAAM,QAAQ,MAAM,IAAI,MAAM,WAAW,GACrE,QAAO;AAGT,OAAI,YAAY,MAAM,QAAQ,MAAM,IAAI,MAAM,SAAS,SACrD,QAAO,WAAW,SAAS,OAAO,WAAW,IAAI,MAAM,GAAG;AAG5D,OAAI,YAAY,MAAM,QAAQ,MAAM,IAAI,MAAM,SAAS,SACrD,QAAO,WAAW,SAAS,OAAO,WAAW,IAAI,MAAM,GAAG;AAG5D,UAAO;KAEV;EACD,SAAS,EAAE,YAAY,EAAE,cAAc;GACrC,MAAM,WAAW,CAAC,CAAC;GAGnB,MAAM,qBAAqB,sBAAsB;IAC/C;IACA;IACA;IACA,eAAe,CAAC,CAAC;IAClB,CAAC;AAGF,UACE,4CAAC;IACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;IAC7F,GAAI;IACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;;KAG5E,SACC,2CAAC;MAAI,WAAU;gBACb,4CAAC;OAAM,SAAS;;QACb;QAAM;QAAE,cAAc,2CAAC;SAAK,WAAU;mBAAmB;UAAQ;;QAC5D;OACJ;KAIR,2CAAC;MAAI,WAAU;gBACZ,OAAO,WAAW,IACjB,2CAAC;OAAI,WAAU;iBAAiF;QAE1F,GAEN,OAAO,KAAK,OAAO,UAAU;OAG3B,MAAM,eAA8B;QAClC,GAAG;QACH,IAAI,MAAM;QACV,MAAM,GAAG,KAAK,GAAG;QACjB,OAAO,oBAAoB,SAAS;QACpC,MAAM,oBAAoB,QAAQ;QAClC,YAAY,oBAAoB,cAAc,EAAE;QAChD,aAAa,oBAAoB;QACjC,YAAY,oBAAoB;QAChC,OAAO;QACP,UAAU,oBAAoB,YAAY;QAC3C;AAED,cACE,4CAAC;QAAmB,WAAU;;SAC5B,2CAAC;UAAI,WAAU;oBAIb,2CAACC,6BAAa,WAAU,iCAAiC;WACrD;SACN,2CAAC;UAAI,WAAU;oBACZ,gBACC,cAAc,cAAc,MAAM,GAIlC,4CAAC;WAAI,WAAU;;YAAgC;YAC1B;YAAY;;YAC3B;WAEJ;SACL,CAAC,YAAY,aACZ,2CAAC;UACC,MAAK;UACL,SAAQ;UACR,MAAK;UACL,eAAe,iBAAiB,MAAM;UACtC,WAAU;UACV,cAAY,eAAe,QAAQ;oBAEnC,2CAACC,kBAAE,WAAU,WAAW;WACjB;;UA5BH,MAAM,GA8BV;QAER;OAEA;KAGL,CAAC,YAAY,cACZ,4CAAC;MACC,MAAK;MACL,SAAQ;MACR,MAAK;MACL,SAAS;MACT,WAAU;iBAGV,2CAACC,qBAAK,WAAU,WAAW;OAEpB;KAIV,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACC;MAAoB;MAAO,IAAI;OAAW;;KACvC;;GAGV;;AAKN,WAAW,cAAc;;;;;;;;;;;;;;;;;AChTzB,SAAgB,iBAAiE,EAC/E,IACA,OACA,YACA,SACA,MACA,QAAQ,QACR,YACA,aAAa,EAAE,EACf,WAAW,GACX,UACA,gBACA,cAAc,MACd,mBAAmB,OACnB,UACA,aACA,kBAC0D;CAC1D,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAG5B,MAAM,mDAA8B;CACpC,MAAM,mBAAmB,WAAW,YAAY;CAGhD,MAAM,EAAE,QAAQ,QAAQ,8CAAyB;EAC/C,SAAS;EAEH;EAEP,CAAC;CAGF,MAAM,CAAC,gBAAgB,qBAAqBC,cAAM,eAAwC;EAKxF,MAAM,UAAmC,EAAE;AAC3C,SAAO,SAAS,UAAU;AACxB,WAAQ,MAAM,MAAM;IACpB;AACF,SAAO;GACP;CAGF,MAAM,sBAA4B;EAEhC,MAAM,gBAAyC,EAAE;AACjD,aAAW,SAAS,cAAc;AAMhC,OAAI,UAAU,KAAK,SAAS,OAAO,CACjC,eAAc,UAAU,QAAQ;YACvB,UAAU,KAAK,SAAS,MAAM,IAAI,UAAU,KAAK,SAAS,OAAO,CAC1E,eAAc,UAAU,QAAQ;YACvB,UAAU,KAAK,SAAS,KAAK,CAEtC,eAAc,UAAU,QAAQ,EAAE;YACzB,UAAU,KAAK,WAAW,QAAQ,CAE3C,eAAc,UAAU,QAAQ,EAAE;OAGlC,eAAc,UAAU,QAAQ;IAElC;AAMF,SAAO,cAAqB;;CAI9B,MAAM,mBAAmB,YAA0B;AACjD,qBAAmB,UAAU;GAC3B,GAAG;IACF,UAAU,CAAC,KAAK;GAClB,EAAE;;CAIL,MAAM,aAAa,CAAC,YAAY,OAAO,SAAS;CAGhD,MAAM,YAAY,OAAO,SAAS;AAKlC,QACE,2CAACC;EACC,SAAS;EACH;EACN,OAAO,EAEL,WAAW,UAAU;AACnB,OAAI,YAAY,aAAa,CAAC,SAAS,CAAC,MAAM,QAAQ,MAAM,IAAI,MAAM,WAAW,GAC/E,QAAO;AAET,OAAI,YAAY,MAAM,QAAQ,MAAM,IAAI,MAAM,SAAS,SACrD,QAAO,WAAW,SAAS,OAAO,WAAW,IAAI,MAAM,GAAG;AAE5D,OAAI,YAAY,MAAM,QAAQ,MAAM,IAAI,MAAM,SAAS,SACrD,QAAO,WAAW,SAAS,OAAO,WAAW,IAAI,MAAM,GAAG;AAE5D,UAAO;KAEV;EACD,SAAS,EAAE,YAAY,EAAE,cAAc;GACrC,MAAM,WAAW,CAAC,CAAC;GACnB,MAAM,qBAAqB,sBAAsB;IAC/C;IACA;IACA;IACA,eAAe,CAAC,CAAC;IAClB,CAAC;AAGF,UACE,4CAAC;IACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;IAC7F,GAAI;IACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;;KAE5E,SACC,2CAAC;MAAI,WAAU;gBACb,4CAAC;OAAM,SAAS;;QACb;QAAM;QAAE,cAAc,2CAAC;SAAK,WAAU;mBAAmB;UAAQ;;QAC5D;OACJ;KAGR,2CAAC;MAAI,WAAU;gBACZ,OAAO,WAAW,IACjB,2CAAC;OAAI,WAAU;iBAAiF;QAE1F,GAEN,OAAO,KAAK,OAAO,UAAU;OAC3B,MAAM,cAAc,eAAe,MAAM,OAAO;AAEhD,cACE,4CAAC;QAAoB,WAAU;mBAC7B,4CAAC;SAAI,WAAU;oBACb,4CAAC;UAAI,WAAU;;WAEb,2CAACC,6BAAa,WAAU,iCAAiC;WACxD,eACC,2CAAC;YACC,MAAK;YACL,SAAQ;YACR,MAAK;YACL,eAAe,gBAAgB,MAAM,GAAG;YACxC,WAAU;YACV,cAAY,cAAc,gBAAgB;sBAGzC,cACC,2CAACC,6BAAa,WAAU,YAAY,GAEpC,2CAACC,4BAAY,WAAU,YAAY;aAE9B;WAEV,eACC,2CAAC;YAAI,WAAU;sBACb,2CAAC;aACO;aACC;aACK;aACZ,SAAS;cACT;aACE;;WAEJ,EACL,CAAC,YAAY,aACZ,2CAAC;UACC,MAAK;UACL,SAAQ;UACR,MAAK;UACL,eAAe,OAAO,MAAM;UAC5B,cAAY,eAAe,QAAQ;oBAEnC,2CAACC,kBAAE,WAAU,YAAY;WAClB;UAEP,EAEL,CAAC,eACA,2CAAC;SAAI,WAAU;mBAEJ,WAAW,KAAK,cAAc;AAEnC,cAAI,CAAC,YACH,OAAM,IAAI,MACR,yGAAyG,UAAU,KAAK,GACzH;UAGH,MAAM,iBAAiB,YAAY,qBACjC,WACA,eACD;UAGD,MAAM,gBAA+B;WACnC,GAAG;WACH,IAAI,GAAG,GAAG,GAAG,MAAM,GAAG,UAAU;WAChC,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU;WACpC,OAAO,UAAU,eAAe,UAAU;WAC1C,YAAY;YACV,GAAG,eAAe;YAClB,UAAU,YAAY;YACvB;WACD,aAAa,SAAS,UAAU,eAAe,UAAU;WACzD,YACE,UAAU,gBACT,eAAe,SAAS,WAAW,iBAAiB;WACvD,OAAO;WACP;WAEA,GAAI,UAAU,cAAc,EAC1B,YAAY,UAAU,YACvB;WAEF;AAED,iBACE,2CAAC,mBACE,iBACC,eAAe,eAAe,OAAO,UAAU,KAAK,GAEpD,4CAAC;WAAI,WAAU;;YAAgC;YAC5B,UAAU;YAAK;;YAE5B,IAPA,UAAU,KASd;WAER;UAEA;UAnGC,MAAM,GAqGV;QAET;OAEA;KAGL,CAAC,YAAY,cACZ,4CAAC;MACC,MAAK;MACL,SAAQ;MACR,MAAK;MACL,SAAS;MACT,WAAU;iBAGV,2CAACC,qBAAK,WAAU,YAAY;OAErB;KAGV,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAER,2CAACC;MAAoB;MAAO,IAAI;OAAW;;KACvC;;GAGV;;;;;;;;AAUN,SAAS,iBAAiB,EACxB,MACA,OACA,YACA,WAMqB;CAIrB,MAAM,2CAAsB;EAC1B;EACA,MAAM,GAAG,KAAK,GAAG;EAClB,CAAC;CAEF,MAAM,eAAe,WAClB,MAAM,GAAG,EAAE,CACX,KAAK,cAAc;EAClB,MAAM,aAAa,aAAa,UAAU;EAC1C,MAAM,eACJ,eAAe,UAAa,eAAe,MAAM,eAAe,KAAK,eAAe,QAChF,OAAO,WAAW,CAAC,SAAS,KAC1B,GAAG,OAAO,WAAW,CAAC,UAAU,GAAG,GAAG,CAAC,OACvC,OAAO,WAAW,GACpB;AAEN,SAAO,eACL,4CAAC;GAA0B,WAAU;cACnC,4CAAC;IAAK,WAAU;eAAe,UAAU,eAAe,UAAU,MAAK;KAAQ,EAC/E,2CAAC;IAAK,WAAU;cAAmB;KAAoB;KAF9C,UAAU,KAGd,GACL;GACJ,CACD,OAAO,QAAQ;AAQlB,MALE,CAAC,cACD,OAAO,OAAO,WAAW,CAAC,OACvB,UAAU,UAAU,UAAa,UAAU,MAAM,UAAU,KAAK,UAAU,MAC5E,KAEY,aAAa,WAAW,EAErC,QAAO,2CAAC;EAAK,WAAU;YAAS;GAAiB;AAGnD,QACE,qFACG,aAAa,SAAS,IACrB,eAEA,2CAAC;EAAK,WAAU;YAAS;GAA6C,EAOvE,WAAW,SAAS,KACnB,aAAa,SAAS,WAAW,UAC/B,4CAAC;EAAK,WAAU;;GAAU;GAAE,WAAW,SAAS,aAAa;GAAO;;GAAY,IAEnF;;AAKP,iBAAiB,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;ACtW/B,SAAgB,UAA0D,EACxE,IACA,OACA,YACA,SACA,MACA,QAAQ,QACR,eAOe;AACf,QACE,2CAAC;EACU;EACH;EACN,SAAS,EAAE,YACT,4CAAC;GAAS,WAAW,gBAAgB,MAAM;;IACzC,2CAAC;KAAU,SAAS;eAAK;MAAkB;IAC3C,2CAAC,yBAAa,YAAY,OAAO,EAAE,IAAI,CAAC,GAAe;IACtD,cAAc,2CAAC;KAAgB,IAAI,GAAG,GAAG;eAAgB;MAA6B;IACvF,2CAAC,eAAY,IAAI,GAAG,GAAG,UAAW;;IACzB;GAEb;;AAKN,UAAU,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;AC1ExB,SAAgB,YAA4D,EAC1E,IACA,OACA,aACA,YACA,SACA,MACA,QAAQ,QACR,YACA,gBACA,YACqD;CACrD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAI5B,MAAM,qBAAqB;EACzB,GAAG;EACH,SAAS,YAAY,WAAWC;EACjC;CAGD,MAAM,uBAAuB,UAAiC;EAE5D,MAAM,qBAAqBC,mCAAc,OAAO,mBAAmB;AACnE,MAAI,uBAAuB,KAAM,QAAO;AAGxC,MAAI,gBAAgB;GAClB,MAAM,mBAAmB,eAAe,MAAM;AAC9C,OAAI,qBAAqB,QAAQ,OAAO,qBAAqB,SAC3D,QAAO;;AAIX,SAAO;;AAGT,QACE,4CAAC;EACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;aAE5F,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACN,OAAO,EACL,WAAW,UAAU;AAEnB,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GACrD,QAAO,YAAY,WAAW,2BAA2B;AAI3D,QAAI,UAAU,IACZ,QAAO;AAIT,QAAI,OAAO,UAAU,SACnB,QAAO,oBAAoB,MAAM;AAInC,QAAI,OAAO,UAAU,SACnB,QAAO,oBAAoB,MAAM,UAAU,CAAC;AAG9C,WAAO;MAEV;GACD,UAAU;GACV,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,kBAAkB;IACvD,MAAM,WAAW,CAAC,CAAC;IACnB,MAAM,kBAAkB,YAAY;IACpC,MAAM,oBAAoBC,+CAA0B,OAAO,UAAU;IAGrE,MAAM,qBAAqB,MAAiD;KAC1E,MAAM,WAAW,EAAE,OAAO;AAG1B,SAAI,aAAa,IAAI;AACnB,YAAM,SAAS,GAAG;AAClB;;AAIF,SAAI,aAAa,KAAK;AACpB,YAAM,SAAS,SAAS;AACxB;;AAKF,SAAIC,2CAAsB,KAAK,SAAS,CACtC,OAAM,SAAS,SAAS;;IAM5B,MAAM,iBAAiB,MAAmD;KAExE,MAAM,cAAc;MAClB;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACD;AAGD,UACG,EAAE,WAAW,EAAE,YAChB;MAAC;MAAK;MAAK;MAAK;MAAK;MAAI,CAAC,SAAS,EAAE,IAAI,aAAa,CAAC,CAEvD;AAGF,SAAI,CAAC,YAAY,SAAS,EAAE,IAAI,IAAI,CAAC,EAAE,WAAW,CAAC,EAAE,QACnD,GAAE,gBAAgB;AAIpB,SAAI,EAAE,QAAQ,UAAU;AACtB,sBAAgB,MAAM,UAAU,MAAM,MAAM,CAAC,EAAE;AAC/C;;;IAKJ,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,eAAe,CAAC,CAAC;KAClB,CAAC;AAEF,WACE;KACE,2CAAC;MACC,GAAI;MACJ,OAAO,MAAM,SAAS;MAClB;MACJ,aAAa,eAAe;MAC5B,MAAK;MACL,WAAW;MACX,WAAW;MACX,aAAU;MACV,UAAU;MACV,WAAU;MACV,SAASC;MACT,GAAI;MACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;MAC7E,UAAU;OACV;KAGD,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACC;MACQ;MACP,IAAI;MACJ,SAAS,kBAAkB,OAAO,UAAU;OAC5C;QACD;;IAGP;GACE;;AAKV,YAAY,cAAc;;;;;;;;;;;;;;;;;;;;;;AChN1B,SAAgB,aAA6D,EAC3E,IACA,OACA,YACA,SACA,MACA,QAAQ,QACR,YACA,iBACA,YACsD;CACtD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAG5B,MAAM,wBAAwB,UAAkC;EAE9D,MAAM,qBAAqBC,mCAAc,OAAO,WAAW;AAC3D,MAAI,uBAAuB,KAAM,QAAO;AAGxC,MAAI,iBAAiB;GACnB,MAAM,mBAAmB,gBAAgB,MAAM;AAC/C,OAAI,qBAAqB,QAAQ,OAAO,qBAAqB,SAC3D,QAAO;;AAIX,SAAO;;AAGT,QACE,2CAAC;EACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;YAE7F,2CAACC;GACU;GACH;GACN,cAAc;GACd,OAAO,EACL,WAAW,UAAU;AAEnB,QAAI,UAAU,UAAa,UAAU,KACnC,QAAO,YAAY,WAAW,2BAA2B;AAI3D,QAAI,OAAO,UAAU,UAInB,QAAO,qBAAqB,MAAM;AAGpC,WAAO;MAEV;GACD,UAAU;GACV,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,kBAAkB;IACvD,MAAM,WAAW,CAAC,CAAC;IACnB,MAAM,oBAAoBC,+CAA0B,OAAO,UAAU;IAGrE,MAAM,uBAAuB,YAA6C;KACxE,MAAM,QAAQ,YAAY;AAC1B,WAAM,SAAS,MAAM;AAGrB,SAAI,cAAc,CAAC,MACjB,kBAAiB,MAAM,QAAQ,EAAE,EAAE;;IAKvC,MAAM,iBAAiB,MAAoD;AACzE,sBAAiB,MAAM,UAAU,CAAC,CAAC,MAAM,MAAM,CAAC,EAAE;AAGlD,SAAI,EAAE,QAAQ,OAAO,EAAE,QAAQ,SAC7B;UAAI,WACF,kBAAiB,MAAM,QAAQ,EAAE,EAAE;;;IAMzC,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,YAAY;KACZ,eAAe,CAAC,CAAC;KAClB,CAAC;AAEF,WACE;KACE,4CAAC;MAAI,WAAU;iBACb,2CAAC;OACC,GAAI;OACA;OACJ,SAAS,CAAC,CAAC,MAAM;OACjB,iBAAiB;OACjB,WAAW;OACX,WAAW;OACX,UAAU;OACV,GAAI;OACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;QAC7E,EACF,4CAAC;OAAM,SAAS;;QACb;QAAM;QAAE,cAAc,2CAAC;SAAK,WAAU;mBAAmB;UAAQ;;QAC5D;OACJ;KAEL,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAGR,2CAACC;MAAoB;MAAO,IAAI;MAAS,WAAU;OAAS;QAC3D;;IAGP;GACE;;AAIV,aAAa,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;ACjG3B,SAAgB,WAA2D,EACzE,IACA,OACA,YACA,SACA,MACA,QAAQ,QACR,YACA,cAAc,qCACd,OAAO,GACP,UACA,YACA,kBAAkB,QAClB,aAAa,OACb,iBAAiB,MACjB,YACoD;CACpD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;;;;CAK5B,MAAM,sBAAsB,UAAoC;AAC9D,yDAA2B,OAAO;GAChC;GACA;GACA;GACA;GACD,CAAC;;;;;CAMJ,MAAM,eAAe,UAA0B;AAC7C,MAAI,CAAC,SAAS,CAAC,WAAY,QAAO;EAElC,MAAM,aAAa,MAAM,MAAM,CAAC,QAAQ,QAAQ,GAAG;EACnD,MAAM,gBAAgB,WAAW,WAAW,KAAK,GAAG,WAAW,MAAM,EAAE,GAAG;AAG1E,MAAI,iBAAiB,iBAAiB,KAAK,cAAc,IAAI,cAAc,SAAS,MAAM,EACxF,QAAO,WAAW,WAAW,KAAK,GAAG,aAAa,KAAK;AAGzD,SAAO;;AAGT,QACE,4CAAC;EACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;aAE5F,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACN,UAAU;GACV,OAAO,EACL,WAAW,UAAU;AAEnB,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GACrD,QAAO,YAAY,WAAW,2BAA2B;AAI3D,WAAO,mBAAmB,MAAM;MAEnC;GACD,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,kBAAkB;IACvD,MAAM,WAAW,CAAC,CAAC;IACnB,MAAM,kBAAkB,aAAa,aAAa,YAAY;IAC9D,MAAM,oBAAoBC,+CAA0B,OAAO,UAAU;IAGrE,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,YAAY;KACZ,eAAe,CAAC,CAAC;KAClB,CAAC;AAEF,WACE;KACE,2CAAC;MACK;MACJ,MAAM,MAAM;MACZ,KAAK,MAAM;MACE;MACP;MACN,WAAW;MACX,UAAU;MACV,OAAO,MAAM,SAAS;MACtB,WAAW,MAAM;AAEf,aAAM,SAAS,EAAE,OAAO,MAAM;;MAEhC,SAAS,MAAM;OAEb,MAAM,YAAY,YAAY,EAAE,OAAO,MAAM;AAC7C,aAAM,SAAS,UAAU;AAEzB,aAAM,QAAQ;;MAEhB,WAAW,gBAAgB,MAAM,UAAU,MAAM,MAAM;MACvD,GAAI;MACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU,KAAK,MAAM;OACxF;KAGD,cACC,4CAAC;MAAI,IAAI;MAAe,WAAU;iBAC/B,YACD,4CAAC;OAAI,WAAU;;QACZ,oBAAoB,SAAS;QAC7B,oBAAoB,YAAY;QAChC,oBAAoB,UACnB;QACD,cAAc,cAAc,WAAW,UAAU,aAAa,EAAE;QAChE,CAAC,cAAc,YAAY,UAAU,SAAS;;QAC3C;OACF;KAIR,2CAACC;MACQ;MACP,IAAI;MACJ,SAAS,kBAAkB,OAAO,UAAU;OAC5C;QACD;;IAGP;GACE;;AAKV,WAAW,cAAc;;;;;;;;;;;;;;;;;;;;;;AC7KzB,SAAgB,cAA8D,EAC5E,IACA,OACA,aACA,YACA,SACA,MACA,QAAQ,QACR,YACA,UACA,gBAAgB,QACuC;;;;;;CAMvD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAG5B,MAAM,qBAAqB,UAAiC;EAC1D,MAAM,mBAAmBC,mCAAc,OAAO,WAAW;AACzD,SAAO,qBAAqB,OAAO,OAAQ;;AAG7C,QACE,4CAAC;EACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;aAE5F,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACN,OAAO,EACL,WAAW,UAAU;AACnB,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GACrD,QAAO,YAAY,WAAW,2BAA2B;AAE3D,QAAI,OAAO,UAAU,SACnB,QAAO,kBAAkB,MAAM;AAEjC,WAAO;MAEV;GACD,UAAU;GACV,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,kBAAkB;IACvD,MAAM,WAAW,CAAC,CAAC;IACnB,MAAM,kBAAkB,YAAY;IACpC,MAAM,oBAAoBC,+CAA0B,OAAO,UAAU;IAErE,MAAM,gBAAgB,MAAiD;KACrE,MAAM,MAAM,EAAE,OAAO;AACrB,SAAI,CAAC,KAAK;AACR,YAAM,SAAS,GAAG;AAClB;;KAIF,MAAM,CAAC,UAAU,YAAY,IAAI,MAAM,IAAI;KAC3C,MAAM,CAAC,MAAM,OAAO,OAAO,SAAS,MAAM,IAAI,CAAC,KAAK,MAAM,OAAO,EAAE,CAAC;KACpE,MAAM,CAAC,OAAO,WAAW,SAAS,MAAM,IAAI,CAAC,KAAK,MAAM,OAAO,EAAE,CAAC;KAClE,MAAM,YAAY,IAAI,KAAK,MAAM,QAAQ,GAAG,KAAK,OAAO,SAAS,GAAG,EAAE;KAEtE,MAAM,OAAO,MAAsB,OAAO,EAAE,CAAC,SAAS,GAAG,IAAI;KAC7D,MAAM,aAAa,GAAG,UAAU,aAAa,CAAC,GAAG,IAAI,UAAU,UAAU,GAAG,EAAE,CAAC,GAAG,IAAI,UAAU,SAAS,CAAC,CAAC,GAAG,IAAI,UAAU,UAAU,CAAC,CAAC,GAAG,IAAI,UAAU,YAAY,CAAC;AACtK,WAAM,SAAS,WAAW;;IAG5B,MAAM,iBAAiB,MAAmD;AACxE,SAAI,EAAE,QAAQ,SACZ,KAAI,cACF,iBAAgB,MAAM,UAAiC,MAAM,MAAM,CAAC,EAAE;SAEtE,CAAC,EAAE,OAAuB,MAAM;;IAKtC,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,eAAe,CAAC,CAAC;KACjB,YAAY,CAAC,CAAC;KACf,CAAC;IAEF,MAAM,uBAAuB,QAAyB;AACpD,SAAI,CAAC,IAAK,QAAO;AACjB,SAAI;MACF,MAAM,IAAI,IAAI,KAAK,IAAc;AACjC,UAAI,MAAM,EAAE,SAAS,CAAC,CAAE,QAAO;MAC/B,MAAM,OAAO,MAAsB,OAAO,EAAE,CAAC,SAAS,GAAG,IAAI;AAO7D,aAAO,GANM,EAAE,aAAa,CAMb,GALD,IAAI,EAAE,UAAU,GAAG,EAAE,CAKX,GAJZ,IAAI,EAAE,SAAS,CAAC,CAIG,GAHjB,IAAI,EAAE,UAAU,CAAC,CAGS,GAFxB,IAAI,EAAE,YAAY,CAAC;aAG7B;AACN,aAAO;;;IAIX,MAAM,aAAqB,oBAAoB,MAAM,MAAM;AAE3D,WACE;KACE,2CAAC;MACC,GAAI;MACA;MACS;MACb,WAAW;MACX,UAAU;MACV,WAAW;MACX,aAAU;MACV,OAAO;MACP,MAAK;MACL,GAAI;MACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;MAC7E,UAAU;OACV;KAED,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAGR,2CAACC;MACQ;MACP,IAAI;MACJ,SAAS,kBAAkB,OAAO,UAAU;OAC5C;QACD;;IAGP;GACE;;AAIV,cAAc,cAAc;;;;;;;;;;;;;;;AC9G5B,SAAgB,UAA0D,EACxE,IACA,OACA,cAAc,kBACd,YACA,SACA,MACA,QAAQ,QACR,YACA,cACA,cACA,oBACA,YACmD;CACnD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAG5B,MAAM,aAAa,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;AAG9E,KAAI,CAAC,gBAAgB,aAAa,SAAS,WAAW,EACpD,QACE,4CAAC;EAAI,0CAAc,uBAAuB,WAAW;aAClD,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACN,UAAU;GACV,OAAO,EACL,WAAW,UAAU;IAEnB,MAAM,qBAAqBC,mCAAc,OAAO,WAAW;AAC3D,QAAI,uBAAuB,KACzB,QAAO;AAIT,QAAI,OAAO,UAAU,SACnB,KAAI;AAGF,SAAI,CAFW,KAAK,MAAM,MAAM,CAEpB,IACV,QAAO;YAEH;AACN,YAAO;;AAKX,QAAI,OAAO,UAAU,YAAY,UAAU,MACzC;SAAI,EAAE,SAAS,OACb,QAAO;;AAIX,WAAO;MAEV;GACD,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,kBAAkB;IACvD,MAAM,WAAW,CAAC,CAAC;IACnB,MAAM,oBAAoBC,+CAA0B,OAAO,UAAU;IAGrE,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,eAAe,CAAC,CAAC;KAClB,CAAC;AAEF,WACE;KACE,4CAAC;MAAI,WAAU;iBACb,4CAAC;OAAI,WAAU;kBACb,2CAAC;QAAE,WAAU;kBAAgC;SAEzC,EACJ,4CAAC;QAAE,WAAU;;SAAqC;SACtC;SAAgB;SAAK;;SAC7B;QACA,EAEN,2CAAC;OACK;OACJ,GAAI;OACJ,0CAAc,gBAAgB,kBAAkB;OAChD,aAAa;OACb,OACE,OAAO,MAAM,UAAU,WACnB,MAAM,QACN,KAAK,UAAU,MAAM,SAAS,EAAE,CAAC;OAEvC,WAAW,MAAM;AACf,YAAI;SAEF,MAAM,SAAS,KAAK,MAAM,EAAE,OAAO,MAAM;AACzC,eAAM,SAAS,OAAO;gBAChB;AAEN,eAAM,SAAS,EAAE,OAAO,MAAM;;;OAGlC,QAAQ,MAAM;OACd,MAAM,MAAM;OACZ,UAAU;QACV;OACE;KAEL,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAGR,2CAACC;MAAoB;MAAO,IAAI;OAAW;QAC1C;;IAGP;GACE;AAIV,QACE,4CAAC;EAAI,0CAAc,uBAAuB,WAAW;aAClD,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACH;GACU;GACH;GACN,UAAU;GACV,OAAO,EACL,WAAW,UAAU;IAEnB,MAAM,qBAAqBC,mCAAc,OAAO,WAAW;AAC3D,QAAI,uBAAuB,KACzB,QAAO;AAIT,QAAI,CAAC,SAAS,CAAC,MAAM,IACnB,QAAO,YAAY,WAAW,2BAA2B;AAI3D,QAAI,gBAAgB,OAAO;KACzB,MAAM,mBAAmB,aAAa,MAAM;AAC5C,SAAI,qBAAqB,QAAQ,OAAO,qBAAqB,SAC3D,QAAO;;AAIX,WAAO;MAEV;GACD,SAAS,EAAE,OAAO,YAAY,EAAE,cAAc;IAC5C,MAAM,WAAW,CAAC,CAAC;IACnB,MAAM,eAA+B,MAAM,SAAS,EAAE,KAAK,IAAI;IAG/D,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,eAAe,CAAC,CAAC;KAClB,CAAC;IAGF,MAAM,uBAAuB,gBAA8B;KACzD,MAAMG,oBAAkB,aAAa,SAAS,MAAM,MAAM,EAAE,SAAS,YAAY;AACjF,SAAI,CAACA,kBAAiB;AAEtB,SAAIA,kBAAgB,SAAS,UAAUA,kBAAgB,SAAS,UAE9D,OAAM,SAAS,EAAE,KAAK,aAAa,CAAC;UAC/B;MAEL,MAAM,gBAAgB,IAAI,MAAMA,kBAAgB,cAAc,UAAU,EAAE,CAAC,KAAK,GAAG;AAEnF,YAAM,SAAS;OACb,KAAK;OACL,QAAQ;OACT,CAAC;;;IAKN,MAAM,uBAAuB,OAAe,UAAwB;KAClE,MAAM,YAAY,CAAC,GAAI,aAAa,UAAU,EAAE,CAAE;AAElD,eAAU,SAAS;KACnB,MAAM,eAAe;MAAE,GAAG;MAAc,QAAQ;MAAW;AAC3D,WAAM,SAAS,aAAa;;IAG9B,MAAM,kBAAkB,aAAa,SAAS,MAAM,MAAM,EAAE,SAAS,aAAa,IAAI;AAEtF,WACE;KAEE,4CAAC;MACC,OAAO,aAAa;MACpB,eAAe;MACf,UAAU;iBAEV,2CAAC;OAAkB;OAAI,GAAI;iBACzB,2CAAC,eAAyB,cAAe;QAC3B,EAChB,2CAAC,2BACE,aAAa,SAAS,KAAK,YAC1B,4CAAC;OAA8B,OAAO,QAAQ;;QAC3C,QAAQ;QACR,QAAQ,SAAS,aAAa,QAAQ,UAAU,UAC/C,4CAAC;SAAK,WAAU;;UAA6B;UAAE,QAAQ;UAAM;;UAAQ;QAEtE,QAAQ,SAAS,WAAW,QAAQ,gBACnC,4CAAC;SAAK,WAAU;;UAA6B;UACzC,QAAQ,aAAa,KAAK,KAAK;UAAC;;UAC7B;;SARM,QAAQ,KAUZ,CACb,GACY;OACT;KAGR,mBACC,gBAAgB,SAAS,WACzB,gBAAgB,gBACd,4CAAC;MAAI,WAAU;iBACb,4CAAC;OAAE,WAAU;;QAAgC;QACzB,gBAAgB;QAAK;;QACrC,EACH,gBAAgB,aAAa,KAAK,aAAa,UAAU;OAExD,MAAM,eAA8B;QAClC,IAAI,GAAG,GAAG,WAAW;QACrB,MAAM,GAAG,KAAK,UAAU;QACxB,OAAO;QACP,MAAM;QACN,YAAY,EAAE;QACd,aAAa,SAAS,YAAY;QAClC,YAAY;QACZ,OAAO;QACP,uBAAuB;QACb;QACV,GAAI,gBAAgB,oBAAoB,UAAU,EAChD,YAAY,gBAAgB,kBAAkB,QAC/C;QACF;AAED,cACE,2CAAC;QAAgB,WAAU;kBACxB,qBACC,mBAAmB,cAAc,MAAM,GAGvC,4CAAC;SAAI,WAAU;oBACb,2CAAC;UAAM,SAAS,GAAG,GAAG,WAAW;UAAS,WAAU;oBACjD;WACK,EACR,2CAAC;UACC,IAAI,GAAG,GAAG,WAAW;UACrB,MAAK;UACL,aAAa,SAAS,YAAY;UAClC,OAAQ,aAAa,SAAS,UAAqB;UACnD,WAAW,MAAM,oBAAoB,OAAO,EAAE,OAAO,MAAM;UAC3D,UAAU;WACV;UACE;UAjBA,MAmBJ;QAER;OACE;KAIT,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACD;MAAoB;MAAO,IAAI;OAAW;QAC1C;;IAGP;GACE;;AAKV,UAAU,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;ACxVxB,SAAS,eAAe,OAAuB;AAC7C,KAAI,UAAU,EAAG,QAAO;CACxB,MAAM,IAAI;CACV,MAAM,QAAQ;EAAC;EAAS;EAAM;EAAM;EAAK;CACzC,MAAM,IAAI,KAAK,MAAM,KAAK,IAAI,MAAM,GAAG,KAAK,IAAI,EAAE,CAAC;AACnD,QAAO,GAAG,YAAY,QAAQ,KAAK,IAAI,GAAG,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,GAAG,MAAM;;;AAIrE,SAAgB,gBAAgE,EAC9E,IACA,OACA,cAAc,0CACd,YACA,SACA,MACA,QAAQ,QACR,YACA,UACA,QACA,SACA,kBAAkB,SACuC;CACzD,MAAM,iCAAwC,KAAK;CACnD,MAAM,CAAC,UAAU,mCAAgC,GAAG;CACpD,MAAM,CAAC,UAAU,mCAAgC,EAAE;CACnD,MAAM,CAAC,cAAc,uCAA4B,MAAM;CACvD,MAAM,CAAC,YAAY,qCAA0B,MAAM;CACnD,MAAM,CAAC,cAAc,uCAA0D,OAAO;CAEtF,MAAM,sBAAsB,SAAgC;AAC1D,SAAO,IAAI,SAAS,SAAS,WAAW;GACtC,MAAM,SAAS,IAAI,YAAY;AAC/B,UAAO,eAAqB;AAC1B,QAAI,OAAO,OAAO,WAAW,UAAU;KAErC,MAAM,QAAQ,OAAO,OAAO,MAAM,IAAI;AACtC,SAAI,MAAM,WAAW,GAAG;AACtB,6BAAO,IAAI,MAAM,0BAA0B,CAAC;AAC5C;;KAEF,MAAM,SAAS,MAAM;AACrB,aAAQ,OAAO;UAEf,wBAAO,IAAI,MAAM,mCAAmC,CAAC;;AAGzD,UAAO,gBAAsB;AAC3B,WAAO,OAAO,MAAM;;AAEtB,UAAO,cAAc,KAAK;IAC1B;;CAGJ,MAAM,mBAAmB,OACvB,MACA,aACkB;AAClB,MAAI,CAAC,MAAM;AACT,eAAY,GAAG;AACf,eAAY,EAAE;AACd,mBAAgB,OAAO;AACvB,YAAS,GAAG;AACZ;;AAIF,MAAI,WAAW,KAAK,OAAO,SAAS;GAClC,MAAM,aAAa,WAAW,OAAO,OAAO,QAAQ,EAAE;AACtD,YAAS,GAAG;AACZ,eAAY,GAAG;AACf,eAAY,EAAE;AACd,mBAAgB,QAAQ;AAExB,SAAM,IAAI,MAAM,qBAAqB,UAAU,WAAW;;AAG5D,cAAY,KAAK,KAAK;AACtB,cAAY,KAAK,KAAK;AACtB,kBAAgB,OAAO;AAIvB,WAAS,KAAK;AAKd,MAAI,CAAC,iBAAiB;AACpB,mBAAgB,UAAU;AAC1B;;AAGF,kBAAgB,KAAK;AAErB,MAAI;AAEF,YADe,MAAM,mBAAmB,KAAK,CAC7B;AAChB,mBAAgB,UAAU;UACpB;AACN,YAAS,GAAG;AACZ,eAAY,GAAG;AACf,eAAY,EAAE;AACd,mBAAgB,QAAQ;YAChB;AACR,mBAAgB,MAAM;;;CAI1B,MAAM,kBAAkB,MAA6C;AACnE,IAAE,gBAAgB;AAClB,IAAE,iBAAiB;AACnB,MAAI,CAAC,YAAY,CAAC,aAChB,eAAc,KAAK;;CAIvB,MAAM,mBAAmB,MAA6C;AACpE,IAAE,gBAAgB;AAClB,IAAE,iBAAiB;AACnB,gBAAc,MAAM;;CAGtB,MAAM,cACJ,GACA,aACS;AACT,IAAE,gBAAgB;AAClB,IAAE,iBAAiB;AACnB,gBAAc,MAAM;AAEpB,MAAI,YAAY,aAAc;EAE9B,MAAM,OAAO,EAAE,aAAa,QAAQ,MAAM;AAC1C,MAAI,KACF,kBAAiB,MAAM,SAAS;;CAIpC,MAAM,aAAa,aAAmD;AACpE,MAAI,aAAa,QACf,cAAa,QAAQ,QAAQ;AAE/B,cAAY,GAAG;AACf,cAAY,EAAE;AACd,kBAAgB,OAAO;AACvB,WAAS,GAAG;;AAGd,QACE,2CAACE;EACU;EACH;EACN,OAAO,EACL,WAAW,UAAU;AACnB,OAAI,CAAC,MAAO,QAAOC,mCAAc,OAAO,WAAW;AAGnD,OACE,WACA,SACA,OAAO,UAAU,YACjB,UAAU,SACV,MAAM,OAAO,QAGb,QAAO,gCADY,WAAW,OAAO,OAAO,QAAQ,EAAE,CACN;AAGlD,UAAOA,mCAAc,OAAO,WAAW;KAE1C;EACD,UAAU;EACV,SAAS,EAAE,OAAO,EAAE,UAAU,UAAU,YAAY,EAAE,cAAc;GAClE,MAAM,UAAU,GAAG,GAAG;GACtB,MAAM,UAAU,GAAG,QAAQ;GAC3B,MAAM,WAAW,CAAC,CAAC;GACnB,MAAM,aAAa,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;GAG9E,MAAM,mBAAmB,EAAE;AAC3B,OAAI,QAAQ;IACV,MAAM,QAAQ,OACX,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,KAAK,KAAK;AACb,qBAAiB,KAAK,mBAAmB,QAAQ;;AAEnD,OAAI,QACF,kBAAiB,KAAK,aAAa,eAAe,QAAQ,GAAG;GAE/D,MAAM,iBAAiB,cAAc,iBAAiB,KAAK,MAAM;AAEjE,UACE,4CAAC;IAAI,WAAW,uBAAuB;;KACrC,4CAAC;MAAM,SAAS;iBACb,OACA,YAAY,YAAY,2CAAC;OAAK,WAAU;iBAAoB;QAAQ;OAC/D;KAGR,2CAAC;MACC,KAAK;MACL,IAAI;MACJ,MAAK;MACG;MACR,UAAU,YAAY;MACd;MACR,WAAW,MAAM;AAEf,wBADa,EAAE,OAAO,QAAQ,MAAM,MACb,SAAS;;MAElC,WAAU;MACV,GAAI,sBAAsB;OACxB,IAAI;OACJ;OACA,YAAY,YAAY;OACxB,YAAY,YAAY;OACzB,CAAC;OACF;KAGF,2CAAC;MACC,YAAY;MACZ,aAAa;MACb,SAAS,MAAM,WAAW,GAAG,SAAS;MACtC,eAAe;AACb,WAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,SACjC,cAAa,SAAS,OAAO;;MAGjC,WAAW;;kBAGP,aACI,kCACA,WACE,wCACA,WACE,8BACA,yEACT;kBACC,YAAY,eAAe,kCAAkC,WAAW,mBAAmB,iBAAiB;;;gBAI/G,CAAC,WAEA,4CAAC;OAAI,WAAU;kBACb,2CAAC;QACC,WAAW,sCACT,aAAa,mBAAmB;kBAGlC,2CAACC,uBACC,WAAW,6BACT,aAAa,kBAAkB,4BAEjC;SACE,EACN,4CAAC;QAAI,WAAU;mBACb,2CAAC;SAAE,WAAU;mBACV,aAAa,mBAAmB;UAC/B,EACH,kBAAkB,CAAC,cAClB,2CAAC;SAAE,WAAU;mBAAiC;UAAmB;SAE/D;QACF,GAGN,4CAAC;OAAI,WAAU;kBACb,2CAAC;QACC,WAAW,kBACT,iBAAiB,YACb,kBACA,iBAAiB,UACf,sBACA;kBAGR,2CAACC,qBACC,WAAW,WACT,iBAAiB,YACb,iBACA,iBAAiB,UACf,qBACA,4BAER;SACE,EACN,4CAAC;QAAI,WAAU;mBACb,4CAAC;SAAI,WAAU;oBACb,4CAAC;UAAI,WAAU;qBACb,2CAAC;WAAE,WAAU;qBAAgC;YAAa,EAC1D,4CAAC;WAAE,WAAU;sBACV,eAAe,SAAS,EACxB,gBAAgB;YACf;WACA,EACN,4CAAC;UAAI,WAAU;;WACZ,iBAAiB,aAAa,CAAC,gBAC9B,2CAACC,6BAAa,WAAU,yBAAyB;WAElD,iBAAiB,WAChB,2CAACC,4BAAY,WAAU,6BAA6B;WAErD,CAAC,YAAY,CAAC,gBACb,2CAAC;YACC,MAAK;YACL,SAAQ;YACR,MAAK;YACL,UAAU,MAAM;AACd,eAAE,iBAAiB;AACnB,uBAAU,SAAS;;YAErB,WAAU;sBAEV,2CAACC,kBAAE,WAAU,YAAY;aAClB;;WAEP;UACF,EACL,CAAC,gBACA,2CAAC;SACC,MAAK;SACL,SAAQ;SACR,MAAK;SACL,UAAU;SACV,UAAU,MAAM;AACd,YAAE,iBAAiB;AACnB,uBAAa,SAAS,OAAO;;SAE/B,WAAU;mBACX;UAEQ;SAEP;QACF;OAEJ;KAEN,2CAACC;MAAoB;MAAO,IAAI;OAAW;;KACvC;;GAGV;;;;;;;;ACvXN,SAAS,kBAAkB,WAAmB,UAA2B;AACvE,KAAI,CAAC,SACH,QAAO;AAET,QAAO,GAAG,UAAU,IAAI,SAAS;;;;;AAMnC,SAAS,mBAAmB,aAG1B;AACA,QAAO;EACL,KAAK,aAAa,gBAAgB,0DACP,YAAY,eAAe,KAAK,GACvD;EACJ,OAAO,aAAa,kBAAkB,0DACX,YAAY,iBAAiB,KAAK,GACzD;EACL;;;;;;;;;;;;;;;;;;;;;;;AA2DH,SAAgB,SAAyD,EACvE,IACA,OACA,YACA,SACA,MACA,QAAQ,QACR,YACA,aACA,WAAW,GACX,gBACA,kBACA,YACkD;CAClD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAG5B,MAAM,mDAA8B;CACpC,MAAM,mBAAmB,WAAW,YAAY;CAGhD,MAAM,EAAE,QAAQ,QAAQ,QAAQ,+CAA0B;EACxD,SAAS;EAEH;EACP,CAAC;CAGF,MAAM,6CAAwB;EAC5B,SAAS;EAEH;EACP,CAAC;CACF,MAAM,kBAAkBC,cAAM,cAAc,KAAK,UAAU,aAAa,EAAE,CAAC,aAAa,CAAC;CAGzF,MAAM,iBAAiB,gBAAgB,cAAc,OAAO,QAAQ,QAAQ;AAQ5E,eAAM,gBAAgB;AACpB,MAAI,CAAC,YAAa;AAClB,MAAI,eAAe,QAAS;EAE5B,MAAM,WAAW,MAAM,QAAQ,aAAa,GACvC,eACD,EAAE;EAEN,IAAI,gBAAgB;AACpB,OAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;GACxC,MAAM,UAAU,GAAG,KAAK,GAAG,EAAE;GAC7B,MAAM,YAAY,GAAG,KAAK,GAAG,EAAE;GAC/B,MAAM,WAAY,YAAY,UAAU,OACtC,UACC;GACH,MAAM,aAAc,YAAY,UAAU,OACxC,YACC;AACH,OAAI,YAAY,YAAY;AAC1B,oBAAgB;AAChB;;;EAIJ,MAAM,aAAa,qBAAqB;GACtC,OAAO;GACP,UAAU,CAAC,CAAC,YAAY;GACxB;GACD,CAAC;EAEF,IAAI;AACJ,MAAI,iBAAiB,YAAY,SAC/B,eAAc;WACL,eAAe,KACxB,eAAc;EAGhB,MAAM,iBAAmB,YAAY,UAAU,OAC7C,OACC,WAAW;AAEd,MAAI,eAAe,gBAAgB,eAEjC,aAAY,SAAS,MAAa;GAAE,MAAM;GAAU,SAAS;GAAa,CAAC;WAClE,CAAC,eAAe,eAEzB,aAAY,YAAY,KAAY;IAErC;EACD;EACA;EACA;EACA;EACA,YAAY;EACZ;EACA;EACD,CAAC;CAEF,MAAM,sBAAsB,uBAAuB,aAAa;AAEhE,QACE,4CAAC;EACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;aAE5F,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACC,SAAS;GACH;GACN,UAAU;GACV,OAAO,EACL,WAAW,UACT,qBAAqB;IAAE;IAAO,UAAU,CAAC,CAAC,YAAY;IAAU;IAAU,CAAC,EAC9E;GACD,SAAS,EAAE,YAAY,EAAE,OAAO,kBAAkB;IAGhD,MAAM,kBAAkB,oBAAoB,aAAa,MAAM,aAAa;IAC5E,MAAM,qBAAqB,aAAa;IACxC,MAAM,WAAW,CAAC,CAAC,OAAO;IAK1B,MAAM,kBAAkB,aAAa,sBAAsB;IAG3D,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,eAAe,CAAC,CAAC;KAClB,CAAC;IAGF,MAAM,uBAA6B;AAEjC,oBAAe,UAAU;AACzB,YAAO,mBAAmB,YAAY,CAA6B;AAGnE,0BAAqB;AACnB,qBAAe,UAAU;OACzB;;IAIJ,MAAM,qBAAqB,UAAwB;AACjD,SAAI,OAAO,SAAS,UAAU;AAE5B,qBAAe,UAAU;AACzB,aAAO,MAAM;AAGb,2BAAqB;AACnB,sBAAe,UAAU;QACzB;;;AAIN,WACE;KACE,4CAAC;MACC,WAAU;MACV,GAAI;MACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU,KAAK,MAAM;iBAEvF,OAAO,WAAW,IACjB,2CAAC;OAAI,WAAU;iBAA8F;QAEvG,GAEN,OAAO,KAAK,OAAO,UAAU;OAE3B,MAAM,iBAAiB,oBAAoB,IAAI,MAAM;AAmCrD,cACE,4CAAC;QAEC,WAAU;mBAEV,2CAAC;SACC,UAvC0B;UAC9B,GAAG,aAAa;UAChB,IAAI,GAAG,GAAG,OAAO;UACjB,MAAM,GAAG,KAAK,GAAG,MAAM;UACvB,OAAO,kBACL,OACA,aAAa,gBAAgB,yBAAyB,aAAa,QACpE;UACD,MAAM,aAAa,gBAAgB,QAAQ;UAC3C,YAAY;WAAE,UAAU;WAAM,GAAG,aAAa,gBAAgB;WAAY;UAC1E,aAAa,aAAa,gBAAgB,eAAe;UACzD,OAAO;UACG;UACV,uBAAuB,aAAa,gBAAgB;UACrD;SA0BK,YAxB4B;UAChC,GAAG,aAAa;UAChB,IAAI,GAAG,GAAG,SAAS;UACnB,MAAM,GAAG,KAAK,GAAG,MAAM;UACvB,OAAO,kBACL,SACA,aAAa,kBAAkB,yBAC7B,aAAa,UAChB;UACD,MAAM,aAAa,kBAAkB,QAAQ;UAC7C,YAAY;WAAE,UAAU;WAAM,GAAG,aAAa,kBAAkB;WAAY;UAC5E,aAAa,aAAa,kBAAkB,eAAe;UAC3D,OAAO;UACG;UACV,uBAAuB,aAAa,kBAAkB;UACvD;SAUqB;SACA;SACE;SACX;UACP,EAED,CAAC,YAAY,OAAO,SAAS,YAC5B,2CAAC;SACC,MAAK;SACL,SAAQ;SACR,MAAK;SACL,eAAe,kBAAkB,MAAM;SACvC,WAAU;SACV,cAAY,eAAe,QAAQ;mBAEnC,2CAACC,kBAAE,WAAU,WAAW;UACjB;UAtBN,MAAM,GAwBP;QAER,EAIH,CAAC,YACA,4CAAC;OACC,MAAK;OACL,SAAQ;OACR,MAAK;OACL,WAAU;OACV,SAAS;kBAET,2CAACC,qBAAK,WAAU,iBAAiB;QAE1B;OAEP;KAGL,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACC;MACC,SAAS,kBAAkB,OAAO,UAAU;MACrC;MACP,IAAI;OACJ;QACD;;IAGP;GACE;;AAKV,SAAS,cAAc;;;;;ACvXvB,SAAgB,YAAY,EAC1B,UACA,YACA,gBACA,gBACA,kBACA,SAC4B;AAC5B,QACE,4CAAC;EAAI,WAAU;aACb,2CAAC;GAAI,WAAU;aACZ,iBACC,qFACG,eAAe,UAAU,MAAM,EAC/B,kBACC,2CAAC;IAAI,WAAU;IAAgC,MAAK;cAAQ;KAEtD,IAEP,GAEH,4CAAC;IAAI,WAAU;;KAA+E;KACrE,SAAS;KAAK;;KACjC;IAEJ,EAEN,2CAAC;GAAI,WAAU;aACZ,mBACC,iBAAiB,YAAY,MAAM,GAEnC,4CAAC;IAAI,WAAU;;KAA+E;KACnE,WAAW;KAAK;;KACrC;IAEJ;GACF;;;;;;AC/CV,SAAgB,oBACd,aACA,MACA,cACS;CACT,MAAM,WAAW,MAAM,QAAQ,aAAa,GACvC,eACD,EAAE;AACN,KAAI,CAAC,eAAe,SAAS,WAAW,EAAG,QAAO;AAElD,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;EACxC,MAAM,UAAU,GAAG,KAAK,GAAG,EAAE;EAC7B,MAAM,YAAY,GAAG,KAAK,GAAG,EAAE;EAC/B,MAAM,WAAW,YAAY,cAAc,SAAS,YAAY,UAAU;EAC1E,MAAM,aAAa,YAAY,cAAc,WAAW,YAAY,UAAU;AAC9E,MAAI,SAAS,aAAa,WAAW,UAAW,QAAO;;AAEzD,QAAO;;;;;;ACjBT,SAAgB,uBAAuB,cAAoC;AACzE,QAAOC,cAAM,cAAc;EACzB,MAAM,6BAAa,IAAI,KAAa;AACpC,MAAI,CAAC,MAAM,QAAQ,aAAa,CAAE,QAAO;EAEzC,MAAM,4BAAY,IAAI,KAAuB;AAC7C,eAAa,SAAS,MAAyB,UAAkB;GAC/D,MAAM,MAAM,MAAM;AAClB,OAAI,QAAQ,UAAa,QAAQ,QAAQ,QAAQ,IAAI;IACnD,MAAM,SAAS,OAAO,IAAI;AAC1B,QAAI,CAAC,UAAU,IAAI,OAAO,CAAE,WAAU,IAAI,QAAQ,EAAE,CAAC;AACrD,cAAU,IAAI,OAAO,CAAE,KAAK,MAAM;;IAEpC;AAEF,OAAK,MAAM,GAAG,YAAY,UACxB,KAAI,QAAQ,SAAS,EACnB,SAAQ,SAAS,MAAM,WAAW,IAAI,EAAE,CAAC;AAG7C,SAAO;IACN,CAAC,aAAa,CAAC;;;;;;;;;AClBpB,SAAgB,gBACd,cACA,cACA,SAC0C;CAC1C,MAAM,iBAAiBC,cAAM,OAAO,MAAM;AAE1C,eAAM,gBAAgB;AACpB,MAAI,eAAe,QAAS;AAE5B,MAAI,MAAM,QAAQ,aAAa,IAAI,iBAAiB,aAAa,QAAQ;AACvE,kBAAe,UAAU;AACzB,WAAQ,aAA8B;AACtC,wBAAqB;AACnB,mBAAe,UAAU;KACzB;;IAEH;EAAC;EAAc;EAAc;EAAQ,CAAC;AAEzC,QAAO;;;;;;ACdT,SAAgB,qBAAqB,EAAE,OAAO,UAAU,YAAyC;AAE/F,KAAI,6CAAiB,MAAM,EAAE;AAC3B,MAAI,SAAU,QAAO;AACrB,SAAO;;CAGT,MAAM,WAAuB;CAE7B,MAAM,iBAAiBC,wCAAmB,SAAS;AACnD,KAAI,eAAgB,QAAO;AAS3B,KAPmB,SAAS,MAAM,UAAoB;EACpD,MAAM,MAAM,MAAM;EAClB,MAAM,MAAM,MAAM;EAClB,MAAM,WAAW,QAAQ,MAAM,OAAO;EACtC,MAAM,WAAW,QAAQ,MAAM,OAAO;AACtC,SAAQ,YAAY,CAAC,YAAc,CAAC,YAAY;GAChD,CACc,QAAO;CAEvB,MAAM,eAAe,SAAS,QAAQ,UAAoB;EACxD,MAAM,MAAM,MAAM;EAClB,MAAM,MAAM,MAAM;AAClB,SAAO,QAAQ,MAAM,OAAO,QAAQ,QAAQ,MAAM,OAAO;GACzD;AAEF,KAAI,YAAY,aAAa,WAAW,EAAG,QAAO;AAElD,KAAI,YAAY,aAAa,SAAS,SACpC,QAAO,YAAY,SAAS,OAAO,WAAW,IAAI,MAAM,GAAG;AAG7D,QAAO;;;;;;;;;;;;;;;;;;;;;;;ACcT,SAAgB,YAA4D,EAC1E,IACA,OACA,aACA,YACA,SACA,MACA,QAAQ,QACR,YACA,KACA,KACA,OAAO,GACP,gBACA,YACqD;CACrD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAG5B,MAAM,mBAAmB;EACvB,GAAG;EACH,KAAK,YAAY,QAAQ,SAAY,WAAW,MAAM;EACtD,KAAK,YAAY,QAAQ,SAAY,WAAW,MAAM;EACvD;CAGD,MAAM,eAAe;EAEnB,cAAc;EAEd,iBAAiB;EAClB;CAGD,MAAM,wBAAwB,UAAiC;EAE7D,MAAM,qBAAqBC,mCAAc,OAAO,iBAAiB;AACjE,MAAI,uBAAuB,KAAM,QAAO;AAGxC,MAAI,gBAAgB;GAClB,MAAM,mBAAmB,eAAe,MAAM;AAC9C,OAAI,qBAAqB,QAAQ,OAAO,qBAAqB,SAC3D,QAAO;;AAIX,SAAO;;AAGT,QACE,4CAAC;EACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;aAE5F,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACN,OAAO,EACL,WAAW,UAAU;AAEnB,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GACrD,QAAO,kBAAkB,WAAW,2BAA2B;AAIjE,QAAI,UAAU,IACZ,QAAO;AAIT,QAAI,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,CAClD,QAAO;AAIT,QAAI,OAAO,UAAU,UAAU;KAE7B,MAAM,YAAY,WAAW,MAAM;AACnC,SAAI,MAAM,UAAU,CAClB,QAAO;AAET,YAAO,qBAAqB,UAAU;;AAIxC,QAAI,OAAO,UAAU,SACnB,QAAO,qBAAqB,MAAM;AAGpC,WAAO;MAEV;GACD,UAAU;GACV,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,kBAAkB;IACvD,MAAM,WAAW,CAAC,CAAC;IACnB,MAAM,kBAAkB,YAAY;IACpC,MAAM,oBAAoBC,+CAA0B,OAAO,UAAU;IAGrE,MAAM,qBAAqB,MAAiD;KAC1E,MAAM,WAAW,EAAE,OAAO;AAK1B,SAAI,CAFwB,aAAa,aAAa,KAAK,SAAS,IAExC,aAAa,GAGvC;AAIF,SAAI,aAAa,GAEf,OAAM,SAAS,GAAG;cACT,aAAa,IAEtB,OAAM,SAAS,SAAS;cACf,SAAS,SAAS,IAAI,CAE/B,OAAM,SAAS,SAAS;UACnB;MAEL,MAAM,WAAW,WAAW,SAAS;AACrC,YAAM,SAAS,MAAM,SAAS,GAAG,WAAW,SAAS;;;IAQzD,MAAM,iBAAiB,MAAmD;KAGxE,MAAM,cAAc;MAClB;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACD;AAGD,UACG,EAAE,WAAW,EAAE,YAChB;MAAC;MAAK;MAAK;MAAK;MAAK;MAAI,CAAC,SAAS,EAAE,IAAI,aAAa,CAAC,CAEvD;AAGF,SAAI,CAAC,YAAY,SAAS,EAAE,IAAI,IAAI,CAAC,EAAE,WAAW,CAAC,EAAE,QACnD,GAAE,gBAAgB;AAIpB,SAAI,EAAE,QAAQ,UAAU;AACtB,sBAAgB,MAAM,UAAU,MAAM,MAAM,CAAC,EAAE;AAC/C;;AAIF,SAAI,EAAE,QAAQ,aAAa,EAAE,QAAQ,aAAa;AAChD,QAAE,gBAAgB;MAGlB,IAAI,eAAe;AACnB,UAAI,OAAO,MAAM,UAAU,SACzB,gBAAe,MAAM;eAErB,OAAO,MAAM,UAAU,YACvB,aAAa,gBAAgB,KAAK,MAAM,MAAM,CAE9C,gBAAe,WAAW,MAAM,MAAM;MAIxC,MAAM,YAAY,EAAE,QAAQ,YAAY,OAAO,CAAC;MAChD,MAAM,WAAW,KAAK,IACpB,QAAQ,SAAY,MAAM,UAC1B,KAAK,IAAI,QAAQ,SAAY,MAAM,WAAW,eAAe,UAAU,CACxE;AAGD,YAAM,SAAS,SAAS;;;IAM5B,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,eAAe,CAAC,CAAC;KAClB,CAAC;AAEF,WACE;KACE,2CAAC;MACC,GAAI;MACJ,OAAO,MAAM,SAAS;MAClB;MACS;MACb,MAAK;MACA;MACA;MACC;MACN,WAAW;MACX,WAAW;MACX,aAAU;MACV,UAAU;MACV,WAAU;MACV,SAAQ;MACR,GAAI;MACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;MAC7E,UAAU;OACV;KAGD,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACC;MACQ;MACP,IAAI;MACJ,SAAS,kBAAkB,OAAO,UAAU;OAC5C;QACD;;IAGP;GACE;;AAKV,YAAY,cAAc;;;;;;;;;;;;;;;;AC5P1B,SAAgB,YAA4D,EAC1E,IACA,OACA,YACA,SACA,MACA,QAAQ,QACR,YACA,aAAa,EAAE,EACf,gBACA,WAAW,MACX,UACA,aACA,kBACqD;CACrD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAG5B,MAAM,mDAA8B;AAMpC,QACE,2CAACC;EACC,SAPqB,WAAW,YAAY;EAQtC;EACN,OAAO,EAKL,WAAW,UAAU;AAEnB,OACE,YAAY,aACX,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,MAAM,EAE5D,QAAO;AAIT,UAAO;KAEV;EACD,SAAS,EAAE,YAAY,EAAE,cAAc;GACrC,MAAM,WAAW,CAAC,CAAC;GAGnB,MAAM,qBAAqB,sBAAsB;IAC/C;IACA;IACA;IACA,eAAe,CAAC,CAAC;IAClB,CAAC;GAEF,MAAM,UACJ;IAEE,2CAAC;KAAI,WAAU;eACZ,WAAW,WAAW,IACrB,2CAAC;MAAI,WAAU;gBAAgC;OAEzC,GAEN,WAAW,KAAK,cAAc;AAE5B,UAAI,CAAC,YACH,OAAM,IAAI,MACR,oGAAoG,UAAU,KAAK,GACpH;MAGH,MAAM,iBAAiB,YAAY,qBACjC,WACA,eACD;MAGD,MAAM,gBAA+B;OACnC,GAAG;OACH,IAAI,GAAG,GAAG,GAAG,UAAU;OACvB,MAAM,GAAG,KAAK,GAAG,UAAU;OAC3B,OAAO,UAAU,eAAe,UAAU;OAK1C,YAAY;QACV,GAAG,eAAe;QAClB,UAAU,YAAY;QACvB;OACD,aAAa,SAAS,UAAU,eAAe,UAAU;OACzD,YACE,UAAU,gBACT,eAAe,SAAS,WAAW,iBAAiB;OACvD,OAAO;OACP;OAEA,GAAI,UAAU,cAAc,EAC1B,YAAY,UAAU,YACvB;OACF;AAED,aACE,2CAAC,mBACE,iBACC,eAAe,eAAe,UAAU,KAAK,GAI7C,4CAAC;OAAI,WAAU;;QAAgC;QAC5B,UAAU;QAAK;;QAC5B,IARA,UAAU,KAUd;OAER;MAEA;IAGL,cACC,2CAAC;KAAI,IAAI;KAAe,WAAU;eAC/B;MACG;IAIR,2CAACC;KAAoB;KAAO,IAAI;MAAW;OAC1C;AAGL,UACE,4CAAC;IACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;IAC7F,GAAI;IACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;eAG5E,SACC,4CAAC;KAAM,SAAS;;MACb;MAAM;MAAE,cAAc,2CAAC;OAAK,WAAU;iBAAmB;QAAQ;;MAC5D,EAMT,WAAW,2CAAC;KAAK,WAAU;eAAO;MAAe,GAAG;KACjD;;GAGV;;AAKN,YAAY,cAAc;;;;;;;;;;;;;;;;;;;;;;;ACnL1B,SAAgB,cAA8D,EAC5E,IACA,OACA,aACA,YACA,SACA,MACA,QAAQ,QACR,YACA,UACA,aAAa,QAC0C;CACvD,MAAM,CAAC,cAAc,uCAA4B,MAAM;CACvD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAG5B,MAAM,yBAAyB,UAAiC;EAC9D,MAAM,mBAAmBC,mCAAc,OAAO,WAAW;AACzD,SAAO,qBAAqB,OAAO,OAAQ;;CAI7C,MAAM,iCAAuC;AAC3C,mBAAiB,SAAS,CAAC,KAAK;;AAGlC,QACE,4CAAC;EACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;aAE5F,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACN,OAAO,EACL,WAAW,UAAU;AAEnB,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GACrD,QAAO,YAAY,WAAW,2BAA2B;AAI3D,QAAI,OAAO,UAAU,SACnB,QAAO,sBAAsB,MAAM;AAGrC,WAAO;MAEV;GACD,UAAU;GACV,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,kBAAkB;IACvD,MAAM,WAAW,CAAC,CAAC;IACnB,MAAM,kBAAkB,YAAY;IACpC,MAAM,oBAAoBC,+CAA0B,OAAO,UAAU;IAGrE,MAAM,qBAAqB,MAAiD;KAC1E,MAAM,QAAQ,EAAE,OAAO;AACvB,WAAM,SAAS,MAAM;AAGrB,SAAI,cAAc,UAAU,GAC1B,kBAAiB,MAAM,QAAQ,EAAE,EAAE;;IAKvC,MAAM,iBAAiB,MAAmD;AACxE,SAAI,EAAE,QAAQ,UAAU;AACtB,sBAAgB,MAAM,UAAU,MAAM,MAAM,CAAC,EAAE;AAG/C,UAAI,WACF,kBAAiB,MAAM,QAAQ,EAAE,EAAE;;;IAMzC,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,eAAe,CAAC,CAAC;KAClB,CAAC;AAEF,WACE;KACE,4CAAC;MAAI,WAAU;iBACb,2CAAC;OACC,GAAI;OACA;OACJ,MAAM,eAAe,SAAS;OACjB;OACb,WAAW,GAAG,kBAAkB,GAAG,aAAa,UAAU;OAC1D,UAAU;OACV,WAAW;OACX,aAAU;OACV,OAAO,MAAM,SAAS;OACtB,GAAI;OACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;OAC7E,UAAU;QACV,EACD,cAAc,CAAC,YACd,2CAAC;OACC,MAAK;OACL,SAAQ;OACR,MAAK;OACL,WAAU;OACV,SAAS;OACT,cAAY,eAAe,kBAAkB;iBAE5C,eACC,2CAACC,uBAAO,WAAU,kCAAkC,GAEpD,2CAACC,oBAAI,WAAU,kCAAkC;QAE5C;OAEP;KAGL,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACC;MACQ;MACP,IAAI;MACJ,SAAS,kBAAkB,OAAO,UAAU;OAC5C;QACD;;IAGP;GACE;;AAKV,cAAc,cAAc;;;;;;;;;;;;;;;;;;;;;;ACxI5B,SAAgB,WAA2D,EACzE,IACA,OACA,YACA,SACA,MACA,QAAQ,QACR,YACA,UAAU,EAAE,EACZ,SAAS,YACT,iBACoD;CACpD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAC5B,MAAM,eAAe,GAAG,GAAG;AAE3B,QACE,4CAAC;EACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;aAE5F,SACC,4CAAC;GAAM,SAAS;GAAc,WAAU;;IACrC;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACN,OAAO,EACL,WAAW,UAAU;AAEnB,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GACrD,QAAO,YAAY,WAAW,2BAA2B;AAI3D,QAAI,iBAAiB,OAAO;KAC1B,MAAMC,eAAa,cAAc,MAAM;AACvC,SAAIA,iBAAe,QAAQ,OAAOA,iBAAe,SAC/C,QAAOA;;AAIX,WAAO;MAEV;GACD,SAAS,EAAE,OAAO,YAAY,EAAE,cAAc;IAC5C,MAAM,WAAW,CAAC,CAAC;IAGnB,MAAM,0BAA0B,sBAAsB;KACpD,IAAI;KACJ;KACA;KACA,eAAe,CAAC,CAAC;KAClB,CAAC;AAEF,WACE;KACE,2CAAC;MACC,IAAI;MACJ,MAAK;MACL,WAAW,QAAQ,WAAW,aAAa,mBAAmB;MAC9D,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;MAC7E,GAAI;gBAEH,QAAQ,KAAK,QAAQ,UAAU;OAC9B,MAAM,WAAW,GAAG,GAAG,UAAU;OACjC,MAAM,aAAa,MAAM,UAAU,OAAO;OAC1C,MAAM,aAAa,OAAO;AAE1B,cACE,4CAAC;QAEC,SAAS;QACT,WAAW,0GACT,aAAa,kCAAkC,oBAChD,GAAG,cAAc,CAAC,WAAW,kBAAkB;;SAEhD,2CAAC;UACC,MAAK;UACL,IAAI;UACJ,OAAO,OAAO;UACd,UAAU;UACV,SAAS;UACT,gBAAgB,MAAM,SAAS,OAAO,MAAM;UAC5C,WAAU;UACV,oBAAkB,WAAW,UAAU;WACvC;SAGF,4CAAC;UAAI,WAAU;qBACb,2CAAC,SACC,WAAW,qEACT,aACI,WACE,yCACA,mCACF,WACE,0BACA,oEACP,GAAG,CAAC,cAAc,4BACnB,EAGF,2CAAC,SACC,WAAW,8DACT,aACI,WACE,yCACA,sCACF,wBAEN;WACE;SAGN,2CAAC;UACC,WAAW,0CACT,aACI,0BACA,aACE,WACE,iCACA,gCACF;oBAGP,OAAO;WACH;SAGP,2CAAC,SACC,WAAW,0HACT,cAAc,CAAC,aACX,uCACA,gBAEN;;UAjEG,OAAO,MAkEN;QAEV;OACE;KAGL,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACC;MAAoB;MAAO,IAAI;OAAW;QAC1C;;IAGP;GACE;;AAKV,WAAW,cAAc;;;;;;;;;;;;;;;;;;;;;;ACjKzB,SAAgB,YAA4D,EAC1E,IACA,OACA,cAAc,oBACd,YACA,SACA,MACA,QAAQ,QACR,YACA,UAAU,EAAE,EACZ,gBACA,gBACqD;CACrD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAG5B,MAAM,kBAAkB,UAAU,SAAS,SAAS,UAAU,SAAS,QAAQ;AAG/E,QACE,4CAAC;EAAI,0CAAc,uBAHF,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU,QAGvB;EAAE,OAAO,EAAE,OAAO,iBAAiB;aACrF,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACQ;GACd,OAAO,EACL,WAAW,UAAU;AAEnB,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GACrD,QAAO,YAAY,WAAW,2BAA2B;AAI3D,QAAI,kBAAkB,OAAO;KAC3B,MAAMC,eAAa,eAAe,MAAM;AACxC,SAAIA,iBAAe,QAAQ,OAAOA,iBAAe,SAC/C,QAAOA;;AAIX,WAAO;MAEV;GACD,SAAS,EAAE,OAAO,YAAY,EAAE,cAAc;IAC5C,MAAM,WAAW,CAAC,CAAC;IAGnB,MAAM,qBAAqB;KACzB,gBAAgB;KAChB,iBAAiB;KACjB,oBACE,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU,KAAK,MAAM;KACzE;IAGD,MAAM,qBAAqB,aAA2B;AACpD,WAAM,SAAS,SAAS;;AAG1B,WACE;KACE,4CAAC;MACC,cAAc,MAAM;MACpB,eAAe;MACf,OAAO,MAAM;iBAEb,2CAAC;OAAkB;OAAI,GAAI;iBACzB,2CAAC,eAAyB,cAAe;QAC3B,EAChB,2CAAC;OAEC,OAAO;QACL,OAAO;QACP,UAAU;QACX;iBAEA,QAAQ,WAAW,IAClB,2CAAC;QAAI,WAAU;kBAA4C;SAErD,GAEN,QAAQ,KAAK,WACX,2CAAC;QAEC,OAAO,OAAO;QACd,UAAU,OAAO;kBAEhB,OAAO;UAJH,OAAO,MAKD,CACb;QAEU;OACT;KAGR,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACC;MAAoB;MAAO,IAAI;OAAW;QAC1C;;IAGP;GACE;;AAKV,YAAY,cAAc;;;;;;;;;;;;;;;;;;;;;;AChG1B,SAAgB,mBAAmE,EACjF,IACA,OACA,cAAc,oBACd,YACA,SACA,MACA,QAAQ,QACR,YACA,SAAS,EAAE,EACX,kBAC4D;CAC5D,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAG5B,MAAM,kBAAkB,UAAU,SAAS,SAAS,UAAU,SAAS,QAAQ;AAG/E,QACE,4CAAC;EAAI,0CAAc,uBAHF,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU,QAGvB;EAAE,OAAO,EAAE,OAAO,iBAAiB;aACrF,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACN,OAAO,EACL,WAAW,UAAU;AAEnB,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GACrD,QAAO,YAAY,WAAW,2BAA2B;AAI3D,QAAI,kBAAkB,OAAO;KAC3B,MAAMC,eAAa,eAAe,MAAM;AACxC,SAAIA,iBAAe,QAAQ,OAAOA,iBAAe,SAC/C,QAAOA;;AAIX,WAAO;MAEV;GACD,SAAS,EAAE,OAAO,YAAY,EAAE,cAAc;IAC5C,MAAM,WAAW,CAAC,CAAC;IAGnB,MAAM,qBAAqB;KACzB,gBAAgB;KAChB,iBAAiB;KACjB,oBACE,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU,KAAK,MAAM;KACzE;IAGD,MAAM,qBAAqB,aAA2B;AACpD,WAAM,SAAS,SAAS;;AAG1B,WACE;KACE,4CAAC;MACC,cAAc,MAAM;MACpB,eAAe;MACf,OAAO,MAAM;iBAEb,2CAAC;OAAkB;OAAI,GAAI;iBACzB,2CAAC,eAAyB,cAAe;QAC3B,EAChB,2CAAC;OAEC,OAAO;QACL,OAAO;QACP,UAAU;QACX;iBAEA,OAAO,KAAK,OAAO,eAClB,4CAACC,cAAM,uBACJ,aAAa,KAAK,2CAAC,oBAAkB,EACtC,4CAAC,0BACC,2CAAC,yBAAa,MAAM,QAAoB,EACvC,MAAM,QAAQ,KAAK,WAClB,2CAAC;QAEC,OAAO,OAAO;QACd,UAAU,OAAO;QACjB,0CAAc,OAAO,WAAW,OAAO,YAAY,aAAa;kBAEhE,2CAAC,oBAAM,OAAO,QAAa;UALtB,OAAO,MAMD,CACb,IACU,KAdK,SAAS,aAeb,CACjB;QACY;OACT;KAGR,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACC;MAAoB;MAAO,IAAI;OAAW;QAC1C;;IAGP;GACE;;AAKV,mBAAmB,cAAc;;;;;;;;;;;;;;;;;;;;;;AC3KjC,SAAgB,UAA0D,EACxE,IACA,OACA,aACA,YACA,SACA,MACA,QAAQ,QACR,YACA,YACmD;CACnD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;CAG5B,MAAM,qBAAqB,UAAiC;EAC1D,MAAM,mBAAmBC,mCAAc,OAAO,WAAW;AACzD,SAAO,qBAAqB,OAAO,OAAQ;;AAG7C,QACE,4CAAC;EACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;aAE5F,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACN,OAAO,EACL,WAAW,UAAU;AAEnB,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GACrD,QAAO,YAAY,WAAW,2BAA2B;AAI3D,QAAI,OAAO,UAAU,SACnB,QAAO,kBAAkB,MAAM;AAGjC,WAAO;MAEV;GACD,UAAU;GACV,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,kBAAkB;IACvD,MAAM,WAAW,CAAC,CAAC;IACnB,MAAM,kBAAkB,YAAY;IACpC,MAAM,oBAAoBC,+CAA0B,OAAO,UAAU;IAGrE,MAAM,qBAAqB,MAAiD;KAC1E,MAAM,QAAQ,EAAE,OAAO;AACvB,WAAM,SAAS,MAAM;;IAMvB,MAAM,iBAAiB,MAAmD;AACxE,SAAI,EAAE,QAAQ,SACZ,iBAAgB,MAAM,UAAU,MAAM,MAAM,CAAC,EAAE;;IAOnD,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,eAAe,CAAC,CAAC;KAClB,CAAC;AAEF,WACE;KACE,2CAAC;MACC,GAAI;MACA;MACS;MACb,WAAW;MACX,UAAU;MACV,WAAW;MACX,aAAU;MACV,OAAO,MAAM,SAAS;MACtB,GAAI;MACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;MAC7E,UAAU;OACV;KAGD,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACC;MACQ;MACP,IAAI;MACJ,SAAS,kBAAkB,OAAO,UAAU;OAC5C;QACD;;IAGP;GACE;;AAKV,UAAU,cAAc;;;;;;;AC9IxB,SAAgB,SAAyD,EACvE,IACA,OACA,aACA,YACA,SACA,MACA,QAAQ,QACR,YACA,YACmD;CACnD,MAAM,aAAa,CAAC,CAAC,YAAY;CACjC,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,gBAAgB,GAAG,GAAG;AAE5B,QACE,4CAAC;EACC,WAAW,uBAAuB,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;aAE5F,SACC,4CAAC;GAAM,SAAS;;IACb;IAAM;IAAE,cAAc,2CAAC;KAAK,WAAU;eAAmB;MAAQ;;IAC5D,EAGV,2CAACC;GACU;GACH;GACN,OAAO,EACL,WAAW,UAAU;AAEnB,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GACrD,QAAO,YAAY,WAAW,2BAA2B;IAI3D,MAAM,2BAA2BC,mCAAc,OAAO,WAAW;AACjE,QAAI,6BAA6B,KAC/B,QAAO;AAIT,QAAI,OAAO,UAAU,YAAY,SAAS,wCAAY,MAAM,CAC1D,0DAA6B;AAI/B,WAAO;MAEV;GACD,UAAU;GACV,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,kBAAkB;IACvD,MAAM,WAAW,CAAC,CAAC;IACnB,MAAM,kBAAkB,YAAY;IACpC,MAAM,oBAAoBC,+CAA0B,OAAO,UAAU;IAGrE,MAAM,qBAAqB,MAAiD;KAC1E,MAAM,QAAQ,EAAE,OAAO;AACvB,WAAM,SAAS,MAAM;AAGrB,SAAI,cAAc,UAAU,GAC1B,kBAAiB,MAAM,QAAQ,EAAE,EAAE;;IAKvC,MAAM,iBAAiB,MAAmD;AACxE,SAAI,EAAE,QAAQ,UAAU;AACtB,sBAAgB,MAAM,UAAU,MAAM,MAAM,CAAC,EAAE;AAG/C,UAAI,WACF,kBAAiB,MAAM,QAAQ,EAAE,EAAE;;;IAMzC,MAAM,qBAAqB,sBAAsB;KAC/C;KACA;KACA;KACA,eAAe,CAAC,CAAC;KAClB,CAAC;AAEF,WACE;KACE,2CAAC;MACC,GAAI;MACA;MACJ,MAAK;MACL,aAAa,eAAe;MAC5B,WAAW;MACX,UAAU;MACV,WAAW;MACX,aAAU;MACV,OAAO,MAAM,SAAS;MACtB,GAAI;MACJ,oBAAkB,GAAG,aAAa,gBAAgB,GAAG,GAAG,WAAW,UAAU;MAC7E,UAAU;OACV;KAGD,cACC,2CAAC;MAAI,IAAI;MAAe,WAAU;gBAC/B;OACG;KAIR,2CAACC;MACQ;MACP,IAAI;MACJ,SAAS,kBAAkB,OAAO,UAAU;OAC5C;QACD;;IAGP;GACE;;AAIV,SAAS,cAAc;;;;AC3GvB,MAAa,sBAAyD,EACpE,SACA,iBACA,UAAU,OACV,WACA,aACI;CACJ,MAAM,iBAAiB,mBAAmB;CAE1C,MAAM,IAAI;EACR,cAAc,QAAQ,gBAAgB;EACtC,QAAQ,QAAQ,UAAU;EAC1B,QAAQ,QAAQ,UAAU;EAC1B,gBAAgB,QAAQ,kBAAkB;EAC1C,SAAS,QAAQ,WAAW;EAC5B,WAAW,QAAQ,aAAa;EAChC,SAAS,QAAQ,WAAW;EAC5B,OAAO,QAAQ,SAAS;EACxB,SAAS,QAAQ,WAAW;EAC5B,iBAAiB,QAAQ,mBAAmB;EAC7C;CAGD,MAAM,mBAAmB,cAA8B;AACrD,MAAI;AAEF,UADa,IAAI,KAAK,UAAU,CACpB,gBAAgB;UACtB;AACN,UAAO;;;AAIX,QACE,4CAAC;EACC,0CACE,2GACA,UACD;aAED,2CAACC,qBAAK,WAAU,6DAA6D,EAC7E,4CAAC;GAAI,WAAU;cACb,4CAAC;IACC,2CAAC;KAAG,WAAU;eAA4B,EAAE;MAAkB;IAG9D,4CAAC;KAAI,WAAU;gBACb,2CAAC;MAAE,WAAU;gBAAgD,eAAe;OAAS,EACrF,2CAAC;MACC,0CACE,kFACA,eAAe,UAAU,iBAAiB,iBACtC,4BACA,8BACL;gBAEA,eAAe,UAAU,iBAAiB,iBACzC,qFACE,2CAACC,4BAAY,WAAU,gBAAgB,EACtC,iBAAiB,iBAAiB,EAAE,iBAAiB,EAAE,UACvD,GAEH,qFACE,2CAACC,4BAAY,WAAU,gBAAgB,EACtC,EAAE,UACF;OAEA;MACH;IAGN,2CAAC;KAAI,WAAU;eACb,2CAAC;MACC,WAAU;MACV,SAAS,eAAe;MACxB,UAAU;MACV,YAAY;MACZ,UAAU;MACV;OACA;MACE;IAGN,4CAAC;KAAI,WAAU;gBACb,4CAAC;MAAI,WAAU;iBACb,2CAACC,wBAAQ,WAAU,iDAAiD,EACpE,4CAAC;OAAE,WAAU;;QACX,4CAAC;SAAK,WAAU;oBAAe,EAAE,SAAQ;UAAQ;;QAAE,eAAe;;QAChE;OACA,EAEN,4CAAC;MAAI,WAAU;iBACb,2CAACC,qBAAK,WAAU,wDAAwD,EACxE,4CAAC;OAAI,WAAU;;QACb,4CAAC;SAAK,WAAU;oBAAe,EAAE,WAAU;UAAQ;QAAC;QACpD,2CAAC;SAAK,WAAU;mBACb,eAAe;UACX;;QACH;OACF;MACF;IAGL,WACC,4CAAC;KAAI,WAAU;gBACb,2CAACC,wBAAQ,WAAU,wBAAwB;MAEvC;IAGP,CAAC,WAAW,mBACX,4CAAC;KAAI,WAAU;;MAEZ,gBAAgB,WACf,4CAAC;OAAI,WAAU;kBACb,2CAACC,2BAAW,WAAU,iDAAiD,EACvE,4CAAC;QAAI,WAAU;;SACb,4CAAC;UAAK,WAAU;qBAAe,EAAE,SAAQ;WAAQ;SAAC;SAClD,2CAAC;UAAK,WAAU;oBAAa,gBAAgB;WAAe;;SACxD;QACF;MAIP,gBAAgB,SACf,4CAAC;OAAI,WAAU;kBACb,2CAACF,qBAAK,WAAU,iDAAiD,EACjE,4CAAC;QAAK,WAAU;;SACd,4CAAC;UAAK,WAAU;qBAAe,EAAE,OAAM;WAAQ;;SAAE,gBAAgB;;SAC5D;QACH;MAIP,gBAAgB,6BAA6B,UAC5C,4CAAC;OAAI,WAAU;kBACb,2CAACG,sBAAM,WAAU,iDAAiD,EAClE,4CAAC;QAAK,WAAU;;SACd,4CAAC;UAAK,WAAU;qBAAe,EAAE,SAAQ;WAAQ;SAAC;SACjD,gBAAgB;;SACZ;QACH;MAIP,gBAAgB,qCACf,4CAAC;OAAI,WAAU;kBACb,2CAACL,4BAAY,WAAU,wDAAwD,EAC/E,4CAAC;QAAI,WAAU;;SACb,4CAAC;UAAK,WAAU;qBAAe,EAAE,iBAAgB;WAAQ;SACzD,2CAAC,SAAK;SACN,2CAAC;UAAK,WAAU;oBACb,gBAAgB,gBAAgB,kCAAkC;WAC9D;;SACH;QACF;;MAEJ;OAEJ,GAGJ,eAAe,UAAU,iBAAiB,mBAC1C,2CAAC;IAAI,WAAU;cACb,4CAAC;KAAE,WAAU;gBACX,2CAACD,4BAAY,WAAU,gCAAgC,EACvD,2CAAC;MAAK,WAAU;gBACb,iBAAiB,iBACd,kFACA;OACC;MACL;KACA;IAEJ;GACF;;;;;AC/MV,MAAa,+CAA0E,OAAU;;;;;ACSjG,SAAgB,iCAAiC,EAC/C,YACyD;CACzD,MAAM,CAAC,QAAQ,iCAAsC,EAAE,CAAC;CACxD,MAAM,CAAC,4BAA4B,sDAEhC;CACH,MAAM,mDAA6C,IAAI,KAAK,CAAC;CAE7D,MAAM,6CACH,MAAwB,WAAmB,aAAqB,YAAoB;EAEnF,MAAM,YAAY,GAAG,KAAK,GAAG,UAAU,GAAG;EAC1C,MAAM,MAAM,KAAK,KAAK;EACtB,MAAM,eAAe,eAAe,QAAQ,IAAI,UAAU;AAG1D,MAAI,gBAAgB,MAAM,eAAe,IACvC;AAGF,iBAAe,QAAQ,IAAI,WAAW,IAAI;EAE1C,MAAM,QAAsB;GAC1B,IAAI,GAAG,KAAK,GAAG,UAAU,GAAG;GAC5B;GACA;GACA;GACA;GACA,WAAW;GACZ;AAED,aAAW,SAAS;AAElB,UADkB,CAAC,GAAG,MAAM,MAAM;IAElC;EAGF,MAAM,YAAY,SAAS,QAAQ,QAAQ;AAC3C,eAAM,MAAM,GAAG,UAAU,WAAW,eAAe;GACjD,aAAa;GACb,UAAU;GACV,QAAQ,6BACJ;IACE,OAAO;IACP,eAAqB;AACnB,gCAA2B,UAAU;;IAExC,GACD;GACL,CAAC;AAGF,mBAAiB;AACf,cAAW,SAAS,KAAK,QAAQ,MAAM,EAAE,OAAO,MAAM,GAAG,CAAC;AAC1D,kBAAe,QAAQ,OAAO,UAAU;KACvC,IAAM;IAEX,CAAC,2BAA2B,CAC7B;CAED,MAAM,qCAA0B,OAAe;AAC7C,aAAW,SAAS,KAAK,QAAQ,MAAM,EAAE,OAAO,GAAG,CAAC;IACnD,EAAE,CAAC;CAEN,MAAM,8CAAmC;AACvC,YAAU,EAAE,CAAC;AACb,iBAAe,QAAQ,OAAO;IAC7B,EAAE,CAAC;CAEN,MAAM,2CAAgC,YAAyC;AAC7E,sCAAoC,QAAQ;IAC3C,EAAE,CAAC;CAEN,MAAM,kCACG;EACL;EACA;EACA;EACA;EACA,uBAAuB;EACvB,+BAA+B;EAChC,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACD,CACF;AAED,QAAO,2CAAC,oBAAoB;EAAgB;EAAQ;GAAwC;;;;;;ACxE9F,SAAgB,mBAA6C;CAC3D,MAAM,gCAAqB,oBAAoB;AAC/C,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,wEAAwE;AAE1F,QAAO;;;;;AAMT,SAAgB,wBAAwB,YAGtC;CACA,MAAM,EAAE,uBAAuB,kBAAkB;AA4BjD,QAAO;EACL,wCA1BC,YAAoB;AACnB,OAAI,CAAC,WAAY;AACjB,sBACE,OACA,WAAW,cAAc,IACzB,WAAW,cAAc,MACzB,QACD;KAEH,CAAC,YAAY,mBAAmB,CACjC;EAiBC,6CAdC,YAAoB;AACnB,OAAI,CAAC,WAAY;AACjB,sBACE,YACA,WAAW,cAAc,IACzB,WAAW,cAAc,MACzB,QACD;KAEH,CAAC,YAAY,mBAAmB,CACjC;EAKA;;;;;;;;ACrEH,SAAgB,4BACd,YACU;CACV,MAAM,EAAE,uBAAuB,kBAAkB;CACjD,MAAM,yCAAwC,KAAK;AAEnD,4BAAgB;AACd,MAAI,CAAC,YAAY;AACf,wBAAqB,UAAU;AAC/B;;AA6DF,uBAAqB,UAzDK,IAAI,MAAM,YAAY,EAC9C,IAAI,QAAQ,MAAM,UAAmB;GACnC,MAAM,QAAQ,QAAQ,IAAI,QAAQ,MAAM,SAAS;AAGjD,OACE,OAAO,UAAU,eAChB,SAAS,uBAAuB,SAAS,gBAE1C,QAAO,OAAO,GAAG,SAAoB;AACnC,QAAI;AACF,YAAO,MAAM,MAAM,MAAM,QAAQ,KAAK;aAC/B,OAAO;KACd,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAG9D,SACE,aAAa,aAAa,CAAC,SAAS,MAAM,IAC1C,aAAa,aAAa,CAAC,SAAS,UAAU,IAC9C,aAAa,aAAa,CAAC,SAAS,UAAU,IAC9C,aAAa,aAAa,CAAC,SAAS,QAAQ,IAC5C,aAAa,aAAa,CAAC,SAAS,aAAa,CAEjD,oBACE,OACA,OAAO,cAAc,IACrB,OAAO,cAAc,MACrB,aACD;AAIH,SACE,aAAa,aAAa,CAAC,SAAS,WAAW,IAC/C,aAAa,aAAa,CAAC,SAAS,YAAY,IAChD,aAAa,aAAa,CAAC,SAAS,UAAU,IAC9C,aAAa,aAAa,CAAC,SAAS,MAAM,IAC1C,aAAa,aAAa,CAAC,SAAS,WAAW,CAE/C,oBACE,YACA,OAAO,cAAc,IACrB,OAAO,cAAc,MACrB,aACD;AAIH,WAAM;;;AAKZ,UAAO;KAEV,CAAC;IAGD,CAAC,YAAY,mBAAmB,CAAC;AAEpC,QAAO,qBAAqB;;;;;;;;;;;;;;;AC3C9B,SAAgB,0BAA0B,EACxC,eACA,aACA,cACA,OACA,aACA,uBAAuB,6BAC2B;CAElD,MAAM,gCAAqB,oBAAoB;CAC/C,MAAM,wBAAwB,6BAA6B,SAAS;CAEpE,MAAM,2BAAiC;AACrC,0BAAwB,cAAc,GAAG;;CAG3C,MAAM,gEAAoC,YAAY;CACtD,MAAM,eAAe,wBAAwB,cAAc;CAC3D,MAAM,qBAAqB,wBACvB,6HAA6H,YAAY,aAAa,CAAC,sCACvJ;AAEJ,QACE,4CAAC;EAAM,SAAQ;EAAc,WAAU;;GACrC,2CAACO,yBAAS,WAAU,2CAA2C;GAC/D,2CAAC;IAAW,WAAU;cAAkC,SAAS;KAA0B;GAC3F,4CAAC;IAAiB,WAAU;;KAC1B,2CAAC;MAAE,WAAU;gBACV,gBACC,OAAO,YAAY,aAAa,CAAC,OAAO,cAAc,KAAK;OAC3D;KACJ,2CAAC;MAAE,WAAU;gBAAgB,eAAe;OAAuB;KAClE,yBACC,4CAAC;MACC,SAAS;MACT,SAAQ;MACR,MAAK;MACL,WAAU;;OAEV,2CAACC,yBAAS,WAAU,iBAAiB;;OAC1B;OAAY;;OAChB;;KAEM;;GACb;;;;;;;;;AC/DZ,SAAgB,0BAA0B,EACxC,SACA,iBACA,aAC4D;AAC5D,KAAI,gEAAoC,CACtC,QAAO;CAGT,MAAM,EAAE,OAAO,uBAAuB,4FACG,QAAQ;AAEjD,QACE,4CAAC;EAAiB;;GAChB,2CAACC,qBAAK,WAAU,YAAY;GAC5B,2CAAC,wBAAY,QAAmB;GAChC,4CAAC;IACE;IACD,2CAAC;KACC,MAAM;KACN,QAAO;KACP,KAAI;KACJ,WAAU;eAET;MACC;;OAEa;;GACb;;;;;AC9CZ,MAAM,WAAW,EAAE,GAAG,YAAuC;CAC3D,MAAM,EAAE,QAAQ,wCAAuB;AAEvC,QACE,2CAACC;EACQ;EACP,WAAU;EACV,cAAc,EACZ,YAAY;GACV,OACE;GACF,aAAa;GACb,cACE;GACF,cACE;GACF,OACE;GACH,EACF;EACD,GAAI;GACJ"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["React","AccordionPrimitive","ChevronDown","TooltipPrimitive","React","React","React","Check","Copy","ExternalLink","Pencil","TriangleAlert","React","React","React","React","React","React","X","React","Slot","DayPicker","ChevronLeft","ChevronRight","CheckboxPrimitive","CheckIcon","PopoverPrimitive","React","CalendarIcon","DialogPrimitive","React","DropdownMenuPrimitive","React","ChevronRight","Check","Circle","React","ChevronDown","Check","FileText","React","ExternalLinkIcon","React","LabelPrimitive","FormProvider","React","Controller","Menu","React","React","Slot","Slottable","React","ChevronDown","Search","Check","MoreHorizontal","React","React","ProgressPrimitive","React","RadioGroupPrimitive","Circle","SelectPrimitive","React","ChevronDown","ChevronUp","Check","CollapsiblePrimitive","ChevronRight","TabsPrimitive","React","FileText","Check","Pencil","AlertCircle","React","X","ChevronLeft","ChevronRight","validateField","getValidationStateClasses","ErrorMessage","Controller","validation","getValidationStateClasses","ErrorMessage","Info","Plus","X","Plus","ClipboardPaste","PencilLine","React","React","React","Controller","validation","getValidationStateClasses","ErrorMessage","React","Controller","GripVertical","X","Plus","ErrorMessage","React","Controller","GripVertical","ChevronRight","ChevronDown","X","Plus","ErrorMessage","INTEGER_PATTERN","validateField","Controller","getValidationStateClasses","INTEGER_INPUT_PATTERN","INTEGER_HTML_PATTERN","ErrorMessage","validateField","Controller","getValidationStateClasses","ErrorMessage","Controller","getValidationStateClasses","ErrorMessage","validateField","Controller","getValidationStateClasses","ErrorMessage","Controller","validateField","getValidationStateClasses","ErrorMessage","selectedVariant","Controller","validateField","Upload","FileIcon","CheckCircle2","AlertCircle","X","ErrorMessage","React","Controller","X","Plus","ErrorMessage","React","React","validateMapEntries","validateField","Controller","getValidationStateClasses","ErrorMessage","Controller","ErrorMessage","validateField","Controller","getValidationStateClasses","EyeOff","Eye","ErrorMessage","Controller","validation","ErrorMessage","Controller","validation","ErrorMessage","Controller","validation","React","ErrorMessage","validateField","Controller","getValidationStateClasses","ErrorMessage","Controller","validateField","getValidationStateClasses","ErrorMessage","Info","AlertCircle","CheckCircle","Network","Hash","Loader2","DollarSign","Timer","CloudOff","Settings","Info","Sonner"],"sources":["../src/version.ts","../src/components/ui/accordion.tsx","../src/components/ui/tooltip.tsx","../src/components/ui/address-display/address-avatar.tsx","../src/components/ui/address-display/context.ts","../src/components/ui/address-display/address-display.tsx","../src/components/ui/address-display/address-label-context.tsx","../src/components/ui/address-display/use-address-label.ts","../src/components/ui/address-display/address-name-context.tsx","../src/components/ui/address-display/use-address-name.ts","../src/components/ui/alert.tsx","../src/components/ui/banner.tsx","../src/utils/button-variants.ts","../src/components/ui/button.tsx","../src/components/ui/calendar.tsx","../src/components/ui/card.tsx","../src/components/ui/checkbox.tsx","../src/components/ui/popover.tsx","../src/components/ui/date-range-picker.tsx","../src/components/ui/dialog.tsx","../src/components/ui/dropdown-menu.tsx","../src/components/ui/ecosystem-dropdown.tsx","../src/components/icons/MidnightIcon.tsx","../src/components/ui/ecosystem-icon.tsx","../src/components/ui/empty-state.tsx","../src/components/ui/external-link.tsx","../src/components/ui/footer.tsx","../src/components/ui/label.tsx","../src/components/ui/form.tsx","../src/components/ui/header.tsx","../src/components/ui/input.tsx","../src/components/ui/loading-button.tsx","../src/components/ui/network-icon.tsx","../src/components/ui/network-selector.tsx","../src/components/ui/network-status-badge.tsx","../src/components/ui/overflow-menu.tsx","../src/components/ui/progress.tsx","../src/components/ui/radio-group.tsx","../src/components/ui/select.tsx","../src/components/ui/sidebar/SidebarButton.tsx","../src/components/ui/sidebar/SidebarGroup.tsx","../src/components/ui/sidebar/SidebarLayout.tsx","../src/components/ui/sidebar/SidebarSection.tsx","../src/components/ui/tabs.tsx","../src/components/ui/textarea.tsx","../src/components/ui/view-contract-state-button.tsx","../src/components/ui/wizard/WizardStepper.tsx","../src/components/ui/wizard/WizardNavigation.tsx","../src/components/ui/wizard/hooks.ts","../src/components/ui/wizard/WizardLayout.tsx","../src/components/fields/address-suggestion/AddressSuggestionList.tsx","../src/components/fields/address-suggestion/context.ts","../src/components/fields/address-suggestion/useAddressSuggestionField.ts","../src/components/fields/name-resolution/useInjectedNameResolution.ts","../src/components/fields/name-resolution/context.ts","../src/components/fields/name-resolution/useNameResolver.ts","../src/components/fields/name-resolution/useResolvingAnnouncerCopy.ts","../src/components/fields/utils/accessibility.ts","../src/components/fields/utils/layout.ts","../src/components/fields/AddressField.tsx","../src/components/fields/TextAreaField.tsx","../src/components/fields/AddressListField/labels.ts","../src/components/fields/AddressListField/AddressListBulkEntry.tsx","../src/components/fields/AddressListField/AddressListEntries.tsx","../src/components/fields/AddressListField/AddressListSingleEntry.tsx","../src/components/fields/AddressListField/AddressListField.tsx","../src/components/fields/address-suggestion/address-suggestion-context.tsx","../src/components/fields/address-suggestion/useAddressSuggestions.ts","../src/components/fields/name-resolution/name-resolver-context.tsx","../src/components/fields/AmountField.tsx","../src/components/fields/ArrayField.tsx","../src/components/fields/ArrayObjectField.tsx","../src/components/fields/BaseField.tsx","../src/components/fields/BigIntField.tsx","../src/components/fields/BooleanField.tsx","../src/components/fields/BytesField.tsx","../src/components/fields/DateTimeField.tsx","../src/components/fields/EnumField.tsx","../src/components/fields/FileUploadField.tsx","../src/components/fields/MapField/MapField.tsx","../src/components/fields/MapField/MapEntryRow.tsx","../src/components/fields/MapField/hooks/useChildTouched.ts","../src/components/fields/MapField/hooks/useDuplicateKeyIndexes.ts","../src/components/fields/MapField/hooks/useMapFieldSync.ts","../src/components/fields/MapField/validation/validateMapStructure.ts","../src/components/fields/NumberField.tsx","../src/components/fields/ObjectField.tsx","../src/components/fields/PasswordField.tsx","../src/components/fields/RadioField.tsx","../src/components/fields/SelectField.tsx","../src/components/fields/SelectGroupedField.tsx","../src/components/fields/TextField.tsx","../src/components/fields/UrlField.tsx","../src/components/RelayerDetailsCard/RelayerDetailsCard.tsx","../src/components/network-errors/NetworkErrorContext.ts","../src/components/network-errors/NetworkErrorNotificationProvider.tsx","../src/components/network-errors/useNetworkErrors.ts","../src/components/network-errors/NetworkErrorAwareAdapter.tsx","../src/components/network-errors/NetworkServiceErrorBanner.tsx","../src/components/network-availability/NetworkAvailabilityNotice.tsx","../src/components/ui/sonner.tsx"],"sourcesContent":["declare const __PACKAGE_VERSION__: string;\nexport const VERSION: string = __PACKAGE_VERSION__;\n","import * as AccordionPrimitive from '@radix-ui/react-accordion';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { ChevronDown } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst accordionItemVariants = cva('', {\n variants: {\n variant: {\n default: 'border-b',\n card: 'mb-3 rounded-lg border bg-card overflow-hidden',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\nconst accordionTriggerVariants = cva(\n 'flex flex-1 items-center justify-between font-medium transition-all [&[data-state=open]>svg]:rotate-180',\n {\n variants: {\n variant: {\n default: 'py-4 hover:underline',\n card: 'px-4 py-3 hover:bg-muted/50',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n);\n\nconst accordionContentVariants = cva(\n 'overflow-hidden text-sm transition-all duration-300 ease-in-out will-change-[height,opacity] data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down',\n {\n variants: {\n variant: {\n default: '',\n card: '',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n);\n\nconst accordionContentInnerVariants = cva('', {\n variants: {\n variant: {\n default: 'pb-4 pt-0',\n card: 'px-4 pb-4 pt-1',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\n// Create a context for the variant\ntype AccordionVariant = 'default' | 'card';\nconst AccordionVariantContext = React.createContext<AccordionVariant>('default');\n\n// Extend the Accordion component to accept and provide variant\ntype AccordionProps = (\n | AccordionPrimitive.AccordionSingleProps\n | AccordionPrimitive.AccordionMultipleProps\n) & {\n variant?: AccordionVariant;\n};\n\nconst Accordion = React.forwardRef<HTMLDivElement, AccordionProps>(\n ({ variant = 'default', ...props }, ref) => (\n <AccordionVariantContext.Provider value={variant}>\n <AccordionPrimitive.Root ref={ref} {...props} />\n </AccordionVariantContext.Provider>\n )\n);\nAccordion.displayName = 'Accordion';\n\ninterface AccordionItemProps\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>,\n VariantProps<typeof accordionItemVariants> {}\n\nconst AccordionItem = React.forwardRef<HTMLDivElement, AccordionItemProps>(\n ({ className, variant: variantProp, ...props }, ref) => {\n const contextVariant = React.useContext(AccordionVariantContext);\n const variant = variantProp ?? contextVariant;\n\n return (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(accordionItemVariants({ variant }), className)}\n {...props}\n />\n );\n }\n);\nAccordionItem.displayName = 'AccordionItem';\n\ninterface AccordionTriggerProps\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>,\n VariantProps<typeof accordionTriggerVariants> {}\n\nconst AccordionTrigger = React.forwardRef<HTMLButtonElement, AccordionTriggerProps>(\n ({ className, children, variant: variantProp, ...props }, ref) => {\n const contextVariant = React.useContext(AccordionVariantContext);\n const variant = variantProp ?? contextVariant;\n\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(accordionTriggerVariants({ variant }), className)}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n );\n }\n);\nAccordionTrigger.displayName = 'AccordionTrigger';\n\ninterface AccordionContentProps\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>,\n VariantProps<typeof accordionContentVariants> {}\n\nconst AccordionContent = React.forwardRef<HTMLDivElement, AccordionContentProps>(\n ({ className, children, variant: variantProp, ...props }, ref) => {\n const contextVariant = React.useContext(AccordionVariantContext);\n const variant = variantProp ?? contextVariant;\n\n return (\n <AccordionPrimitive.Content\n ref={ref}\n className={cn(accordionContentVariants({ variant }), className)}\n {...props}\n >\n <div className={cn(accordionContentInnerVariants({ variant }))}>{children}</div>\n </AccordionPrimitive.Content>\n );\n }\n);\nAccordionContent.displayName = 'AccordionContent';\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\nexport type { AccordionProps, AccordionItemProps, AccordionTriggerProps, AccordionContentProps };\n","import * as TooltipPrimitive from '@radix-ui/react-tooltip';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst TooltipProvider = TooltipPrimitive.Provider;\n\nconst Tooltip = TooltipPrimitive.Root;\n\nconst TooltipTrigger = TooltipPrimitive.Trigger;\n\nconst TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 overflow-hidden rounded-md px-3 py-1.5 text-xs',\n className\n )}\n {...props}\n />\n </TooltipPrimitive.Portal>\n));\nTooltipContent.displayName = TooltipPrimitive.Content.displayName;\n\nexport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };\n","import * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\n/**\n * Visual treatment for {@link AddressAvatar}.\n *\n * - `'fill'` – a square avatar that stretches to the parent slot's full\n * height and sits flush against its edges (default). Intended for a chip\n * whose container clips it with `overflow-hidden` + a border radius.\n * - `'circle'` – small round avatar sitting inline with the text (the\n * original look, kept as an opt-in).\n */\nexport type AddressAvatarVariant = 'circle' | 'fill';\n\n/**\n * Props for {@link AddressAvatar}.\n *\n * The design sketched a required `name` used as the `alt` source. It is\n * replaced by an optional `alt` defaulting to `''` (decorative): the\n * forward-verified name renders as adjacent visible label text and already\n * carries the accessible identity, so announcing it again via the avatar\n * would be redundant (INV-67, locked decorative-alt decision 2026-07-04).\n * A future descriptive convention (e.g. SF-6) can pass `alt` explicitly.\n */\nexport interface AddressAvatarProps {\n /** Avatar URL from `ResolvedName.avatarUrl`. */\n readonly src: string;\n /**\n * Accessible text for the image. Defaults to `''` (decorative), because the\n * visible name already carries the identity (INV-67). Never omitted from\n * the rendered `<img>`.\n */\n readonly alt?: string;\n /**\n * Visual treatment. Defaults to `'fill'` (a square avatar stretched to the\n * slot's full height); `'circle'` opts into the original inline round avatar.\n */\n readonly variant?: AddressAvatarVariant;\n /**\n * Escape-hatch Tailwind size/shape classes. When provided, overrides the\n * `variant`-derived classes entirely. Left for advanced call-sites; the\n * `variant` prop covers the standard looks.\n */\n readonly sizeClassName?: string;\n}\n\n/**\n * Allowlist for name-owner-controlled avatar URLs at the render site.\n * Only `https:` and `data:image/*` pass; `http:` (mixed content), `javascript:`,\n * and other schemes are dropped. Does not rely on adapter sanitization.\n */\nfunction isAllowedAvatarSrc(src: string): boolean {\n try {\n const url = new URL(src);\n if (url.protocol === 'https:') return true;\n // `data:image/png;base64,...` — reject non-image data URLs (e.g. data:text/html).\n if (url.protocol === 'data:') return /^data:image\\/[a-z0-9.+-]+/i.test(src);\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * @internal Avatar image for a resolved name, hiding itself on load error\n * (never a broken-image icon) — the name renders as a complete, avatar-less\n * row. Purely presentational; its only state is the per-instance load-error\n * flag (INV-121).\n *\n * The error state is keyed to the current `src` rather than a bare boolean,\n * so it resets automatically when `src` changes — a virtualized/reused list\n * row that scrolls to a new address re-attempts its avatar instead of staying\n * permanently hidden by a prior URL's failure (INV-59).\n *\n * @param props - {@link AddressAvatarProps}.\n * @returns The avatar `<img>`, or `null` when the load failed for this `src`.\n */\nexport function AddressAvatar({\n src,\n alt = '',\n variant = 'fill',\n sizeClassName,\n}: AddressAvatarProps): React.ReactElement | null {\n // INV-59: track the src that failed, not a plain flag — `failed` is derived\n // as `failedSrc === src`, so a new src is never suppressed by an old failure.\n const [failedSrc, setFailedSrc] = React.useState<string | null>(null);\n\n // Drop disallowed schemes before render (http / javascript / arbitrary hosts\n // via non-https). Fail closed — no <img>, same as a load error (INV-55).\n if (!isAllowedAvatarSrc(src)) return null;\n\n // INV-55: hidden on load error — the name displays with no avatar, no glyph,\n // no reserved box.\n if (failedSrc === src) return null;\n\n // `'fill'` positions the image absolutely so its intrinsic dimensions never\n // drive layout — the square, self-stretched parent slot (in AddressDisplay)\n // sizes it to the text block's height. `'circle'` is the original inline\n // round avatar sized by its own box.\n const variantClassName =\n variant === 'fill'\n ? 'absolute inset-0 h-full w-full rounded-none'\n : 'h-4 w-4 shrink-0 rounded-full';\n\n return (\n <img\n src={src}\n // INV-67: decorative — never omitted, and non-redundant with the visible name.\n alt={alt}\n className={cn('object-cover', sizeClassName ?? variantClassName)}\n // Name-owner-controlled URL: never leak the document referrer to the avatar host.\n referrerPolicy=\"no-referrer\"\n // INV-55: 404 / network failure / non-image payload → hide (no broken icon).\n onError={() => setFailedSrc(src)}\n />\n );\n}\n","import { createContext } from 'react';\n\nimport type { AddressLabelResolver, AddressNameResolver } from '@openzeppelin/ui-types';\n\n/**\n * @internal Shared context instance consumed by both AddressDisplay and\n * AddressLabelProvider. Kept in its own file so component files export\n * only components (required by React Fast Refresh).\n */\nexport const AddressLabelContext = createContext<AddressLabelResolver | null>(null);\n\n/**\n * @internal Shared context instance consumed by AddressDisplay,\n * AddressNameProvider, and useAddressName. Sibling of AddressLabelContext\n * (SF-4 INV-122): carries a synchronous, value-only reverse-name resolver.\n * Defaults to `null` — no provider means no resolution and a byte-identical\n * zero-injection render (INV-54).\n */\nexport const AddressNameContext = createContext<AddressNameResolver | null>(null);\n","import { Check, Copy, ExternalLink, Pencil, TriangleAlert } from 'lucide-react';\nimport * as React from 'react';\n\nimport type { ResolvedName } from '@openzeppelin/ui-types';\nimport {\n cn,\n crossNetworkFallbackMessageNames,\n getFallbackNetworks,\n isCrossNetworkFallback,\n nameResolutionCrossNetworkFallbackMessage,\n truncateMiddle,\n} from '@openzeppelin/ui-utils';\n\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../tooltip';\nimport { AddressAvatar, type AddressAvatarVariant } from './address-avatar';\nimport { AddressLabelContext, AddressNameContext } from './context';\n\n/**\n * True when the primary input can hover (e.g. desktop with mouse).\n * Touch-first phones typically report false. SSR assumes hover-capable.\n */\nfunction usePrefersHover(): boolean {\n return React.useSyncExternalStore(\n React.useCallback((onStoreChange) => {\n if (typeof window === 'undefined' || typeof window.matchMedia === 'undefined') {\n return (): void => {};\n }\n const mq = window.matchMedia('(hover: hover)');\n mq.addEventListener('change', onStoreChange);\n return (): void => mq.removeEventListener('change', onStoreChange);\n }, []),\n () =>\n typeof window !== 'undefined' && typeof window.matchMedia !== 'undefined'\n ? window.matchMedia('(hover: hover)').matches\n : true,\n () => true\n );\n}\n\n/**\n * Strip C0/C1 controls, bidi embeds/isolates, and zero-width characters from a\n * verified name at the display seam. ENSIP-15 normalization remains the\n * adapter's job; this only removes invisible directionality/control glyphs so\n * a raw render cannot spoof adjacent UI (homoglyph confusables are out of scope).\n */\nfunction sanitizeVerifiedNameForDisplay(name: string): string {\n return name.replace(\n /[\\u0000-\\u001F\\u007F-\\u009F\\u200B-\\u200F\\u202A-\\u202E\\u2060-\\u2064\\u2066-\\u206F\\uFEFF]/g,\n ''\n );\n}\n\n/**\n * Visual style for the component container.\n *\n * - `\"chip\"` – rounded pill with a slate background (default).\n * - `\"inline\"` – no background, padding, or border-radius; just the text\n * and optional action buttons. Use when dropping into existing layouts\n * where the parent already provides styling (e.g. wallet display bars).\n */\nexport type AddressDisplayVariant = 'chip' | 'inline';\n\nexport interface AddressDisplayProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * The blockchain address to display\n */\n address: string;\n\n /**\n * Whether to truncate the address in the middle.\n * When omitted, defaults to `true` unless `truncateWhenLabeled` applies.\n */\n truncate?: boolean;\n\n /**\n * When `true` and `truncate` is **not** explicitly set, the address truncates\n * only when a label is shown (via the `label` prop or\n * `AddressLabelContext`). Use this when a long raw address should stay\n * fully visible unless an alias already identifies the row.\n * @default false\n */\n truncateWhenLabeled?: boolean;\n\n /**\n * When `truncate` is true, show the full address while the pointer is over\n * the component (on devices that support hover), or toggle on tap\n * (on touch-first / `(hover: none)` devices).\n * Has no effect when `truncate` is false.\n * @default false\n */\n untruncateOnHover?: boolean;\n\n /**\n * Number of characters to show at the beginning when truncating\n * @default 6\n */\n startChars?: number;\n\n /**\n * Number of characters to show at the end when truncating\n * @default 4\n */\n endChars?: number;\n\n /**\n * Whether to show a copy button\n * @default false\n */\n showCopyButton?: boolean;\n\n /**\n * Whether to show the copy button only on hover\n * @default false\n */\n showCopyButtonOnHover?: boolean;\n\n /**\n * Optional explorer URL to make the address clickable\n */\n explorerUrl?: string;\n\n /**\n * Human-readable label to display alongside the address.\n * Takes priority over any label resolved via `AddressLabelContext`.\n */\n label?: string;\n\n /**\n * Callback to trigger label editing for this address.\n * When provided, a pencil icon is rendered. Takes priority over\n * the `onEditLabel` from `AddressLabelContext`.\n */\n onLabelEdit?: () => void;\n\n /**\n * Optional network identifier used when resolving labels and triggering\n * edits via `AddressLabelContext`. Important for multi-network scenarios\n * where the same address may have different aliases per network.\n */\n networkId?: string;\n\n /**\n * When `true`, render the instance fully raw: skip label resolution from\n * `AddressLabelContext` AND suppress any injected resolved name\n * (`resolvedName` prop / `AddressNameContext`). Useful for rendering an\n * address without any decoration (e.g. in a contract selector where the\n * contract name is already shown) — existing `disableLabel` call-sites\n * must not sprout a name once a resolver is wired app-wide.\n * @default false\n */\n disableLabel?: boolean;\n\n /**\n * When `true` and the address is truncated, a tooltip shows the full\n * address on hover. Has no visual effect when `truncate` is `false`.\n * Mutually exclusive with `untruncateOnHover` — if both are set,\n * `showTooltip` takes precedence.\n * @default false\n */\n showTooltip?: boolean;\n\n /**\n * Visual variant of the component container.\n * @default \"chip\"\n */\n variant?: AddressDisplayVariant;\n\n /**\n * Optional presentational leading element (e.g. an avatar or icon), rendered\n * before the label/address block and vertically centered against it. Purely\n * visual — a `React.ReactNode`, not a capability, so this component stays\n * chain-agnostic. When omitted (the default at every existing call-site), the\n * rendered DOM and layout are byte-for-byte identical to the pre-avatar\n * component: no wrapper element, no reserved slot, in both render branches.\n */\n avatar?: React.ReactNode;\n\n /**\n * Visual treatment for the leading avatar (both the record-constructed ENS\n * avatar and an explicit `avatar` node):\n *\n * - `'fill'` – a square avatar that stretches to the chip's full height and\n * sits flush against its top, bottom, and left edges (default; the chip\n * clips its outer corners). No effect when no avatar is shown.\n * - `'circle'` – small round avatar sitting inline with the text (the\n * original look, kept as an opt-in).\n *\n * @default \"fill\"\n */\n avatarVariant?: AddressAvatarVariant;\n\n /**\n * An already-resolved reverse name record for this address (value type).\n * Highest precedence for the name channel — shadows the\n * `AddressNameContext` resolver, exactly as `label` shadows\n * `AddressLabelContext` (INV-120). The record's name renders only when\n * `forwardVerified === true` (INV-52, LOCKED): a mismatched record is\n * suppressed to hex — never name-alone, never name+warning. `undefined`\n * falls back to the context (if any), then to hex.\n */\n resolvedName?: ResolvedName;\n\n /**\n * When `false`, suppresses the reverse cross-network fallback indicator\n * (amber triangle-alert icon + tooltip) inline after the verified name.\n * Default `true`. Provenance classification is unchanged — only presentation\n * is omitted so the labeled branch stays byte-identical to a row without fallback.\n */\n showCrossNetworkFallbackDisclaimer?: boolean;\n\n /**\n * Additional CSS classes\n */\n className?: string;\n}\n\n/**\n * Displays a blockchain address with optional truncation, copy button,\n * explorer link, tooltip, human-readable label, and (when an already-resolved\n * record is injected) a forward-verified name + avatar.\n *\n * Labels are resolved in priority order (INV-56):\n * 1. Explicit `label` prop\n * 2. `AddressLabelContext` resolver (via `AddressLabelProvider`)\n * 3. Forward-verified resolved name (`resolvedName` prop, else\n * `AddressNameContext` via `AddressNameProvider`) — a record with\n * `forwardVerified: false` is suppressed to hex (INV-52, LOCKED)\n * 4. No label (renders address only, identical to previous behavior)\n *\n * The component is synchronous and capability-free (INV-121): it never\n * resolves anything itself — it reads injected values. Hex renders on first\n * commit; the name+avatar swap in when the react layer feeds an updated\n * record (progressive enhancement, INV-61). With no `resolvedName` and no\n * `AddressNameProvider`, output is byte-identical to the pre-enhancement\n * component (INV-54, LOCKED).\n *\n * Pass `disableLabel` to render fully raw — it suppresses both the context\n * alias and any injected resolved name (e.g. when the surrounding UI already\n * shows a name, such as a contract selector).\n *\n * @example\n * ```tsx\n * // Basic usage (unchanged)\n * <AddressDisplay address=\"0x742d35Cc...\" showCopyButton />\n *\n * // Explicit label\n * <AddressDisplay address=\"0x742d35Cc...\" label=\"Treasury\" />\n *\n * // Auto-resolved via context (no changes needed at call site)\n * <AddressLabelProvider resolveLabel={myResolver}>\n * <AddressDisplay address=\"0x742d35Cc...\" />\n * </AddressLabelProvider>\n *\n * // Suppress label resolution for a specific instance\n * <AddressDisplay address=\"0x742d35Cc...\" disableLabel />\n *\n * // Reveal full address on hover (still truncated when idle)\n * <AddressDisplay address=\"0x742d35Cc...\" untruncateOnHover />\n *\n * // Tooltip with full address on hover + copy icon on hover\n * <AddressDisplay address=\"0x742d35Cc...\" showTooltip showCopyButton showCopyButtonOnHover />\n *\n * // Inline variant (no chip background) — useful inside wallet bars\n * <AddressDisplay address=\"0x742d35Cc...\" variant=\"inline\" showTooltip showCopyButton />\n *\n * // Reverse-resolved name + avatar via an injected value (react layer owns the async)\n * <AddressDisplay address=\"0x742d35Cc...\" resolvedName={record} showCopyButton />\n *\n * // Or subtree-wide via context (rows stay plain <AddressDisplay/>)\n * <AddressNameProvider resolveAddressName={readFromResolutionCache}>\n * <AddressDisplay address=\"0x742d35Cc...\" />\n * </AddressNameProvider>\n *\n * // Truncate only when an alias/label is present (full address when unlabeled)\n * <AddressDisplay address=\"G...\" truncateWhenLabeled />\n * ```\n */\nexport function AddressDisplay({\n address,\n truncate: truncateProp,\n truncateWhenLabeled = false,\n untruncateOnHover = false,\n startChars = 6,\n endChars = 4,\n showCopyButton = false,\n showCopyButtonOnHover = false,\n explorerUrl,\n label: labelProp,\n onLabelEdit: onLabelEditProp,\n networkId,\n disableLabel = false,\n showTooltip = false,\n variant = 'chip',\n avatar,\n avatarVariant = 'fill',\n resolvedName,\n showCrossNetworkFallbackDisclaimer = true,\n className,\n onPointerEnter,\n onPointerLeave,\n onMouseEnter,\n onMouseLeave,\n onClick,\n ...props\n}: AddressDisplayProps): React.ReactElement {\n const [copied, setCopied] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n const copyTimeoutRef = React.useRef<number | null>(null);\n const prefersHover = usePrefersHover();\n\n // INV-60: both context reads are unconditional (stable hook order); the\n // record is derived by plain synchronous expressions — no resolution hook,\n // no async, ever (INV-121).\n const resolver = React.useContext(AddressLabelContext);\n const nameResolver = React.useContext(AddressNameContext);\n\n const resolvedLabel = disableLabel\n ? undefined\n : (labelProp ?? resolver?.resolveLabel(address, networkId));\n\n // INV-120: record source — the `resolvedName` prop shadows the context\n // resolver (mirrors the label channel's prop-shadows-context convention).\n // `disableLabel` renders the instance fully raw, so it gates this channel\n // too (dev-pinned 2026-07-06; deviation from the invariants-doc's\n // only-alias recommendation — existing disableLabel call-sites must not\n // sprout a name once a resolver is wired app-wide).\n const record = disableLabel\n ? undefined\n : (resolvedName ?? nameResolver?.resolveAddressName(address, networkId));\n\n // INV-52 (LOCKED, suppress-to-hex): the ONLY expression that can yield a\n // displayable resolved name. A record with `forwardVerified: false`\n // (forward-mismatch) and an undefined record (idle/loading/no-record/error,\n // collapsed upstream) both fall through to `undefined` → hex. No name-alone,\n // no name+warning. Control/bidi/zw stripped at this seam; confusables stay\n // with adapter ENSIP-15 normalization.\n const ensName =\n record?.forwardVerified === true ? sanitizeVerifiedNameForDisplay(record.name) : undefined;\n\n // INV-56: precedence — explicit `label` > alias > verified name > hex.\n // Collapses to the pre-enhancement `resolvedLabel` when nothing is injected\n // (INV-54: zero-injection byte-identical).\n const effectiveLabel = resolvedLabel ?? ensName;\n\n // INV-178 / INV-189: disclaimer only when the verified ENS name won label precedence.\n const showFallbackNote =\n showCrossNetworkFallbackDisclaimer &&\n ensName !== undefined &&\n effectiveLabel === ensName &&\n record !== undefined &&\n isCrossNetworkFallback(record.provenance);\n\n const fallbackNote = (() => {\n if (!showFallbackNote) return undefined;\n const networks = getFallbackNetworks(record.provenance);\n if (networks === undefined) return undefined;\n return nameResolutionCrossNetworkFallbackMessage(\n networks,\n crossNetworkFallbackMessageNames(networks, nameResolver?.resolveNetworkLabel)\n );\n })();\n\n const effectiveTruncate =\n truncateProp !== undefined\n ? truncateProp\n : truncateWhenLabeled\n ? Boolean(effectiveLabel)\n : true;\n\n const contextEditHandler = React.useCallback(() => {\n resolver?.onEditLabel?.(address, networkId);\n }, [resolver, address, networkId]);\n\n const editHandler = disableLabel\n ? undefined\n : (onLabelEditProp ?? (resolver?.onEditLabel ? contextEditHandler : undefined));\n\n const canUntruncate = untruncateOnHover && effectiveTruncate && !showTooltip;\n const showFullAddress = !effectiveTruncate || (canUntruncate && isHovered);\n const displayAddress = showFullAddress ? address : truncateMiddle(address, startChars, endChars);\n\n const addressTextClassName = cn(\n !showFullAddress && 'truncate',\n (showFullAddress || !effectiveTruncate) && 'break-all'\n );\n\n const expandInteractionClassName = canUntruncate && !prefersHover ? 'cursor-pointer' : undefined;\n\n const handlePointerEnter = (e: React.PointerEvent<HTMLDivElement>): void => {\n if (canUntruncate && prefersHover) {\n setIsHovered(true);\n }\n onPointerEnter?.(e);\n onMouseEnter?.(e as unknown as React.MouseEvent<HTMLDivElement>);\n };\n\n const handlePointerLeave = (e: React.PointerEvent<HTMLDivElement>): void => {\n if (canUntruncate && prefersHover) {\n setIsHovered(false);\n }\n onPointerLeave?.(e);\n onMouseLeave?.(e as unknown as React.MouseEvent<HTMLDivElement>);\n };\n\n const handleUntruncateClick = (e: React.MouseEvent<HTMLDivElement>): void => {\n if (canUntruncate && !prefersHover) {\n setIsHovered((open) => !open);\n }\n onClick?.(e);\n };\n\n const handleCopy = (e: React.MouseEvent): void => {\n e.stopPropagation();\n navigator.clipboard.writeText(address);\n setCopied(true);\n\n if (copyTimeoutRef.current) {\n window.clearTimeout(copyTimeoutRef.current);\n }\n copyTimeoutRef.current = window.setTimeout(() => {\n setCopied(false);\n copyTimeoutRef.current = null;\n }, 2000);\n };\n\n React.useEffect(() => {\n return (): void => {\n if (copyTimeoutRef.current) {\n window.clearTimeout(copyTimeoutRef.current);\n }\n };\n }, []);\n\n const isChip = variant === 'chip';\n\n const actionButtons = (\n <>\n {showCopyButton && (\n <button\n type=\"button\"\n onClick={handleCopy}\n className={cn(\n 'shrink-0 text-slate-500',\n !copied && 'hover:text-slate-700',\n showCopyButtonOnHover\n ? 'ml-0 w-0 overflow-hidden opacity-0 transition-all duration-150 group-hover:ml-1.5 group-hover:w-3.5 group-hover:opacity-100 focus:ml-1.5 focus:w-3.5 focus:opacity-100'\n : 'ml-1.5 transition-colors'\n )}\n aria-label={copied ? 'Copied' : 'Copy address'}\n >\n {copied ? (\n <Check className=\"h-3.5 w-3.5 text-emerald-600\" />\n ) : (\n <Copy className=\"h-3.5 w-3.5\" />\n )}\n </button>\n )}\n\n {explorerUrl && (\n <a\n href={explorerUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={(e) => {\n e.stopPropagation();\n }}\n className=\"ml-1.5 shrink-0 text-slate-500 transition-colors hover:text-slate-700\"\n aria-label=\"View in explorer\"\n >\n <ExternalLink className=\"h-3.5 w-3.5\" />\n </a>\n )}\n\n {editHandler && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n editHandler();\n }}\n className=\"ml-0 w-0 shrink-0 overflow-hidden text-slate-500 opacity-0 transition-all duration-150 hover:text-slate-700 group-hover:ml-1.5 group-hover:w-3.5 group-hover:opacity-100 focus:ml-1.5 focus:w-3.5 focus:opacity-100\"\n aria-label=\"Edit label\"\n >\n <Pencil className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </>\n );\n\n // INV-58: a constructed avatar exists ONLY when the verified name WON the\n // precedence (no explicit label, no alias) and the record carries a URL —\n // never next to an alias, explicit label, or bare hex. An explicit `avatar`\n // prop is highest precedence and always wins (preserves the D2 slot).\n const ensAvatarUrl =\n ensName !== undefined && resolvedLabel === undefined ? record?.avatarUrl : undefined;\n const effectiveAvatar =\n avatar ??\n (ensAvatarUrl ? <AddressAvatar src={ensAvatarUrl} variant={avatarVariant} /> : undefined);\n\n // A `'fill'` avatar stretches to the chip's full height flush to its edges;\n // it only changes layout when an avatar is actually shown.\n const isFillAvatar = avatarVariant === 'fill' && Boolean(effectiveAvatar);\n\n // On a chip, the `'fill'` avatar must break out of the container's padding to\n // sit flush against the top/bottom/left edges, and the container clips the\n // avatar's square outer corners to the chip radius.\n const fillAvatarChipClassName = isFillAvatar && isChip ? 'overflow-hidden' : undefined;\n\n // Leading avatar slot. Only materialized when an avatar exists, so an\n // undefined avatar leaves the rendered tree byte-for-byte identical (INV-54:\n // no wrapper element, no reserved space). `shrink-0` keeps it from\n // compressing. `'circle'`: the container's `items-center` vertically centers\n // a small round avatar. `'fill'`: a square, `self-stretch` box sized to the\n // text block's height (so the image, positioned absolutely inside, never\n // drives layout); negative margins cancel the chip padding on three edges and\n // `overflow-hidden` clips the image to the square.\n const avatarSlot = effectiveAvatar ? (\n <span\n className={cn(\n 'flex shrink-0',\n isFillAvatar\n ? // `self-stretch` fills the text block's height (edge-to-edge vertically);\n // `w-9` gives a definite width so the absolutely positioned image is\n // visible (a stretch-resolved height can't feed `aspect-square`).\n // Negative margins cancel the chip padding to sit flush to the edges.\n cn('relative w-9 self-stretch overflow-hidden mr-2', isChip && '-my-1 -ml-2')\n : 'mr-1.5 items-center'\n )}\n >\n {effectiveAvatar}\n </span>\n ) : null;\n\n const shouldShowTooltip = showTooltip && effectiveTruncate;\n\n const wrapWithTooltip = (content: React.ReactElement): React.ReactElement => {\n if (!shouldShowTooltip) return content;\n return (\n <TooltipProvider delayDuration={300}>\n <Tooltip>\n <TooltipTrigger asChild>{content}</TooltipTrigger>\n <TooltipContent className=\"font-mono text-xs\">{address}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n };\n\n if (effectiveLabel) {\n // The label-over-mono-hex column. Its internal structure is invariant across\n // the avatar / no-avatar paths (INV-54): with an avatar it is wrapped in a\n // leading-slot row; without one it is the container's direct children, so\n // the tree matches the pre-avatar component exactly. The verified name\n // flows through the SAME labeled branch an alias uses, so the mono hex\n // secondary line, copy button, explorer link, and edit pencil all keep\n // their existing a11y surface (INV-68).\n const labelColumn = (\n <>\n <span className=\"inline-flex min-w-0 max-w-full items-center gap-1\">\n <span className=\"truncate font-sans font-medium text-slate-900 leading-snug\">\n {effectiveLabel}\n </span>\n {fallbackNote && showCrossNetworkFallbackDisclaimer ? (\n <TooltipProvider delayDuration={300}>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex shrink-0 rounded-sm text-amber-500 outline-none focus-visible:ring-2 focus-visible:ring-amber-500/50\"\n aria-label={fallbackNote}\n >\n <TriangleAlert className=\"h-3 w-3\" aria-hidden />\n </button>\n </TooltipTrigger>\n <TooltipContent className=\"max-w-xs font-sans text-xs font-normal normal-case\">\n {fallbackNote}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n ) : null}\n </span>\n <div className=\"flex min-w-0 items-center font-mono text-[10px] text-slate-400 leading-snug\">\n <span className={addressTextClassName}>{displayAddress}</span>\n {actionButtons}\n </div>\n </>\n );\n\n return wrapWithTooltip(\n <div\n className={cn(\n 'group inline-flex max-w-full min-w-0',\n // Row when an avatar leads the block; the original flex-col otherwise.\n effectiveAvatar ? 'items-center' : 'flex-col',\n isChip && 'rounded-md bg-slate-100 px-2 py-1',\n fillAvatarChipClassName,\n 'text-xs text-slate-700',\n expandInteractionClassName,\n className\n )}\n onPointerEnter={handlePointerEnter}\n onPointerLeave={handlePointerLeave}\n onClick={handleUntruncateClick}\n {...props}\n >\n {effectiveAvatar ? (\n <>\n {avatarSlot}\n <div className=\"inline-flex min-w-0 flex-col\">{labelColumn}</div>\n </>\n ) : (\n labelColumn\n )}\n </div>\n );\n }\n\n return wrapWithTooltip(\n <div\n className={cn(\n 'group inline-flex max-w-full min-w-0 items-center',\n isChip && 'rounded-md bg-slate-100 px-2 py-1',\n fillAvatarChipClassName,\n 'text-xs font-mono text-slate-700',\n expandInteractionClassName,\n className\n )}\n onPointerEnter={handlePointerEnter}\n onPointerLeave={handlePointerLeave}\n onClick={handleUntruncateClick}\n {...props}\n >\n {avatarSlot}\n <span className={addressTextClassName}>{displayAddress}</span>\n {actionButtons}\n </div>\n );\n}\n","/**\n * Address Label Context\n *\n * Provides a React context for resolving human-readable labels for blockchain\n * addresses. When an `AddressLabelProvider` is mounted, every `AddressDisplay`\n * in the subtree automatically resolves and renders labels without any\n * call-site changes.\n *\n * @example\n * ```tsx\n * import { AddressLabelProvider } from '@openzeppelin/ui-components';\n *\n * function App() {\n * const resolver = useAliasLabelResolver(db);\n * return (\n * <AddressLabelProvider {...resolver}>\n * <MyApp />\n * </AddressLabelProvider>\n * );\n * }\n * ```\n */\nimport * as React from 'react';\n\nimport type { AddressLabelResolver } from '@openzeppelin/ui-types';\n\nimport { AddressLabelContext } from './context';\n\n// ============================================================================\n// Provider\n// ============================================================================\n\n/**\n * Props for `AddressLabelProvider`.\n *\n * Accepts the same shape as `AddressLabelResolver` so the provider can be\n * spread directly from a resolver hook: `<AddressLabelProvider {...resolver}>`.\n */\nexport interface AddressLabelProviderProps extends AddressLabelResolver {\n children: React.ReactNode;\n}\n\n/**\n * Provides address label resolution to all `AddressDisplay` instances in the\n * subtree. Wrap your application (or a subsection) with this provider and\n * supply a `resolveLabel` function.\n *\n * @param props - Resolver functions and children\n *\n * @example\n * ```tsx\n * <AddressLabelProvider\n * resolveLabel={(addr) => addressBook.get(addr)}\n * onEditLabel={(addr) => openEditor(addr)}\n * >\n * <App />\n * </AddressLabelProvider>\n * ```\n */\nexport function AddressLabelProvider({\n children,\n resolveLabel,\n onEditLabel,\n}: AddressLabelProviderProps): React.ReactElement {\n const value = React.useMemo<AddressLabelResolver>(\n () => ({ resolveLabel, onEditLabel }),\n [resolveLabel, onEditLabel]\n );\n\n return <AddressLabelContext.Provider value={value}>{children}</AddressLabelContext.Provider>;\n}\n","/**\n * Convenience hook for resolving an address label from the nearest\n * `AddressLabelProvider`.\n *\n * Kept in its own file so that `address-label-context.tsx` exports only\n * components (required by React Fast Refresh).\n */\nimport * as React from 'react';\n\nimport { AddressLabelContext } from './context';\n\n/**\n * Return type for the `useAddressLabel` convenience hook.\n */\nexport interface UseAddressLabelResult {\n /** Resolved label, or `undefined` if no resolver/label exists */\n label: string | undefined;\n /** Edit handler bound to this address, or `undefined` if editing is not supported */\n onEdit: (() => void) | undefined;\n}\n\n/**\n * Convenience hook that resolves a label for a specific address using the\n * nearest `AddressLabelProvider`. Returns `undefined` values when no provider\n * is mounted.\n *\n * @param address - The blockchain address to resolve\n * @param networkId - Optional network identifier for network-specific aliases\n * @returns Resolved label and edit handler for the address\n *\n * @example\n * ```tsx\n * function MyAddress({ address }: { address: string }) {\n * const { label, onEdit } = useAddressLabel(address, 'ethereum-mainnet');\n * return <span>{label ?? address}</span>;\n * }\n * ```\n */\nexport function useAddressLabel(address: string, networkId?: string): UseAddressLabelResult {\n const resolver = React.useContext(AddressLabelContext);\n\n const label = resolver?.resolveLabel(address, networkId);\n\n const onEdit = React.useCallback(() => {\n resolver?.onEditLabel?.(address, networkId);\n }, [resolver, address, networkId]);\n\n return { label, onEdit: resolver?.onEditLabel ? onEdit : undefined };\n}\n","/**\n * Address Name Context\n *\n * Provides a React context for surfacing already-resolved reverse name\n * records (`ResolvedName`) for blockchain addresses. When an\n * `AddressNameProvider` is mounted, every `AddressDisplay` in the subtree\n * reads its record synchronously — no call-site changes — and renders the\n * name/avatar only when the record is forward-verified (INV-52).\n *\n * Structural mirror of `AddressLabelProvider` (INV-122): synchronous,\n * value-only, no-op by default. The resolver implementation lives in the\n * react/renderer layer, which bridges async resolution state into this\n * synchronous read; this file stays capability-free (INV-121).\n *\n * @example\n * ```tsx\n * import { AddressNameProvider } from '@openzeppelin/ui-components';\n *\n * <AddressNameProvider resolveAddressName={readFromResolutionCache}>\n * <TxHistory /> {// rows are plain <AddressDisplay/> — verified names fill in }\n * </AddressNameProvider>\n * ```\n */\nimport * as React from 'react';\n\nimport type { AddressNameResolver } from '@openzeppelin/ui-types';\n\nimport { AddressNameContext } from './context';\n\n/**\n * Props for `AddressNameProvider`.\n *\n * Accepts the same shape as `AddressNameResolver` so the provider can be\n * spread directly from a resolver source: `<AddressNameProvider {...resolver}>`.\n */\nexport interface AddressNameProviderProps extends AddressNameResolver {\n children: React.ReactNode;\n}\n\n/**\n * Provides reverse-name resolution to all `AddressDisplay` instances in the\n * subtree. `resolveAddressName` MUST be synchronous — it is called during\n * render (INV-122). A resolver that returns `undefined` for an address is\n * behaviorally identical to mounting no provider (INV-54).\n *\n * @param props - Resolver function and children\n */\nexport function AddressNameProvider({\n children,\n resolveAddressName,\n resolveNetworkLabel,\n}: AddressNameProviderProps): React.ReactElement {\n const value = React.useMemo<AddressNameResolver>(\n () => ({ resolveAddressName, resolveNetworkLabel }),\n [resolveAddressName, resolveNetworkLabel]\n );\n\n return <AddressNameContext.Provider value={value}>{children}</AddressNameContext.Provider>;\n}\n","/**\n * Convenience hook for reading a reverse name record from the nearest\n * `AddressNameProvider`.\n *\n * Kept in its own file so that `address-name-context.tsx` exports only\n * components (required by React Fast Refresh) — mirrors `use-address-label.ts`.\n */\nimport * as React from 'react';\n\nimport type { ResolvedName } from '@openzeppelin/ui-types';\n\nimport { AddressNameContext } from './context';\n\n/**\n * Return type for the `useAddressName` convenience hook.\n */\nexport interface UseAddressNameResult {\n /** Resolved record, or `undefined` if no provider/record exists */\n record: ResolvedName | undefined;\n}\n\n/**\n * Reads the `AddressNameContext` for one address, synchronously (INV-122).\n * Returns `{ record: undefined }` when no provider is mounted — never throws,\n * never suspends. Note the record is returned verbatim: callers rendering a\n * name from it must apply the same `forwardVerified === true` gate that\n * `AddressDisplay` applies (INV-52).\n *\n * @param address - The blockchain address to reverse-resolve\n * @param networkId - Optional network identifier scoping the lookup\n * @returns The current best-known record for the address\n *\n * @example\n * ```tsx\n * function EnsBadge({ address }: { address: string }) {\n * const { record } = useAddressName(address);\n * return record?.forwardVerified ? <Badge>{record.name}</Badge> : null;\n * }\n * ```\n */\nexport function useAddressName(address: string, networkId?: string): UseAddressNameResult {\n const resolver = React.useContext(AddressNameContext);\n\n return { record: resolver?.resolveAddressName(address, networkId) };\n}\n","import { cva, type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst alertVariants = cva(\n 'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground',\n {\n variants: {\n variant: {\n default: 'bg-background text-foreground',\n destructive:\n 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',\n success: 'border-green-500/50 text-green-700 dark:border-green-500 [&>svg]:text-green-700',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div ref={ref} role=\"alert\" className={cn(alertVariants({ variant }), className)} {...props} />\n));\nAlert.displayName = 'Alert';\n\nconst AlertTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(\n ({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn('mb-1 font-medium leading-none tracking-tight', className)}\n {...props}\n />\n )\n);\nAlertTitle.displayName = 'AlertTitle';\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn('text-sm [&_p]:leading-relaxed', className)} {...props} />\n));\nAlertDescription.displayName = 'AlertDescription';\n\nexport { Alert, AlertTitle, AlertDescription };\n","import { X } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport type BannerVariant = 'info' | 'success' | 'warning' | 'error' | 'neutral';\n\nexport type BannerSize = 'default' | 'compact';\n\nexport interface BannerProps {\n /**\n * The variant/style of the banner\n * @default 'info'\n */\n variant?: BannerVariant;\n\n /**\n * Density preset for padding and typography\n * @default 'default'\n */\n size?: BannerSize;\n\n /**\n * Title text displayed at the top of the banner\n */\n title?: React.ReactNode;\n\n /**\n * Body text/content of the banner\n */\n children: React.ReactNode;\n\n /**\n * Whether the banner can be dismissed\n * @default true\n */\n dismissible?: boolean;\n\n /**\n * Callback when the banner is dismissed\n */\n onDismiss?: () => void;\n\n /**\n * Icon to display on the left (replaces default based on variant)\n */\n icon?: React.ReactNode;\n\n /**\n * Additional CSS classes\n */\n className?: string;\n}\n\nconst variantStyles: Record<\n BannerVariant,\n { container: string; icon: string; title: string; body: string }\n> = {\n info: {\n container: 'border-blue-200 bg-blue-50',\n icon: 'text-blue-600',\n title: 'text-blue-900',\n body: 'text-blue-800',\n },\n success: {\n container: 'border-green-200 bg-green-50',\n icon: 'text-green-600',\n title: 'text-green-900',\n body: 'text-green-800',\n },\n warning: {\n container: 'border-amber-200 bg-amber-50',\n icon: 'text-amber-600',\n title: 'text-amber-900',\n body: 'text-amber-800',\n },\n error: {\n container: 'border-red-200 bg-red-50',\n icon: 'text-red-600',\n title: 'text-red-900',\n body: 'text-red-800',\n },\n neutral: {\n container: 'border-border bg-muted/30',\n icon: 'text-muted-foreground',\n title: 'text-foreground',\n body: 'text-muted-foreground',\n },\n};\n\nconst sizeStyles: Record<\n BannerSize,\n { container: string; gap: string; title: string; body: string; dismissIcon: string }\n> = {\n default: {\n container: 'p-4',\n gap: 'gap-3',\n title: 'mb-2 text-sm font-semibold',\n body: 'text-sm whitespace-pre-line',\n dismissIcon: 'h-5 w-5',\n },\n compact: {\n container: 'px-4 py-3',\n gap: 'gap-2',\n title: 'mb-1 text-xs font-medium',\n body: 'text-xs leading-relaxed whitespace-pre-line',\n dismissIcon: 'h-4 w-4',\n },\n};\n\n/**\n * Dismissible banner component for notifications and alerts\n * Can be used with various variants (info, success, warning, error, neutral)\n */\nexport const Banner = React.forwardRef<HTMLDivElement, BannerProps>(\n (\n {\n className,\n variant = 'info',\n size = 'default',\n title,\n children,\n dismissible = true,\n onDismiss,\n icon,\n },\n ref\n ) => {\n const styles = variantStyles[variant];\n const sizing = sizeStyles[size];\n\n return (\n <div\n ref={ref}\n role=\"alert\"\n className={cn('rounded-md border', sizing.container, styles.container, className)}\n >\n <div className={cn('flex', sizing.gap)}>\n {icon && <div className={cn('mt-0.5 shrink-0', styles.icon)}>{icon}</div>}\n <div className=\"min-w-0 flex-1\">\n {title && <h4 className={cn(sizing.title, styles.title)}>{title}</h4>}\n <div className={cn(sizing.body, styles.body)}>{children}</div>\n </div>\n {dismissible && (\n <button\n type=\"button\"\n onClick={onDismiss}\n className={cn('self-start shrink-0 transition-colors hover:opacity-70', styles.icon)}\n aria-label=\"Dismiss banner\"\n >\n <X className={sizing.dismissIcon} />\n </button>\n )}\n </div>\n </div>\n );\n }\n);\nBanner.displayName = 'Banner';\n","import { cva } from 'class-variance-authority';\n\nexport const buttonVariants = cva(\n 'ring-offset-background focus-visible:ring-ring inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\n outline:\n 'border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground border',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n ghost: 'text-foreground hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-10 px-4 py-2',\n sm: 'h-9 rounded-md px-3',\n lg: 'h-11 rounded-md px-8',\n icon: 'size-10',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n);\n","import { Slot } from '@radix-ui/react-slot';\nimport { type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { buttonVariants } from '../../utils/button-variants';\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button';\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant || 'default'}\n data-size={size || 'default'}\n className={cn(buttonVariants({ variant, size, className }), 'cursor-pointer')}\n ref={ref}\n {...props}\n />\n );\n }\n);\nButton.displayName = 'Button';\n\nexport { Button };\n","'use client';\n\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\nimport * as React from 'react';\nimport { DayPicker } from 'react-day-picker';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { buttonVariants } from '../../utils/button-variants';\n\nexport type CalendarProps = React.ComponentProps<typeof DayPicker>;\n\n/**\n * Calendar component built on react-day-picker with shadcn/ui styling.\n * Supports single date, multiple dates, and date range selection modes.\n */\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n ...props\n}: CalendarProps): React.ReactElement {\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn('relative p-3', className)}\n classNames={{\n months: 'flex flex-col sm:flex-row gap-2 px-5',\n month: 'flex flex-col gap-4',\n month_caption: 'flex justify-center pt-1 relative items-center w-full',\n caption_label: 'text-sm font-medium',\n nav: 'flex items-center gap-1',\n button_previous: cn(\n buttonVariants({ variant: 'outline' }),\n 'absolute left-1 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100'\n ),\n button_next: cn(\n buttonVariants({ variant: 'outline' }),\n 'absolute right-1 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100'\n ),\n month_grid: 'w-full border-collapse space-y-1',\n weekdays: 'flex',\n weekday: 'text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]',\n week: 'flex w-full mt-2',\n day: cn(\n 'relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-selected/15 [&:has([aria-selected].day-outside)]:bg-selected/10 [&:has([aria-selected].day-range-end)]:rounded-r-md',\n props.mode === 'range'\n ? '[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md'\n : '[&:has([aria-selected])]:rounded-md'\n ),\n day_button: cn(\n buttonVariants({ variant: 'ghost' }),\n 'h-9 w-9 p-0 font-normal aria-selected:opacity-100 rounded-none hover:rounded-none'\n ),\n range_start: 'day-range-start rounded-l-md',\n range_end: 'day-range-end rounded-r-md',\n selected:\n 'bg-selected text-selected-foreground hover:bg-selected hover:text-selected-foreground focus:bg-selected focus:text-selected-foreground',\n today: 'bg-accent text-accent-foreground',\n outside:\n 'day-outside text-muted-foreground opacity-50 aria-selected:bg-selected/10 aria-selected:text-muted-foreground aria-selected:opacity-30',\n disabled: 'text-muted-foreground opacity-50',\n range_middle: 'aria-selected:bg-selected/15 aria-selected:text-foreground',\n hidden: 'invisible',\n ...classNames,\n }}\n components={{\n Chevron: ({ orientation }) => {\n const Icon = orientation === 'left' ? ChevronLeft : ChevronRight;\n return <Icon className=\"h-4 w-4\" />;\n },\n }}\n {...props}\n />\n );\n}\nCalendar.displayName = 'Calendar';\n\nexport { Calendar };\n","import { JSX } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\n/** Card container component with rounded borders. */\nfunction Card({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card\"\n className={cn('bg-card text-card-foreground flex flex-col rounded-xl border', className)}\n {...props}\n />\n );\n}\n\n/** Card header section for title and description. Provides top padding for the card. */\nfunction CardHeader({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-header\"\n className={cn('flex flex-col gap-1.5 px-6 pt-6', className)}\n {...props}\n />\n );\n}\n\n/** Card title with semibold styling. */\nfunction CardTitle({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-title\"\n className={cn('leading-none font-semibold', className)}\n {...props}\n />\n );\n}\n\n/** Card description with muted text styling. */\nfunction CardDescription({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-description\"\n className={cn('text-muted-foreground text-sm', className)}\n {...props}\n />\n );\n}\n\n/** Card content area with horizontal padding, top spacing, and bottom padding. */\nfunction CardContent({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return <div data-slot=\"card-content\" className={cn('px-6 pt-4 pb-6', className)} {...props} />;\n}\n\n/** Card footer with flex alignment for actions, top spacing, and bottom padding. */\nfunction CardFooter({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn('flex items-center px-6 pt-4 pb-6', className)}\n {...props}\n />\n );\n}\n\nexport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };\n","import * as CheckboxPrimitive from '@radix-ui/react-checkbox';\nimport { CheckIcon } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\n/** Checkbox component wrapping Radix UI Checkbox primitive. */\nfunction Checkbox({\n className,\n ...props\n}: React.ComponentProps<typeof CheckboxPrimitive.Root>): React.ReactElement {\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n 'border-input data-[state=checked]:bg-selected data-[state=checked]:text-selected-foreground data-[state=checked]:border-selected focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"flex items-center justify-center text-current transition-none\"\n >\n <CheckIcon data-slot=\"checkbox-indicator-icon\" className=\"size-3.5\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n );\n}\n\nexport { Checkbox };\n","'use client';\n\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst Popover = PopoverPrimitive.Root;\n\nconst PopoverTrigger = PopoverPrimitive.Trigger;\n\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 w-72 rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md outline-none',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2',\n 'data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };\n","'use client';\n\nimport { format } from 'date-fns';\nimport { Calendar as CalendarIcon } from 'lucide-react';\nimport type { DateRange } from 'react-day-picker';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Button } from './button';\nimport { Calendar } from './calendar';\nimport { Popover, PopoverContent, PopoverTrigger } from './popover';\n\n/**\n * Props for the DateRangePicker component.\n */\nexport interface DateRangePickerProps {\n /** The selected date range */\n value?: DateRange;\n /** Callback when the date range changes */\n onChange?: (range: DateRange | undefined) => void;\n /** Placeholder text when no date is selected */\n placeholder?: string;\n /** Additional CSS classes */\n className?: string;\n /** Whether the picker is disabled */\n disabled?: boolean;\n /** Number of months to display (default: 2) */\n numberOfMonths?: number;\n /** Alignment of the popover */\n align?: 'start' | 'center' | 'end';\n}\n\n/**\n * DateRangePicker component for selecting a date range.\n * Uses react-day-picker with Radix Popover for a shadcn-styled date range selection.\n *\n * @example\n * ```tsx\n * const [dateRange, setDateRange] = useState<DateRange | undefined>();\n *\n * <DateRangePicker\n * value={dateRange}\n * onChange={setDateRange}\n * placeholder=\"Select date range\"\n * />\n * ```\n */\nfunction DateRangePicker({\n value,\n onChange,\n placeholder = 'Pick a date range',\n className,\n disabled = false,\n numberOfMonths = 2,\n align = 'start',\n}: DateRangePickerProps): React.ReactElement {\n return (\n <div className={cn('grid gap-2', className)}>\n <Popover>\n <PopoverTrigger asChild>\n <Button\n id=\"date-range\"\n variant=\"outline\"\n disabled={disabled}\n className={cn(\n 'w-[280px] justify-start text-left font-normal',\n !value && 'text-muted-foreground'\n )}\n >\n <CalendarIcon className=\"mr-2 h-4 w-4\" />\n {value?.from ? (\n value.to ? (\n <>\n {format(value.from, 'LLL dd, y')} - {format(value.to, 'LLL dd, y')}\n </>\n ) : (\n format(value.from, 'LLL dd, y')\n )\n ) : (\n <span>{placeholder}</span>\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align={align}>\n <Calendar\n autoFocus\n mode=\"range\"\n defaultMonth={value?.from}\n selected={value}\n onSelect={onChange}\n numberOfMonths={numberOfMonths}\n />\n </PopoverContent>\n </Popover>\n </div>\n );\n}\nDateRangePicker.displayName = 'DateRangePicker';\n\nexport { DateRangePicker };\n\n// Re-export DateRange type for convenience\nexport type { DateRange };\n","import * as DialogPrimitive from '@radix-ui/react-dialog';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst Dialog = DialogPrimitive.Root;\n\nconst DialogTrigger = DialogPrimitive.Trigger;\n\nconst DialogPortal = DialogPrimitive.Portal;\n\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80',\n className\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n 'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 flex flex-col w-full max-w-lg translate-x-[-50%] translate-y-[-50%] border shadow-lg duration-200 sm:rounded-lg max-h-[90vh]',\n className\n )}\n {...props}\n >\n <DialogPrimitive.Close className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none z-10\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-x\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n <div className=\"overflow-y-auto p-6 flex flex-col gap-4\">{children}</div>\n </DialogPrimitive.Content>\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element => (\n <div className={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)} {...props} />\n);\nDialogHeader.displayName = 'DialogHeader';\n\nconst DialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element => (\n <div\n className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}\n {...props}\n />\n);\nDialogFooter.displayName = 'DialogFooter';\n\nconst DialogTitle = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn('text-lg leading-none font-semibold tracking-tight', className)}\n {...props}\n />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n className={cn('text-muted-foreground text-sm', className)}\n {...props}\n />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","'use client';\n\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { Check, ChevronRight, Circle } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst DropdownMenu = DropdownMenuPrimitive.Root;\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group;\n\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal;\n\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub;\n\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <DropdownMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n 'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent',\n inset && 'pl-8',\n className\n )}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto h-4 w-4\" />\n </DropdownMenuPrimitive.SubTrigger>\n));\nDropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;\n\nconst DropdownMenuSubContent = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n));\nDropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;\n\nconst DropdownMenuContent = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nconst DropdownMenuItem = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n inset && 'pl-8',\n className\n )}\n {...props}\n />\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n));\nDropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Circle className=\"h-2 w-2 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n));\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;\n\nconst DropdownMenuLabel = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', className)}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-muted', className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nconst DropdownMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>): React.ReactNode => {\n return (\n <span className={cn('ml-auto text-xs tracking-widest opacity-60', className)} {...props} />\n );\n};\nDropdownMenuShortcut.displayName = 'DropdownMenuShortcut';\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuGroup,\n DropdownMenuPortal,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuRadioGroup,\n};\n","import { Check, ChevronDown } from 'lucide-react';\nimport * as React from 'react';\n\nimport type { Ecosystem } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '.';\n\nexport interface EcosystemDropdownOption {\n value: Ecosystem;\n label: string;\n enabled: boolean;\n disabledLabel?: string;\n}\n\nexport interface EcosystemDropdownProps {\n options: EcosystemDropdownOption[];\n value: Ecosystem | null;\n onValueChange: (ecosystem: Ecosystem) => void;\n getEcosystemIcon?: (ecosystem: Ecosystem) => React.ReactNode;\n disabled?: boolean;\n className?: string;\n placeholder?: string;\n 'aria-labelledby'?: string;\n}\n\n/** Simple dropdown selector for choosing a blockchain ecosystem. */\nexport function EcosystemDropdown({\n options,\n value,\n onValueChange,\n getEcosystemIcon,\n disabled = false,\n className,\n placeholder = 'Select blockchain...',\n 'aria-labelledby': ariaLabelledby,\n}: EcosystemDropdownProps): React.ReactElement {\n const [open, setOpen] = React.useState(false);\n const selectedOption = options.find((o) => o.value === value);\n\n return (\n <DropdownMenu open={open} onOpenChange={setOpen}>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n aria-labelledby={ariaLabelledby}\n disabled={disabled}\n className={cn('w-full justify-between', className)}\n >\n <span className=\"flex items-center gap-2 truncate\">\n {selectedOption ? (\n <>\n {getEcosystemIcon?.(selectedOption.value)}\n <span className=\"truncate\">{selectedOption.label}</span>\n </>\n ) : (\n <span className=\"text-muted-foreground\">{placeholder}</span>\n )}\n </span>\n <ChevronDown className=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-[--radix-dropdown-menu-trigger-width] min-w-[200px]\"\n align=\"start\"\n >\n {options.map((option) => (\n <DropdownMenuItem\n key={option.value}\n disabled={!option.enabled}\n onSelect={() => {\n onValueChange(option.value);\n setOpen(false);\n }}\n className=\"gap-2\"\n >\n {getEcosystemIcon?.(option.value)}\n <span className=\"flex-1 truncate\">{option.label}</span>\n {!option.enabled && option.disabledLabel && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{option.disabledLabel}</span>\n )}\n {value === option.value && <Check className=\"h-4 w-4 shrink-0 opacity-100\" />}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","import React from 'react';\n\nexport interface MidnightIconProps {\n size?: number;\n className?: string;\n variant?: 'mono' | 'branded';\n}\n\n/**\n * MidnightIcon - SVG icon for the Midnight blockchain\n * Inline SVG to ensure it renders correctly when this package is consumed as a library\n */\nexport function MidnightIcon({\n size = 16,\n className = '',\n variant: _variant,\n}: MidnightIconProps): React.ReactElement {\n // variant is accepted for API consistency but not used as MidnightIcon is always branded\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 789.37 789.37\"\n width={size}\n height={size}\n className={className}\n aria-hidden=\"true\"\n >\n <path\n d=\"m394.69,0C176.71,0,0,176.71,0,394.69s176.71,394.69,394.69,394.69,394.69-176.71,394.69-394.69S612.67,0,394.69,0Zm0,716.6c-177.5,0-321.91-144.41-321.91-321.91S217.18,72.78,394.69,72.78s321.91,144.41,321.91,321.91-144.41,321.91-321.91,321.91Z\"\n fill=\"currentColor\"\n />\n <rect x=\"357.64\" y=\"357.64\" width=\"74.09\" height=\"74.09\" fill=\"currentColor\" />\n <rect x=\"357.64\" y=\"240.66\" width=\"74.09\" height=\"74.09\" fill=\"currentColor\" />\n <rect x=\"357.64\" y=\"123.69\" width=\"74.09\" height=\"74.09\" fill=\"currentColor\" />\n </svg>\n );\n}\n","import React from 'react';\n\nimport type { EcosystemMetadata } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { MidnightIcon } from '../icons/MidnightIcon';\n\nexport interface EcosystemIconProps {\n ecosystem: Pick<EcosystemMetadata, 'id' | 'iconComponent'>;\n /** Text used to derive the initial letter when no icon is available */\n fallbackLabel?: string;\n className?: string;\n size?: number;\n variant?: 'mono' | 'branded';\n}\n\n/** Displays the appropriate icon for a blockchain ecosystem. */\nexport function EcosystemIcon({\n ecosystem,\n fallbackLabel,\n className,\n size = 16,\n variant = 'branded',\n}: EcosystemIconProps): React.ReactElement {\n if (ecosystem.id === 'midnight') {\n return <MidnightIcon size={size} variant={variant} className={cn('shrink-0', className)} />;\n }\n\n if (ecosystem.iconComponent) {\n return (\n <ecosystem.iconComponent\n size={size}\n variant={variant}\n className={cn('shrink-0', className)}\n />\n );\n }\n\n const initial = (fallbackLabel ?? ecosystem.id).charAt(0).toUpperCase();\n\n return (\n <div\n className={cn(\n 'bg-muted text-muted-foreground shrink-0 rounded-full flex items-center justify-center font-medium',\n className\n )}\n style={{ width: size, height: size, fontSize: size * 0.5 }}\n role=\"img\"\n aria-label={fallbackLabel ?? ecosystem.id}\n >\n {initial}\n </div>\n );\n}\n","import { FileText } from 'lucide-react';\nimport React from 'react';\n\nexport interface EmptyStateProps {\n /**\n * The icon to display - can be a React component or SVG path\n */\n icon?: React.ReactNode;\n\n /**\n * Main heading text\n */\n title: string;\n\n /**\n * Descriptive text explaining the empty state\n */\n description: string;\n\n /**\n * Additional CSS classes for the container\n */\n className?: string;\n\n /**\n * Size variant for the empty state\n * @default 'default'\n */\n size?: 'small' | 'default' | 'large';\n}\n\n/**\n * Reusable empty state component for showing helpful messages when content is not available\n */\nexport function EmptyState({\n icon,\n title,\n description,\n className = '',\n size = 'default',\n}: EmptyStateProps): React.ReactElement {\n // Default icon using lucide-react\n const defaultIcon = <FileText className=\"h-6 w-6 text-muted-foreground\" />;\n\n // Size-based styling\n const sizeClasses = {\n small: {\n container: 'py-6',\n iconContainer: 'p-2 mb-2',\n title: 'text-base font-medium mb-1',\n description: 'text-xs max-w-sm',\n },\n default: {\n container: 'py-12',\n iconContainer: 'p-3 mb-4',\n title: 'text-lg font-medium mb-2',\n description: 'text-sm max-w-md',\n },\n large: {\n container: 'py-16',\n iconContainer: 'p-4 mb-6',\n title: 'text-xl font-medium mb-3',\n description: 'text-base max-w-lg',\n },\n };\n\n const styles = sizeClasses[size];\n\n return (\n <div\n className={`flex flex-col items-center justify-center text-center ${styles.container} ${className}`}\n >\n <div className={`rounded-full bg-muted ${styles.iconContainer}`}>{icon || defaultIcon}</div>\n <h3 className={`${styles.title}`}>{title}</h3>\n <p className={`text-muted-foreground ${styles.description}`}>{description}</p>\n </div>\n );\n}\n","import { ExternalLinkIcon } from 'lucide-react';\nimport React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\n// TODO: Add props\n// interface ExternalLinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n// // No additional props needed for basic functionality\n// }\n\n// export const ExternalLink = React.forwardRef<HTMLAnchorElement, ExternalLinkProps>(\nexport const ExternalLink = React.forwardRef<\n HTMLAnchorElement,\n React.AnchorHTMLAttributes<HTMLAnchorElement>\n>(({ children, className, ...props }, ref) => {\n return (\n <a\n ref={ref}\n className={cn(\n 'inline-flex items-center gap-1 text-primary underline-offset-4 hover:underline',\n className\n )}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n {...props}\n >\n {children}\n <ExternalLinkIcon className=\"h-3 w-3 ml-1\" /> {/* Adjust size/margin as needed */}\n </a>\n );\n});\n\nExternalLink.displayName = 'ExternalLink';\n","import { JSX } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\n/**\n * Props for the Footer component\n */\nexport interface FooterProps {\n /**\n * Company or organization name for the copyright notice\n * @default 'OpenZeppelin'\n */\n companyName?: string;\n\n /**\n * Copyright year to display\n * @default Current year\n */\n copyrightYear?: number;\n\n /**\n * URL for the privacy policy link\n * @default 'https://www.openzeppelin.com/privacy'\n */\n privacyPolicyUrl?: string;\n\n /**\n * Text for the privacy policy link\n * @default 'Privacy Policy'\n */\n privacyPolicyText?: string;\n\n /**\n * URL for the terms of service link\n * @default 'https://www.openzeppelin.com/tos'\n */\n termsOfServiceUrl?: string;\n\n /**\n * Text for the terms of service link\n * @default 'Terms of Service'\n */\n termsOfServiceText?: string;\n\n /**\n * Whether to show the privacy policy link\n * @default true\n */\n showPrivacyPolicy?: boolean;\n\n /**\n * Whether to show the terms of service link\n * @default true\n */\n showTermsOfService?: boolean;\n\n /**\n * Additional CSS classes for the footer container\n */\n className?: string;\n}\n\n/**\n * Application footer component with customizable legal links and branding.\n *\n * This component provides a consistent footer layout with customizable:\n * - Company name and copyright year\n * - Privacy policy and terms of service links and text\n * - Optional visibility controls for legal links\n * - Custom styling support\n */\nexport const Footer = ({\n companyName = 'OpenZeppelin',\n copyrightYear = new Date().getFullYear(),\n privacyPolicyUrl = 'https://www.openzeppelin.com/privacy',\n privacyPolicyText = 'Privacy Policy',\n termsOfServiceUrl = 'https://www.openzeppelin.com/tos',\n termsOfServiceText = 'Terms of Service',\n showPrivacyPolicy = true,\n showTermsOfService = true,\n className,\n}: FooterProps = {}): JSX.Element => {\n const hasLegalLinks = showPrivacyPolicy || showTermsOfService;\n\n return (\n <footer className={cn('border-t bg-background border-[#F5F5F5]', className)}>\n <div className=\"px-6 py-4 sm:h-12\">\n <div className=\"text-sm text-muted-foreground flex flex-col items-center gap-2 sm:flex-row sm:items-center sm:justify-between\">\n <span>\n © {copyrightYear} {companyName}\n </span>\n {hasLegalLinks && (\n <div className=\"flex flex-col items-center gap-2 sm:flex-row sm:gap-4\">\n {showPrivacyPolicy && (\n <a\n href={privacyPolicyUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"hover:text-foreground transition-colors\"\n >\n {privacyPolicyText}\n </a>\n )}\n {showTermsOfService && (\n <a\n href={termsOfServiceUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"hover:text-foreground transition-colors\"\n >\n {termsOfServiceText}\n </a>\n )}\n </div>\n )}\n </div>\n </div>\n </footer>\n );\n};\n","import * as LabelPrimitive from '@radix-ui/react-label';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\ntype LabelProps = React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>;\n/**\n * Label component for form fields, following shadcn/ui styling\n */\nconst Label = React.forwardRef<HTMLLabelElement, LabelProps>(({ className, ...props }, ref) => {\n return (\n <LabelPrimitive.Root\n ref={ref}\n data-slot=\"label\"\n className={cn('text-sm leading-none font-medium', className)}\n {...props}\n />\n );\n});\n\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label };\n","import * as React from 'react';\nimport type { FieldError, FieldPath, FieldValues, UseFormReturn } from 'react-hook-form';\nimport { Controller, FormProvider, useFormContext } from 'react-hook-form';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Label } from './label';\n\n/**\n * Context provider for the form\n */\nconst Form = <TFieldValues extends FieldValues = FieldValues, TContext = unknown>({\n ...props\n}: React.ComponentProps<typeof FormProvider<TFieldValues, TContext>>): React.ReactElement => {\n return <FormProvider {...props} />;\n};\n\n/**\n * Props for form field components\n */\ninterface FormFieldContextValue<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> {\n name: TName;\n}\n\n/**\n * Context for form field state\n */\nconst FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);\n\n/**\n * Get form field context\n */\nconst useFormField = (): {\n id: string;\n name: string;\n formItemId: string;\n formDescriptionId: string;\n formMessageId: string;\n error?: FieldError;\n} => {\n const fieldContext = React.useContext(FormFieldContext);\n const itemContext = React.useContext(FormItemContext);\n const { getFieldState, formState } = useFormContext();\n\n const fieldState = getFieldState(fieldContext.name, formState);\n\n if (!fieldContext) {\n throw new Error('useFormField should be used within <FormField>');\n }\n\n const { id } = itemContext;\n\n return {\n id,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n error: fieldState.error as FieldError | undefined,\n };\n};\n\n/**\n * Form field component\n */\nconst FormField = <\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n ...props\n}: ControllerProps<TFieldValues, TName>): React.ReactElement => {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n );\n};\n\n/**\n * Context for form item state\n */\ninterface FormItemContextValue {\n id: string;\n}\n\nconst FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);\n\n/**\n * Form item component\n */\nconst FormItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const id = React.useId();\n\n return (\n <FormItemContext.Provider value={{ id }}>\n <div\n ref={ref}\n data-slot=\"form-item\"\n className={cn('flex flex-col gap-2', className)}\n {...props}\n />\n </FormItemContext.Provider>\n );\n }\n);\nFormItem.displayName = 'FormItem';\n\n/**\n * Form label component\n */\nconst FormLabel = React.forwardRef<HTMLLabelElement, React.ComponentPropsWithoutRef<typeof Label>>(\n ({ className, ...props }, ref) => {\n const { error, formItemId } = useFormField();\n\n return (\n <Label\n ref={ref}\n className={error ? cn('text-destructive', className) : className}\n htmlFor={formItemId}\n {...props}\n />\n );\n }\n);\nFormLabel.displayName = 'FormLabel';\n\n/**\n * Form control component\n */\nconst FormControl = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ ...props }, ref) => {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField();\n\n return (\n <div\n ref={ref}\n id={formItemId}\n aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}\n aria-invalid={!!error}\n {...props}\n />\n );\n }\n);\nFormControl.displayName = 'FormControl';\n\n/**\n * Form description component\n */\nconst FormDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => {\n const { formDescriptionId } = useFormField();\n\n return (\n <p\n ref={ref}\n id={formDescriptionId}\n data-slot=\"form-description\"\n className={cn('text-muted-foreground text-sm', className)}\n {...props}\n />\n );\n});\nFormDescription.displayName = 'FormDescription';\n\n/**\n * Form error message component\n */\nconst FormMessage = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, children, ...props }, ref) => {\n const { error, formMessageId } = useFormField();\n const body = error ? String(error?.message) : children;\n\n if (!body) {\n return null;\n }\n\n return (\n <p\n ref={ref}\n id={formMessageId}\n data-slot=\"form-message\"\n className={cn('text-destructive text-sm font-medium', className)}\n {...props}\n >\n {body}\n </p>\n );\n});\nFormMessage.displayName = 'FormMessage';\n\n/**\n * Types for form controller props\n */\ntype ControllerProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> = {\n name: TName;\n control?: UseFormReturn<TFieldValues>['control'];\n render: (props: {\n field: {\n value: unknown;\n onChange: (...event: unknown[]) => void;\n onBlur: () => void;\n name: TName;\n ref: React.RefCallback<HTMLInputElement>;\n };\n fieldState: {\n invalid: boolean;\n isTouched: boolean;\n isDirty: boolean;\n error?: unknown;\n };\n formState: UseFormReturn<TFieldValues>['formState'];\n }) => React.ReactElement;\n};\n\nexport { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage };\n","import { Menu } from 'lucide-react';\nimport React from 'react';\n\nexport interface HeaderProps {\n title?: string;\n /** Open the mobile sidebar */\n onOpenSidebar?: () => void;\n /** Content to display on the right side of the header */\n rightContent?: React.ReactNode;\n}\n\nexport const Header = ({ title, onOpenSidebar, rightContent }: HeaderProps): React.ReactElement => {\n return (\n <header className=\"border-b border-[#F5F5F5] bg-background\">\n <div className=\"flex h-16 items-center px-3 sm:px-4 md:px-5 min-w-0\">\n {/* Mobile menu button */}\n <button\n type=\"button\"\n aria-label=\"Open menu\"\n onClick={onOpenSidebar}\n className=\"mr-2 sm:mr-3 inline-flex items-center justify-center rounded-md p-2 text-foreground hover:bg-muted focus:outline-none focus:ring-2 focus:ring-primary xl:hidden\"\n >\n <Menu className=\"size-5\" />\n </button>\n {/* Left side - Title (conditional) */}\n {title && (\n <div className=\"flex items-center min-w-0\">\n <h1 className=\"truncate max-w-[50vw] text-base font-semibold text-foreground\">\n {title}\n </h1>\n </div>\n )}\n\n {/* Right side - Wallet Connection or other content */}\n <div className=\"ml-auto flex items-center\">{rightContent}</div>\n </div>\n </header>\n );\n};\n","import * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\n/**\n * Input component that follows shadcn/ui styling and accessibility patterns\n */\nexport type InputProps = React.InputHTMLAttributes<HTMLInputElement>;\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n 'border-input bg-background ring-offset-background focus-visible:ring-ring placeholder:text-muted-foreground h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n ref={ref}\n {...props}\n />\n );\n }\n);\n\nInput.displayName = 'Input';\n\nexport { Input };\n","import { Slot, Slottable } from '@radix-ui/react-slot';\nimport { type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { buttonVariants } from '../../utils/button-variants';\n\n/**\n * Loading spinner component\n */\nconst Spinner = (): React.ReactElement => (\n <svg\n className=\"mr-2 h-4 w-4 animate-spin\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n);\n\nexport interface LoadingButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n loading?: boolean;\n}\n\nconst LoadingButton = React.forwardRef<HTMLButtonElement, LoadingButtonProps>(\n (\n { className, loading = false, children, disabled, variant, size, asChild = false, ...props },\n ref\n ) => {\n const Comp = asChild ? Slot : 'button';\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant || 'default'}\n data-size={size || 'default'}\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n disabled={loading || disabled}\n {...props}\n >\n {loading && <Spinner />}\n <Slottable>{children}</Slottable>\n </Comp>\n );\n }\n);\nLoadingButton.displayName = 'LoadingButton';\n\nexport { LoadingButton };\n","import React from 'react';\n\nimport type { NetworkConfig } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { MidnightIcon } from '../icons/MidnightIcon';\n\nexport interface NetworkIconProps {\n network: Pick<NetworkConfig, 'ecosystem' | 'iconComponent'>;\n className?: string;\n size?: number;\n variant?: 'mono' | 'branded';\n}\n\n/** Displays the appropriate icon for a blockchain network. */\nexport function NetworkIcon({\n network,\n className,\n size = 16,\n variant = 'branded',\n}: NetworkIconProps): React.ReactElement {\n if (network.ecosystem === 'midnight') {\n return <MidnightIcon size={size} variant={variant} className={cn('shrink-0', className)} />;\n }\n\n if (network.iconComponent) {\n return (\n <network.iconComponent size={size} variant={variant} className={cn('shrink-0', className)} />\n );\n }\n\n return (\n <div\n className={cn('bg-muted shrink-0 rounded-full', className)}\n style={{ width: size, height: size }}\n aria-hidden=\"true\"\n />\n );\n}\n","import { Check, ChevronDown, Search } from 'lucide-react';\nimport * as React from 'react';\n\nimport type { NetworkType } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Input,\n} from '.';\n\ninterface NetworkSelectorBaseProps<T> {\n networks: T[];\n getNetworkLabel: (network: T) => string;\n getNetworkIcon?: (network: T) => React.ReactNode;\n getNetworkType?: (network: T) => NetworkType | undefined;\n getNetworkId: (network: T) => string;\n groupByEcosystem?: boolean;\n getEcosystem?: (network: T) => string;\n filterNetwork?: (network: T, query: string) => boolean;\n /** When true, the network cannot be selected */\n isNetworkDisabled?: (network: T) => boolean;\n /** Optional label for disabled networks (e.g. \"Self-host required\") */\n getNetworkDisabledLabel?: (network: T) => string | undefined;\n className?: string;\n placeholder?: string;\n}\n\ninterface SingleSelectProps<T> {\n multiple?: false;\n selectedNetwork: T | null;\n onSelectNetwork: (network: T) => void;\n selectedNetworkIds?: never;\n onSelectionChange?: never;\n renderTrigger?: never;\n}\n\ninterface MultiSelectProps<_T> {\n multiple: true;\n selectedNetworkIds: string[];\n onSelectionChange: (ids: string[]) => void;\n /** Override the default trigger button with a custom element. */\n renderTrigger?: (props: { selectedCount: number; open: boolean }) => React.ReactNode;\n selectedNetwork?: never;\n onSelectNetwork?: never;\n}\n\nexport type NetworkSelectorProps<T> = NetworkSelectorBaseProps<T> &\n (SingleSelectProps<T> | MultiSelectProps<T>);\n\n/** Searchable dropdown selector for blockchain networks with optional grouping and multi-select. */\nexport function NetworkSelector<T>({\n networks,\n getNetworkLabel,\n getNetworkIcon,\n getNetworkType,\n getNetworkId,\n groupByEcosystem = false,\n getEcosystem,\n filterNetwork,\n isNetworkDisabled,\n getNetworkDisabledLabel,\n className,\n placeholder = 'Select Network',\n ...modeProps\n}: NetworkSelectorProps<T>): React.ReactElement {\n const [open, setOpen] = React.useState(false);\n const [searchQuery, setSearchQuery] = React.useState('');\n\n const isMultiple = modeProps.multiple === true;\n\n const selectedNetworkIds = isMultiple ? modeProps.selectedNetworkIds : undefined;\n const onSelectionChange = isMultiple ? modeProps.onSelectionChange : undefined;\n const selectedNetwork = !isMultiple ? modeProps.selectedNetwork : undefined;\n const onSelectNetwork = !isMultiple ? modeProps.onSelectNetwork : undefined;\n\n const filteredNetworks = React.useMemo(() => {\n if (!searchQuery) return networks;\n if (filterNetwork) return networks.filter((n) => filterNetwork(n, searchQuery));\n return networks.filter((n) =>\n getNetworkLabel(n).toLowerCase().includes(searchQuery.toLowerCase())\n );\n }, [networks, searchQuery, filterNetwork, getNetworkLabel]);\n\n const groupedNetworks = React.useMemo(() => {\n if (!groupByEcosystem || !getEcosystem) {\n return { All: filteredNetworks };\n }\n return filteredNetworks.reduce(\n (acc, network) => {\n const ecosystem = getEcosystem(network);\n if (!acc[ecosystem]) {\n acc[ecosystem] = [];\n }\n acc[ecosystem].push(network);\n return acc;\n },\n {} as Record<string, T[]>\n );\n }, [filteredNetworks, groupByEcosystem, getEcosystem]);\n\n const isSelected = React.useCallback(\n (network: T): boolean => {\n if (isMultiple && selectedNetworkIds) {\n return selectedNetworkIds.includes(getNetworkId(network));\n }\n return selectedNetwork ? getNetworkId(selectedNetwork) === getNetworkId(network) : false;\n },\n [isMultiple, selectedNetworkIds, selectedNetwork, getNetworkId]\n );\n\n const handleSelect = React.useCallback(\n (network: T) => {\n if (isNetworkDisabled?.(network)) {\n return;\n }\n\n if (isMultiple && selectedNetworkIds && onSelectionChange) {\n const id = getNetworkId(network);\n const next = selectedNetworkIds.includes(id)\n ? selectedNetworkIds.filter((x) => x !== id)\n : [...selectedNetworkIds, id];\n onSelectionChange(next);\n } else if (onSelectNetwork) {\n onSelectNetwork(network);\n setOpen(false);\n }\n },\n [\n isMultiple,\n selectedNetworkIds,\n onSelectionChange,\n onSelectNetwork,\n getNetworkId,\n isNetworkDisabled,\n ]\n );\n\n const handleClearAll = React.useCallback(() => {\n if (isMultiple && onSelectionChange) {\n onSelectionChange([]);\n }\n }, [isMultiple, onSelectionChange]);\n\n const selectedCount = selectedNetworkIds?.length ?? 0;\n const renderTrigger = isMultiple ? modeProps.renderTrigger : undefined;\n\n const triggerContent = (() => {\n if (isMultiple && renderTrigger) {\n return renderTrigger({ selectedCount, open });\n }\n\n if (isMultiple) {\n return (\n <Button\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n className={cn('w-full justify-between', className)}\n >\n <span className=\"truncate text-muted-foreground\">\n {selectedCount > 0\n ? `${selectedCount} network${selectedCount > 1 ? 's' : ''} selected`\n : placeholder}\n </span>\n <ChevronDown className=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n );\n }\n\n return (\n <Button\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n className={cn('w-full justify-between', className)}\n >\n <span className=\"flex items-center gap-2 truncate\">\n {selectedNetwork ? (\n <>\n {getNetworkIcon?.(selectedNetwork)}\n <span className=\"truncate\">{getNetworkLabel(selectedNetwork)}</span>\n {getNetworkType && (\n <span className=\"shrink-0 rounded-sm bg-muted px-1.5 py-0.5 text-[10px] font-medium uppercase text-muted-foreground\">\n {getNetworkType(selectedNetwork)}\n </span>\n )}\n </>\n ) : (\n <span className=\"text-muted-foreground\">{placeholder}</span>\n )}\n </span>\n <ChevronDown className=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n );\n })();\n\n return (\n <DropdownMenu open={open} onOpenChange={setOpen}>\n <DropdownMenuTrigger asChild>{triggerContent}</DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-[--radix-dropdown-menu-trigger-width] min-w-[240px] p-0\"\n align=\"start\"\n >\n <div className=\"flex items-center border-b px-3\">\n <Search className=\"mr-2 h-4 w-4 shrink-0 opacity-50\" />\n <Input\n placeholder=\"Search network...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' && e.key !== 'Enter') {\n e.stopPropagation();\n }\n }}\n className=\"h-9 w-full border-0 bg-transparent p-0 placeholder:text-muted-foreground focus-visible:ring-0 focus-visible:ring-offset-0\"\n aria-label=\"Search networks\"\n />\n </div>\n <div className=\"max-h-[300px] overflow-y-auto p-1\">\n {isMultiple && selectedCount > 0 && (\n <>\n <div className=\"flex items-center justify-between px-2 py-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n {selectedCount} selected\n </span>\n <button\n onClick={handleClearAll}\n className=\"text-xs text-muted-foreground hover:text-foreground\"\n >\n Clear all\n </button>\n </div>\n <DropdownMenuSeparator />\n </>\n )}\n\n {Object.entries(groupedNetworks).length === 0 ? (\n <div className=\"py-6 text-center text-sm text-muted-foreground\">No network found.</div>\n ) : (\n Object.entries(groupedNetworks).map(([group, groupNetworks], index) => (\n <React.Fragment key={group}>\n {groupByEcosystem && (\n <DropdownMenuLabel className=\"text-xs font-medium text-muted-foreground\">\n {group}\n </DropdownMenuLabel>\n )}\n <DropdownMenuGroup>\n {groupNetworks.map((network) => {\n const disabled = isNetworkDisabled?.(network) ?? false;\n const disabledLabel = disabled ? getNetworkDisabledLabel?.(network) : undefined;\n\n return (\n <DropdownMenuItem\n key={getNetworkId(network)}\n disabled={disabled}\n onSelect={(e) => {\n if (disabled) {\n e.preventDefault();\n return;\n }\n if (isMultiple) e.preventDefault();\n handleSelect(network);\n }}\n className={cn('gap-2', disabled && 'cursor-not-allowed opacity-60')}\n >\n {isMultiple ? (\n <div\n className={cn(\n 'flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border transition-colors',\n isSelected(network)\n ? 'border-selected bg-selected text-selected-foreground'\n : 'border-input bg-background',\n disabled && 'opacity-50'\n )}\n >\n {isSelected(network) && <Check className=\"h-3 w-3\" />}\n </div>\n ) : null}\n {getNetworkIcon?.(network)}\n <div className=\"flex flex-1 items-center gap-2 min-w-0\">\n <span className=\"truncate\">{getNetworkLabel(network)}</span>\n {getNetworkType && (\n <span className=\"shrink-0 rounded-sm bg-muted px-1.5 py-0.5 text-[10px] font-medium uppercase text-muted-foreground\">\n {getNetworkType(network)}\n </span>\n )}\n {disabledLabel ? (\n <span className=\"shrink-0 rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground\">\n {disabledLabel}\n </span>\n ) : null}\n </div>\n {!isMultiple && isSelected(network) && (\n <Check className=\"h-4 w-4 text-selected opacity-100\" />\n )}\n </DropdownMenuItem>\n );\n })}\n </DropdownMenuGroup>\n {index < Object.keys(groupedNetworks).length - 1 && <DropdownMenuSeparator />}\n </React.Fragment>\n ))\n )}\n </div>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","import React from 'react';\n\nimport type { NetworkConfig } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { NetworkIcon } from './network-icon';\n\ninterface NetworkStatusBadgeProps {\n network: NetworkConfig | null;\n className?: string;\n}\n\n// Define constants for consistency\nconst ICON_SIZE = 16;\n\n/**\n * NetworkStatusBadge - Displays network information in a compact badge format\n * Shows the network icon, ecosystem, and name with dashed borders for testnet/devnet\n */\nexport function NetworkStatusBadge({\n network,\n className,\n}: NetworkStatusBadgeProps): React.ReactElement | null {\n if (!network) return null;\n\n const isTestnetLike = network.type === 'testnet' || network.type === 'devnet';\n\n return (\n <div\n className={cn(\n 'inline-flex items-center gap-2 rounded-full bg-muted px-3 py-2',\n isTestnetLike ? 'border-2 border-dashed border-muted-foreground/40' : 'border-0',\n className\n )}\n >\n {/* Network icon */}\n <NetworkIcon network={network} size={ICON_SIZE} />\n\n {/* Combined ecosystem + network name */}\n <div className=\"flex items-baseline gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground uppercase\">\n {network.ecosystem}\n </span>\n <span className=\"text-xs font-medium\">{network.name}</span>\n </div>\n </div>\n );\n}\n","import { MoreHorizontal } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '.';\n\n/** Single action item within an OverflowMenu dropdown. */\nexport interface OverflowMenuItem {\n id: string;\n label: string;\n icon?: React.ReactNode;\n destructive?: boolean;\n disabled?: boolean;\n onSelect: () => void;\n}\n\n/** Props for the OverflowMenu component. */\nexport interface OverflowMenuProps {\n items: OverflowMenuItem[];\n /** Align dropdown relative to trigger. @default \"end\" */\n align?: 'start' | 'center' | 'end';\n /** Additional classes on the trigger button. */\n className?: string;\n /** Accessible label for the trigger button. @default \"More actions\" */\n 'aria-label'?: string;\n}\n\n/** Compact \"...\" dropdown menu for secondary actions. */\nexport function OverflowMenu({\n items,\n align = 'end',\n className,\n 'aria-label': ariaLabel = 'More actions',\n}: OverflowMenuProps) {\n if (items.length === 0) return null;\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className={cn('h-8 w-8', className)}\n aria-label={ariaLabel}\n >\n <MoreHorizontal className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align={align} className=\"min-w-[140px]\">\n {items.map((item, index) => (\n <React.Fragment key={item.id}>\n {item.destructive && index > 0 && <DropdownMenuSeparator />}\n <DropdownMenuItem\n onClick={item.onSelect}\n disabled={item.disabled}\n className={cn(item.destructive && 'text-destructive focus:text-destructive')}\n >\n {item.icon}\n {item.label}\n </DropdownMenuItem>\n </React.Fragment>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","import * as ProgressPrimitive from '@radix-ui/react-progress';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst Progress = React.forwardRef<\n React.ElementRef<typeof ProgressPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n>(({ className, value, ...props }, ref) => (\n <ProgressPrimitive.Root\n ref={ref}\n className={cn(\n 'relative h-2 w-full overflow-hidden rounded-full bg-gray-100 dark:bg-gray-800',\n className\n )}\n {...props}\n >\n <ProgressPrimitive.Indicator\n className=\"bg-primary h-full w-full flex-1 transition-all\"\n style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\n />\n </ProgressPrimitive.Root>\n));\nProgress.displayName = ProgressPrimitive.Root.displayName;\n\nexport { Progress };\n","import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';\nimport { Circle } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst RadioGroup = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>\n>(({ className, ...props }, ref) => {\n return (\n <RadioGroupPrimitive.Root\n className={cn('flex flex-col space-y-2', className)}\n data-slot=\"radiogroup\"\n {...props}\n ref={ref}\n />\n );\n});\nRadioGroup.displayName = RadioGroupPrimitive.Root.displayName;\n\nconst RadioGroupItem = React.forwardRef<\n HTMLButtonElement,\n React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>\n>(({ className, ...props }, ref) => {\n return (\n <RadioGroupPrimitive.Item\n ref={ref}\n className={cn(\n 'border-input bg-background text-selected h-4 w-4 rounded-full border shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator className=\"flex items-center justify-center\">\n <Circle className=\"h-2.5 w-2.5 fill-current text-current\" />\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n );\n});\nRadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;\n\nexport { RadioGroup, RadioGroupItem };\n","import * as SelectPrimitive from '@radix-ui/react-select';\nimport { Check, ChevronDown, ChevronUp } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nconst Select = SelectPrimitive.Root;\n\nconst SelectGroup = SelectPrimitive.Group;\n\nconst SelectValue = SelectPrimitive.Value;\n\nconst SelectTrigger = React.forwardRef<\n HTMLButtonElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger\n ref={ref}\n data-slot=\"select-trigger\"\n className={cn(\n 'border-input bg-background placeholder:text-muted-foreground flex h-10 w-full items-center justify-between rounded-md border px-3 py-2 text-sm focus:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDown className=\"h-4 w-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n));\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName;\n\nconst SelectScrollUpButton = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n data-slot=\"select-scroll-button\"\n className={className}\n {...props}\n >\n <ChevronUp className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollUpButton>\n));\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;\n\nconst SelectScrollDownButton = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n data-slot=\"select-scroll-button\"\n className={className}\n {...props}\n >\n <ChevronDown className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollDownButton>\n));\nSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;\n\nconst SelectContent = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = 'popper', ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n data-slot=\"select-content\"\n className={cn(\n 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-96 w-[var(--radix-select-trigger-width)] overflow-hidden rounded-md border shadow-md',\n position === 'popper' &&\n 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n className\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n 'p-1',\n position === 'popper' &&\n 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\nSelectContent.displayName = SelectPrimitive.Content.displayName;\n\nconst SelectLabel = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n data-slot=\"select-label\"\n className={cn('py-1.5 pr-2 pl-8 text-sm font-semibold', className)}\n {...props}\n />\n));\nSelectLabel.displayName = SelectPrimitive.Label.displayName;\n\nconst SelectItem = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n data-slot=\"select-item\"\n className={cn(\n 'hover:bg-accent relative flex w-full cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors duration-150 outline-none select-none focus:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span\n data-slot=\"select-item-indicator\"\n className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\"\n >\n <SelectPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n));\nSelectItem.displayName = SelectPrimitive.Item.displayName;\n\nconst SelectSeparator = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n data-slot=\"select-separator\"\n className={cn('bg-muted -mx-1 my-1 h-px', className)}\n {...props}\n />\n));\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName;\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n};\n","import React, { ReactNode } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport interface SidebarButtonProps {\n icon?: ReactNode;\n children: ReactNode;\n onClick?: () => void;\n size?: 'default' | 'small';\n badge?: string;\n disabled?: boolean;\n isSelected?: boolean;\n /** When provided, renders as an anchor element instead of a button */\n href?: string;\n target?: React.HTMLAttributeAnchorTarget;\n rel?: string;\n className?: string;\n}\n\n/**\n * A styled button component for sidebar actions with consistent styling.\n * Can render as a button or anchor element depending on whether href is provided.\n */\nexport function SidebarButton({\n icon,\n children,\n onClick,\n size = 'default',\n badge,\n disabled = false,\n isSelected = false,\n href,\n target,\n rel,\n className,\n}: SidebarButtonProps): React.ReactElement {\n const minHeight = size === 'small' ? 'min-h-10' : 'min-h-11';\n\n const commonClass = cn(\n 'group relative flex flex-wrap items-center gap-x-2 gap-y-0.5 px-3 py-2 rounded-lg font-semibold text-sm transition-colors',\n badge ? 'justify-between' : 'justify-start',\n disabled\n ? 'text-muted-foreground/60 cursor-not-allowed'\n : isSelected\n ? 'text-selected bg-selected/10'\n : 'text-muted-foreground hover:text-foreground cursor-pointer hover:before:content-[\"\"] hover:before:absolute hover:before:inset-x-0 hover:before:top-1 hover:before:bottom-1 hover:before:bg-muted/80 hover:before:rounded-lg hover:before:-z-10',\n minHeight,\n className\n );\n\n const content = (\n <>\n <div className=\"flex items-center gap-2\">\n {icon}\n {children}\n </div>\n {badge && (\n <span className=\"text-xs px-2 py-0.5 bg-muted text-muted-foreground rounded-full font-medium\">\n {badge}\n </span>\n )}\n </>\n );\n\n if (href) {\n return (\n <a href={href} target={target} rel={rel} className={commonClass} onClick={onClick}>\n {content}\n </a>\n );\n }\n\n return (\n <button className={commonClass} onClick={disabled ? undefined : onClick} disabled={disabled}>\n {content}\n </button>\n );\n}\n","import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';\nimport { ChevronRight } from 'lucide-react';\nimport React, { ReactNode, useState } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport interface SidebarGroupProps {\n /** Title displayed in the collapsible trigger */\n title: string;\n /** Optional icon displayed before the title */\n icon?: ReactNode;\n /** Content to render when expanded */\n children: ReactNode;\n /** Whether the group is open by default */\n defaultOpen?: boolean;\n /** Controlled open state */\n open?: boolean;\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Additional CSS classes for the container */\n className?: string;\n /** Additional CSS classes for the trigger */\n triggerClassName?: string;\n /** Additional CSS classes for the content wrapper */\n contentClassName?: string;\n}\n\n/**\n * A collapsible group component for organizing sidebar navigation items.\n * Supports both controlled and uncontrolled modes.\n */\nexport function SidebarGroup({\n title,\n icon,\n children,\n defaultOpen = false,\n open: controlledOpen,\n onOpenChange,\n className,\n triggerClassName,\n contentClassName,\n}: SidebarGroupProps): React.ReactElement {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : uncontrolledOpen;\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (!isControlled) {\n setUncontrolledOpen(nextOpen);\n }\n onOpenChange?.(nextOpen);\n };\n\n return (\n <CollapsiblePrimitive.Root\n open={isOpen}\n onOpenChange={handleOpenChange}\n className={cn('w-full', className)}\n >\n <CollapsiblePrimitive.Trigger\n className={cn(\n 'group flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-semibold',\n 'text-muted-foreground transition-colors hover:text-foreground',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n triggerClassName\n )}\n >\n <ChevronRight\n className={cn('size-4 shrink-0 transition-transform duration-200', isOpen && 'rotate-90')}\n />\n {icon && <span className=\"shrink-0\">{icon}</span>}\n <span className=\"flex-1 text-left\">{title}</span>\n </CollapsiblePrimitive.Trigger>\n\n <CollapsiblePrimitive.Content\n className={cn(\n 'overflow-hidden transition-all duration-200 ease-in-out',\n 'data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down',\n contentClassName\n )}\n >\n <div className=\"py-1 pl-4\">{children}</div>\n </CollapsiblePrimitive.Content>\n </CollapsiblePrimitive.Root>\n );\n}\n","import React, { ReactNode } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport interface SidebarLayoutProps {\n /** Content for the sidebar header (e.g., logo) */\n header?: ReactNode;\n /** Content to be displayed below the header but above the scrollable area */\n subHeader?: ReactNode;\n /** Main scrollable content area */\n children: ReactNode;\n /** Content for the fixed footer (e.g., nav icons) */\n footer?: ReactNode;\n /** Additional CSS classes for the sidebar container */\n className?: string;\n /** Width of the sidebar (default: 289px) */\n width?: number | string;\n /** Background color/class for the sidebar */\n background?: string;\n /** Controls visibility in mobile slide-over */\n mobileOpen?: boolean;\n /** Close handler for mobile slide-over */\n onMobileOpenChange?: (open: boolean) => void;\n /** Aria label for mobile dialog */\n mobileAriaLabel?: string;\n}\n\n/**\n * A flexible sidebar layout component with desktop sidebar and mobile slide-over.\n * Provides slots for header, scrollable content, and footer.\n */\nexport function SidebarLayout({\n header,\n subHeader,\n children,\n footer,\n className,\n width = 289,\n background = 'bg-[rgba(245,245,245,0.31)]',\n mobileOpen,\n onMobileOpenChange,\n mobileAriaLabel = 'Menu',\n}: SidebarLayoutProps): React.ReactElement {\n const widthStyle = typeof width === 'number' ? `${width}px` : width;\n\n return (\n <>\n {/* Desktop Sidebar */}\n <div\n className={cn(\n 'fixed left-0 top-0 z-40 h-full hidden xl:flex xl:flex-col',\n background,\n className\n )}\n style={{ width: widthStyle }}\n >\n {/* Fixed Header */}\n {header && <div className=\"shrink-0 px-8 pt-12\">{header}</div>}\n\n {/* Fixed SubHeader */}\n {subHeader && <div className=\"shrink-0 px-8 mt-6\">{subHeader}</div>}\n\n {/* Scrollable Content Area */}\n <div className=\"flex-1 overflow-y-auto px-8 pb-24\">{children}</div>\n\n {/* Fixed Footer */}\n {footer && <div className=\"pointer-events-auto sticky bottom-0 px-8 py-4\">{footer}</div>}\n </div>\n\n {/* Spacer to push content (desktop only) */}\n <div className=\"hidden xl:block\" style={{ width: widthStyle }} />\n\n {/* Mobile slide-over */}\n {typeof mobileOpen === 'boolean' && onMobileOpenChange && (\n <div\n className={cn(\n 'xl:hidden fixed inset-0 z-50',\n mobileOpen ? 'pointer-events-auto' : 'pointer-events-none'\n )}\n aria-hidden={!mobileOpen}\n >\n {/* Backdrop */}\n <div\n className={cn(\n 'absolute inset-0 bg-black/40 transition-opacity',\n mobileOpen ? 'opacity-100' : 'opacity-0'\n )}\n onClick={() => onMobileOpenChange(false)}\n />\n {/* Panel */}\n <div\n className={cn(\n 'absolute left-0 top-0 h-full w-[85%] max-w-[320px] bg-[rgba(245,245,245,0.98)] shadow-xl transition-transform',\n mobileOpen ? 'translate-x-0' : '-translate-x-full'\n )}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={mobileAriaLabel}\n >\n <div className=\"flex h-full flex-col\">\n {/* Mobile Header */}\n {header && <div className=\"shrink-0 px-6 pt-10 pb-4\">{header}</div>}\n\n {/* Mobile SubHeader */}\n {subHeader && <div className=\"shrink-0 px-6 pb-4\">{subHeader}</div>}\n\n {/* Mobile Scrollable Content */}\n <div className=\"flex-1 overflow-y-auto px-6 pb-20\">{children}</div>\n\n {/* Mobile Footer */}\n {footer && <div className=\"px-6 py-4\">{footer}</div>}\n </div>\n </div>\n </div>\n )}\n </>\n );\n}\n","import React, { ReactNode } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport interface SidebarSectionProps {\n /** Optional section title displayed above the content */\n title?: string;\n /** Content to render within the section */\n children: ReactNode;\n /** Additional CSS classes */\n className?: string;\n /** CSS classes for the title element */\n titleClassName?: string;\n /** Whether this section should grow to fill available space */\n grow?: boolean;\n}\n\n/**\n * A generic sidebar section wrapper with optional title.\n * Used to group related sidebar items together.\n */\nexport function SidebarSection({\n title,\n children,\n className,\n titleClassName,\n grow = false,\n}: SidebarSectionProps): React.ReactElement {\n return (\n <div className={cn('flex flex-col w-full', grow && 'flex-1', className)}>\n {title && (\n <div className={cn('text-[#5e5e5e] text-xs font-semibold leading-4 mb-1', titleClassName)}>\n {title}\n </div>\n )}\n <div className={cn('flex flex-col', grow && 'flex-1 overflow-hidden')}>{children}</div>\n </div>\n );\n}\n","import * as TabsPrimitive from '@radix-ui/react-tabs';\nimport * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\n/** Tabs container component wrapping Radix UI Tabs Root. */\nfunction Tabs({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Root>): React.ReactElement {\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n className={cn('flex w-full max-w-full min-w-0 flex-col gap-2 overflow-x-hidden', className)}\n {...props}\n />\n );\n}\n\n/** Tabs list component containing tab triggers. */\nfunction TabsList({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.List>): React.ReactElement {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n className={cn(\n 'bg-muted text-muted-foreground flex h-9 w-full max-w-full min-w-0 items-center justify-start rounded-lg p-1 overflow-x-auto overflow-y-hidden flex-nowrap overscroll-x-contain [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden sm:overflow-visible',\n className\n )}\n {...props}\n />\n );\n}\n\n/** Individual tab trigger button. */\nfunction TabsTrigger({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Trigger>): React.ReactElement {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n \"data-[state=active]:bg-background data-[state=active]:text-selected focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring inline-flex flex-1 items-center justify-center gap-1.5 rounded-md px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\n/** Tab content panel displayed when its trigger is active. */\nfunction TabsContent({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Content>): React.ReactElement {\n return (\n <TabsPrimitive.Content\n data-slot=\"tabs-content\"\n className={cn('flex-1 outline-none', className)}\n {...props}\n />\n );\n}\n\nexport { Tabs, TabsContent, TabsList, TabsTrigger };\n","import * as React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, ...props }, ref) => {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n 'border-input bg-background ring-offset-background focus-visible:ring-ring placeholder:text-muted-foreground aria-invalid:ring-destructive/20 aria-invalid:border-destructive dark:aria-invalid:ring-destructive/40 min-h-16 w-full rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n ref={ref}\n {...props}\n />\n );\n }\n);\nTextarea.displayName = 'Textarea';\n\nexport { Textarea };\n","import { FileText } from 'lucide-react';\nimport React from 'react';\n\nimport { truncateMiddle } from '@openzeppelin/ui-utils';\n\nimport { Button } from './button';\n\ninterface ViewContractStateButtonProps {\n contractAddress: string | null;\n onToggle: () => void;\n}\n\n/**\n * ViewContractStateButton - A button to toggle the contract state widget\n * Shows the contract address in a truncated format\n */\nexport function ViewContractStateButton({\n contractAddress,\n onToggle,\n}: ViewContractStateButtonProps): React.ReactElement | null {\n if (!contractAddress) return null;\n\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"px-3 py-2 h-auto gap-2 items-start justify-start sm:items-center\"\n onClick={onToggle}\n title=\"Show Contract State\"\n >\n <FileText size={16} className=\"shrink-0 self-center\" />\n <span className=\"flex flex-col sm:flex-row sm:items-center text-left leading-tight\">\n <span className=\"text-sm font-medium\">View Contract State</span>\n <span className=\"text-xs text-muted-foreground sm:ml-1\">\n ({truncateMiddle(contractAddress)})\n </span>\n </span>\n </Button>\n );\n}\n","import { AlertCircle, Check, Pencil } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport React from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nexport type StepStatus = 'pending' | 'completed' | 'skipped';\n\nexport type StepVisualState = 'completed' | 'current' | 'visited' | 'invalid' | 'upcoming';\n\nexport interface WizardStepDef {\n id: string;\n title: string;\n status?: StepStatus;\n /** When true the step is highlighted with an error indicator. */\n isInvalid?: boolean;\n}\n\nexport interface WizardStepperProps {\n steps: WizardStepDef[];\n currentStepIndex: number;\n /** Index of the furthest step the user has reached. Steps up to this index stay clickable. */\n furthestStepIndex?: number;\n onStepClick?: (index: number) => void;\n variant?: 'vertical' | 'horizontal';\n /** When true all steps are clickable regardless of their state (used by scrollable layout). */\n freeNavigation?: boolean;\n className?: string;\n}\n\nfunction resolveState(\n step: WizardStepDef,\n index: number,\n currentStepIndex: number,\n furthestStepIndex: number\n): StepVisualState {\n if (step.status === 'completed' || step.status === 'skipped') return 'completed';\n if (index === currentStepIndex) return 'current';\n if (step.isInvalid && (index < currentStepIndex || index <= furthestStepIndex)) return 'invalid';\n if (index < currentStepIndex) return 'completed';\n if (index <= furthestStepIndex) return 'visited';\n return 'upcoming';\n}\n\nfunction canClick(state: StepVisualState, freeNavigation = false): boolean {\n if (freeNavigation) return true;\n return state !== 'upcoming';\n}\n\nfunction StepCircle({ state, index }: { state: StepVisualState; index: number }) {\n return (\n <span\n className={cn(\n 'flex size-6 shrink-0 items-center justify-center rounded-full text-xs font-semibold transition-all',\n state === 'completed' && 'bg-selected text-selected-foreground',\n state === 'current' && 'bg-selected text-selected-foreground ring-2 ring-selected/30',\n state === 'visited' && 'bg-selected/10 text-selected ring-1 ring-selected/40',\n state === 'invalid' && 'bg-destructive/10 text-destructive ring-1 ring-destructive/40',\n state === 'upcoming' && 'bg-muted text-muted-foreground'\n )}\n >\n {state === 'completed' ? (\n <Check className=\"size-3.5\" />\n ) : state === 'visited' ? (\n <Pencil className=\"size-3\" />\n ) : state === 'invalid' ? (\n <AlertCircle className=\"size-3.5\" />\n ) : (\n index + 1\n )}\n </span>\n );\n}\n\nfunction StepLabel({\n title,\n state,\n isSkipped,\n}: {\n title: string;\n state: StepVisualState;\n isSkipped: boolean;\n}) {\n return (\n <div className=\"min-w-0 flex-1\">\n <span\n className={cn(\n 'text-sm font-medium transition-colors',\n state === 'current' && 'text-selected',\n state === 'completed' && 'text-foreground',\n state === 'visited' && 'text-selected',\n state === 'invalid' && 'text-destructive',\n state === 'upcoming' && 'text-muted-foreground'\n )}\n >\n {title}\n </span>\n {isSkipped && <span className=\"mt-0.5 block text-[11px] text-muted-foreground\">Skipped</span>}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Vertical variant — card-wrapped sidebar\n// ---------------------------------------------------------------------------\n\nfunction VerticalStepper({\n steps,\n currentStepIndex,\n furthestStepIndex = currentStepIndex,\n onStepClick,\n freeNavigation,\n className,\n}: WizardStepperProps) {\n return (\n <nav\n aria-label=\"Wizard steps\"\n className={cn('rounded-2xl border border-border bg-card p-6', className)}\n >\n <div className=\"flex flex-col gap-1\">\n {steps.map((step, index) => {\n const state = resolveState(step, index, currentStepIndex, furthestStepIndex);\n const clickable = canClick(state, freeNavigation) && !!onStepClick;\n\n return (\n <button\n key={step.id}\n type=\"button\"\n onClick={() => clickable && onStepClick?.(index)}\n disabled={!clickable}\n className={cn(\n 'flex items-center gap-3 rounded-xl border border-transparent px-3 py-3 text-left transition-all duration-150',\n clickable ? 'cursor-pointer' : 'cursor-not-allowed opacity-50',\n state === 'current' && 'border-selected/40 bg-selected/5',\n state === 'completed' && 'bg-card hover:bg-muted/40',\n state === 'visited' && 'bg-card hover:bg-selected/5',\n state === 'invalid' &&\n 'border-destructive/40 bg-destructive/5 hover:bg-destructive/10',\n state === 'upcoming' && 'bg-card'\n )}\n aria-current={state === 'current' ? 'step' : undefined}\n >\n <StepCircle state={state} index={index} />\n <StepLabel title={step.title} state={state} isSkipped={step.status === 'skipped'} />\n </button>\n );\n })}\n </div>\n </nav>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Horizontal variant — card-wrapped top bar with connector lines\n// ---------------------------------------------------------------------------\n\nfunction HorizontalStepper({\n steps,\n currentStepIndex,\n furthestStepIndex = currentStepIndex,\n onStepClick,\n freeNavigation,\n className,\n}: WizardStepperProps) {\n return (\n <nav\n aria-label=\"Wizard steps\"\n className={cn('rounded-2xl border border-border bg-card p-6', className)}\n >\n <div className=\"flex w-full items-center\">\n {steps.map((step, index) => {\n const state = resolveState(step, index, currentStepIndex, furthestStepIndex);\n const clickable = canClick(state, freeNavigation) && !!onStepClick;\n const isLast = index === steps.length - 1;\n\n return (\n <React.Fragment key={step.id}>\n <button\n type=\"button\"\n onClick={() => clickable && onStepClick?.(index)}\n disabled={!clickable}\n className={cn(\n 'flex items-center gap-2 rounded-xl border border-transparent px-3 py-2 text-left transition-all duration-150',\n clickable ? 'cursor-pointer' : 'cursor-not-allowed opacity-50',\n state === 'current' && 'border-selected/40 bg-selected/5',\n state === 'completed' && 'bg-card hover:bg-muted/40',\n state === 'visited' && 'bg-card hover:bg-selected/5',\n state === 'invalid' &&\n 'border-destructive/40 bg-destructive/5 hover:bg-destructive/10',\n state === 'upcoming' && 'bg-card'\n )}\n aria-current={state === 'current' ? 'step' : undefined}\n aria-label={`Step ${index + 1}: ${step.title}`}\n >\n <StepCircle state={state} index={index} />\n <div className=\"hidden sm:block\">\n <StepLabel\n title={step.title}\n state={state}\n isSkipped={step.status === 'skipped'}\n />\n </div>\n </button>\n\n {!isLast && (\n <div\n className={cn(\n 'mx-1 h-px flex-1 transition-colors sm:mx-2',\n index < currentStepIndex ? 'bg-selected' : 'bg-border'\n )}\n />\n )}\n </React.Fragment>\n );\n })}\n </div>\n </nav>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Public component\n// ---------------------------------------------------------------------------\n\n/**\n * A stepper component for navigating through a series of steps.\n *\n * @param props - The props for the WizardStepper component.\n * @returns A React node representing the stepper component.\n */\nexport function WizardStepper(props: WizardStepperProps): ReactNode {\n const { variant = 'horizontal', ...rest } = props;\n return variant === 'vertical' ? (\n <VerticalStepper {...rest} variant={variant} />\n ) : (\n <HorizontalStepper {...rest} variant={variant} />\n );\n}\n","import { ChevronLeft, ChevronRight, X } from 'lucide-react';\nimport type { ReactNode } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Button } from '../button';\n\nexport interface WizardNavigationProps {\n isFirstStep: boolean;\n isLastStep: boolean;\n canProceed?: boolean;\n onPrevious: () => void;\n onNext: () => void;\n onCancel?: () => void;\n /** Extra actions rendered between Cancel/Previous and Next (e.g. Show Code) */\n extraActions?: ReactNode;\n nextLabel?: string;\n lastStepLabel?: string;\n /**\n * Optional secondary action on the **last step** only, shown to the left of the\n * primary control with a less prominent (outline) style. Omitted when either\n * `lastStepSecondaryLabel` or `onLastStepSecondary` is missing.\n */\n onLastStepSecondary?: () => void;\n lastStepSecondaryLabel?: string;\n lastStepSecondaryDisabled?: boolean;\n /**\n * When `false` on the last step, the primary Next/Finish button is omitted\n * (e.g. when the step body provides its own primary action).\n * @default true\n */\n showLastStepPrimary?: boolean;\n className?: string;\n}\n\n/**\n * A navigation component for the wizard.\n *\n * @param props - The props for the WizardNavigation component.\n * @returns A React node representing the navigation component.\n */\nexport function WizardNavigation({\n isFirstStep,\n isLastStep,\n canProceed = true,\n onPrevious,\n onNext,\n onCancel,\n extraActions,\n nextLabel = 'Next',\n lastStepLabel = 'Finish',\n onLastStepSecondary,\n lastStepSecondaryLabel,\n lastStepSecondaryDisabled,\n showLastStepPrimary = true,\n className,\n}: WizardNavigationProps) {\n const showPrimary = !isLastStep || showLastStepPrimary;\n const showSecondary =\n isLastStep &&\n lastStepSecondaryLabel != null &&\n lastStepSecondaryLabel !== '' &&\n onLastStepSecondary != null;\n\n return (\n <div className={cn('flex items-center justify-between', className)}>\n <div className=\"flex gap-2\">\n {onCancel && (\n <Button type=\"button\" variant=\"outline\" onClick={onCancel} className=\"gap-2\">\n <X className=\"size-4\" />\n Cancel\n </Button>\n )}\n {!isFirstStep && (\n <Button type=\"button\" variant=\"outline\" onClick={onPrevious} className=\"gap-2\">\n <ChevronLeft className=\"size-4\" />\n Previous\n </Button>\n )}\n </div>\n\n <div className=\"flex gap-2\">\n {extraActions}\n {showSecondary && (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onLastStepSecondary}\n disabled={lastStepSecondaryDisabled ?? false}\n className=\"gap-2\"\n >\n {lastStepSecondaryLabel}\n </Button>\n )}\n {showPrimary && (\n <Button type=\"button\" onClick={onNext} disabled={!canProceed} className=\"gap-2\">\n {isLastStep ? lastStepLabel : nextLabel}\n {!isLastStep && <ChevronRight className=\"size-4\" />}\n </Button>\n )}\n </div>\n </div>\n );\n}\n","import { useCallback, useEffect, useRef, useState, type RefObject } from 'react';\n\ninterface StepWithId {\n id: string;\n}\n\ninterface UseScrollableWizardStepTrackingOptions<TStep extends StepWithId> {\n steps: TStep[];\n currentStepIndex: number;\n onStepChange: (index: number) => void;\n scrollRef: RefObject<HTMLDivElement | null>;\n sectionId: (stepId: string) => string;\n /**\n * Pixels to keep between the container top and the scrolled-to section.\n * Defaults to 32 (matches the `p-8` padding on the scroll column).\n */\n scrollPadding?: number;\n}\n\n/**\n * Clamp a step index into the valid range for the current wizard.\n */\nexport function getSafeStepIndex(stepCount: number, currentStepIndex: number) {\n if (stepCount === 0) return 0;\n\n return Math.max(0, Math.min(currentStepIndex, stepCount - 1));\n}\n\n/**\n * Track the highest step reached unless a controlled value is provided.\n */\nexport function useFurthestStepIndex(\n currentStepIndex: number,\n controlledFurthestStepIndex?: number\n) {\n const [internalFurthestStepIndex, setInternalFurthestStepIndex] = useState(currentStepIndex);\n\n useEffect(() => {\n setInternalFurthestStepIndex((prev) => Math.max(prev, currentStepIndex));\n }, [currentStepIndex]);\n\n return controlledFurthestStepIndex ?? internalFurthestStepIndex;\n}\n\n/**\n * Keep the scrollable wizard's active and visited step state in sync with scrolling and clicks.\n */\nexport function useScrollableWizardStepTracking<TStep extends StepWithId>({\n steps,\n currentStepIndex,\n onStepChange,\n scrollRef,\n sectionId,\n scrollPadding = SCROLL_PADDING_PX,\n}: UseScrollableWizardStepTrackingOptions<TStep>) {\n const safeIndex = getSafeStepIndex(steps.length, currentStepIndex);\n const initialIndexRef = useRef(safeIndex);\n const rafRef = useRef<number | null>(null);\n const manualSelectionIndexRef = useRef<number | null>(null);\n\n // Keep a ref to the latest steps/sectionId/onStepChange so the scroll\n // handler always uses fresh values without being a dependency.\n const stepsRef = useRef(steps);\n const sectionIdRef = useRef(sectionId);\n const onStepChangeRef = useRef(onStepChange);\n const scrollPaddingRef = useRef(scrollPadding);\n useEffect(() => {\n stepsRef.current = steps;\n sectionIdRef.current = sectionId;\n onStepChangeRef.current = onStepChange;\n scrollPaddingRef.current = scrollPadding;\n });\n\n const [activeIndex, setActiveIndex] = useState(initialIndexRef.current);\n const activeIndexRef = useRef(initialIndexRef.current);\n const [furthestStepIndex, setFurthestStepIndex] = useState(initialIndexRef.current);\n\n // Ref flag used to suppress the onStepChange call from the initial mount\n // scroll evaluation, preventing a React render-order violation where an\n // external store update fires during the commit phase of a sibling component.\n // Using a ref (rather than a local variable) ensures the flag is reliably\n // set before the RAF callback executes, even in environments where the RAF\n // fires synchronously or immediately after scheduling.\n const isMountedRef = useRef(false);\n\n const clearManualSelection = useCallback(() => {\n manualSelectionIndexRef.current = null;\n }, []);\n\n // Wire up scroll tracking once, against the stable scrollRef.\n // Steps/sectionId changes are consumed via refs so this effect never\n // re-runs (and never inadvertently clears the manual selection lock).\n useEffect(() => {\n const container = scrollRef.current;\n if (!container) return;\n const ownerDocument = container.ownerDocument;\n\n isMountedRef.current = false;\n // Gate used inside the first RAF callback to flip isMountedRef only after\n // the initial scroll evaluation completes — ensuring onStepChange is never\n // called during the React commit phase on mount.\n let didCompleteInitialRaf = false;\n\n const releaseManualSelectionOnUserScroll = () => {\n clearManualSelection();\n };\n const handleKeyDown = (event: KeyboardEvent) => {\n if (isScrollableNavigationKey(event)) {\n clearManualSelection();\n }\n };\n\n const handleScroll = () => {\n if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);\n\n rafRef.current = requestAnimationFrame(() => {\n const currentSteps = stepsRef.current;\n const currentSectionId = sectionIdRef.current;\n const currentOnStepChange = onStepChangeRef.current;\n\n if (currentSteps.length === 0) return;\n\n const manualSelectionIndex = manualSelectionIndexRef.current;\n const naturalState = resolveScrollableActiveIndex(\n container,\n currentSteps,\n currentSectionId\n );\n const naturalActiveIndex = naturalState.activeIndex;\n const newActiveIndex = manualSelectionIndex ?? naturalActiveIndex;\n const shouldCommitFurthestStepIndex =\n manualSelectionIndex !== null ? true : naturalState.commitFurthestStepIndex;\n\n const prevActiveIndex = activeIndexRef.current;\n if (prevActiveIndex !== newActiveIndex) {\n activeIndexRef.current = newActiveIndex;\n setActiveIndex(newActiveIndex);\n // Only notify the parent once the initial mount RAF has completed so\n // we don't call setState on a sibling component during React's commit\n // phase. isMountedRef is set to true at the end of the first RAF run.\n if (isMountedRef.current) {\n lastEmittedIndexRef.current = newActiveIndex;\n currentOnStepChange(newActiveIndex);\n }\n } else {\n setActiveIndex(newActiveIndex);\n }\n if (shouldCommitFurthestStepIndex) {\n setFurthestStepIndex((prev) => Math.max(prev, newActiveIndex));\n }\n rafRef.current = null;\n\n // Mark mounted at the very end of the first RAF so subsequent scroll\n // events (and the RAF callbacks they schedule) can call onStepChange.\n if (!didCompleteInitialRaf) {\n didCompleteInitialRaf = true;\n isMountedRef.current = true;\n }\n });\n };\n\n container.addEventListener('wheel', releaseManualSelectionOnUserScroll, { passive: true });\n container.addEventListener('touchmove', releaseManualSelectionOnUserScroll, { passive: true });\n // pointerdown covers scrollbar drag and other pointer-based scrolling that\n // does not fire wheel or touchmove events.\n container.addEventListener('pointerdown', releaseManualSelectionOnUserScroll);\n ownerDocument.addEventListener('keydown', handleKeyDown);\n container.addEventListener('scroll', handleScroll, { passive: true });\n handleScroll();\n\n return () => {\n isMountedRef.current = false;\n container.removeEventListener('wheel', releaseManualSelectionOnUserScroll);\n container.removeEventListener('touchmove', releaseManualSelectionOnUserScroll);\n container.removeEventListener('pointerdown', releaseManualSelectionOnUserScroll);\n ownerDocument.removeEventListener('keydown', handleKeyDown);\n container.removeEventListener('scroll', handleScroll);\n if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);\n };\n // Intentionally only re-run when the scroll container itself changes.\n // steps/sectionId/onStepChange are consumed via refs above.\n }, [clearManualSelection, scrollRef]);\n\n // Tracks the last index this hook reported to the parent via onStepChange.\n // Used to distinguish external prop changes (true programmatic navigation)\n // from echoes of our own scroll-driven updates flowing back as props.\n const lastEmittedIndexRef = useRef(safeIndex);\n\n // Sync activeIndex and scroll position when currentStepIndex is changed\n // externally (e.g. programmatic navigation from outside the scrollable layout).\n // We skip the sync when currentStepIndex simply echoes the value we last\n // emitted ourselves — otherwise scroll-driven onStepChange calls would\n // create a feedback loop that bounces the scroll position back to the\n // previously active section.\n useEffect(() => {\n const newSafeIndex = getSafeStepIndex(stepsRef.current.length, currentStepIndex);\n\n // Echo of our own last emission — not an external command, ignore.\n if (newSafeIndex === lastEmittedIndexRef.current) return;\n\n // External navigation: adopt the new index and scroll to it.\n lastEmittedIndexRef.current = newSafeIndex;\n activeIndexRef.current = newSafeIndex;\n setActiveIndex(newSafeIndex);\n setFurthestStepIndex((prev) => Math.max(prev, newSafeIndex));\n\n const step = stepsRef.current[newSafeIndex];\n if (!step) return;\n const sectionElement = scrollRef.current?.querySelector<HTMLElement>(\n `#${CSS.escape(sectionIdRef.current(step.id))}`\n );\n if (scrollRef.current && sectionElement)\n scrollSectionIntoView(scrollRef.current, sectionElement, scrollPaddingRef.current);\n }, [currentStepIndex, scrollRef]);\n\n const scrollToSection = useCallback(\n (index: number) => {\n const step = stepsRef.current[index];\n if (!step) return;\n\n manualSelectionIndexRef.current = index;\n activeIndexRef.current = index;\n lastEmittedIndexRef.current = index;\n setActiveIndex(index);\n setFurthestStepIndex((prev) => Math.max(prev, index));\n onStepChangeRef.current(index);\n\n const container = scrollRef.current;\n const sectionElement = container?.querySelector<HTMLElement>(\n `#${CSS.escape(sectionIdRef.current(step.id))}`\n );\n if (container && sectionElement)\n scrollSectionIntoView(container, sectionElement, scrollPaddingRef.current);\n },\n [scrollRef]\n );\n\n return {\n activeIndex,\n furthestStepIndex,\n scrollToSection,\n };\n}\n\nfunction resolveScrollableActiveIndex<TStep extends StepWithId>(\n container: HTMLDivElement,\n steps: TStep[],\n sectionId: (stepId: string) => string\n) {\n if (steps.length === 0) {\n return {\n activeIndex: 0,\n commitFurthestStepIndex: false,\n };\n }\n\n const containerRect = container.getBoundingClientRect();\n const anchorY = containerRect.top + Math.min(containerRect.height * 0.35, 220);\n const isScrollable = container.scrollHeight > container.clientHeight + 1;\n const isAtBottom =\n isScrollable && container.scrollTop + container.clientHeight >= container.scrollHeight - 1;\n const isNearBottom =\n isScrollable && container.scrollTop + container.clientHeight >= container.scrollHeight - 4;\n\n if (isAtBottom) {\n return {\n activeIndex: steps.length - 1,\n commitFurthestStepIndex: false,\n };\n }\n\n let activeIndex = 0;\n let highestScore = Number.NEGATIVE_INFINITY;\n for (let i = 0; i < steps.length; i++) {\n const sectionMetrics = getSectionMetrics(container, steps[i].id, sectionId, containerRect);\n if (!sectionMetrics) continue;\n\n const score = scoreScrollableStep({\n stepIndex: i,\n stepCount: steps.length,\n containerRect,\n anchorY,\n isNearBottom,\n ...sectionMetrics,\n });\n\n if (score >= highestScore) {\n highestScore = score;\n activeIndex = i;\n }\n }\n\n return {\n activeIndex,\n commitFurthestStepIndex: true,\n };\n}\n\n// Matches the p-8 (32px) padding on the scrollable content column so that\n// auto-scrolled sections align flush with the sidebar card's top border.\nconst SCROLL_PADDING_PX = 32;\n\nfunction getSectionElement(\n container: HTMLDivElement,\n stepId: string,\n sectionId: (stepId: string) => string\n) {\n return container.querySelector<HTMLElement>(`#${CSS.escape(sectionId(stepId))}`);\n}\n\nfunction scrollSectionIntoView(\n container: HTMLDivElement,\n sectionElement: HTMLElement,\n padding: number\n) {\n const elementTop = sectionElement.getBoundingClientRect().top;\n const containerTop = container.getBoundingClientRect().top;\n const targetScrollTop = container.scrollTop + (elementTop - containerTop) - padding;\n container.scrollTo({\n top: targetScrollTop,\n behavior: 'smooth',\n });\n}\n\nfunction getSectionMetrics(\n container: HTMLDivElement,\n stepId: string,\n sectionId: (stepId: string) => string,\n containerRect: DOMRect\n) {\n const sectionElement = getSectionElement(container, stepId, sectionId);\n if (!sectionElement) return null;\n\n const sectionRect = sectionElement.getBoundingClientRect();\n\n return {\n sectionRect,\n visibleHeight: getVisibleHeight(containerRect, sectionRect),\n };\n}\n\nfunction getVisibleHeight(containerRect: DOMRect, sectionRect: DOMRect) {\n return Math.max(\n 0,\n Math.min(sectionRect.bottom, containerRect.bottom) -\n Math.max(sectionRect.top, containerRect.top)\n );\n}\n\nfunction scoreScrollableStep({\n stepIndex,\n stepCount,\n containerRect,\n sectionRect,\n visibleHeight,\n anchorY,\n isNearBottom,\n}: {\n stepIndex: number;\n stepCount: number;\n containerRect: DOMRect;\n sectionRect: DOMRect;\n visibleHeight: number;\n anchorY: number;\n isNearBottom: boolean;\n}) {\n const isVisible = visibleHeight > 0;\n const focusBandTop = containerRect.top + Math.min(containerRect.height * 0.2, 140);\n const focusBandBottom = containerRect.top + Math.min(containerRect.height * 0.55, 360);\n const focusBandOverlap = getBandOverlapHeight(sectionRect, focusBandTop, focusBandBottom);\n const distanceToFocusBand =\n focusBandOverlap > 0\n ? 0\n : Math.min(\n Math.abs(sectionRect.top - focusBandBottom),\n Math.abs(sectionRect.bottom - focusBandTop)\n );\n const isLastStep = stepIndex === stepCount - 1;\n const lastStepProminent =\n isLastStep &&\n visibleHeight >= Math.min(sectionRect.height, containerRect.height) * 0.25 &&\n sectionRect.top <= containerRect.top + containerRect.height * 0.65;\n\n let score = isVisible ? visibleHeight : Number.NEGATIVE_INFINITY;\n\n if (focusBandOverlap > 0) score += 12_000 + focusBandOverlap * 25;\n if (sectionRect.top <= anchorY) score += 250;\n score += Math.max(0, 1_000 - distanceToFocusBand);\n\n if (isNearBottom && lastStepProminent && isVisible) score += 15_000;\n\n return score;\n}\n\nfunction getBandOverlapHeight(sectionRect: DOMRect, bandTop: number, bandBottom: number) {\n return Math.max(0, Math.min(sectionRect.bottom, bandBottom) - Math.max(sectionRect.top, bandTop));\n}\n\nfunction isScrollableNavigationKey(event: KeyboardEvent) {\n if (event.metaKey || event.ctrlKey || event.altKey) return false;\n\n return ['ArrowDown', 'ArrowUp', 'PageDown', 'PageUp', 'Home', 'End', ' '].includes(event.key);\n}\n","import { useCallback, useId, useLayoutEffect, useRef, type ReactNode } from 'react';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Button } from '../button';\nimport { getSafeStepIndex, useFurthestStepIndex, useScrollableWizardStepTracking } from './hooks';\nimport { WizardNavigation } from './WizardNavigation';\nimport type { StepStatus, WizardStepDef } from './WizardStepper';\nimport { WizardStepper } from './WizardStepper';\n\nexport type { StepStatus, WizardStepDef };\n\nexport interface WizardStepConfig extends WizardStepDef {\n component: ReactNode;\n isValid?: boolean;\n}\n\nexport interface WizardLayoutProps {\n steps: WizardStepConfig[];\n currentStepIndex: number;\n onStepChange: (index: number) => void;\n /**\n * Called when the user completes the wizard from the **scrollable** layout footer\n * (when that footer is shown), or as a fallback when the last step is confirmed\n * in **paged** layouts — see `onLastStepPrimary`.\n */\n onComplete?: () => void;\n /**\n * Called when the user activates the primary control on the **last step** of a\n * **paged** layout (`vertical` / `horizontal`). When omitted, `onComplete` is\n * invoked instead for that interaction.\n */\n onLastStepPrimary?: () => void;\n onCancel?: () => void;\n /** Label for the primary control on non-final steps. @default \"Next\" */\n nextLabel?: string;\n /** Label for the primary control on the last step of paged layouts. @default \"Finish\" */\n lastStepLabel?: string;\n /**\n * Optional secondary control on the **last step** of **paged** layouts only.\n * Rendered to the left of the primary action with an outline style. Both\n * `lastStepSecondaryLabel` and `onLastStepSecondary` must be set for it to appear.\n */\n onLastStepSecondary?: () => void;\n lastStepSecondaryLabel?: string;\n lastStepSecondaryDisabled?: boolean;\n /**\n * When true, the primary Next/Finish control is omitted on the last step of\n * **paged** layouts. Use when the step content provides its own primary action.\n * @default false\n */\n hideLastStepPrimary?: boolean;\n /**\n * When true, the optional footer button at the bottom of the **scrollable**\n * layout is omitted (even if `onComplete` is set).\n * @default false\n */\n hideScrollableCompleteButton?: boolean;\n /** Label for the scrollable layout footer button. @default \"Finish\" */\n scrollableCompleteLabel?: string;\n /**\n * Optional secondary footer button for the **scrollable** layout (outline style),\n * to the left of the complete button. Both `scrollableSecondaryLabel` and\n * `onScrollableSecondary` must be set for it to appear.\n */\n onScrollableSecondary?: () => void;\n scrollableSecondaryLabel?: string;\n scrollableSecondaryDisabled?: boolean;\n /**\n * - `'vertical'` — Vertical sidebar stepper, one step visible at a time (paged).\n * - `'horizontal'` — Horizontal top stepper, one step visible at a time (paged).\n * - `'scrollable'` — Vertical sidebar stepper, all steps on a single scrollable page.\n */\n variant?: 'vertical' | 'horizontal' | 'scrollable';\n /**\n * Optional override for the highest step index reached in paged variants.\n * When omitted, the layout tracks this internally.\n */\n furthestStepIndex?: number;\n /** Extra actions for the bottom navigation bar (paged variants only). */\n navActions?: ReactNode;\n /** Header content rendered above the step content (e.g. title, breadcrumbs). */\n header?: ReactNode;\n /**\n * Pixels of spacing preserved between the container top and an auto-scrolled\n * section heading (`scrollable` variant only). Defaults to 32 (matches `p-8`).\n */\n scrollPadding?: number;\n className?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Paged layout (vertical & horizontal stepper)\n// ---------------------------------------------------------------------------\n\nfunction PagedLayout({\n steps,\n currentStepIndex,\n furthestStepIndex: furthestStepIndexProp,\n onStepChange,\n onComplete,\n onLastStepPrimary,\n onCancel,\n nextLabel,\n lastStepLabel,\n onLastStepSecondary,\n lastStepSecondaryLabel,\n lastStepSecondaryDisabled,\n hideLastStepPrimary,\n navActions,\n header,\n variant,\n className,\n}: WizardLayoutProps & { variant: 'vertical' | 'horizontal' }) {\n const safeIndex = getSafeStepIndex(steps.length, currentStepIndex);\n const resolvedFurthestStepIndex = useFurthestStepIndex(safeIndex, furthestStepIndexProp);\n const stepBodyScrollRef = useRef<HTMLDivElement>(null);\n\n // Paged variants use an inner `overflow-y-auto` body; the document does not scroll.\n // When the user changes steps, reset that panel to the top so the new step starts at the beginning.\n useLayoutEffect(() => {\n const el = stepBodyScrollRef.current;\n if (!el) return;\n el.scrollTop = 0;\n }, [safeIndex]);\n\n if (steps.length === 0) return null;\n\n const isFirstStep = safeIndex === 0;\n const isLastStep = safeIndex === steps.length - 1;\n const currentStep = steps[safeIndex];\n const canProceed = currentStep?.isValid !== false;\n\n const handleNext = () => {\n if (isLastStep) {\n if (onLastStepPrimary) {\n onLastStepPrimary();\n } else {\n onComplete?.();\n }\n return;\n }\n onStepChange(safeIndex + 1);\n };\n\n const handlePrevious = () => {\n if (!isFirstStep) onStepChange(safeIndex - 1);\n };\n\n const stepDefs = toStepDefs(steps, safeIndex);\n\n const navigation = (\n <WizardNavigation\n isFirstStep={isFirstStep}\n isLastStep={isLastStep}\n canProceed={canProceed}\n onPrevious={handlePrevious}\n onNext={handleNext}\n onCancel={onCancel}\n extraActions={navActions}\n nextLabel={nextLabel}\n lastStepLabel={lastStepLabel}\n onLastStepSecondary={onLastStepSecondary}\n lastStepSecondaryLabel={lastStepSecondaryLabel}\n lastStepSecondaryDisabled={lastStepSecondaryDisabled}\n showLastStepPrimary={!hideLastStepPrimary}\n />\n );\n\n const footer = (\n <div className=\"shrink-0 border-t border-border bg-background px-8 py-4\">\n <div className=\"mx-auto max-w-5xl\">{navigation}</div>\n </div>\n );\n\n if (variant === 'vertical') {\n return (\n <div className={cn('flex h-full gap-6', className)}>\n <div className=\"w-[220px] shrink-0 py-6 pl-6\">\n <WizardStepper\n variant=\"vertical\"\n steps={stepDefs}\n currentStepIndex={safeIndex}\n furthestStepIndex={resolvedFurthestStepIndex}\n onStepClick={onStepChange}\n className=\"h-full\"\n />\n </div>\n\n <div className=\"flex min-w-0 flex-1 flex-col overflow-hidden\">\n <div ref={stepBodyScrollRef} className=\"flex-1 overflow-y-auto p-8\">\n <div className=\"mx-auto max-w-5xl\">\n {header}\n {currentStep?.component}\n </div>\n </div>\n {footer}\n </div>\n </div>\n );\n }\n\n return (\n <div className={cn('flex h-full flex-col', className)}>\n <div className=\"shrink-0 p-6 pb-0\">\n <WizardStepper\n variant=\"horizontal\"\n steps={stepDefs}\n currentStepIndex={safeIndex}\n furthestStepIndex={resolvedFurthestStepIndex}\n onStepClick={onStepChange}\n />\n </div>\n\n <div className=\"flex min-w-0 flex-1 flex-col overflow-hidden\">\n <div ref={stepBodyScrollRef} className=\"flex-1 overflow-y-auto p-8\">\n <div className=\"mx-auto max-w-5xl\">\n {header}\n {currentStep?.component}\n </div>\n </div>\n {footer}\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Scrollable layout — all sections on one page, scroll-tracked stepper\n// ---------------------------------------------------------------------------\n\nfunction ScrollableLayout({\n steps,\n currentStepIndex,\n onStepChange,\n header,\n onComplete,\n hideScrollableCompleteButton,\n scrollableCompleteLabel,\n onScrollableSecondary,\n scrollableSecondaryLabel,\n scrollableSecondaryDisabled,\n scrollPadding,\n className,\n}: Pick<\n WizardLayoutProps,\n | 'steps'\n | 'currentStepIndex'\n | 'onStepChange'\n | 'header'\n | 'onComplete'\n | 'hideScrollableCompleteButton'\n | 'scrollableCompleteLabel'\n | 'onScrollableSecondary'\n | 'scrollableSecondaryLabel'\n | 'scrollableSecondaryDisabled'\n | 'scrollPadding'\n | 'className'\n>) {\n const instanceId = useId();\n const scrollRef = useRef<HTMLDivElement>(null);\n const sectionId = useCallback(\n (stepId: string) => `wizard-section-${instanceId}-${stepId}`,\n [instanceId]\n );\n const { activeIndex, furthestStepIndex, scrollToSection } = useScrollableWizardStepTracking({\n steps,\n currentStepIndex,\n onStepChange,\n scrollRef,\n sectionId,\n scrollPadding,\n });\n\n if (steps.length === 0) return null;\n\n const stepDefs = toStepDefs(steps, activeIndex);\n\n const showScrollableSecondary =\n onScrollableSecondary != null &&\n scrollableSecondaryLabel != null &&\n scrollableSecondaryLabel !== '';\n const showScrollablePrimary = onComplete != null && !hideScrollableCompleteButton;\n const showScrollableFooter = showScrollableSecondary || showScrollablePrimary;\n\n return (\n <div className={cn('flex h-full gap-6', className)}>\n <div className=\"w-[220px] shrink-0 py-6 pl-6\">\n <WizardStepper\n variant=\"vertical\"\n steps={stepDefs}\n currentStepIndex={activeIndex}\n furthestStepIndex={furthestStepIndex}\n onStepClick={scrollToSection}\n freeNavigation\n className=\"h-full\"\n />\n </div>\n\n <div ref={scrollRef} className=\"flex min-w-0 flex-1 flex-col overflow-y-auto p-8\">\n {header}\n <div className=\"space-y-12\">\n {steps.map((step) => (\n <section key={step.id} id={sectionId(step.id)}>\n {step.component}\n </section>\n ))}\n </div>\n\n {showScrollableFooter && (\n <div className=\"flex justify-end gap-2 pt-8\">\n {showScrollableSecondary && (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onScrollableSecondary}\n disabled={scrollableSecondaryDisabled ?? false}\n >\n {scrollableSecondaryLabel}\n </Button>\n )}\n {showScrollablePrimary && (\n <Button type=\"button\" onClick={onComplete}>\n {scrollableCompleteLabel ?? 'Finish'}\n </Button>\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction toStepDefs(steps: WizardStepConfig[], currentStepIndex: number): WizardStepDef[] {\n return steps.map((s, i) => {\n // isInvalid on WizardStepDef takes explicit precedence; isValid on\n // WizardStepConfig is the convenience shorthand when not set.\n const isInvalid = s.isInvalid ?? s.isValid === false;\n // Don't auto-assign 'completed' for invalid past steps — resolveState\n // needs to see isInvalid=true to render the error indicator instead.\n const status = s.status ?? (i < currentStepIndex && !isInvalid ? 'completed' : 'pending');\n return { id: s.id, title: s.title, status, isInvalid };\n });\n}\n\n// ---------------------------------------------------------------------------\n// Public component\n// ---------------------------------------------------------------------------\n\n/**\n * A layout component for the wizard.\n *\n * @param props - The props for the WizardLayout component.\n * @returns A React node representing the layout component.\n */\nexport function WizardLayout(props: WizardLayoutProps) {\n const { variant = 'horizontal', ...rest } = props;\n\n if (variant === 'scrollable') {\n return (\n <ScrollableLayout\n steps={rest.steps}\n currentStepIndex={rest.currentStepIndex}\n onStepChange={rest.onStepChange}\n header={rest.header}\n onComplete={rest.onComplete}\n hideScrollableCompleteButton={rest.hideScrollableCompleteButton}\n scrollableCompleteLabel={rest.scrollableCompleteLabel}\n onScrollableSecondary={rest.onScrollableSecondary}\n scrollableSecondaryLabel={rest.scrollableSecondaryLabel}\n scrollableSecondaryDisabled={rest.scrollableSecondaryDisabled}\n scrollPadding={rest.scrollPadding}\n className={rest.className}\n />\n );\n }\n\n return <PagedLayout {...rest} variant={variant} />;\n}\n","/**\n * Presentational ARIA listbox for address suggestions (SF-3, D9).\n *\n * Extracted from `AddressField`'s inline dropdown markup into a reusable\n * presentational listbox so the base `AddressField` renders a consistent\n * suggestion structure (INV-72). Purely presentational and capability-free: it\n * owns no state and no resolution — the consuming field supplies the resolved\n * list, the highlighted index, and the select / hover callbacks.\n *\n * @see INV-72 (byte-identical suggestion structure across both fields)\n * @see INV-94 (`role=\"listbox\"` / `role=\"option\"`, `aria-selected`, `onMouseDown`-preventDefault select)\n */\nimport * as React from 'react';\n\nimport type { AddressSuggestion } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\n/** Props for {@link AddressSuggestionList}. */\nexport interface AddressSuggestionListProps {\n /** Field id — anchors the listbox id (`${id}-suggestions`) and option ids. */\n readonly id: string;\n /** The suggestions to render. */\n readonly suggestions: AddressSuggestion[];\n /** Index of the currently highlighted option, or `-1`. */\n readonly highlightedIndex: number;\n /** Called when an option is selected (click / mouse-down). */\n readonly onSelect: (suggestion: AddressSuggestion) => void;\n /** Called when an option is hovered, to sync the highlight. */\n readonly onHighlight: (index: number) => void;\n}\n\n/**\n * Render the suggestion dropdown. Returns `null` when there are no suggestions\n * (the consuming field also gates on `hasSuggestions`, so this is a safety net).\n *\n * @param props - {@link AddressSuggestionListProps}.\n */\nexport function AddressSuggestionList({\n id,\n suggestions,\n highlightedIndex,\n onSelect,\n onHighlight,\n}: AddressSuggestionListProps): React.ReactElement | null {\n if (suggestions.length === 0) return null;\n\n return (\n <div\n id={`${id}-suggestions`}\n className={cn(\n 'absolute z-50 mt-1 w-full rounded-md border border-border bg-popover shadow-md',\n 'max-h-48 overflow-auto'\n )}\n role=\"listbox\"\n >\n {suggestions.map((s, i) => (\n <button\n key={`${s.value}-${s.description ?? i}`}\n id={`${id}-suggestion-${i}`}\n type=\"button\"\n role=\"option\"\n aria-selected={i === highlightedIndex}\n className={cn(\n 'flex w-full flex-col px-3 py-2 text-left text-sm',\n 'hover:bg-selected/10',\n i === highlightedIndex && 'bg-selected/10'\n )}\n onMouseDown={(e) => {\n e.preventDefault();\n onSelect(s);\n }}\n onMouseEnter={() => onHighlight(i)}\n >\n <span className=\"font-medium\">{s.label}</span>\n <span className=\"truncate font-mono text-xs text-muted-foreground\">{s.value}</span>\n </button>\n ))}\n </div>\n );\n}\n\nAddressSuggestionList.displayName = 'AddressSuggestionList';\n","import { createContext } from 'react';\n\nimport type { AddressSuggestionResolver } from '@openzeppelin/ui-types';\n\n/**\n * @internal Shared context instance consumed by both AddressField and\n * AddressSuggestionProvider. Kept in its own file so component files export\n * only components (required by React Fast Refresh).\n */\nexport const AddressSuggestionContext = createContext<AddressSuggestionResolver | null>(null);\n","/**\n * Headless suggestion-dropdown behavior for address fields.\n *\n * Extracted from `AddressField`'s inline dropdown logic (SF-3, D9) into one\n * reusable headless hook the base `AddressField` consumes — no divergence, no\n * regression (INV-72). It owns:\n * - `AddressSuggestionContext` resolution (explicit `suggestions` prop overrides),\n * - the `MAX_SUGGESTIONS` (5) cap on context-resolved lists,\n * - the 200 ms suggestion debounce,\n * - keyboard highlight state with wrapping ArrowUp / ArrowDown navigation,\n * - click-outside-to-close.\n *\n * It is capability-free and chain-agnostic — nothing about ENS or any chain\n * leaks into `@openzeppelin/ui-components`. The consuming field owns the RHF\n * value write on selection and the Enter / Escape input handlers; this hook\n * exposes the state and primitives they need.\n *\n * Distinct from the pre-existing convenience hook `useAddressSuggestions(query,\n * networkId)`, which resolves a raw suggestion list from context with no\n * debounce / cap / keyboard state — that hook is unchanged and still exported.\n *\n * @see INV-72 (suggestion-dropdown behavior preserved with zero regression; SF-5 depends)\n * @see INV-94 (legacy a11y + suggestion keyboard contract preserved verbatim)\n */\nimport { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\n\nimport type { AddressSuggestion } from '@openzeppelin/ui-types';\n\nimport { AddressSuggestionContext } from './context';\n\n/** Suggestion debounce window (ms). Matches the legacy `AddressField`. */\nconst DEBOUNCE_MS = 200;\n/** Cap on context-resolved suggestions. Explicit arrays are rendered as-is. */\nconst MAX_SUGGESTIONS = 5;\n\n/** Arguments for {@link useAddressSuggestionField}. */\nexport interface UseAddressSuggestionFieldArgs {\n /** The current input text — drives the debounce and dropdown visibility. */\n readonly inputValue: string;\n /**\n * Explicit suggestion list. When an array, it overrides context resolution and\n * is rendered as-is (no cap). `false` disables suggestions entirely (even with\n * a provider mounted). `undefined` falls back to context resolution.\n */\n readonly suggestions?: AddressSuggestion[] | false;\n /** Optional network id forwarded to the context resolver for scoping. */\n readonly networkId?: string;\n}\n\n/** State and handlers returned by {@link useAddressSuggestionField}. */\nexport interface UseAddressSuggestionFieldResult {\n /** Ref for the field container — used for click-outside detection. */\n readonly containerRef: React.RefObject<HTMLDivElement | null>;\n /** The suggestions to render (context-resolved + capped, or the explicit array). */\n readonly resolvedSuggestions: AddressSuggestion[];\n /** `true` when the dropdown is open AND there is at least one suggestion. */\n readonly hasSuggestions: boolean;\n /** Index of the keyboard-highlighted option, or `-1` when none. */\n readonly highlightedIndex: number;\n /** `true` when suggestions are explicitly disabled (`suggestions === false`). */\n readonly suggestionsDisabled: boolean;\n /** Set the highlighted option index (e.g. on hover). */\n readonly setHighlightedIndex: (index: number) => void;\n /** Close the dropdown and clear the highlight. */\n readonly closeSuggestions: () => void;\n /** Notify the hook of an input change — opens/closes the dropdown and resets highlight. */\n readonly onInputChange: (value: string) => void;\n /** Container-level keydown handler: wrapping ArrowUp / ArrowDown navigation. */\n readonly onContainerKeyDown: (e: React.KeyboardEvent) => void;\n}\n\n/**\n * Headless address-suggestion dropdown behavior. See the module docstring for\n * the full behavior contract.\n *\n * @param args - {@link UseAddressSuggestionFieldArgs}.\n * @returns {@link UseAddressSuggestionFieldResult}.\n */\nexport function useAddressSuggestionField({\n inputValue,\n suggestions: suggestionsProp,\n networkId,\n}: UseAddressSuggestionFieldArgs): UseAddressSuggestionFieldResult {\n const contextResolver = useContext(AddressSuggestionContext);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const [debouncedQuery, setDebouncedQuery] = useState('');\n const [showSuggestions, setShowSuggestions] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n\n useEffect(() => {\n if (!inputValue.trim()) {\n setDebouncedQuery('');\n return;\n }\n const timer = setTimeout(() => setDebouncedQuery(inputValue), DEBOUNCE_MS);\n return () => clearTimeout(timer);\n }, [inputValue]);\n\n const suggestionsDisabled = suggestionsProp === false;\n\n const resolvedSuggestions = useMemo<AddressSuggestion[]>(() => {\n if (suggestionsDisabled) return [];\n if (Array.isArray(suggestionsProp)) return suggestionsProp;\n if (!contextResolver || !debouncedQuery.trim()) return [];\n return contextResolver.resolveSuggestions(debouncedQuery, networkId).slice(0, MAX_SUGGESTIONS);\n }, [suggestionsDisabled, suggestionsProp, contextResolver, debouncedQuery, networkId]);\n\n const hasSuggestions = showSuggestions && resolvedSuggestions.length > 0;\n\n useEffect(() => {\n let active = true;\n const handleClickOutside = (e: MouseEvent): void => {\n if (active && containerRef.current && !containerRef.current.contains(e.target as Node)) {\n setShowSuggestions(false);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => {\n active = false;\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, []);\n\n const onContainerKeyDown = useCallback(\n (e: React.KeyboardEvent): void => {\n if (!hasSuggestions) return;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setHighlightedIndex((prev) => (prev < resolvedSuggestions.length - 1 ? prev + 1 : 0));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setHighlightedIndex((prev) => (prev > 0 ? prev - 1 : resolvedSuggestions.length - 1));\n }\n },\n [hasSuggestions, resolvedSuggestions.length]\n );\n\n const onInputChange = useCallback((value: string): void => {\n setShowSuggestions(value.length > 0);\n setHighlightedIndex(-1);\n }, []);\n\n const closeSuggestions = useCallback((): void => {\n setShowSuggestions(false);\n setHighlightedIndex(-1);\n }, []);\n\n return {\n containerRef,\n resolvedSuggestions,\n hasSuggestions,\n highlightedIndex,\n suggestionsDisabled,\n setHighlightedIndex,\n closeSuggestions,\n onInputChange,\n onContainerKeyDown,\n };\n}\n","/**\n * Injected name-resolution machine (SF-3).\n *\n * A thin, capability-free async machine that `AddressField` consumes: given a\n * typed input and the injected `resolveName`, it debounces, dispatches, tracks\n * status, and applies the out-of-order name-drop guard (INV-117). It is the\n * component-boundary analogue of SF-2's `useResolveName`, with all hard\n * mechanics (cache, dedupe, retries, UNSUPPORTED synthesis) deliberately left\n * behind the injected function — this hook does ONLY debounce + status\n * derivation + the funds guards.\n *\n * The machine holds no resolved-hex cache of its own (INV-85): its single\n * `settled` record is valid only while it matches the current debounced input,\n * the current resolver function identity, and the current retry attempt — any\n * mismatch derives `loading`, never a stale `resolved`.\n *\n * Resolver-identity-churn backstop (INV-123/124/125). The dispatch effect keys\n * on the injected `resolveName` function identity, so an unstable (non-memoized)\n * integrator resolver re-fires it on every render. To keep that from becoming an\n * unbounded RPC loop (rate-ban + cost + funds-path DoS), the machine caps\n * dispatches per resolution intent — the pair (normalized debounced input × retry\n * attempt) — at {@link MAX_DISPATCHES_PER_INTENT}, regardless of render count and\n * regardless of how many times `resolveName` identity changes under that intent.\n * The budget resets only on intent change (a new typed name, or `retry()`) or when\n * the field leaves the active name-resolution path (clear / disable). It does\n * *not* reset on `settled.source` mismatch: that would let two settling sources\n * flap and refill the counter (settling churn), silently defeating INV-123. A\n * genuine network swap still re-dispatches within the shared intent budget\n * (INV-119 / acceptance #5) because a single identity change costs one unit.\n * Clear→retype of the same name gets a fresh budget via the leave-path reset, so\n * it cannot accumulate toward the cap across cycles and then strand a later swap.\n * A churning identity that exhausts the budget emits a one-shot, development-only\n * warning (INV-124) and degrades to the safe gated state (bounded RPC, RHF value\n * `''`, submit gated, never a wrong hex, never a throw — INV-125). This backstop\n * is entirely internal: no signature, param, or return-type change; `AddressField`\n * consumes the machine unchanged.\n */\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport type {\n NameResolutionError,\n ResolutionResult,\n ResolvedAddress,\n} from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\n/**\n * Default debounce window (ms) for typed names — mirrors SF-2's\n * `forwardDebounceMs` default so the field and the bare hook feel identical.\n */\nexport const NAME_RESOLUTION_DEBOUNCE_MS = 300;\n\n/**\n * Cap on resolver dispatches per resolution intent — the pair (normalized\n * debounced input × retry attempt) — regardless of how many times the field\n * re-renders or how many times `resolveName` identity changes under that intent\n * (INV-123). Chosen to sit comfortably above the dispatches a single displayed\n * input legitimately incurs (1 initial call + any human-initiated genuine network\n * swaps of that same name, each ≤1 unit — INV-119) and far below per-render\n * identity churn (hundreds/sec): a user does not switch networks eight times\n * while one unedited name sits in the field, whereas churn blows past eight\n * within milliseconds. The budget resets when the intent changes or when the\n * field leaves the name-resolution path (clear / disable) — never on\n * `settled.source` mismatch, so settling-source oscillation cannot refill it.\n */\nexport const MAX_DISPATCHES_PER_INTENT = 8;\n\n/** Forward resolver function injected through `NameResolverContext`. */\nexport type InjectedResolveName = (name: string) => Promise<ResolutionResult<ResolvedAddress>>;\n\n/**\n * Machine result — a discriminated union keyed on `status`, shaped like SF-2's\n * `UseResolveNameResult` so downstream rendering logic carries over verbatim.\n * `name` is always the normalized (trim + lowercase) input the arm refers to.\n */\nexport type InjectedNameResolutionResult =\n | { readonly status: 'idle' }\n | { readonly status: 'debouncing'; readonly name: string }\n | { readonly status: 'loading'; readonly name: string }\n | { readonly status: 'resolved'; readonly name: string; readonly data: ResolvedAddress }\n | {\n readonly status: 'error';\n readonly name: string;\n readonly error: NameResolutionError;\n readonly retry: () => void;\n };\n\n/** Parameters for {@link useInjectedNameResolution}. */\nexport interface UseInjectedNameResolutionParams {\n /** The raw typed input (the field's display string). Normalized internally. */\n readonly input: string;\n /**\n * INV-83: `true` only when `classification === 'name-candidate'` AND an\n * injected `resolveName` exists. `false` forces `idle` with zero calls.\n */\n readonly enabled: boolean;\n /** The injected forward resolver. Absent → the machine stays `idle`. */\n readonly resolveName?: InjectedResolveName;\n /** Debounce override (ms); `<= 0` disables debouncing. */\n readonly debounceMs?: number;\n}\n\n/**\n * The one settled record the machine keeps. `name` / `source` / `attempt`\n * pin the exact dispatch that produced it, so the status derivation can never\n * pair a result with a different input, resolver (network), or retry cycle.\n */\ninterface SettledResolution {\n readonly name: string;\n readonly result: ResolutionResult<ResolvedAddress>;\n readonly source: InjectedResolveName;\n readonly attempt: number;\n}\n\n/**\n * Debounce + dispatch + status derivation over an injected `resolveName`.\n *\n * Guarantees:\n * - INV-83: no call unless `enabled` (name-candidate + injected method), and\n * never for a debounced copy that lags the current normalized input.\n * - INV-117: a settled result whose requested name ≠ the current debounced\n * input is discarded (last-write-wins at the component boundary).\n * - INV-87: a rejecting resolver (contract violation) is mapped to a typed\n * `ADAPTER_ERROR` — nothing throws into the render tree.\n * - INV-123: resolver dispatches are bounded per resolution intent (normalized\n * debounced input × retry attempt) at {@link MAX_DISPATCHES_PER_INTENT},\n * regardless of render count or resolver-identity oscillation; the budget\n * resets on intent change or when leaving the name-resolution path — never on\n * `settled.source` mismatch; `retry()` never consumes an existing budget.\n * - INV-124: an identity-churning resolver that exhausts the budget triggers a\n * one-shot, development-only `logger.warn` (silent in production).\n * - INV-125: under sustained churn the field stays in the safe gated state — the\n * perpetually-changing identity keeps failing the `settled.source` check, so\n * the machine derives `loading`, never `resolved`; combined with INV-87 it\n * never throws and never writes a hex.\n * - No `setState` after unmount: every dispatch is cancelled on cleanup.\n *\n * @param params - {@link UseInjectedNameResolutionParams}\n * @returns The current {@link InjectedNameResolutionResult}.\n */\nexport function useInjectedNameResolution({\n input,\n enabled,\n resolveName,\n debounceMs = NAME_RESOLUTION_DEBOUNCE_MS,\n}: UseInjectedNameResolutionParams): InjectedNameResolutionResult {\n // Normalize exactly as the SF-2 engine does (trim, then lowercase) so the\n // echoed `name` compares cleanly against the engine's normalized result (INV-79).\n const normalized = input.trim().toLowerCase();\n\n // Seed the debounced copy on mount (a prefilled value is not gated behind a\n // debounce window), then debounce only subsequent changes — mirrors SF-2.\n const [debounced, setDebounced] = useState(normalized);\n const seededRef = useRef(false);\n\n useEffect(() => {\n if (!seededRef.current) {\n seededRef.current = true;\n return; // mount value already seeded via useState — no timer\n }\n if (debounceMs <= 0) {\n setDebounced(normalized);\n return;\n }\n const timer = setTimeout(() => setDebounced(normalized), debounceMs);\n return () => clearTimeout(timer);\n }, [normalized, debounceMs]);\n\n const [attempt, setAttempt] = useState(0);\n const [settled, setSettled] = useState<SettledResolution | null>(null);\n\n // INV-117: the machine's current debounced target. A settle handler compares\n // its captured request name against this ref — a mismatch is dropped, so the\n // consumer's INV-79 effect never observes a (resolved, name) pair that\n // mismatches the input it belongs to.\n const currentTargetRef = useRef('');\n currentTargetRef.current = enabled && resolveName ? debounced : '';\n\n // INV-123 budget refs. `intentKeyRef`/`dispatchCountRef` cap dispatches per\n // resolution intent and reset only when the intent changes or when leaving the\n // name-resolution path — never on `settled.source` mismatch (that escape hatch\n // lets two settling sources flap and refill the counter). `churnWarnedRef`\n // makes the INV-124 warning one-shot per field instance (never reset). All hold\n // only a string key + integer counter + boolean flag — never a resolved hex —\n // so INV-85's no-stale-cache guarantee is preserved and they never gate the write.\n const intentKeyRef = useRef('');\n const dispatchCountRef = useRef(0);\n const churnWarnedRef = useRef(false);\n\n const warnOnceOnChurn = useCallback((): void => {\n // INV-124: development-only, one-shot per field instance.\n if (process.env.NODE_ENV === 'production' || churnWarnedRef.current) return;\n churnWarnedRef.current = true;\n logger.warn(\n 'AddressField',\n 'The injected name resolver changes identity on every render, so inline name resolution was ' +\n 'bounded to prevent an unbounded RPC loop. Memoize the resolver (e.g. wrap it in useMemo, ' +\n 'or use useRuntimeNameResolver from @openzeppelin/ui-react) so its function identity is ' +\n 'stable across renders. See the ens-address-input integration guide.'\n );\n }, []);\n\n useEffect(() => {\n // INV-83: dispatch only when the debounced copy belongs to the currently\n // enabled input. On the render where `enabled` flips true, `debounced` may\n // still hold a stale value (a prior hex / rejected shape / earlier name)\n // for one debounce window — dispatching it would be a spurious call.\n // Reset the intent budget when leaving the name-resolution path so\n // clear→retype of the same name does not accumulate toward the cap across\n // cycles (which would otherwise strand a later genuine network swap).\n if (!enabled || !resolveName || debounced === '') {\n intentKeyRef.current = '';\n dispatchCountRef.current = 0;\n return;\n }\n if (debounced !== normalized) return;\n\n // INV-123: bound dispatches per resolution intent (normalized input × retry\n // attempt), regardless of render count. Under identity churn the effect\n // re-fires every render, but the budget check early-returns before any RPC\n // once the intent's budget is spent — closing the unbounded-loop / DoS window\n // (SC-008). The budget resets whenever the intent changes (a new typed name,\n // or `retry()` bumping `attempt`), so `retry()` never consumes an existing\n // budget. A genuine memoized swap (INV-119) shares this same intent budget —\n // one identity change costs one unit and re-dispatches while count < MAX.\n // Do NOT reset on `settled.source !== resolveName`: two settling sources that\n // oscillate would refill the counter on every flap (settling churn).\n const intentKey = `${debounced}\\u0000${attempt}`;\n if (intentKeyRef.current !== intentKey) {\n intentKeyRef.current = intentKey;\n dispatchCountRef.current = 0;\n }\n if (dispatchCountRef.current >= MAX_DISPATCHES_PER_INTENT) {\n warnOnceOnChurn(); // INV-124\n return; // INV-123/125: no further RPC for this intent — degrade to gated\n }\n dispatchCountRef.current += 1;\n\n let cancelled = false;\n const requestedName = debounced;\n const requestedAttempt = attempt;\n const source = resolveName;\n\n const settle = (result: ResolutionResult<ResolvedAddress>): void => {\n if (cancelled) return; // superseded dispatch or unmounted — drop\n if (requestedName !== currentTargetRef.current) return; // INV-117: stale name — drop\n setSettled({ name: requestedName, result, source, attempt: requestedAttempt });\n };\n\n source(requestedName).then(settle, (cause: unknown) => {\n // INV-87 backstop: the injected fn MUST NOT reject for expected failures;\n // map a contract-violating rejection into the closed error union.\n settle({\n ok: false,\n error: {\n code: 'ADAPTER_ERROR',\n message: cause instanceof Error ? cause.message : String(cause),\n cause,\n },\n });\n });\n\n return () => {\n cancelled = true;\n };\n // `resolveName` identity stays the dispatch trigger (INV-119). `warnOnceOnChurn`\n // is a stable `useCallback([])`, so listing it adds no re-fire and keeps the\n // trigger semantics unchanged.\n }, [enabled, resolveName, debounced, normalized, attempt, warnOnceOnChurn]);\n\n const retry = useCallback((): void => {\n setAttempt((current) => current + 1);\n }, []);\n\n // --- Status derivation: a total function of gate state × settled state ---\n\n if (!enabled || !resolveName || normalized === '') {\n return { status: 'idle' }; // INV-83\n }\n if (debounced !== normalized) {\n return { status: 'debouncing', name: normalized };\n }\n if (\n settled !== null &&\n settled.name === debounced &&\n settled.source === resolveName &&\n settled.attempt === attempt\n ) {\n if (settled.result.ok) {\n return { status: 'resolved', name: settled.name, data: settled.result.value };\n }\n return { status: 'error', name: settled.name, error: settled.result.error, retry };\n }\n return { status: 'loading', name: normalized };\n}\n","import { createContext, type Context } from 'react';\n\nimport type { NameResolver, NetworkLabelResolver } from '@openzeppelin/ui-types';\n\n/**\n * Value held by NameResolverContext. Extends the SF-3 injection seam with\n * optional network context for SF-6 chain-scope gating only.\n */\nexport interface NameResolverContextValue extends NameResolver {\n /**\n * Active network id for chain-scope submit gating (opaque string).\n * When absent, `isChainScopeMismatch` is never true and coinType wrong-chain\n * protection is the integrator's responsibility.\n */\n readonly activeNetworkId?: string | null;\n\n /**\n * Optional human-readable active network name — interpolated into the\n * chain-scope mismatch message only (same seam as INV-78 networkName).\n */\n readonly activeNetworkName?: string;\n\n /**\n * Optional slug → display name for provenance disclaimer copy (003 SF-3).\n */\n readonly resolveNetworkLabel?: NetworkLabelResolver;\n}\n\n/**\n * Process-global key for the context object. Uses `Symbol.for` so all duplicated\n * module instances share ONE React context — the same cross-bundle-singleton\n * pattern as `@openzeppelin/ui-react`'s `NameResolutionContext` /\n * `WalletStateContext` (bundler pre-bundling / npm-installed consumers).\n */\nconst CONTEXT_KEY = Symbol.for('@openzeppelin/ui-components/NameResolverContext');\n\ninterface GlobalWithNameResolverContext {\n [CONTEXT_KEY]?: Context<NameResolverContextValue | null>;\n}\n\nfunction getOrCreateSharedContext(): Context<NameResolverContextValue | null> {\n const globalScope = globalThis as GlobalWithNameResolverContext;\n if (!globalScope[CONTEXT_KEY]) {\n globalScope[CONTEXT_KEY] = createContext<NameResolverContextValue | null>(null);\n }\n return globalScope[CONTEXT_KEY];\n}\n\n/**\n * @internal Shared context instance consumed by both AddressField and\n * NameResolverProvider (INV-118). Kept in its own file so component files\n * export only components (required by React Fast Refresh).\n *\n * `null` means no provider is mounted — every ENS branch in `AddressField` is\n * then dead code and the field is byte-identical to its pre-ENS behavior\n * (INV-82).\n */\nexport const NameResolverContext = getOrCreateSharedContext();\n","import { useContext } from 'react';\n\nimport { NameResolverContext, type NameResolverContextValue } from './context';\n\n/**\n * Read the injected resolver context. Returns `null` when no\n * `NameResolverProvider` is mounted — the consuming field must then treat\n * every ENS branch as dead code (INV-82).\n *\n * @returns The extended context value, or `null` when no provider is mounted.\n */\nexport function useNameResolver(): NameResolverContextValue | null {\n return useContext(NameResolverContext);\n}\n","import { useEffect, useState } from 'react';\n\n/** Default escalation threshold for long-latency resolves (INV-129/130). */\nexport const RESOLVING_ANNOUNCER_ESCALATE_AFTER_MS = 3000;\n\nconst PHASE_1_COPY = 'Resolving…';\nconst PHASE_2_COPY = 'Still resolving…';\n\n/** Inputs to the loading-copy hook — no mechanism fields exposed. */\nexport interface UseResolvingAnnouncerCopyParams {\n /** True while the machine is in `debouncing` or `loading`. */\n readonly isPending: boolean;\n /** Escalation threshold (ms). Default 3000. */\n readonly escalateAfterMs?: number;\n}\n\n/**\n * Returns the announcer string for debouncing/loading arms.\n * Phase 1: \"Resolving…\" (SF-3 default, unchanged for first N ms).\n * Phase 2: \"Still resolving…\" after threshold — reduces frozen perception\n * during CCIP-scale latency without naming gateway/CCIP/v2.\n */\nexport function useResolvingAnnouncerCopy({\n isPending,\n escalateAfterMs = RESOLVING_ANNOUNCER_ESCALATE_AFTER_MS,\n}: UseResolvingAnnouncerCopyParams): string {\n const [escalated, setEscalated] = useState(false);\n\n useEffect(() => {\n if (!isPending) {\n setEscalated(false);\n return;\n }\n\n // INV-131: new pending episode starts at phase 1.\n setEscalated(false);\n\n const timeoutId = window.setTimeout(() => {\n setEscalated(true);\n }, escalateAfterMs);\n\n return () => {\n window.clearTimeout(timeoutId);\n };\n }, [isPending, escalateAfterMs]);\n\n if (!isPending) {\n return PHASE_1_COPY;\n }\n\n return escalated ? PHASE_2_COPY : PHASE_1_COPY;\n}\n","/**\n * Accessibility utilities for form field components\n */\n\n/**\n * Default aria-describedby ID generator based on field ID\n */\nexport function getDescribedById(\n id: string,\n type: 'error' | 'description' | 'counter' = 'error'\n): string {\n return `${id}-${type}`;\n}\n\n/**\n * Interface for accessibility attributes to be applied to form fields\n */\nexport interface AccessibilityProps {\n /**\n * ARIA attributes for accessibility\n */\n 'aria-invalid'?: boolean;\n 'aria-required'?: boolean;\n 'aria-describedby'?: string;\n 'aria-errormessage'?: string;\n 'aria-labelledby'?: string;\n\n /**\n * Indicates if the input is required\n */\n required?: boolean;\n\n /**\n * Indicates if the input is disabled\n */\n disabled?: boolean;\n\n /**\n * Indicates if the input is readonly\n */\n readOnly?: boolean;\n\n /**\n * Tab index for keyboard navigation\n * Use 0 for normal tab order\n * Use -1 to remove from tab order\n */\n tabIndex?: number;\n}\n\n/**\n * Generates accessibility attributes for form fields\n */\nexport function getAccessibilityProps({\n id,\n hasError = false,\n isRequired = false,\n isDisabled = false,\n isReadOnly = false,\n hasHelperText = false,\n hasCharacterCounter = false,\n}: {\n id: string;\n hasError?: boolean;\n isRequired?: boolean;\n isDisabled?: boolean;\n isReadOnly?: boolean;\n hasHelperText?: boolean;\n hasCharacterCounter?: boolean;\n}): AccessibilityProps {\n // Build aria-describedby referencing multiple elements if needed\n const describedByIds: string[] = [];\n\n if (hasError) {\n describedByIds.push(getDescribedById(id, 'error'));\n }\n\n if (hasHelperText) {\n describedByIds.push(getDescribedById(id, 'description'));\n }\n\n if (hasCharacterCounter) {\n describedByIds.push(getDescribedById(id, 'counter'));\n }\n\n return {\n 'aria-invalid': hasError,\n 'aria-required': isRequired,\n 'aria-describedby': describedByIds.length > 0 ? describedByIds.join(' ') : undefined,\n 'aria-errormessage': hasError ? getDescribedById(id, 'error') : undefined,\n required: isRequired,\n disabled: isDisabled,\n readOnly: isReadOnly,\n tabIndex: isDisabled ? -1 : 0,\n };\n}\n\n/**\n * Utility function to handle keyboard events for interactive elements\n * Helps ensure keyboard users can interact with form controls\n */\nexport function handleKeyboardEvent(\n event: React.KeyboardEvent,\n handlers: {\n onEnter?: () => void;\n onSpace?: () => void;\n onEscape?: () => void;\n onArrowUp?: () => void;\n onArrowDown?: () => void;\n onArrowLeft?: () => void;\n onArrowRight?: () => void;\n onTab?: () => void;\n }\n): void {\n switch (event.key) {\n case 'Enter':\n if (handlers.onEnter) {\n event.preventDefault();\n handlers.onEnter();\n }\n break;\n case ' ':\n if (handlers.onSpace) {\n event.preventDefault();\n handlers.onSpace();\n }\n break;\n case 'Escape':\n if (handlers.onEscape) {\n event.preventDefault();\n handlers.onEscape();\n }\n break;\n case 'ArrowUp':\n if (handlers.onArrowUp) {\n event.preventDefault();\n handlers.onArrowUp();\n }\n break;\n case 'ArrowDown':\n if (handlers.onArrowDown) {\n event.preventDefault();\n handlers.onArrowDown();\n }\n break;\n case 'ArrowLeft':\n if (handlers.onArrowLeft) {\n event.preventDefault();\n handlers.onArrowLeft();\n }\n break;\n case 'ArrowRight':\n if (handlers.onArrowRight) {\n event.preventDefault();\n handlers.onArrowRight();\n }\n break;\n case 'Tab':\n if (handlers.onTab) {\n event.preventDefault();\n handlers.onTab();\n }\n break;\n default:\n break;\n }\n}\n\n/**\n * Field focus management utility\n * For managing focus within a field group or complex form component\n */\nexport function createFocusManager(): {\n focusFirstElement: (container: HTMLElement | null) => void;\n focusElementById: (id: string) => void;\n trapFocus: (event: KeyboardEvent, container: HTMLElement | null) => void;\n} {\n return {\n /**\n * Focus the first focusable element within a container\n */\n focusFirstElement(container: HTMLElement | null): void {\n if (!container) return;\n\n const focusable = container.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n );\n\n if (focusable.length > 0) {\n focusable[0].focus();\n }\n },\n\n /**\n * Focus a specific element by ID\n */\n focusElementById(id: string): void {\n const element = document.getElementById(id);\n if (element) {\n element.focus();\n }\n },\n\n /**\n * Trap focus within a container (for modals, dropdowns, etc.)\n */\n trapFocus(event: KeyboardEvent, container: HTMLElement | null): void {\n if (!container || event.key !== 'Tab') return;\n\n const focusable = Array.from(\n container.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n )\n );\n\n if (focusable.length === 0) return;\n\n const firstElement = focusable[0];\n const lastElement = focusable[focusable.length - 1];\n\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n } else if (!event.shiftKey && document.activeElement === lastElement) {\n event.preventDefault();\n firstElement.focus();\n }\n },\n };\n}\n\n/**\n * Provides a handler for Escape key to clear input fields\n *\n * @param onChange - Function to call when value changes\n * @param value - Current value of the input\n * @returns A function to handle the Escape key press\n */\nexport function handleEscapeKey(\n onChange: (value: string) => void,\n value: unknown\n): (e: React.KeyboardEvent) => void {\n return (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n\n // Only reset if there's a value to clear\n if (value) {\n onChange('');\n } else {\n // If already empty, blur the field\n (e.target as HTMLElement).blur();\n }\n }\n };\n}\n\n/**\n * Provides a handler for Space/Enter keys for toggle components (checkboxes, switches)\n *\n * @param onChange - Function to call when value changes\n * @param value - Current value of the input\n * @returns A function to handle the Space/Enter key press\n */\nexport function handleToggleKeys(\n onChange: (value: boolean) => void,\n value: boolean\n): (e: React.KeyboardEvent) => void {\n return (e: React.KeyboardEvent) => {\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n onChange(!value);\n }\n };\n}\n\n/**\n * Provides a handler for arrow keys for numeric inputs\n *\n * @param onChange - Function to call when value changes\n * @param value - Current numeric value\n * @param step - Step amount for increments/decrements\n * @param min - Minimum allowed value (optional)\n * @param max - Maximum allowed value (optional)\n * @returns A function to handle arrow key presses\n */\nexport function handleNumericKeys(\n onChange: (value: number) => void,\n value: number,\n step: number = 1,\n min?: number,\n max?: number\n): (e: React.KeyboardEvent) => void {\n return (e: React.KeyboardEvent) => {\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n const direction = e.key === 'ArrowUp' ? 1 : -1;\n let newValue = typeof value === 'number' ? value + step * direction : 0;\n\n // Apply min/max constraints if provided\n if (typeof min === 'number') newValue = Math.max(min, newValue);\n if (typeof max === 'number') newValue = Math.min(max, newValue);\n\n onChange(newValue);\n }\n };\n}\n","/**\n * Layout utility functions for form components\n */\n\n/**\n * Helper function to get width classes based on the field width\n */\nexport function getWidthClasses(width: 'full' | 'half' | 'third'): string {\n switch (width) {\n case 'half':\n return 'form-field-half';\n case 'third':\n return 'form-field-third';\n case 'full':\n default:\n return 'form-field-full';\n }\n}\n","import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FieldValues, useController, useFormState, useWatch } from 'react-hook-form';\n\nimport type { AddressingCapability, AddressSuggestion } from '@openzeppelin/ui-types';\nimport {\n classifyAddressInput,\n crossNetworkFallbackMessageNames,\n getFallbackNetworks,\n isChainScopeMismatch,\n isCrossNetworkFallback,\n nameResolutionChainScopeMismatchMessage,\n nameResolutionCrossNetworkFallbackMessage,\n nameResolutionMessageForCode,\n type AddressInputClassification,\n type NameResolutionErrorCode,\n} from '@openzeppelin/ui-utils';\n\nimport { AddressSuggestionList } from './address-suggestion/AddressSuggestionList';\nimport { useAddressSuggestionField } from './address-suggestion/useAddressSuggestionField';\nimport {\n useInjectedNameResolution,\n type InjectedNameResolutionResult,\n} from './name-resolution/useInjectedNameResolution';\nimport { useNameResolver } from './name-resolution/useNameResolver';\nimport { useResolvingAnnouncerCopy } from './name-resolution/useResolvingAnnouncerCopy';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n validateField,\n} from './utils';\n\nexport interface AddressFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n addressing?: AddressingCapability;\n\n /**\n * Explicit suggestion list. When provided, overrides context-based resolution.\n * Pass `false` to disable suggestions entirely (even when a context provider is mounted).\n *\n * Note: context-resolved suggestions are automatically capped at\n * `MAX_SUGGESTIONS` (5) entries, while explicitly passed arrays are\n * rendered as-is — callers should pre-slice if needed.\n */\n suggestions?: AddressSuggestion[] | false;\n\n /**\n * Called when the user selects a suggestion. Receives the selected suggestion\n * so callers can perform additional side-effects beyond filling the field value.\n */\n onSuggestionSelect?: (suggestion: AddressSuggestion) => void;\n\n /**\n * Fired when the resolved-and-name-matched name changes. Emits the resolved\n * NAME (not the hex) on `resolved` + name-match, and `undefined` in every\n * other state (idle / debouncing / loading / error / hex / cleared).\n *\n * Pure notification for consumers that want the human-readable name (e.g.\n * the address book's alias suggestion, SF-5 INV-109..111). It reads existing\n * resolution state and does NOT participate in the resolved-hex write path\n * (INV-75/79/80/81/85 unaffected). With no injected resolver it only ever\n * emits `undefined`, so the field stays behavior-identical (INV-82).\n */\n onResolvedNameChange?: (name: string | undefined) => void;\n\n /**\n * When `false`, suppresses the forward cross-network fallback disclaimer under\n * the frozen \"Resolved to …\" template. Default `true`. Use when a sibling\n * `AddressDisplay` already surfaces the same message (e.g. demo resolved card).\n */\n showCrossNetworkFallbackDisclaimer?: boolean;\n}\n\n/**\n * Non-user-facing gate string returned by the sync validator while a typed name\n * is resolving, so `formState.isValid` is `false` even for an optional field\n * (INV-84). The visible message comes from the aria-live region, never this string.\n */\nconst NAME_RESOLUTION_PENDING_GATE = '__ens_name_resolution_pending__';\n\n/** Codes for which a `retry()` affordance is offered — transient only (INV-90). */\nconst TRANSIENT_ERROR_CODES: ReadonlySet<NameResolutionErrorCode> = new Set([\n 'RESOLUTION_TIMEOUT',\n 'EXTERNAL_GATEWAY_ERROR',\n 'ADAPTER_ERROR',\n]);\n\n/**\n * Normalize a typed name for the resolved-write match guard: trim then lowercase,\n * mirroring the SF-2 engine (whose echoed `result.name` is already normalized).\n * Comparing the raw typed value would spuriously fail on case/whitespace (INV-79).\n */\nfunction normalizeResolvedName(value: string): string {\n return value.trim().toLowerCase();\n}\n\n/**\n * Address input field component specifically designed for blockchain addresses via React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like AddressField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles blockchain address-specific rendering and validation using the passed addressing capability\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Blockchain address validation through the provided addressing capability\n * - Automatic error handling and reporting\n * - Chain-agnostic design (validation handled by capabilities)\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation\n *\n * Autocomplete suggestions can be provided in two ways:\n *\n * 1. **Context-based (zero-config)**: Mount an `AddressSuggestionProvider` in the\n * component tree. Every `AddressField` below it automatically resolves suggestions.\n *\n * 2. **Prop-based (explicit)**: Pass `suggestions` directly. This overrides context.\n * Pass `suggestions={false}` to opt out when a provider is mounted.\n *\n * The suggestion dropdown includes built-in debouncing, keyboard navigation (Arrow keys,\n * Enter, Escape), click-outside dismissal, and ARIA listbox semantics — all provided by\n * the shared headless `useAddressSuggestionField` hook + `AddressSuggestionList`.\n *\n * **Inline name resolution (SF-3, opt-in via context).** When a\n * `NameResolverProvider` is mounted, the field also accepts a name (e.g.\n * `alice.eth`): the name is resolved inline through the injected `resolveName`\n * and the RHF form value becomes the resolved hex — never the name, never a\n * silently-coerced value. The correctness spine is a shadow-state model:\n * the `<input>` always shows the typed string (`inputValue`, INV-69); the RHF\n * value is `''` for every unresolved name state so submit stays gated with no\n * async validator (INV-75); the single name→hex write fires only on\n * `resolved` + normalized name-match (INV-79/80). With **no** provider mounted\n * every resolution branch below is dead code and the field is byte-identical\n * to its pre-ENS behavior (INV-82 — the LOCKED backward-compat guarantee).\n * The component stays capability-free: it never reads a runtime or wallet\n * state; everything arrives through the injected context (INV-118).\n */\nexport function AddressField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n addressing,\n readOnly,\n suggestions: suggestionsProp,\n onSuggestionSelect,\n onResolvedNameChange,\n showCrossNetworkFallbackDisclaimer = true,\n}: AddressFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n const resolutionRegionId = `${id}-resolution`;\n\n // Injected forward resolver — `null` with no NameResolverProvider mounted,\n // in which case every resolution branch below is dead code (INV-82).\n const resolver = useNameResolver();\n const resolveName = resolver?.resolveName;\n const isValidName = resolver?.isValidName;\n const activeNetworkId = resolver?.activeNetworkId;\n const activeNetworkName = resolver?.activeNetworkName;\n const resolveNetworkLabel = resolver?.resolveNetworkLabel;\n\n const lastSetValueRef = useRef<string>('');\n const [inputValue, setInputValue] = useState('');\n\n const watchedFieldValue = useWatch({ control, name }) as string | undefined;\n\n useEffect(() => {\n const currentFieldValue = watchedFieldValue ?? '';\n if (currentFieldValue !== lastSetValueRef.current) {\n lastSetValueRef.current = currentFieldValue;\n setInputValue(currentFieldValue);\n }\n }, [watchedFieldValue]);\n\n // Stable injected predicate for the classifier (chain-neutral; no capability leak).\n const isValidAddress = useMemo(\n () => (addressing ? (v: string): boolean => addressing.isValidAddress(v) : undefined),\n [addressing]\n );\n\n const classification = useMemo(\n () => classifyAddressInput(inputValue, { isValidAddress, isValidName }),\n [inputValue, isValidAddress, isValidName]\n );\n\n // Master gate for every resolution branch (INV-82).\n const resolverActive = resolver !== null && classification === 'name-candidate';\n // INV-83: the machine runs only for a name candidate with an injected resolveName.\n const nameEnabled = resolverActive && resolveName != null;\n // Provider mounted but no forward method on this runtime → the name-candidate\n // surfaces UNSUPPORTED_NETWORK with zero calls (SC-006 / INV-87 / INV-119).\n const forwardUnsupported = resolverActive && resolveName == null;\n\n const resolution = useInjectedNameResolution({\n input: inputValue,\n enabled: nameEnabled,\n resolveName,\n });\n\n const chainScopeBlocked =\n resolution.status === 'resolved' &&\n isChainScopeMismatch(resolution.data.provenance, activeNetworkId);\n\n const isResolutionPending =\n !forwardUnsupported && (resolution.status === 'debouncing' || resolution.status === 'loading');\n const resolvingAnnouncerCopy = useResolvingAnnouncerCopy({\n isPending: isResolutionPending,\n });\n\n // Refs the synchronous `validate` reads. Kept current below (and synchronously in\n // `commitTypedValue`) so the pending guard (INV-84) sees the latest state even\n // when RHF revalidates before the next render commits.\n const resolverPresentRef = useRef(false);\n const classificationRef = useRef<AddressInputClassification>('empty');\n const statusRef = useRef<InjectedNameResolutionResult['status']>('idle');\n const resolvedNameRef = useRef<string | undefined>(undefined);\n const chainScopeBlockedRef = useRef(false);\n const validationRef = useRef(validation);\n const addressingRef = useRef(addressing);\n resolverPresentRef.current = resolver !== null;\n classificationRef.current = classification;\n statusRef.current = resolution.status;\n resolvedNameRef.current = resolution.status === 'resolved' ? resolution.name : undefined;\n chainScopeBlockedRef.current = chainScopeBlocked;\n validationRef.current = validation;\n addressingRef.current = addressing;\n\n const validate = useCallback((value: unknown): string | boolean => {\n // INV-84: optional-field resolution-pending guard — a pending name gates submit\n // regardless of `required`. Checked BEFORE the legacy empty short-circuit, and\n // gated on resolver presence so the no-resolver validator is byte-identical (INV-82).\n if (\n resolverPresentRef.current &&\n classificationRef.current === 'name-candidate' &&\n (statusRef.current !== 'resolved' || chainScopeBlockedRef.current)\n ) {\n return NAME_RESOLUTION_PENDING_GATE;\n }\n\n // Check required field explicitly first\n if (value === undefined || value === null || value === '') {\n return validationRef.current?.required ? 'This field is required' : true;\n }\n\n // Perform standard validations (min, max, pattern, etc.) if they exist\n // Using the existing validateField utility for this part\n const standardValidationResult = validateField(value, validationRef.current);\n if (standardValidationResult !== true) {\n return standardValidationResult;\n }\n\n // Perform capability-specific address validation if addressing exists\n if (addressingRef.current && typeof value === 'string') {\n if (!addressingRef.current.isValidAddress(value)) {\n return 'Invalid address format for the selected chain';\n }\n }\n\n // If all checks pass\n return true;\n }, []);\n\n const { field, fieldState } = useController({\n control,\n name,\n rules: { validate },\n disabled: readOnly,\n });\n const fieldOnChange = field.onChange;\n\n // INV-84 enforcement at the formState level. RHF (^7.79) includes `isValid`\n // in a state emission only when it differs from its internal snapshot, and\n // the mount-time isValid computation is async — so a name keystroke that\n // does not change the RHF value ('' → '') can have its isValid=false lost to\n // a stale in-flight `{isValid: true}` emission, leaving `formState.isValid`\n // stuck `true` through debouncing/loading/error (nothing later reconciles,\n // because pending-state commits never change the value). Observing isValid\n // and re-asserting the gate error converges regardless of emission order:\n // every stale `true` re-renders this component and re-triggers the effect,\n // and `control.setError` unconditionally emits isValid=false.\n // With no resolver the subscription is disabled and `.isValid` is never read\n // (the proxy read is what opts the form into isValid tracking), so the field\n // adds zero validation traffic and zero re-renders (INV-82).\n const gateFormState = useFormState({ control, disabled: resolver === null });\n const observedIsValid = resolver !== null && gateFormState.isValid;\n const pendingNameGate =\n resolver !== null &&\n classification === 'name-candidate' &&\n (resolution.status !== 'resolved' || chainScopeBlocked);\n useEffect(() => {\n if (pendingNameGate && observedIsValid) {\n control.setError(name, { type: 'validate', message: NAME_RESOLUTION_PENDING_GATE });\n }\n }, [pendingNameGate, observedIsValid, control, name]);\n\n // INV-79 / INV-80 / INV-85: the single name→hex write site. Reads the CURRENT\n // resolution inline (no cached hex), fires only on `resolved` AND when the typed\n // input still normalizes to the resolved name — so a stale in-flight resolution\n // can never write a hex after the user has typed on. The machine-level\n // out-of-order drop (INV-117) guarantees this effect never even sees a\n // mismatched (resolved, name) pair.\n const resolvedAddress = resolution.status === 'resolved' ? resolution.data.address : undefined;\n const resolvedName = resolution.status === 'resolved' ? resolution.name : undefined;\n const isResolvedNameMatch =\n resolvedName !== undefined && normalizeResolvedName(inputValue) === resolvedName;\n useEffect(() => {\n // INV-79 / INV-80 / INV-85 / INV-134: the single name→hex write site.\n if (isResolvedNameMatch && resolvedAddress !== undefined && !chainScopeBlocked) {\n // Keep the display decoupled: the useWatch sync must not overwrite the\n // typed name with the hex we are about to write (INV-69).\n lastSetValueRef.current = resolvedAddress;\n fieldOnChange(resolvedAddress);\n }\n }, [isResolvedNameMatch, resolvedAddress, chainScopeBlocked, fieldOnChange]);\n\n // Additive, READ-ONLY name-notification channel (SF-5 INV-109..111). A separate\n // effect that never touches the hex-write path — it only surfaces the resolved\n // NAME (never the hex) through the same `isResolvedNameMatch` guard, so the\n // emitted name and the written hex can never derive from divergent compares.\n const matchedName = isResolvedNameMatch ? resolvedName : undefined;\n useEffect(() => {\n onResolvedNameChange?.(matchedName);\n }, [matchedName, onResolvedNameChange]);\n\n const {\n containerRef,\n resolvedSuggestions,\n hasSuggestions,\n highlightedIndex,\n suggestionsDisabled,\n setHighlightedIndex,\n closeSuggestions,\n onInputChange,\n onContainerKeyDown,\n } = useAddressSuggestionField({ inputValue, suggestions: suggestionsProp });\n\n /**\n * The single site for the typed/raw write (the name→hex write lives in the\n * effect above). With no resolver this is the legacy write, verbatim (INV-82);\n * with a resolver, only the `name-candidate` classification diverges:\n * - hex / malformed / empty → the raw value (legacy sync validate applies)\n * - name-candidate → `''` — gates submit and synchronously invalidates any\n * prior resolved hex before re-resolution (INV-75 / INV-81)\n */\n const commitTypedValue = useCallback(\n (value: string): void => {\n setInputValue(value);\n\n if (!resolverPresentRef.current) {\n // Legacy path — byte-identical (INV-82 part 1).\n lastSetValueRef.current = value;\n fieldOnChange(value);\n return;\n }\n\n const c = classifyAddressInput(value, { isValidAddress, isValidName });\n // Sync the validator's refs so a validation triggered by the write below\n // sees this keystroke's state immediately (INV-84).\n classificationRef.current = c;\n if (c === 'name-candidate') {\n // Same-normalized re-entry (e.g. 'alice.eth' → 'ALICE.ETH' / trailing\n // space): the resolution machine stays `resolved`, so clearing RHF to\n // '' would strand the form (UI still announces success, write-effect\n // deps unchanged → hex never rewritten). Keep the hex.\n const normalized = normalizeResolvedName(value);\n if (\n statusRef.current === 'resolved' &&\n resolvedNameRef.current === normalized &&\n !chainScopeBlockedRef.current\n ) {\n return;\n }\n statusRef.current = 'debouncing';\n lastSetValueRef.current = '';\n fieldOnChange('');\n } else {\n // hex / malformed / empty passthrough — identical to the legacy field (INV-82 part 2).\n lastSetValueRef.current = value;\n fieldOnChange(value);\n }\n },\n [fieldOnChange, isValidAddress, isValidName]\n );\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n commitTypedValue(e.target.value);\n onInputChange(e.target.value);\n };\n\n const applySuggestion = (suggestion: AddressSuggestion): void => {\n commitTypedValue(suggestion.value);\n onSuggestionSelect?.(suggestion);\n closeSuggestions();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n if (hasSuggestions && e.key === 'Enter' && highlightedIndex >= 0) {\n e.preventDefault();\n applySuggestion(resolvedSuggestions[highlightedIndex]);\n return;\n }\n\n if (e.key === 'Escape') {\n if (hasSuggestions) {\n closeSuggestions();\n return;\n }\n handleEscapeKey(commitTypedValue, inputValue)(e);\n }\n };\n\n // Distinguish a real validation error (shown, red, aria-invalid) from the\n // non-user-facing pending gate (neutral; the aria-live region shows \"Resolving…\").\n // With no resolver the gate can never be set, so these equal the legacy values (INV-82).\n const hasError = !!fieldState.error;\n const isPendingGate = fieldState.error?.message === NAME_RESOLUTION_PENDING_GATE;\n const hasRealError = hasError && !isPendingGate;\n const shouldShowError = hasRealError && fieldState.isTouched;\n const validationClasses = getValidationStateClasses(\n hasRealError ? fieldState.error : undefined,\n isPendingGate ? false : fieldState.isTouched\n );\n\n // Safely extract the pattern error message. The `pattern` validation rule can be either a\n // RegExp object or an object with a `value` (RegExp) and a `message` (string). This\n // type guard ensures we only try to access `.message` on the correct object type.\n const patternErrorMessage =\n validation?.pattern && typeof validation.pattern === 'object' && 'message' in validation.pattern\n ? (validation.pattern.message as string)\n : undefined;\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError: hasRealError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n // INV-70 / INV-89: exactly one outcome per resolution state, each with a designed,\n // non-blank rendering. A single switch guarantees mutual exclusivity.\n const renderOutcome = (): React.ReactNode => {\n if (forwardUnsupported) {\n // INV-78: no runtime read inside ui-components — with no injected method\n // there is no result to source a network label from, so the message names\n // \"this network\" generically. No retry: definitive negative (INV-90).\n return (\n <span role=\"alert\" className=\"text-destructive text-sm\">\n {nameResolutionMessageForCode('UNSUPPORTED_NETWORK')}\n </span>\n );\n }\n switch (resolution.status) {\n case 'idle':\n return null;\n case 'debouncing':\n case 'loading':\n // INV-129 / INV-130: phase-1 then phase-2 loading copy — no mechanism words.\n return <span className=\"text-muted-foreground text-sm\">{resolvingAnnouncerCopy}</span>;\n case 'resolved':\n // INV-137: chain-scope mismatch — utils-only message, no retry (INV-148).\n if (chainScopeBlocked) {\n return (\n <span role=\"alert\" className=\"text-destructive text-sm\">\n {nameResolutionChainScopeMismatchMessage({\n activeNetworkName,\n })}\n </span>\n );\n }\n const fallbackNetworks =\n showCrossNetworkFallbackDisclaimer && isCrossNetworkFallback(resolution.data.provenance)\n ? getFallbackNetworks(resolution.data.provenance)\n : undefined;\n const fallbackMessage =\n fallbackNetworks &&\n nameResolutionCrossNetworkFallbackMessage(\n fallbackNetworks,\n crossNetworkFallbackMessageNames(fallbackNetworks, resolveNetworkLabel)\n );\n // INV-126 / INV-127 / INV-128: frozen mechanism-neutral success template.\n return (\n <span className=\"text-sm\">\n <span>\n Resolved to <code className=\"font-mono\">{resolution.data.address}</code>\n </span>\n {fallbackMessage ? (\n <span className=\"mt-1 block text-muted-foreground text-xs\" role=\"note\">\n {fallbackMessage}\n </span>\n ) : null}\n </span>\n );\n case 'error': {\n // INV-78: the network identifier comes from the injected result itself\n // (only UNSUPPORTED_NETWORK carries one) — never from the prop adapter,\n // never from a runtime read inside ui-components.\n const networkName =\n resolution.error.code === 'UNSUPPORTED_NETWORK'\n ? resolution.error.networkId || undefined\n : undefined;\n // INV-88 / INV-91: the code-derived message only — never a raw diagnostic field.\n const message = nameResolutionMessageForCode(resolution.error.code, { networkName });\n const isTransient = TRANSIENT_ERROR_CODES.has(resolution.error.code);\n const retry = resolution.retry;\n return (\n <span role=\"alert\" className=\"text-destructive text-sm\">\n {message}\n {/* INV-90: retry offered only for transient codes. */}\n {isTransient ? (\n <button type=\"button\" className=\"ml-2 underline\" onClick={retry}>\n Retry\n </button>\n ) : null}\n </span>\n );\n }\n }\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <div ref={containerRef} className=\"relative\" onKeyDown={onContainerKeyDown}>\n <Input\n {...field}\n id={id}\n placeholder={placeholder || (resolver !== null ? '0x... or name' : '0x...')}\n className={validationClasses}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n // INV-69: the input always shows the typed string — never the resolved hex.\n // Identical to binding `field.value` when no resolver is mounted (INV-82).\n value={inputValue}\n {...accessibilityProps}\n // INV-92: preserve the legacy describedby wiring verbatim when no resolver\n // is mounted; with a resolver, additively associate the dedicated\n // resolution announcer (never overwriting error/description).\n aria-describedby={\n resolver === null\n ? `${helperText ? descriptionId : ''} ${hasRealError ? errorId : ''}`\n : [helperText ? descriptionId : '', hasRealError ? errorId : '', resolutionRegionId]\n .filter(Boolean)\n .join(' ') || undefined\n }\n aria-expanded={hasSuggestions}\n aria-autocomplete={suggestionsDisabled ? undefined : 'list'}\n aria-controls={hasSuggestions ? `${id}-suggestions` : undefined}\n aria-activedescendant={\n hasSuggestions && highlightedIndex >= 0\n ? `${id}-suggestion-${highlightedIndex}`\n : undefined\n }\n disabled={readOnly}\n />\n\n {hasSuggestions && (\n <AddressSuggestionList\n id={id}\n suggestions={resolvedSuggestions}\n highlightedIndex={highlightedIndex}\n onSelect={applySuggestion}\n onHighlight={setHighlightedIndex}\n />\n )}\n </div>\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message — unchanged; the pending gate string is suppressed. */}\n <ErrorMessage\n error={hasRealError ? fieldState.error : undefined}\n id={errorId}\n message={shouldShowError ? fieldState.error?.message || patternErrorMessage : undefined}\n />\n\n {/* INV-92: dedicated aria-live announcer, distinct from the RHF error region;\n absent entirely with no resolver (INV-82). Kept mounted while a resolver is\n present so live-region announcements are reliable. INV-93: it never steals\n focus — announcement is via aria-live only. */}\n {resolver !== null && (\n <div id={resolutionRegionId} aria-live=\"polite\" className=\"min-h-5\">\n {renderOutcome()}\n </div>\n )}\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nAddressField.displayName = 'AddressField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Label } from '../ui/label';\nimport { Textarea } from '../ui/textarea';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n} from './utils';\n\n/**\n * TextAreaField component properties\n */\nexport interface TextAreaFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Number of rows for the textarea\n */\n rows?: number;\n\n /**\n * Maximum characters allowed in textarea\n */\n maxLength?: number;\n\n /**\n * Custom validation function for textarea values\n */\n validateTextArea?: (value: string) => boolean | string;\n}\n\n/**\n * Multi-line text input field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles textarea-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Resizable multi-line text input\n * - Character limit support\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation with Escape to clear\n */\nexport function TextAreaField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n rows = 4,\n maxLength,\n validateTextArea,\n readOnly,\n}: TextAreaFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Run custom validation if provided\n if (validateTextArea && value) {\n const validation = validateTextArea(value);\n if (validation !== true && typeof validation === 'string') {\n return validation;\n }\n }\n\n // Check maximum length\n if (maxLength && typeof value === 'string' && value.length > maxLength) {\n return `Maximum length is ${maxLength} characters`;\n }\n\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <Textarea\n {...field}\n id={id}\n placeholder={placeholder}\n rows={rows}\n maxLength={maxLength}\n className={validationClasses}\n value={field.value ?? ''}\n disabled={readOnly}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n onKeyDown={handleEscapeKey((value) => {\n if (typeof field.onChange === 'function') {\n field.onChange(value);\n }\n }, field.value)}\n />\n\n {/* Display character count if maxLength is provided */}\n {maxLength && typeof field.value === 'string' && (\n <div className=\"text-muted-foreground text-right text-xs\">\n {field.value.length}/{maxLength}\n </div>\n )}\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nTextAreaField.displayName = 'TextAreaField';\n","import type { AddressCandidateClassification } from '@openzeppelin/ui-utils';\n\n/**\n * Localizable UI strings for {@link AddressListField} built-in chrome\n * (buttons, previews, bulk-add feedback). Domain copy such as placeholders and\n * format hints are passed as component props instead.\n */\nexport interface AddressListFieldLabels {\n addSingleAddress: string;\n invalidSingleAddress: string;\n enableBulkEntry: string;\n enableSingleEntry: string;\n addAddresses: string;\n addAddressCount: (count: number) => string;\n invalidPrefix: string;\n invalidMore: (extraCount: number) => string;\n maxItemsReached: (maxItems: number) => string;\n addressesAdded: (count: number) => string;\n removeAddress: (index: number) => string;\n previewReadyToAdd: (count: number) => string;\n previewInvalid: (count: number) => string;\n previewAlreadyListed: (count: number) => string;\n previewDuplicateInPaste: (count: number) => string;\n bulkNothingAdded: string;\n bulkAdded: (count: number) => string;\n bulkInvalidFormats: (count: number) => string;\n bulkAlreadyListed: (count: number) => string;\n bulkDuplicatesInPaste: (count: number) => string;\n}\n\n/** Default English labels for {@link AddressListField}. */\nexport const DEFAULT_ADDRESS_LIST_FIELD_LABELS: AddressListFieldLabels = {\n addSingleAddress: 'Add',\n invalidSingleAddress: 'Enter a valid address',\n enableBulkEntry: 'Bulk paste',\n enableSingleEntry: 'Single entry',\n addAddresses: 'Add addresses',\n addAddressCount: (count) => `Add ${count} address${count === 1 ? '' : 'es'}`,\n invalidPrefix: 'Invalid:',\n invalidMore: (extraCount) => `(+${extraCount} more)`,\n maxItemsReached: (maxItems) => `Maximum of ${maxItems} addresses reached.`,\n addressesAdded: (count) => `${count} address${count === 1 ? '' : 'es'} added`,\n removeAddress: (index) => `Remove address ${index + 1}`,\n previewReadyToAdd: (count) => `${count} ready to add`,\n previewInvalid: (count) => `${count} invalid`,\n previewAlreadyListed: (count) => `${count} already listed`,\n previewDuplicateInPaste: (count) => `${count} duplicate in paste`,\n bulkNothingAdded: 'No addresses were added. Check formatting and try again.',\n bulkAdded: (count) => `Added ${count} address${count === 1 ? '' : 'es'}`,\n bulkInvalidFormats: (count) => `${count} invalid format${count === 1 ? '' : 's'}`,\n bulkAlreadyListed: (count) => `${count} already listed`,\n bulkDuplicatesInPaste: (count) => `${count} duplicate${count === 1 ? '' : 's'} in paste`,\n};\n\n/** Merges {@link DEFAULT_ADDRESS_LIST_FIELD_LABELS} with optional overrides. */\nexport function resolveAddressListFieldLabels(\n overrides?: Partial<AddressListFieldLabels>\n): AddressListFieldLabels {\n return { ...DEFAULT_ADDRESS_LIST_FIELD_LABELS, ...overrides };\n}\n\n/** Builds the inline helper preview shown while the user types in the draft textarea. */\nexport function buildAddressListPreviewSummary(\n classification: AddressCandidateClassification | null,\n labels: AddressListFieldLabels\n): string | null {\n if (!classification) return null;\n\n const skipped =\n classification.invalid.length +\n classification.alreadyListed.length +\n classification.duplicatesInInput.length;\n if (classification.accepted.length === 0 && skipped === 0) return null;\n\n const parts: string[] = [];\n if (classification.accepted.length > 0) {\n parts.push(labels.previewReadyToAdd(classification.accepted.length));\n }\n if (classification.invalid.length > 0) {\n parts.push(labels.previewInvalid(classification.invalid.length));\n }\n if (classification.alreadyListed.length > 0) {\n parts.push(labels.previewAlreadyListed(classification.alreadyListed.length));\n }\n if (classification.duplicatesInInput.length > 0) {\n parts.push(labels.previewDuplicateInPaste(classification.duplicatesInInput.length));\n }\n return parts.join(' · ');\n}\n\n/** Formats post-add feedback after the user commits parsed addresses to the list. */\nexport function formatAddressBulkSummary(\n classification: AddressCandidateClassification,\n addedCount: number,\n labels: AddressListFieldLabels\n): string | null {\n if (addedCount === 0 && classification.accepted.length === 0) {\n const skipped =\n classification.invalid.length +\n classification.alreadyListed.length +\n classification.duplicatesInInput.length;\n if (skipped === 0) return null;\n return labels.bulkNothingAdded;\n }\n\n const parts: string[] = [];\n if (addedCount > 0) {\n parts.push(labels.bulkAdded(addedCount));\n }\n if (classification.invalid.length > 0) {\n parts.push(labels.bulkInvalidFormats(classification.invalid.length));\n }\n if (classification.alreadyListed.length > 0) {\n parts.push(labels.bulkAlreadyListed(classification.alreadyListed.length));\n }\n if (classification.duplicatesInInput.length > 0) {\n parts.push(labels.bulkDuplicatesInPaste(classification.duplicatesInInput.length));\n }\n\n if (parts.length === 0) return null;\n\n return parts.join('. ') + '.';\n}\n","import { Info, Plus } from 'lucide-react';\nimport { useCallback, useMemo, useState, type ReactNode } from 'react';\nimport { useForm } from 'react-hook-form';\n\nimport type { AddressingCapability } from '@openzeppelin/ui-types';\nimport { classifyAddressCandidates, parseDelimitedAddressInput } from '@openzeppelin/ui-utils';\n\nimport { Button } from '../../ui/button';\nimport { TextAreaField } from '../TextAreaField';\nimport {\n buildAddressListPreviewSummary,\n formatAddressBulkSummary,\n type AddressListFieldLabels,\n} from './labels';\n\ninterface AddressListBulkDraftForm {\n input: string;\n}\n\nexport interface AddressListBulkEntryProps {\n fieldId: string;\n value: readonly string[];\n onAdd: (addresses: string[]) => void;\n placeholder: string;\n formatHint: string;\n addressing?: AddressingCapability;\n maxItems?: number;\n disabled?: boolean;\n maxInvalidPreview?: number;\n labels: AddressListFieldLabels;\n /** Entry-mode toggle rendered flush to the textarea's right edge. */\n modeToggle?: ReactNode;\n}\n\n/** Bulk paste entry — info callout, textarea, and add action in a compact stack. */\nexport function AddressListBulkEntry({\n fieldId,\n value,\n onAdd,\n placeholder,\n formatHint,\n addressing,\n maxItems,\n disabled = false,\n maxInvalidPreview = 3,\n labels,\n modeToggle,\n}: AddressListBulkEntryProps) {\n const atLimit = maxItems != null && value.length >= maxItems;\n const inputDisabled = disabled || atLimit;\n const [feedback, setFeedback] = useState<string | null>(null);\n\n const { control, reset, watch } = useForm<AddressListBulkDraftForm>({\n defaultValues: { input: '' },\n mode: 'onChange',\n });\n\n const rawInput = watch('input');\n const classification = useMemo(() => {\n if (!rawInput.trim()) return null;\n return classifyAddressCandidates(\n parseDelimitedAddressInput(rawInput),\n value,\n addressing,\n maxItems\n );\n }, [rawInput, value, addressing, maxItems]);\n\n const previewSummary = useMemo(\n () => buildAddressListPreviewSummary(classification, labels),\n [classification, labels]\n );\n\n const statusMessage = rawInput.trim() ? (previewSummary ?? undefined) : (feedback ?? undefined);\n\n const handleAdd = useCallback(() => {\n if (!classification || classification.accepted.length === 0 || atLimit) return;\n onAdd(classification.accepted);\n reset({ input: '' });\n setFeedback(formatAddressBulkSummary(classification, classification.accepted.length, labels));\n }, [classification, atLimit, onAdd, reset, labels]);\n\n const acceptedCount = classification?.accepted.length ?? 0;\n const addButtonLabel =\n acceptedCount > 0 ? labels.addAddressCount(acceptedCount) : labels.addAddresses;\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-start gap-2 rounded-lg border border-border/70 bg-muted/30 px-3 py-2.5\">\n <Info className=\"mt-0.5 size-4 shrink-0 text-muted-foreground\" />\n <p className=\"text-xs leading-relaxed text-muted-foreground\">{formatHint}</p>\n </div>\n\n <div>\n <div className=\"relative\">\n <TextAreaField\n id={`address-list-bulk-${fieldId}`}\n name=\"input\"\n label=\"\"\n placeholder={placeholder}\n helperText={statusMessage}\n control={control}\n rows={4}\n validation={{ required: false }}\n readOnly={inputDisabled}\n />\n </div>\n {modeToggle ? <div className=\"flex justify-end pr-2\">{modeToggle}</div> : null}\n </div>\n\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <div className=\"min-w-0 flex-1\">\n {classification && classification.invalid.length > 0 ? (\n <p className=\"text-xs text-destructive\">\n {labels.invalidPrefix} {classification.invalid.slice(0, maxInvalidPreview).join(', ')}\n {classification.invalid.length > maxInvalidPreview\n ? ` ${labels.invalidMore(classification.invalid.length - maxInvalidPreview)}`\n : ''}\n </p>\n ) : null}\n {atLimit && maxItems != null ? (\n <p className=\"text-xs text-muted-foreground\">{labels.maxItemsReached(maxItems)}</p>\n ) : null}\n </div>\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"shrink-0\"\n disabled={inputDisabled || acceptedCount === 0}\n onClick={() => handleAdd()}\n >\n <Plus className=\"mr-1 size-4\" />\n {addButtonLabel}\n </Button>\n </div>\n </div>\n );\n}\n","import { X } from 'lucide-react';\n\nimport { AddressDisplay } from '../../ui/address-display';\nimport { Button } from '../../ui/button';\nimport type { AddressListFieldLabels } from './labels';\n\nexport interface AddressListEntriesProps {\n value: readonly string[];\n getExplorerUrl?: (address: string) => string | null | undefined;\n disabled?: boolean;\n labels: AddressListFieldLabels;\n onRemove: (index: number) => void;\n}\n\n/** Renders committed addresses with remove actions. Shared by single and bulk entry modes. */\nexport function AddressListEntries({\n value,\n getExplorerUrl,\n disabled = false,\n labels,\n onRemove,\n}: AddressListEntriesProps) {\n if (value.length === 0) return null;\n\n return (\n <div className=\"space-y-1\">\n <p className=\"text-xs text-muted-foreground\">{labels.addressesAdded(value.length)}</p>\n <div className=\"max-h-44 space-y-1 overflow-y-auto rounded-md border border-border/70 p-1\">\n {value.map((address, index) => (\n <div\n key={`${address}-${index}`}\n className=\"flex items-center justify-between rounded bg-muted p-2\"\n >\n <AddressDisplay\n address={address}\n variant=\"inline\"\n truncateWhenLabeled\n showCopyButton\n explorerUrl={getExplorerUrl?.(address) ?? undefined}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"size-7 shrink-0 p-0 text-muted-foreground hover:text-destructive\"\n onClick={() => onRemove(index)}\n disabled={disabled}\n aria-label={labels.removeAddress(index)}\n >\n <X className=\"size-3.5\" />\n </Button>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { Plus } from 'lucide-react';\nimport { useCallback, useMemo, type ReactNode } from 'react';\nimport { useForm, useWatch } from 'react-hook-form';\n\nimport type { AddressingCapability } from '@openzeppelin/ui-types';\n\nimport { Button } from '../../ui/button';\nimport { AddressField } from '../AddressField';\nimport type { AddressListFieldLabels } from './labels';\n\ninterface AddressListSingleDraftForm {\n draft: string;\n}\n\nexport interface AddressListSingleEntryProps {\n fieldId: string;\n value: readonly string[];\n onAdd: (address: string) => void;\n placeholder: string;\n addressing?: AddressingCapability;\n maxItems?: number;\n disabled?: boolean;\n labels: AddressListFieldLabels;\n /** Entry-mode toggle rendered flush to the input's right edge. */\n modeToggle?: ReactNode;\n}\n\n/** Single-address entry — inline {@link AddressField} with an Add button (address-book aware). */\nexport function AddressListSingleEntry({\n fieldId,\n value,\n onAdd,\n placeholder,\n addressing,\n maxItems,\n disabled = false,\n labels,\n modeToggle,\n}: AddressListSingleEntryProps) {\n const atLimit = maxItems != null && value.length >= maxItems;\n const inputDisabled = disabled || atLimit;\n\n const { control, reset, getValues, handleSubmit } = useForm<AddressListSingleDraftForm>({\n defaultValues: { draft: '' },\n mode: 'onChange',\n });\n\n const draft = useWatch({ control, name: 'draft' });\n const trimmedDraft = (draft ?? '').trim();\n\n const validationState = useMemo(() => {\n if (!trimmedDraft) return { canAdd: false, showInvalid: false };\n if (value.includes(trimmedDraft)) return { canAdd: false, showInvalid: false };\n if (atLimit) return { canAdd: false, showInvalid: false };\n if (addressing && !addressing.isValidAddress(trimmedDraft)) {\n return { canAdd: false, showInvalid: true };\n }\n return { canAdd: true, showInvalid: false };\n }, [trimmedDraft, value, atLimit, addressing]);\n\n const submitAdd = useCallback(() => {\n if (!validationState.canAdd) return;\n onAdd(getValues('draft').trim());\n reset({ draft: '' });\n }, [validationState.canAdd, onAdd, getValues, reset]);\n\n return (\n <div className=\"space-y-1\">\n <div className=\"flex items-start gap-2\">\n <div className=\"min-w-0 flex-1\">\n <AddressField\n id={`address-list-single-${fieldId}`}\n name=\"draft\"\n label=\"\"\n placeholder={placeholder}\n helperText={validationState.showInvalid ? labels.invalidSingleAddress : undefined}\n control={control}\n addressing={addressing}\n validation={{ required: false }}\n readOnly={inputDisabled}\n />\n {modeToggle ? <div className=\"-mt-px flex justify-end pr-2\">{modeToggle}</div> : null}\n </div>\n <Button\n type=\"button\"\n className=\"h-10 shrink-0\"\n disabled={inputDisabled || !validationState.canAdd}\n onClick={handleSubmit(submitAdd)}\n >\n <Plus className=\"mr-1 size-4\" />\n {labels.addSingleAddress}\n </Button>\n </div>\n\n {atLimit && maxItems != null && (\n <p className=\"text-xs text-muted-foreground\">{labels.maxItemsReached(maxItems)}</p>\n )}\n </div>\n );\n}\n","import { ClipboardPaste, PencilLine } from 'lucide-react';\nimport { useCallback, useId, useMemo, useState } from 'react';\n\nimport type { AddressingCapability } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Label } from '../../ui/label';\nimport { AddressListBulkEntry } from './AddressListBulkEntry';\nimport { AddressListEntries } from './AddressListEntries';\nimport { AddressListSingleEntry } from './AddressListSingleEntry';\nimport { resolveAddressListFieldLabels, type AddressListFieldLabels } from './labels';\n\nexport type AddressListEntryMode = 'single' | 'bulk';\n\n/**\n * AddressListField component properties.\n *\n * Uses a controlled `value` / `onChange` API for the committed address list.\n * Entry defaults to single-address mode ({@link AddressField} with address-book\n * suggestions); users can toggle to bulk paste mode — never both at once.\n */\nexport interface AddressListFieldProps {\n /** Committed addresses currently shown in the list. */\n value: readonly string[];\n /** Called when addresses are added or removed. */\n onChange: (addresses: string[]) => void;\n /** Placeholder for single-address entry (default mode). */\n placeholder: string;\n /** Placeholder for bulk paste. Defaults to {@link placeholder}. */\n bulkPlaceholder?: string;\n /** Shown in bulk mode only — delimiter and validation guidance. */\n formatHint: string;\n /** When provided, each candidate is validated via {@link AddressingCapability.isValidAddress}. */\n addressing?: AddressingCapability;\n /** Optional explorer URL resolver passed through to {@link AddressDisplay}. */\n getExplorerUrl?: (address: string) => string | null | undefined;\n /** Optional field label rendered above the active entry control. */\n label?: string;\n /** Optional domain-specific helper shown below the header row. */\n helperText?: string;\n /** Maximum number of addresses allowed in {@link value}. */\n maxItems?: number;\n /** Disables entry and remove actions. */\n disabled?: boolean;\n /** Maximum invalid entries shown inline before truncating with a count suffix (bulk mode). */\n maxInvalidPreview?: number;\n className?: string;\n /** Entry mode shown on mount. Defaults to `'single'`. */\n defaultEntryMode?: AddressListEntryMode;\n /**\n * Whether users can switch between single and bulk entry. Defaults to `true`.\n * Set to `false` to hide the toggle and lock the field to {@link defaultEntryMode}.\n */\n allowModeToggle?: boolean;\n /** Optional UI labels to override {@link DEFAULT_ADDRESS_LIST_FIELD_LABELS}. */\n labels?: Partial<AddressListFieldLabels>;\n}\n\n/**\n * Multi-address list field with single-entry default and optional bulk paste.\n */\nexport function AddressListField({\n value,\n onChange,\n placeholder,\n bulkPlaceholder,\n formatHint,\n addressing,\n getExplorerUrl,\n label,\n helperText,\n maxItems,\n disabled = false,\n maxInvalidPreview = 3,\n className,\n defaultEntryMode = 'single',\n allowModeToggle = true,\n labels: labelOverrides,\n}: AddressListFieldProps) {\n const fieldId = useId();\n const labels = useMemo(() => resolveAddressListFieldLabels(labelOverrides), [labelOverrides]);\n const [entryMode, setEntryMode] = useState<AddressListEntryMode>(defaultEntryMode);\n const resolvedBulkPlaceholder = bulkPlaceholder ?? placeholder;\n\n const handleRemove = useCallback(\n (index: number) => {\n onChange(value.filter((_, currentIndex) => currentIndex !== index));\n },\n [onChange, value]\n );\n\n const handleAddSingle = useCallback(\n (address: string) => {\n onChange([...value, address]);\n },\n [onChange, value]\n );\n\n const handleAddBulk = useCallback(\n (addresses: string[]) => {\n onChange([...value, ...addresses]);\n },\n [onChange, value]\n );\n\n const switchToBulk = useCallback(() => setEntryMode('bulk'), []);\n const switchToSingle = useCallback(() => setEntryMode('single'), []);\n\n const toggleClassName =\n 'inline-flex items-center gap-1 rounded-b-md rounded-t-none border border-t-0 border-input bg-muted/40 px-2 py-1 text-xs font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground';\n const modeToggle = !allowModeToggle ? undefined : entryMode === 'single' ? (\n <button type=\"button\" onClick={switchToBulk} className={toggleClassName}>\n <ClipboardPaste className=\"size-3\" />\n {labels.enableBulkEntry}\n </button>\n ) : (\n <button type=\"button\" onClick={switchToSingle} className={toggleClassName}>\n <PencilLine className=\"size-3\" />\n {labels.enableSingleEntry}\n </button>\n );\n\n return (\n <div className={cn('space-y-3', className)}>\n {label ? <Label className=\"text-sm font-medium leading-none\">{label}</Label> : null}\n {helperText && entryMode === 'single' ? (\n <p className=\"text-sm leading-relaxed text-muted-foreground\">{helperText}</p>\n ) : null}\n\n {entryMode === 'single' ? (\n <AddressListSingleEntry\n fieldId={fieldId}\n value={value}\n onAdd={handleAddSingle}\n placeholder={placeholder}\n addressing={addressing}\n maxItems={maxItems}\n disabled={disabled}\n labels={labels}\n modeToggle={modeToggle}\n />\n ) : (\n <AddressListBulkEntry\n fieldId={fieldId}\n value={value}\n onAdd={handleAddBulk}\n placeholder={resolvedBulkPlaceholder}\n formatHint={formatHint}\n addressing={addressing}\n maxItems={maxItems}\n disabled={disabled}\n maxInvalidPreview={maxInvalidPreview}\n labels={labels}\n modeToggle={modeToggle}\n />\n )}\n\n <AddressListEntries\n value={value}\n getExplorerUrl={getExplorerUrl}\n disabled={disabled}\n labels={labels}\n onRemove={handleRemove}\n />\n </div>\n );\n}\n","/**\n * Address Suggestion Context\n *\n * Provides a React context for resolving address autocomplete suggestions.\n * When an `AddressSuggestionProvider` is mounted, every `AddressField`\n * in the subtree automatically renders a suggestion dropdown as the user types.\n *\n * @example\n * ```tsx\n * import { AddressSuggestionProvider } from '@openzeppelin/ui-components';\n * import { useAliasSuggestionResolver } from '@openzeppelin/ui-storage';\n *\n * function App() {\n * const resolver = useAliasSuggestionResolver(db);\n * return (\n * <AddressSuggestionProvider {...resolver}>\n * <MyApp />\n * </AddressSuggestionProvider>\n * );\n * }\n * ```\n */\nimport * as React from 'react';\n\nimport type { AddressSuggestionResolver } from '@openzeppelin/ui-types';\n\nimport { AddressSuggestionContext } from './context';\n\n/**\n * Props for `AddressSuggestionProvider`.\n *\n * Accepts the same shape as `AddressSuggestionResolver` so the provider can be\n * spread directly from a resolver hook: `<AddressSuggestionProvider {...resolver}>`.\n */\nexport interface AddressSuggestionProviderProps extends AddressSuggestionResolver {\n children: React.ReactNode;\n}\n\n/**\n * Provides address suggestion resolution to all `AddressField` instances in the\n * subtree. Wrap your application (or a subsection) with this provider and\n * supply a `resolveSuggestions` function.\n *\n * @param props - Resolver function and children\n *\n * @example\n * ```tsx\n * <AddressSuggestionProvider\n * resolveSuggestions={(query, networkId) => filterAliases(query, networkId)}\n * >\n * <App />\n * </AddressSuggestionProvider>\n * ```\n */\nexport function AddressSuggestionProvider({\n children,\n resolveSuggestions,\n}: AddressSuggestionProviderProps): React.ReactElement {\n const value = React.useMemo<AddressSuggestionResolver>(\n () => ({ resolveSuggestions }),\n [resolveSuggestions]\n );\n\n return (\n <AddressSuggestionContext.Provider value={value}>{children}</AddressSuggestionContext.Provider>\n );\n}\n","/**\n * Convenience hook that resolves suggestions for a query string using the\n * nearest `AddressSuggestionProvider`. Returns an empty array when no provider\n * is mounted or when the query is empty.\n *\n * @param query - Current input value to match against\n * @param networkId - Optional network identifier for scoping results\n * @returns Object containing the resolved suggestions array\n *\n * @example\n * ```tsx\n * function MyField({ query }: { query: string }) {\n * const { suggestions } = useAddressSuggestions(query, 'ethereum-mainnet');\n * return (\n * <ul>\n * {suggestions.map(s => <li key={s.value}>{s.label}</li>)}\n * </ul>\n * );\n * }\n * ```\n */\nimport * as React from 'react';\n\nimport type { AddressSuggestion } from '@openzeppelin/ui-types';\n\nimport { AddressSuggestionContext } from './context';\n\n/**\n * Return type for the `useAddressSuggestions` convenience hook.\n */\nexport interface UseAddressSuggestionsResult {\n /** Resolved suggestions for the current query */\n suggestions: AddressSuggestion[];\n}\n\n/** Resolves address suggestions from the nearest `AddressSuggestionProvider`. */\nexport function useAddressSuggestions(\n query: string,\n networkId?: string\n): UseAddressSuggestionsResult {\n const resolver = React.useContext(AddressSuggestionContext);\n\n const suggestions = React.useMemo(() => {\n if (!resolver || !query.trim()) return [];\n return resolver.resolveSuggestions(query, networkId);\n }, [resolver, query, networkId]);\n\n return { suggestions };\n}\n","/**\n * Name Resolver Context (SF-3)\n *\n * Provides a React context for forward name resolution (name → address).\n * When a `NameResolverProvider` is mounted, every `AddressField` in the\n * subtree resolves typed names inline through the injected `resolveName`\n * and submits the resolved hex — never the name (SC-004).\n *\n * The provider is deliberately **dumb** (INV-118): it memoizes the injected\n * functions into the context value and nothing else — no hook state, no\n * capability, no chain dependency. The smart runtime wiring lives upstream in\n * `@openzeppelin/ui-react` (`useRuntimeNameResolver`), which an app or the\n * renderer mounts ambiently:\n *\n * @example\n * ```tsx\n * import { NameResolverProvider } from '@openzeppelin/ui-components';\n * import { useRuntimeNameResolver } from '@openzeppelin/ui-react';\n *\n * function FormRoot() {\n * const resolver = useRuntimeNameResolver();\n * return (\n * <NameResolverProvider {...resolver}>\n * <MyForm />\n * </NameResolverProvider>\n * );\n * }\n * ```\n */\nimport * as React from 'react';\n\nimport { NameResolverContext, type NameResolverContextValue } from './context';\n\n/**\n * Props for `NameResolverProvider`.\n *\n * Accepts the same shape as `NameResolver` so the provider can be spread\n * directly from a resolver hook: `<NameResolverProvider {...resolver}>` —\n * the same idiom as `AddressSuggestionProvider` / `AddressLabelProvider`.\n */\nexport interface NameResolverProviderProps extends NameResolverContextValue {\n children: React.ReactNode;\n}\n\n/**\n * Provides forward name resolution to all `AddressField` instances in the\n * subtree (zero call-site wiring, SC-001). Both functions are optional: an\n * absent `resolveName` means forward resolution is unsupported and a typed\n * name surfaces `UNSUPPORTED_NETWORK` (INV-119 / SC-006).\n *\n * ## Stable resolver identity (integrator contract)\n *\n * The injected resolver **must be referentially stable across renders** —\n * memoize it (e.g. `useMemo`) or use `useRuntimeNameResolver` from\n * `@openzeppelin/ui-react`, which is stable by construction. A resolver whose\n * function identity changes on every render (e.g. a fresh inline function) is a\n * misconfiguration: the field keys inline resolution on that identity, so a\n * churning identity would otherwise re-dispatch on every render — an unbounded\n * RPC loop on a funds path.\n *\n * The base component **detects and withstands** this (it is not merely a caveat):\n * dispatch is bounded per resolution intent so a churning resolver can never drive\n * an unbounded loop (INV-123), a one-shot development-only warning names the\n * misconfiguration (INV-124), and the field degrades to a **safe gated state**\n * (empty value, submit blocked — never a wrong address, never a throw; INV-125)\n * until the resolver is memoized. A **genuine** resolver/network swap — a single\n * identity change for a given input — is still honored and re-resolves within\n * budget (INV-119). The bound is a backstop; the contract is a stable identity.\n *\n * @param props - Injected resolver functions and children\n */\nexport function NameResolverProvider({\n children,\n isValidName,\n resolveName,\n activeNetworkId,\n activeNetworkName,\n resolveNetworkLabel,\n}: NameResolverProviderProps): React.ReactElement {\n // INV-118: memoize-and-provide only — no hook state, no capability call.\n const value = React.useMemo<NameResolverContextValue>(\n () => ({ isValidName, resolveName, activeNetworkId, activeNetworkName, resolveNetworkLabel }),\n [isValidName, resolveName, activeNetworkId, activeNetworkName, resolveNetworkLabel]\n );\n\n return <NameResolverContext.Provider value={value}>{children}</NameResolverContext.Provider>;\n}\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n handleNumericKeys,\n} from './utils';\n\n/**\n * AmountField component properties\n */\nexport interface AmountFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Minimum value validation\n */\n min?: number;\n\n /**\n * Maximum value validation\n */\n max?: number;\n\n /**\n * Step value for increment/decrement\n */\n step?: number;\n\n /**\n * Number of decimal places to allow\n */\n decimals?: number;\n\n /**\n * Currency/token symbol to display\n */\n symbol?: string;\n\n /**\n * Position of the symbol (before or after the amount)\n */\n symbolPosition?: 'prefix' | 'suffix';\n\n /**\n * Custom validation function for amount values\n */\n validateAmount?: (value: number) => boolean | string;\n}\n\n/**\n * Amount input field component specifically designed for currency/token amounts with React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles amount-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Support for currency/token symbols\n * - Numeric-specific validations (min, max, decimals)\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation with arrow keys for numeric increment/decrement\n */\nexport function AmountField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n min,\n max,\n step = 0.01,\n decimals = 2,\n symbol = '',\n symbolPosition = 'suffix',\n validateAmount,\n}: AmountFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Formatter for displaying currency/token values\n const formatCurrency = (value: string | number): string => {\n if (value === '' || value === undefined || value === null) return '';\n\n const numValue = typeof value === 'string' ? parseFloat(value) : value;\n if (isNaN(numValue)) return '';\n\n return numValue.toFixed(decimals);\n };\n\n // Parse string input to number\n const parseAmount = (value: string): number => {\n const parsed = parseFloat(value);\n return isNaN(parsed) ? 0 : parsed;\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Convert to number for validation\n const numValue = typeof value === 'string' ? parseFloat(value) : value;\n\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '' || isNaN(numValue)) {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Validate min/max constraints\n if (min !== undefined && numValue < min) {\n return `Value must be at least ${min}`;\n }\n\n if (max !== undefined && numValue > max) {\n return `Value must be at most ${max}`;\n }\n\n // Run custom validation if provided\n if (validateAmount && !isNaN(numValue)) {\n const validation = validateAmount(numValue);\n if (validation !== true && typeof validation === 'string') {\n return validation;\n }\n }\n\n return true;\n },\n }}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error?.message;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n // Format display value\n const displayValue = field.value !== undefined && field.value !== null ? field.value : '';\n\n return (\n <>\n <div className=\"relative\">\n {symbol && symbolPosition === 'prefix' && (\n <span className=\"absolute top-1/2 left-3 -translate-y-1/2 text-gray-500\">\n {symbol}\n </span>\n )}\n\n <Input\n {...field}\n id={id}\n type=\"text\"\n inputMode=\"decimal\"\n placeholder={placeholder}\n value={displayValue}\n className={`${validationClasses} ${\n symbol && symbolPosition === 'prefix' ? 'pl-8' : ''\n } ${symbol && symbolPosition === 'suffix' ? 'pr-8' : ''}`}\n data-slot=\"input\"\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n onChange={(e) => {\n // Allow numeric values and decimal point\n const value = e.target.value;\n if (value === '' || /^-?\\d*\\.?\\d*$/.test(value)) {\n field.onChange(value);\n }\n }}\n onBlur={(e) => {\n // Format on blur\n if (e.target.value) {\n const parsed = parseFloat(e.target.value);\n if (!isNaN(parsed)) {\n field.onChange(formatCurrency(parsed));\n }\n }\n if (field.onBlur) {\n field.onBlur();\n }\n }}\n onKeyDown={(e) => {\n // Handle Escape key\n if (e.key === 'Escape') {\n handleEscapeKey((value) => {\n field.onChange(value === '' ? null : value);\n }, field.value)(e);\n return;\n }\n\n // Handle arrow keys for increment/decrement\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n handleNumericKeys(\n (newValue) => {\n field.onChange(formatCurrency(newValue));\n },\n parseAmount(field.value || ''),\n step,\n min,\n max\n )(e);\n }\n }}\n />\n\n {symbol && symbolPosition === 'suffix' && (\n <span className=\"absolute top-1/2 right-3 -translate-y-1/2 text-gray-500\">\n {symbol}\n </span>\n )}\n </div>\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nAmountField.displayName = 'AmountField';\n","import { GripVertical, Plus, X } from 'lucide-react';\nimport React from 'react';\nimport { Controller, FieldValues, useFieldArray, useFormContext, useWatch } from 'react-hook-form';\n\nimport type { FormFieldType } from '@openzeppelin/ui-types';\n\nimport { Button } from '../ui/button';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage, getAccessibilityProps } from './utils';\n\n/**\n * ArrayField component properties\n */\nexport interface ArrayFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * The type of elements in the array (e.g., 'text', 'number', 'blockchain-address')\n */\n elementType?: FormFieldType['type']; // TODO: Consider if a more specific subset of FieldType is relevant here if this component only renders simple types directly.\n\n /**\n * Minimum number of array elements\n */\n minItems?: number;\n\n /**\n * Maximum number of array elements\n */\n maxItems?: number;\n\n /**\n * Base configuration for array element fields.\n * This allows specifying common properties like placeholder, helperText, or specific validation\n * for each element in the array.\n */\n // TODO: Refine elementFieldConfig type. `id` and `name` are derived internally.\n // Consider a type like `Omit<Partial<FormFieldType>, 'id' | 'name'> & { defaultValue?: unknown }`\n // to allow specifying a more complex default value for appended items.\n elementFieldConfig?: Partial<FormFieldType>;\n\n /**\n * Render function for array elements.\n * This is crucial for rendering complex elements or integrating custom field components.\n */\n // TODO: Explore a fallback rendering mechanism if `renderElement` is not provided,\n // especially if `elementType` is a known simple type (e.g., 'text', 'number').\n // This could make the component more self-contained for basic array types.\n renderElement?: (field: FormFieldType, index: number) => React.ReactNode;\n}\n\n/**\n * Array input field component specifically designed for React Hook Form integration.\n *\n * This component provides a dynamic interface for managing array inputs with:\n * - Add/remove functionality for array items\n * - Validation for array length constraints\n * - Integration with existing field components for array elements\n * - Full accessibility support\n *\n * The component reuses existing field components (TextField, NumberField, etc.)\n * for individual array elements, maintaining consistency across the form system.\n *\n * Why the extra guards and synchronization exist (post-mortem/rationale):\n * - In certain runtime states (StrictMode double-invocation, preview remounts, state rehydration\n * from storage), React Hook Form's useFieldArray may not synchronously reflect an `append()`\n * or `remove()` call in the immediately subsequent read (e.g., reading `fields.length` or\n * `getValues(name)` right after the call). This resulted in newly added items (especially\n * falsy defaults like 0/false) appearing briefly and then disappearing, or remove operations\n * not updating the UI.\n * - To make array operations deterministic and resilient across flows (preview form with\n * FormProvider and the wizard's \"Use Hardcoded Value\" without a provider), we:\n * 1) Read a stable snapshot of the array value BEFORE `append()` and, if the immediate\n * post-append read doesn't reflect the addition, we coerce the state to\n * \"previousSnapshot + newValue\" via `setValue` (when context exists) or `replace`.\n * 2) Avoid `remove()` race conditions by always computing the new array via filter and\n * applying it with `replace`, which proved to be the most consistent across contexts.\n * 3) Keep `fields` in sync with the watched array value using a guarded `replace` in an effect.\n * A ref flag (`isReplacingRef`) prevents infinite loops when we ourselves are driving\n * the `replace`.\n * 4) Use optional chaining for form context (`formContext?.control`, `formContext?.getValues`,\n * `formContext?.setValue`) so the component works with either an inherited FormProvider or\n * an explicit `control` prop.\n * 5) Use `queueMicrotask` to reset the guard flag after our `replace` has been scheduled,\n * avoiding an extra timer tick while ensuring the effect observes the final state.\n *\n * Guarantees:\n * - Operations are idempotent: the fallback only runs when the immediate read does not reflect\n * the intended state, so we don't double-append/remove.\n * - Works both with and without FormProvider (preview vs wizard) due to context-agnostic state\n * reads and `replace` fallback.\n */\nexport function ArrayField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n elementType = 'text',\n minItems = 0,\n maxItems,\n elementFieldConfig,\n renderElement,\n readOnly,\n}: ArrayFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Get form context for nested field registration (may be absent in some builder flows)\n const formContext = useFormContext();\n\n // Use useFieldArray for dynamic array management\n const { fields, append, replace } = useFieldArray({\n control: control || formContext?.control,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n name: name as any, // Type assertion needed due to generic constraints\n // TODO: Investigate if stricter typing for `name` can be achieved to avoid `as any`\n // with react-hook-form's useFieldArray and deeply nested field names.\n });\n\n // Watch current array value in a context-agnostic way (works with provided control)\n const rawWatchedArray = useWatch({ control: control || formContext?.control, name }) as\n | unknown[]\n | undefined;\n const watchedArrayValue = React.useMemo<unknown[]>(() => {\n return Array.isArray(rawWatchedArray) ? rawWatchedArray : [];\n }, [rawWatchedArray]);\n\n // Ensure field array is synchronized with current value length on mount/reset\n // Keep field array synchronized with watched values, but prevent infinite loops\n const isReplacingRef = React.useRef(false);\n React.useEffect(() => {\n if (isReplacingRef.current) {\n // Skip sync if we're in the middle of a replace operation\n return;\n }\n\n if (Array.isArray(watchedArrayValue) && fields.length !== watchedArrayValue.length) {\n isReplacingRef.current = true;\n replace(watchedArrayValue as unknown as never);\n\n // Reset the flag in a microtask to allow the replace to complete without a timer tick\n queueMicrotask(() => {\n isReplacingRef.current = false;\n });\n }\n }, [fields.length, watchedArrayValue, replace]);\n\n // Note: Structural changes are observed via useWatch and the sync effect above; no additional tracking needed here.\n\n // Handle removing an array item with fallback for stale reads\n const handleRemoveItem = (index: number): void => {\n const valuesBeforeRemove = Array.isArray(watchedArrayValue)\n ? (watchedArrayValue as unknown[])\n : ([] as unknown[]);\n\n // Always use the fallback approach for remove to ensure consistency\n const updatedArray = valuesBeforeRemove.filter((_, i) => i !== index);\n\n // Set flag to prevent sync loop during manual replace\n isReplacingRef.current = true;\n replace(updatedArray as unknown as never);\n\n // Reset flag after operation\n queueMicrotask(() => {\n isReplacingRef.current = false;\n });\n };\n\n // Handle adding new array item\n const handleAddItem = (): void => {\n // Determine default value based on element type\n // TODO: Enhance default value generation.\n // 1. Allow `elementFieldConfig.defaultValue` to override this basic logic.\n // 2. For 'object' or 'array-object' elementType (if supported directly later),\n // this would need to be more sophisticated (e.g., an empty object/array).\n // 3. Consider a more generic `getDefaultValueByFieldType` utility if not already used/available.\n const defaultValue =\n elementFieldConfig?.defaultValue !== undefined\n ? elementFieldConfig.defaultValue\n : elementType === 'number' || elementType === 'amount'\n ? 0\n : elementType === 'checkbox'\n ? false\n : ''; // Default for text, address, etc.\n\n // Background and rationale:\n // In certain runtime states (e.g., preview remounts, incidental resets, StrictMode double-invocations),\n // an immediate read right after useFieldArray.append(...) can be stale and still reflect the\n // pre-append array. This manifested as a user-visible bug where adding an item (notably value 0)\n // either did nothing or briefly appeared and then disappeared.\n //\n // To make the operation deterministic, we snapshot the array BEFORE calling append and then\n // verify that the length actually increased. If not, we force-set the array using the snapshot\n // plus the new value. This is safe and idempotent because it only runs when the immediate read\n // did not reflect the append; it does not double-append.\n\n // Set flag to prevent sync interference during add operation\n isReplacingRef.current = true;\n\n const fieldsBeforeAppend = fields.length;\n const valuesBeforeAppend = Array.isArray(watchedArrayValue)\n ? (watchedArrayValue as unknown[])\n : ([] as unknown[]);\n\n append(defaultValue as FieldValues[typeof name]);\n\n // Verify append actually reflected in form state; if not, force set\n const afterAppendFieldsCount =\n (formContext?.getValues?.(name) as unknown[] | undefined)?.length ?? fields.length;\n\n // Fallback: if the immediate read did not reflect the append, coerce to\n // \"previous snapshot + new value\" so the UI consistently renders the new item.\n if (afterAppendFieldsCount <= fieldsBeforeAppend) {\n const baseArray = Array.isArray(valuesBeforeAppend)\n ? (valuesBeforeAppend as unknown[])\n : ([] as unknown[]);\n const coercedArray = [...baseArray, defaultValue] as unknown[];\n\n if (formContext?.setValue) {\n formContext.setValue(name as never, coercedArray as never, {\n shouldDirty: true,\n shouldTouch: true,\n });\n } else {\n // No form context (e.g., builder hardcoded flow). Use useFieldArray.replace to force state.\n replace(coercedArray as unknown as never);\n }\n }\n\n // Reset flag after operation completes\n queueMicrotask(() => {\n isReplacingRef.current = false;\n });\n };\n\n // Check if we can add more items\n const canAddMore = !maxItems || fields.length < maxItems;\n\n // Check if we can remove items\n const canRemove = fields.length > minItems;\n\n // TODO: For future enhancement, consider adding drag-and-drop reordering functionality for array items.\n // The GripVertical icon hints at this, but implementation would require additional libraries/logic.\n\n return (\n <Controller\n control={control || formContext?.control}\n name={name}\n rules={{\n // TODO: Consider if custom validation functions passed via `validation.validate` prop\n // should also be callable here, in addition to these built-in length checks.\n validate: (value) => {\n // Validate array constraints\n if (validation?.required && (!Array.isArray(value) || value.length === 0)) {\n return 'At least one item is required';\n }\n\n if (minItems && Array.isArray(value) && value.length < minItems) {\n return `Minimum ${minItems} item${minItems > 1 ? 's' : ''} required`;\n }\n\n if (maxItems && Array.isArray(value) && value.length > maxItems) {\n return `Maximum ${maxItems} item${maxItems > 1 ? 's' : ''} allowed`;\n }\n\n return true;\n },\n }}\n render={({ fieldState: { error } }) => {\n const hasError = !!error;\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n // TODO: Review aria-controls/aria-labelledby for the \"Add Item\" button and the list of items for improved accessibility.\n\n return (\n <div\n className={`flex flex-col gap-4 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n >\n {/* Label */}\n {label && (\n <div className=\"flex items-center justify-between\">\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n </div>\n )}\n\n {/* Array items */}\n <div className=\"space-y-3\">\n {fields.length === 0 ? (\n <div className=\"text-muted-foreground text-sm py-4 text-center border border-dashed rounded-md\">\n No items added yet. Click “Add Item” to begin.\n </div>\n ) : (\n fields.map((field, index) => {\n // Create field configuration for array element\n // Spread elementFieldConfig first to preserve all properties (including enumMetadata, components)\n const elementField: FormFieldType = {\n ...elementFieldConfig, // Include all props from config (enumMetadata, components, etc.)\n id: field.id, // Use RHF field.id for stable, unique keys per item\n name: `${name}.${index}`, // RHF name for the element\n label: elementFieldConfig?.label || '', // Label for the element's field (can be empty if not desired)\n type: elementFieldConfig?.type || elementType, // Prefer elementFieldConfig.type if available\n validation: elementFieldConfig?.validation || {},\n placeholder: elementFieldConfig?.placeholder,\n helperText: elementFieldConfig?.helperText,\n width: 'full', // Typically, elements take full width within their row\n readOnly: elementFieldConfig?.readOnly ?? readOnly, // Inherit readOnly from parent\n };\n\n return (\n <div key={field.id} className=\"flex gap-2 items-center\">\n <div className=\"flex items-center\">\n {/* TODO: The GripVertical icon is purely visual currently.\n If drag-and-drop is implemented, this would be the drag handle.\n Ensure it has appropriate ARIA attributes if it becomes interactive. */}\n <GripVertical className=\"size-4 text-muted-foreground\" />\n </div>\n <div className=\"flex-1\">\n {renderElement ? (\n renderElement(elementField, index)\n ) : (\n // This fallback is okay, but a more robust solution might attempt to\n // render a default UI field based on `elementType` if it's a known simple type.\n <div className=\"text-sm text-muted-foreground\">\n Field type “{elementType}” requires a render function\n </div>\n )}\n </div>\n {!readOnly && canRemove && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => handleRemoveItem(index)}\n className=\"size-8 p-0\"\n aria-label={`Remove item ${index + 1}`}\n >\n <X className=\"size-4\" />\n </Button>\n )}\n </div>\n );\n })\n )}\n </div>\n\n {/* Add Item button */}\n {!readOnly && canAddMore && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={handleAddItem}\n className=\"gap-1 w-full sm:w-auto\"\n // TODO: Add aria-live region or other announcement for screen readers when an item is added/removed.\n >\n <Plus className=\"size-3\" />\n Add Item\n </Button>\n )}\n\n {/* Helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Error message */}\n <ErrorMessage error={error} id={errorId} />\n </div>\n );\n }}\n />\n );\n}\n\n// Set display name for debugging\nArrayField.displayName = 'ArrayField';\n","import { ChevronDown, ChevronRight, GripVertical, Plus, X } from 'lucide-react';\nimport React from 'react';\nimport { Controller, FieldValues, useFieldArray, useFormContext, useWatch } from 'react-hook-form';\n\nimport type {\n ContractSchema,\n FormFieldType,\n FunctionParameter,\n TypeMappingCapability,\n} from '@openzeppelin/ui-types';\n\nimport { Button } from '../ui/button';\nimport { Card } from '../ui/card';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage, getAccessibilityProps } from './utils';\n\n/**\n * ArrayObjectField component properties\n */\nexport interface ArrayObjectFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * The components/properties of each object in the array.\n * Defines the schema for the nested fields within each object item.\n */\n components?: FunctionParameter[]; // TODO: As above, review type for `components`.\n\n /**\n * Minimum number of array elements\n */\n minItems?: number;\n\n /**\n * Maximum number of array elements\n */\n maxItems?: number;\n\n /**\n * Render function for object properties.\n * This function is responsible for rendering each individual property\n * of an object within an array item.\n */\n // TODO: Explore a fallback rendering mechanism if `renderProperty` is not provided,\n // for known simple property types.\n renderProperty?: (\n field: FormFieldType,\n itemIndex: number,\n propertyName: string\n ) => React.ReactNode;\n\n /**\n * Whether items should be collapsible.\n * Useful for managing UI complexity when objects have many properties.\n */\n collapsible?: boolean;\n\n /**\n * Whether items should start collapsed.\n */\n defaultCollapsed?: boolean;\n\n /**\n * The type-mapping capability for chain-specific field generation.\n * Essential for correctly determining field types for object properties.\n */\n typeMapping?: TypeMappingCapability;\n\n /**\n * Optional contract schema to enrich nested field generation.\n */\n contractSchema?: ContractSchema;\n}\n\n/**\n * Array of objects input field component specifically designed for React Hook Form integration.\n *\n * This component provides a dynamic interface for managing arrays of composite objects with:\n * - Add/remove functionality for array items\n * - Structured rendering of object properties within each array item\n * - Collapsible items for better UX with complex objects\n * - Validation for array constraints and object properties (though individual property validation is largely via rendered component)\n * - Full accessibility support\n *\n * The component combines the functionality of ArrayField and ObjectField to handle\n * complex nested data structures commonly found in blockchain contracts.\n */\nexport function ArrayObjectField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n components = [],\n minItems = 0,\n maxItems,\n renderProperty,\n collapsible = true,\n defaultCollapsed = false,\n readOnly,\n typeMapping,\n contractSchema,\n}: ArrayObjectFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Get form context for nested field registration\n const formContext = useFormContext();\n const effectiveControl = control || formContext.control;\n\n // Use useFieldArray for dynamic array management\n const { fields, append, remove } = useFieldArray({\n control: effectiveControl,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n name: name as any, // Type assertion needed due to generic constraints\n // TODO: Investigate if stricter typing for `name` can be achieved here.\n });\n\n // Track collapsed state for each item\n const [collapsedItems, setCollapsedItems] = React.useState<Record<string, boolean>>(() => {\n // TODO: Initialize collapsedItems based on `fields` from useFieldArray if `defaultCollapsed`\n // needs to apply to dynamically added items after initial render.\n // Current initialization only covers items present on first render.\n // This might require a useEffect hook that syncs with `fields`.\n const initial: Record<string, boolean> = {};\n fields.forEach((field) => {\n initial[field.id] = defaultCollapsed;\n });\n return initial;\n });\n\n // Handle adding new array item\n const handleAddItem = (): void => {\n // Create default object based on components\n const defaultObject: Record<string, unknown> = {};\n components.forEach((component) => {\n // TODO: This default value logic is extensive.\n // 1. Consider moving to a utility function `generateDefaultObject(components: FunctionParameter[]): Record<string, unknown>`.\n // 2. For nested 'tuple' (objects), recursively call this utility to generate deeply nested default structures.\n // Currently, `defaultObject[component.name] = {};` is a shallow empty object.\n // 3. Ensure consistency with any default value generation used elsewhere (e.g., in FormGenerator or core).\n if (component.type.includes('bool')) {\n defaultObject[component.name] = false;\n } else if (component.type.includes('int') || component.type.includes('uint')) {\n defaultObject[component.name] = 0; // Or perhaps '' to align with NumberField's initial controlled state?\n } else if (component.type.includes('[]')) {\n // Array types\n defaultObject[component.name] = [];\n } else if (component.type.startsWith('tuple')) {\n // Object/tuple types\n defaultObject[component.name] = {}; // TODO: Recursive default generation for nested tuples.\n } else {\n // Default for string and other types\n defaultObject[component.name] = '';\n }\n });\n\n // TODO: RHF's `append` type for nested field arrays is complex. `defaultObject` is Record<string, unknown>.\n // Casting to `any` here is a pragmatic approach if precisely matching RHF's expected generic type\n // (e.g., FieldArray<TFieldValues, TFieldName>[number]) proves too difficult for this dynamically built object.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n append(defaultObject as any);\n };\n\n // Toggle collapsed state for an item\n const toggleCollapsed = (fieldId: string): void => {\n setCollapsedItems((prev) => ({\n ...prev,\n [fieldId]: !prev[fieldId],\n }));\n };\n\n // Check if we can add more items\n const canAddMore = !maxItems || fields.length < maxItems;\n\n // Check if we can remove items\n const canRemove = fields.length > minItems;\n\n // TODO: For future enhancement, consider drag-and-drop reordering for array items.\n // TODO: Performance for very large arrays of complex objects. Virtualization might be needed.\n\n return (\n <Controller\n control={effectiveControl}\n name={name}\n rules={{\n // TODO: Similar to ArrayField, consider integration of custom validation functions.\n validate: (value) => {\n if (validation?.required && (!value || !Array.isArray(value) || value.length === 0)) {\n return 'At least one item is required';\n }\n if (minItems && Array.isArray(value) && value.length < minItems) {\n return `Minimum ${minItems} item${minItems > 1 ? 's' : ''} required`;\n }\n if (maxItems && Array.isArray(value) && value.length > maxItems) {\n return `Maximum ${maxItems} item${maxItems > 1 ? 's' : ''} allowed`;\n }\n return true;\n },\n }}\n render={({ fieldState: { error } }) => {\n const hasError = !!error;\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n // TODO: Review aria-controls/aria-labelledby for the \"Add Item\" button and the list of items.\n\n return (\n <div\n className={`flex flex-col gap-4 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n >\n {label && (\n <div className=\"flex items-center justify-between\">\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n </div>\n )}\n\n <div className=\"space-y-3\">\n {fields.length === 0 ? (\n <div className=\"text-muted-foreground text-sm py-4 text-center border border-dashed rounded-md\">\n No items added yet. Click “Add Item” to begin.\n </div>\n ) : (\n fields.map((field, index) => {\n const isCollapsed = collapsedItems[field.id] ?? defaultCollapsed;\n\n return (\n <Card key={field.id} className=\"p-4\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-center gap-2 flex-1\">\n {/* TODO: Aria attributes for GripVertical if it becomes interactive (drag handle). */}\n <GripVertical className=\"size-4 text-muted-foreground\" />\n {collapsible && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => toggleCollapsed(field.id)}\n className=\"p-0 h-auto\"\n aria-label={isCollapsed ? 'Expand item' : 'Collapse item'}\n // TODO: Add aria-expanded={!isCollapsed} and aria-controls={`item-content-${field.id}`}\n >\n {isCollapsed ? (\n <ChevronRight className=\"h-4 w-4\" />\n ) : (\n <ChevronDown className=\"h-4 w-4\" />\n )}\n </Button>\n )}\n {isCollapsed && (\n <div className=\"flex items-center gap-4 text-sm text-muted-foreground ml-2\">\n <CollapsedSummary\n name={name}\n index={index}\n components={components}\n control={effectiveControl}\n />\n </div>\n )}\n </div>\n {!readOnly && canRemove && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => remove(index)}\n aria-label={`Remove item ${index + 1}`}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n\n {!isCollapsed && (\n <div className=\"space-y-4 mt-4\">\n {((): React.ReactNode[] => {\n return components.map((component) => {\n // Generate field using the type-mapping capability to preserve nested metadata.\n if (!typeMapping) {\n throw new Error(\n `ArrayObjectField: No typeMapping capability provided for field generation. Cannot generate field for \"${component.name}\"`\n );\n }\n\n const generatedField = typeMapping.generateDefaultField(\n component,\n contractSchema\n );\n\n // Override with array object-specific configuration\n const propertyField: FormFieldType = {\n ...generatedField, // Include elementType and other capability-specific properties\n id: `${id}-${index}-${component.name}`,\n name: `${name}.${index}.${component.name}`,\n label: component.displayName || component.name,\n validation: {\n ...generatedField.validation, // Preserve validation from type mapping (includes min/max bounds)\n required: validation?.required, // Override required from parent\n },\n placeholder: `Enter ${component.displayName || component.name}`,\n helperText:\n component.description ||\n (generatedField.type === 'number' ? 'Numbers only' : undefined),\n width: 'full',\n readOnly,\n // Pass components for nested objects\n ...(component.components && {\n components: component.components,\n }),\n // TODO: Consider passing nested capability requirements down explicitly if needed.\n };\n\n return (\n <div key={component.name}>\n {renderProperty ? (\n renderProperty(propertyField, index, component.name)\n ) : (\n <div className=\"text-sm text-muted-foreground\">\n Property “{component.name}” requires a render\n function\n </div>\n )}\n </div>\n );\n });\n })()}\n </div>\n )}\n </Card>\n );\n })\n )}\n </div>\n\n {/* Add Item button */}\n {!readOnly && canAddMore && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={handleAddItem}\n className=\"gap-1 w-full sm:w-auto\"\n >\n {/* TODO: Add aria-live region or other announcement for item add/remove. */}\n <Plus className=\"h-3 w-3\" />\n Add Item\n </Button>\n )}\n\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n <ErrorMessage error={error} id={errorId} />\n </div>\n );\n }}\n />\n );\n}\n\n/**\n * Component to display collapsed item summary\n * TODO: This component is quite specific to ArrayObjectField.\n * If similar summaries are needed elsewhere, consider making it more generic\n * or moving it to a shared utils/components location.\n */\nfunction CollapsedSummary({\n name,\n index,\n components,\n control,\n}: {\n name: string;\n index: number;\n components: FunctionParameter[];\n control: FieldValues['control']; // TODO: useFormContext<TFieldValues>['control'] for better type safety if possible\n}): React.ReactElement {\n // Watch all values for this item\n // TODO: `useWatch` can be performance-intensive if the object is large and updates frequently.\n // If performance issues arise, consider optimizing what's watched or how often.\n const itemValues = useWatch({\n control,\n name: `${name}.${index}`, // Watch the entire object at this index\n });\n\n const summaryItems = components\n .slice(0, 3)\n .map((component) => {\n const fieldValue = itemValues?.[component.name];\n const displayValue =\n fieldValue !== undefined && fieldValue !== '' && fieldValue !== 0 && fieldValue !== false\n ? String(fieldValue).length > 20\n ? `${String(fieldValue).substring(0, 20)}...`\n : String(fieldValue)\n : null;\n\n return displayValue ? (\n <span key={component.name} className=\"flex items-center gap-1\">\n <span className=\"font-medium\">{component.displayName || component.name}:</span>\n <span className=\"text-foreground\">{displayValue}</span>\n </span>\n ) : null;\n })\n .filter(Boolean);\n\n const isEmpty =\n !itemValues ||\n Object.values(itemValues).every(\n (value) => value === undefined || value === '' || value === 0 || value === false\n );\n\n if (isEmpty && summaryItems.length === 0) {\n // Ensure we don't show \"Empty item\" if summaryItems has content\n return <span className=\"italic\">Empty item</span>;\n }\n\n return (\n <>\n {summaryItems.length > 0 ? (\n summaryItems\n ) : (\n <span className=\"italic\">Item has values (not shown in summary)</span>\n )}\n {/* TODO: The \"+ X more\" count should be accurate based on total properties vs. shown in summary.\n If summaryItems is empty but the item is not (due to values not fitting summary criteria),\n this count might be misleading.\n Consider `components.length - (actually displayed count in summaryItems)`\n */}\n {components.length > 3 &&\n summaryItems.length < components.length && ( // Only show \"more\" if not all are summarized or could be summarized\n <span className=\"text-xs\">+{components.length - summaryItems.length} more</span>\n )}\n </>\n );\n}\n\n// Set display name for debugging\nArrayObjectField.displayName = 'ArrayObjectField';\n","import { type ForwardedRef, type ReactElement, type ReactNode } from 'react';\nimport type { Control, FieldPath, FieldValues } from 'react-hook-form';\n\nimport { type FieldValidation } from '@openzeppelin/ui-types';\n\nimport { getWidthClasses } from './utils/layout';\n\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '../ui/form';\n\n/**\n * Base props shared by all field components\n *\n * @template TFieldValues The field values type from React Hook Form\n */\nexport interface BaseFieldProps<TFieldValues extends FieldValues = FieldValues> {\n /**\n * Unique identifier for the field\n */\n id: string;\n\n /**\n * Label text to display\n */\n label: string;\n\n /**\n * Placeholder text when empty\n */\n placeholder?: string;\n\n /**\n * Helper text to display below the field\n */\n helperText?: string;\n\n /**\n * Field width for layout\n */\n width?: 'full' | 'half' | 'third';\n\n /**\n * Validation rules for the field\n */\n validation?: FieldValidation;\n\n /**\n * Form control from React Hook Form\n */\n control: Control<TFieldValues>;\n\n /**\n * Field name in the form\n */\n name: FieldPath<TFieldValues>;\n\n /**\n * Whether the field should be displayed as read-only/disabled.\n * @default false\n */\n readOnly?: boolean;\n}\n\n/**\n * BaseField component to provide a consistent layout for form fields\n *\n * @important This component is the foundation of the app rendering architecture and should\n * ONLY be used by field-specific components within the system, not as a standalone component.\n *\n * Architecture role:\n * 1. Provides a consistent layout structure for all field types\n * 2. Handles integration with React Hook Form through the FormField component\n * 3. Manages common rendering aspects like labels, error messages, and help text\n * 4. Delegates actual input rendering to field-specific components via renderInput\n *\n * Field component hierarchy:\n * - TransactionForm (top-level renderer)\n * - DynamicFormField (field type selector)\n * - Specific field components (TextField, NumberField, etc.)\n * - BaseField (common field structure - this component)\n * - Actual input element rendered by renderInput\n *\n * This component should only be extended by field-specific components like\n * TextField, NumberField, and AddressField - it is not meant for direct use in forms.\n */\nexport function BaseField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n renderInput,\n}: BaseFieldProps<TFieldValues> & {\n renderInput: (\n field: Record<string, unknown>,\n props: { id: string; ref?: ForwardedRef<HTMLElement> }\n ) => ReactNode;\n ref?: ForwardedRef<HTMLElement>;\n}): ReactElement {\n return (\n <FormField\n control={control}\n name={name}\n render={({ field }) => (\n <FormItem className={getWidthClasses(width)}>\n <FormLabel htmlFor={id}>{label}</FormLabel>\n <FormControl>{renderInput(field, { id })}</FormControl>\n {helperText && <FormDescription id={`${id}-description`}>{helperText}</FormDescription>}\n <FormMessage id={`${id}-error`} />\n </FormItem>\n )}\n />\n );\n}\n\n// Set displayName properly\nBaseField.displayName = 'BaseField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n INTEGER_HTML_PATTERN,\n INTEGER_INPUT_PATTERN,\n INTEGER_PATTERN,\n validateField,\n} from './utils';\n\n/**\n * BigIntField component properties\n */\nexport interface BigIntFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Custom validation function for big integer string values\n */\n validateBigInt?: (value: string) => boolean | string;\n}\n\n/**\n * Big integer input field component for large numbers beyond JavaScript's Number precision.\n *\n * This component is designed for blockchain integer types like uint128, uint256, int128, int256\n * that can hold values larger than JavaScript's Number.MAX_SAFE_INTEGER (2^53 - 1).\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects BigIntField for large integer types\n * 4. This component handles string-based integer input with validation\n * 5. Adapters convert the string to BigInt when submitting transactions\n *\n * The component includes:\n * - Integer-only validation (no decimals allowed)\n * - String-based storage to avoid JavaScript Number precision issues\n * - Integration with React Hook Form\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation\n */\nexport function BigIntField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n validateBigInt,\n readOnly,\n}: BigIntFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Ensure validation includes integer-only pattern\n // This will be handled by validateField utility, avoiding duplication\n const enhancedValidation = {\n ...validation,\n pattern: validation?.pattern || INTEGER_PATTERN,\n };\n\n // Validation function for big integer strings\n const validateBigIntValue = (value: string): string | true => {\n // Run standard validation with integer pattern (includes pattern validation)\n const standardValidation = validateField(value, enhancedValidation);\n if (standardValidation !== true) return standardValidation as string;\n\n // Run custom validator if provided\n if (validateBigInt) {\n const customValidation = validateBigInt(value);\n if (customValidation !== true && typeof customValidation === 'string') {\n return customValidation;\n }\n }\n\n return true;\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Skip validation if empty and check required separately\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Handle incomplete inputs\n if (value === '-') {\n return 'Please enter a complete number';\n }\n\n // For string values, validate as big integer\n if (typeof value === 'string') {\n return validateBigIntValue(value);\n }\n\n // Convert numbers to strings (in case value is accidentally a number)\n if (typeof value === 'number') {\n return validateBigIntValue(value.toString());\n }\n\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Handle input change\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const rawValue = e.target.value;\n\n // Allow empty string\n if (rawValue === '') {\n field.onChange('');\n return;\n }\n\n // Allow standalone minus sign for negative numbers\n if (rawValue === '-') {\n field.onChange(rawValue);\n return;\n }\n\n // Check if the input is a valid integer format\n // Allow only digits and optional leading minus sign (using input pattern)\n if (INTEGER_INPUT_PATTERN.test(rawValue)) {\n field.onChange(rawValue);\n }\n // If invalid format, don't update (prevents non-numeric input)\n };\n\n // Handle keyboard events\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n // Allow only numeric characters, backspace, delete, tab, escape, enter, arrows, hyphen\n const allowedKeys = [\n '0',\n '1',\n '2',\n '3',\n '4',\n '5',\n '6',\n '7',\n '8',\n '9',\n 'Backspace',\n 'Delete',\n 'Tab',\n 'Escape',\n 'Enter',\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n '-',\n ];\n\n // Allow Ctrl/Cmd+A, C, V, X, Z for common editing operations\n if (\n (e.ctrlKey || e.metaKey) &&\n ['a', 'c', 'v', 'x', 'z'].includes(e.key.toLowerCase())\n ) {\n return;\n }\n\n if (!allowedKeys.includes(e.key) && !e.ctrlKey && !e.metaKey) {\n e.preventDefault();\n }\n\n // Handle escape key to clear input\n if (e.key === 'Escape') {\n handleEscapeKey(field.onChange, field.value)(e);\n return;\n }\n };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <Input\n {...field}\n value={field.value ?? ''}\n id={id}\n placeholder={placeholder || 'Enter integer value'}\n type=\"text\"\n className={validationClasses}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n onChange={handleInputChange}\n inputMode=\"numeric\"\n pattern={INTEGER_HTML_PATTERN}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n disabled={readOnly}\n />\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nBigIntField.displayName = 'BigIntField';\n","import React from 'react';\nimport { Controller, FieldPath, FieldValues, PathValue } from 'react-hook-form';\n\nimport { Checkbox } from '../ui/checkbox';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleToggleKeys,\n validateField,\n} from './utils';\n\n/**\n * BooleanField component properties\n */\nexport interface BooleanFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Custom validation function for boolean values\n */\n validateBoolean?: (value: boolean) => boolean | string;\n}\n\n/**\n * Boolean input field component (checkbox) specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like BooleanField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles boolean-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Checkbox-specific behavior\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation with Space/Enter for toggling\n */\nexport function BooleanField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n validateBoolean,\n readOnly,\n}: BooleanFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Function to validate boolean values\n const validateBooleanValue = (value: boolean): string | true => {\n // Run standard validation first\n const standardValidation = validateField(value, validation);\n if (standardValidation !== true) return standardValidation as string;\n\n // Then run custom validator if provided\n if (validateBoolean) {\n const customValidation = validateBoolean(value);\n if (customValidation !== true && typeof customValidation === 'string') {\n return customValidation;\n }\n }\n\n return true;\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n <Controller\n control={control}\n name={name}\n defaultValue={false as PathValue<TFieldValues, FieldPath<TFieldValues>>}\n rules={{\n validate: (value) => {\n // Handle required validation specifically\n if (value === undefined || value === null) {\n return validation?.required ? 'This field is required' : true;\n }\n\n // For boolean values\n if (typeof value === 'boolean') {\n // If required, it means a boolean value (true or false) must be present.\n // The check for undefined/null above handles the case where it's not set.\n // So, if it's a boolean (true or false), it passes the required check here.\n return validateBooleanValue(value);\n }\n\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Handle checkbox change with validation\n const handleCheckedChange = (checked: boolean | 'indeterminate'): void => {\n const value = checked === true;\n field.onChange(value);\n\n // Trigger validation if required and unchecked\n if (isRequired && !value) {\n setTimeout(() => field.onBlur(), 0);\n }\n };\n\n // Add keyboard accessibility for toggle\n const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>): void => {\n handleToggleKeys(field.onChange, !!field.value)(e);\n\n // Trigger validation for required fields\n if (e.key === ' ' || e.key === 'Enter') {\n if (isRequired) {\n setTimeout(() => field.onBlur(), 0);\n }\n }\n };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n isDisabled: readOnly,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <div className=\"flex items-center space-x-2\">\n <Checkbox\n {...field}\n id={id}\n checked={!!field.value}\n onCheckedChange={handleCheckedChange}\n className={validationClasses}\n onKeyDown={handleKeyDown}\n disabled={readOnly}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n />\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n </div>\n\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground pl-6 text-sm\">\n {helperText}\n </div>\n )}\n\n <ErrorMessage error={error} id={errorId} className=\"pl-6\" />\n </>\n );\n }}\n />\n </div>\n );\n}\n\nBooleanField.displayName = 'BooleanField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { validateBytesSimple } from '@openzeppelin/ui-utils';\n\nimport { Label } from '../ui/label';\nimport { Textarea } from '../ui/textarea';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n} from './utils';\n\n/**\n * BytesField component properties\n */\nexport interface BytesFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Number of rows for the textarea\n */\n rows?: number;\n\n /**\n * Maximum length in bytes (not characters)\n */\n maxBytes?: number;\n\n /**\n * Exact length in bytes required (for fixed-size types like bytes32)\n * When set, the value must be exactly this many bytes.\n * Takes precedence over maxBytes.\n */\n exactBytes?: number;\n\n /**\n * Whether to accept hex, base64, or both formats\n */\n acceptedFormats?: 'hex' | 'base64' | 'both';\n\n /**\n * Whether to automatically add/remove 0x prefix for hex values\n */\n autoPrefix?: boolean;\n\n /**\n * Whether to allow 0x prefix in hex input (defaults to true)\n */\n allowHexPrefix?: boolean;\n}\n\n/**\n * Specialized input field for bytes data with built-in hex/base64 validation.\n *\n * This component provides proper validation for blockchain bytes data including:\n * - Hex encoding validation (with optional 0x prefix support)\n * - Base64 encoding validation\n * - Byte length validation\n * - Format detection and conversion\n *\n * Key props for EVM compatibility:\n * - `allowHexPrefix`: Whether to accept 0x prefixed input (defaults to true)\n * - `autoPrefix`: Whether to automatically add 0x prefixes (defaults to false)\n *\n * These are separate concerns - you can accept 0x input without auto-adding prefixes.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects BytesField for 'bytes' field types\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles bytes-specific validation and formatting\n */\nexport function BytesField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n placeholder = 'Enter hex or base64 encoded bytes',\n rows = 3,\n maxBytes,\n exactBytes,\n acceptedFormats = 'both',\n autoPrefix = false,\n allowHexPrefix = true,\n readOnly,\n}: BytesFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n /**\n * Validates bytes input format and encoding using validator.js\n */\n const validateBytesField = (value: string): boolean | string => {\n return validateBytesSimple(value, {\n acceptedFormats,\n maxBytes,\n exactBytes,\n allowHexPrefix, // Allow prefix based on explicit prop (defaults to true)\n });\n };\n\n /**\n * Formats the input value (adds 0x prefix if needed)\n */\n const formatValue = (value: string): string => {\n if (!value || !autoPrefix) return value;\n\n const cleanValue = value.trim().replace(/\\s+/g, '');\n const withoutPrefix = cleanValue.startsWith('0x') ? cleanValue.slice(2) : cleanValue;\n\n // Only add prefix for valid hex that doesn't already have it\n if (withoutPrefix && /^[0-9a-fA-F]*$/.test(withoutPrefix) && withoutPrefix.length % 2 === 0) {\n return cleanValue.startsWith('0x') ? cleanValue : `0x${cleanValue}`;\n }\n\n return cleanValue;\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n disabled={readOnly}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Run bytes-specific validation using validator.js\n return validateBytesField(value);\n },\n }}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && (isTouched || validation?.required);\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n isDisabled: readOnly,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <Textarea\n id={id}\n name={field.name}\n ref={field.ref}\n placeholder={placeholder}\n rows={rows}\n className={validationClasses}\n disabled={readOnly}\n value={field.value ?? ''}\n onChange={(e) => {\n // Only update value without formatting for better performance\n field.onChange(e.target.value);\n }}\n onBlur={(e) => {\n // Apply formatting on blur when user finishes typing\n const formatted = formatValue(e.target.value);\n field.onChange(formatted);\n // Register field as touched with React Hook Form\n field.onBlur();\n }}\n onKeyDown={handleEscapeKey(field.onChange, field.value)}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`.trim()}\n />\n\n {/* Display helper text with format hint */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n <div className=\"text-xs text-muted-foreground mt-1\">\n {acceptedFormats === 'hex' && 'Hex format (e.g., 48656c6c6f or 0x48656c6c6f)'}\n {acceptedFormats === 'base64' && 'Base64 format (e.g., SGVsbG8=)'}\n {acceptedFormats === 'both' &&\n 'Hex (e.g., 48656c6c6f) or Base64 (e.g., SGVsbG8=) format'}\n {exactBytes && ` • Exactly ${exactBytes} bytes (${exactBytes * 2} hex chars)`}\n {!exactBytes && maxBytes && ` • Max ${maxBytes} bytes`}\n </div>\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nBytesField.displayName = 'BytesField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n validateField,\n} from './utils';\n\n/**\n * DateTimeField component properties\n */\nexport interface DateTimeFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Placeholder text displayed when the field is empty\n */\n placeholder?: string;\n\n /**\n * If true, clears the field when user clicks Escape; otherwise just blurs\n */\n clearOnEscape?: boolean;\n}\n\n/**\n * Datetime-local input field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like DateTimeField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles date-time specific rendering, conversion, and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Conversion between input value (YYYY-MM-DDTHH:mm) and ISO 8601 strings (toISOString)\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation with Escape-to-clear behavior\n */\nexport function DateTimeField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n readOnly,\n clearOnEscape = true,\n}: DateTimeFieldProps<TFieldValues>): React.ReactElement {\n /**\n * TODO: Replace native datetime-local input with a styled popover-based\n * calendar/time picker (Radix Popover + Select) to match the design system.\n * Maintain ISO 8601 value semantics and provide a mobile fallback to native input.\n */\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Validate ISO 8601 string or empty according to validation rules\n const validateDateValue = (value: string): string | true => {\n const validationResult = validateField(value, validation);\n return validationResult === true ? true : (validationResult as string);\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n if (typeof value === 'string') {\n return validateDateValue(value);\n }\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const raw = e.target.value; // YYYY-MM-DDTHH:mm or ''\n if (!raw) {\n field.onChange('');\n return;\n }\n // Preserve the exact local selection instead of converting to UTC.\n // Store as ISO-like local string with timezone offset maintained by parsing components.\n const [datePart, timePart] = raw.split('T');\n const [year, month, day] = datePart.split('-').map((s) => Number(s));\n const [hours, minutes] = timePart.split(':').map((s) => Number(s));\n const localDate = new Date(year, month - 1, day, hours, minutes, 0, 0);\n // Serialize back to local YYYY-MM-DDTHH:mm string so the value remains what the user picked\n const pad = (n: number): string => String(n).padStart(2, '0');\n const serialized = `${localDate.getFullYear()}-${pad(localDate.getMonth() + 1)}-${pad(localDate.getDate())}T${pad(localDate.getHours())}:${pad(localDate.getMinutes())}`;\n field.onChange(serialized);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n if (e.key === 'Escape') {\n if (clearOnEscape) {\n handleEscapeKey(field.onChange as (v: string) => void, field.value)(e);\n } else {\n (e.target as HTMLElement).blur();\n }\n }\n };\n\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n isDisabled: !!readOnly,\n });\n\n const formatDateTimeLocal = (val: unknown): string => {\n if (!val) return '';\n try {\n const d = new Date(val as string);\n if (isNaN(d.getTime())) return '';\n const pad = (n: number): string => String(n).padStart(2, '0');\n const year = d.getFullYear();\n const month = pad(d.getMonth() + 1);\n const day = pad(d.getDate());\n const hours = pad(d.getHours());\n const minutes = pad(d.getMinutes());\n // Return a local datetime string for the input value to avoid timezone shifts\n return `${year}-${month}-${day}T${hours}:${minutes}`;\n } catch {\n return '';\n }\n };\n\n const inputValue: string = formatDateTimeLocal(field.value);\n\n return (\n <>\n <Input\n {...field}\n id={id}\n placeholder={placeholder}\n className={validationClasses}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n value={inputValue}\n type=\"datetime-local\"\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n disabled={readOnly}\n />\n\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\nDateTimeField.displayName = 'DateTimeField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport type { EnumValue, FormFieldType, FunctionParameter } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select';\nimport { Textarea } from '../ui/textarea';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n validateField,\n} from './utils';\n\n/**\n * Enum variant definition\n */\nexport interface EnumVariant {\n /** Name of the variant (e.g., 'One', 'Two', 'Three') */\n name: string;\n /** Type of variant: 'void' for unit variants, 'tuple' for variants with payload, 'integer' for numeric enums */\n type: 'void' | 'tuple' | 'integer';\n /** For tuple variants: array of payload type names (e.g., ['U32', 'ScString']) */\n payloadTypes?: string[];\n /** Optional nested component definitions for tuple payload entries */\n payloadComponents?: (FunctionParameter[] | undefined)[];\n /** For integer variants: the numeric value */\n value?: number;\n /** Flag indicating if this variant has a single Tuple payload (for serialization) */\n isSingleTuplePayload?: boolean;\n}\n\n/**\n * Enum metadata extracted from contract spec\n */\nexport interface EnumMetadata {\n /** Name of the enum type */\n name: string;\n /** Array of variants in the enum */\n variants: EnumVariant[];\n /** True if all variants are unit variants (no payloads), suitable for simple select/radio */\n isUnitOnly: boolean;\n}\n\n/**\n * Enum field value structure for blockchain enum types\n */\nexport type EnumFieldValue = EnumValue;\n\n/**\n * EnumField component properties\n */\nexport interface EnumFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Enum metadata containing variant information\n */\n enumMetadata?: EnumMetadata;\n\n /**\n * Custom validation function for enum values\n */\n validateEnum?: (value: EnumFieldValue) => boolean | string;\n\n /**\n * Render function for payload input fields.\n * This allows the parent component to provide appropriate field components\n * based on the payload type, maintaining separation of concerns.\n */\n renderPayloadField?: (field: FormFieldType, payloadIndex: number) => React.ReactNode;\n}\n\n/**\n * Composite enum field component for blockchain enum types.\n *\n * This component handles both unit enums (simple variants) and tagged enums (variants with payloads).\n * For unit enums, it renders as a simple select dropdown.\n * For tagged enums, it renders a variant picker plus conditional input fields for payload data.\n *\n * The value format is designed to be chain-agnostic:\n * - Unit variants: { tag: \"VariantName\" }\n * - Tuple variants: { tag: \"VariantName\", values: [...] }\n */\nexport function EnumField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder = 'Select variant',\n helperText,\n control,\n name,\n width = 'full',\n validation,\n enumMetadata,\n validateEnum,\n renderPayloadField,\n readOnly,\n}: EnumFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Use consistent width classes\n const widthClass = width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3';\n\n // If no enum metadata or empty variants, fallback to a simple text input with helper text\n if (!enumMetadata || enumMetadata.variants.length === 0) {\n return (\n <div className={cn('flex flex-col gap-2', widthClass)}>\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n disabled={readOnly}\n rules={{\n validate: (value) => {\n // Use standard validation first\n const standardValidation = validateField(value, validation);\n if (standardValidation !== true) {\n return standardValidation;\n }\n\n // If it's a string, try to validate it as JSON\n if (typeof value === 'string') {\n try {\n const parsed = JSON.parse(value);\n // Check if it has the required 'tag' property\n if (!parsed.tag) {\n return 'JSON must have a \"tag\" property specifying the enum variant';\n }\n } catch {\n return 'Invalid JSON format. Please enter valid JSON like {\"tag\":\"VariantName\"}';\n }\n }\n\n // If it's an object, check if it has the required 'tag' property\n if (typeof value === 'object' && value !== null) {\n if (!('tag' in value)) {\n return 'Enum value must have a \"tag\" property specifying the variant';\n }\n }\n\n return true;\n },\n }}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <div className=\"space-y-2\">\n <div className=\"p-3 border border-border rounded-md bg-muted\">\n <p className=\"text-sm text-muted-foreground\">\n Enum metadata not available. Please enter the value in JSON format.\n </p>\n <p className=\"text-xs text-muted-foreground mt-1\">\n Example: {`{\"tag\":\"One\"}`} or {`{\"tag\":\"Two\",\"values\":[42]}`}\n </p>\n </div>\n\n <Textarea\n id={id}\n {...accessibilityProps}\n className={cn('min-h-[80px]', validationClasses)}\n placeholder={`{\"tag\":\"One\"} or {\"tag\":\"Two\",\"values\":[42]}`}\n value={\n typeof field.value === 'string'\n ? field.value\n : JSON.stringify(field.value || {})\n }\n onChange={(e) => {\n try {\n // Try to parse as JSON, if successful store as object\n const parsed = JSON.parse(e.target.value);\n field.onChange(parsed);\n } catch {\n // If parsing fails, store as string (user is still typing)\n field.onChange(e.target.value);\n }\n }}\n onBlur={field.onBlur}\n name={field.name}\n disabled={readOnly}\n />\n </div>\n\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n <ErrorMessage error={error} id={errorId} />\n </>\n );\n }}\n />\n </div>\n );\n }\n\n return (\n <div className={cn('flex flex-col gap-2', widthClass)}>\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n disabled={readOnly}\n rules={{\n validate: (value) => {\n // Use standard validation first\n const standardValidation = validateField(value, validation);\n if (standardValidation !== true) {\n return standardValidation;\n }\n\n // Handle enum-specific validation\n if (!value || !value.tag) {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Run custom validation if provided\n if (validateEnum && value) {\n const customValidation = validateEnum(value);\n if (customValidation !== true && typeof customValidation === 'string') {\n return customValidation;\n }\n }\n\n return true;\n },\n }}\n render={({ field, fieldState: { error } }) => {\n const hasError = !!error;\n const currentValue: EnumFieldValue = field.value || { tag: '' };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n // Handle variant selection\n const handleVariantChange = (selectedTag: string): void => {\n const selectedVariant = enumMetadata.variants.find((v) => v.name === selectedTag);\n if (!selectedVariant) return;\n\n if (selectedVariant.type === 'void' || selectedVariant.type === 'integer') {\n // Unit variant - just set the tag\n field.onChange({ tag: selectedTag });\n } else {\n // Tuple variant - initialize with empty values (chain-agnostic)\n const initialValues = new Array(selectedVariant.payloadTypes?.length || 0).fill('');\n\n field.onChange({\n tag: selectedTag,\n values: initialValues,\n });\n }\n };\n\n // Handle payload value changes for tuple variants (chain-agnostic)\n const handlePayloadChange = (index: number, value: string): void => {\n const newValues = [...(currentValue.values || [])];\n // Simple chain-agnostic structure - just store the raw values\n newValues[index] = value;\n const newEnumValue = { ...currentValue, values: newValues };\n field.onChange(newEnumValue);\n };\n\n const selectedVariant = enumMetadata.variants.find((v) => v.name === currentValue.tag);\n\n return (\n <>\n {/* Variant Picker */}\n <Select\n value={currentValue.tag}\n onValueChange={handleVariantChange}\n disabled={readOnly}\n >\n <SelectTrigger id={id} {...accessibilityProps}>\n <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n <SelectContent>\n {enumMetadata.variants.map((variant) => (\n <SelectItem key={variant.name} value={variant.name}>\n {variant.name}\n {variant.type === 'integer' && variant.value !== undefined && (\n <span className=\"text-muted-foreground ml-2\">({variant.value})</span>\n )}\n {variant.type === 'tuple' && variant.payloadTypes && (\n <span className=\"text-muted-foreground ml-2\">\n ({variant.payloadTypes.join(', ')})\n </span>\n )}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n {/* Conditional Payload Inputs for Tuple Variants */}\n {selectedVariant &&\n selectedVariant.type === 'tuple' &&\n selectedVariant.payloadTypes && (\n <div className=\"ml-4 space-y-2 border-l-2 border-border pl-4\">\n <p className=\"text-sm text-muted-foreground\">\n Enter values for {selectedVariant.name}:\n </p>\n {selectedVariant.payloadTypes.map((payloadType, index) => {\n // Create field configuration for payload input\n const payloadField: FormFieldType = {\n id: `${id}-payload-${index}`,\n name: `${name}.values.${index}`,\n label: payloadType,\n type: 'text' as FormFieldType['type'],\n validation: {},\n placeholder: `Enter ${payloadType} value`,\n helperText: undefined,\n width: 'full',\n originalParameterType: payloadType,\n readOnly: readOnly, // Inherit readOnly state from parent\n ...(selectedVariant.payloadComponents?.[index] && {\n components: selectedVariant.payloadComponents[index],\n }),\n };\n\n return (\n <div key={index} className=\"flex flex-col gap-1\">\n {renderPayloadField ? (\n renderPayloadField(payloadField, index)\n ) : (\n // Fallback to basic input if no render function provided\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor={`${id}-payload-${index}`} className=\"text-sm\">\n {payloadType}\n </Label>\n <Input\n id={`${id}-payload-${index}`}\n type=\"text\"\n placeholder={`Enter ${payloadType} value`}\n value={(currentValue.values?.[index] as string) || ''}\n onChange={(e) => handlePayloadChange(index, e.target.value)}\n disabled={readOnly}\n />\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage error={error} id={errorId} />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nEnumField.displayName = 'EnumField';\n","import { AlertCircle, CheckCircle2, File as FileIcon, Upload, X } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Button } from '../ui/button';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage, getAccessibilityProps, validateField } from './utils';\n\n/**\n * FileUploadField component properties\n */\nexport interface FileUploadFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Accepted file types (e.g., \".zip,.tar.gz\")\n */\n accept?: string;\n /**\n * Maximum file size in bytes\n */\n maxSize?: number;\n /**\n * Whether to convert the file to base64 string\n */\n convertToBase64?: boolean;\n}\n\n/**\n * File upload field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like FileUploadField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles file upload-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - File type and size validation\n * - Optional conversion to base64 for storage\n * - Visual feedback for selected files\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation\n */\n/**\n * Format bytes to human-readable size\n */\nfunction formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;\n}\n\n/** File upload field component with drag-and-drop support. */\nexport function FileUploadField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder = 'Drop your file here or click to browse',\n helperText,\n control,\n name,\n width = 'full',\n validation,\n readOnly,\n accept,\n maxSize,\n convertToBase64 = false,\n}: FileUploadFieldProps<TFieldValues>): React.ReactElement {\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [fileName, setFileName] = useState<string>('');\n const [fileSize, setFileSize] = useState<number>(0);\n const [isProcessing, setIsProcessing] = useState(false);\n const [isDragOver, setIsDragOver] = useState(false);\n const [uploadStatus, setUploadStatus] = useState<'idle' | 'success' | 'error'>('idle');\n\n const handleFileToBase64 = (file: File): Promise<string> => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (): void => {\n if (typeof reader.result === 'string') {\n // Remove data URL prefix to get just base64\n const parts = reader.result.split(',');\n if (parts.length !== 2) {\n reject(new Error('Invalid data URL format'));\n return;\n }\n const base64 = parts[1];\n resolve(base64);\n } else {\n reject(new Error('Failed to convert file to base64'));\n }\n };\n reader.onerror = (): void => {\n reject(reader.error);\n };\n reader.readAsDataURL(file);\n });\n };\n\n const handleFileChange = async (\n file: File | null,\n onChange: (value: string | File) => void\n ): Promise<void> => {\n if (!file) {\n setFileName('');\n setFileSize(0);\n setUploadStatus('idle');\n onChange('');\n return;\n }\n\n // Validate file size\n if (maxSize && file.size > maxSize) {\n const maxSizeMB = (maxSize / (1024 * 1024)).toFixed(2);\n onChange('');\n setFileName('');\n setFileSize(0);\n setUploadStatus('error');\n // This will trigger validation error through React Hook Form\n throw new Error(`File size exceeds ${maxSizeMB} MB limit`);\n }\n\n setFileName(file.name);\n setFileSize(file.size);\n setUploadStatus('idle');\n\n // Immediately set the File object so required-field checks pass\n // and upstream loaders can proceed without waiting for conversion.\n onChange(file);\n\n // If base64 conversion is requested, convert in background and\n // replace the value once ready (keeps UI responsive and avoids\n // triggering preflight missing-field errors).\n if (!convertToBase64) {\n setUploadStatus('success');\n return;\n }\n\n setIsProcessing(true);\n\n try {\n const base64 = await handleFileToBase64(file);\n onChange(base64);\n setUploadStatus('success');\n } catch {\n onChange('');\n setFileName('');\n setFileSize(0);\n setUploadStatus('error');\n } finally {\n setIsProcessing(false);\n }\n };\n\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>): void => {\n e.preventDefault();\n e.stopPropagation();\n if (!readOnly && !isProcessing) {\n setIsDragOver(true);\n }\n };\n\n const handleDragLeave = (e: React.DragEvent<HTMLDivElement>): void => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n };\n\n const handleDrop = (\n e: React.DragEvent<HTMLDivElement>,\n onChange: (value: string | File) => void\n ): void => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n\n if (readOnly || isProcessing) return;\n\n const file = e.dataTransfer.files?.[0] || null;\n if (file) {\n handleFileChange(file, onChange);\n }\n };\n\n const clearFile = (onChange: (value: string | File) => void): void => {\n if (fileInputRef.current) {\n fileInputRef.current.value = '';\n }\n setFileName('');\n setFileSize(0);\n setUploadStatus('idle');\n onChange('');\n };\n\n return (\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n if (!value) return validateField(value, validation);\n\n // Additional file-specific validations\n if (\n maxSize &&\n value &&\n typeof value === 'object' &&\n 'size' in value &&\n value.size > maxSize\n ) {\n const maxSizeMB = (maxSize / (1024 * 1024)).toFixed(2);\n return `File size must be less than ${maxSizeMB} MB`;\n }\n\n return validateField(value, validation);\n },\n }}\n disabled={readOnly}\n render={({ field: { onChange, onBlur }, fieldState: { error } }) => {\n const fieldId = `${id}-field`;\n const errorId = `${fieldId}-error`;\n const hasError = !!error;\n const widthClass = width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3';\n\n // Build helper text with file requirements\n const requirementsText = [];\n if (accept) {\n const types = accept\n .split(',')\n .map((t) => t.trim())\n .join(', ');\n requirementsText.push(`Accepted types: ${types}`);\n }\n if (maxSize) {\n requirementsText.push(`Max size: ${formatFileSize(maxSize)}`);\n }\n const fullHelperText = helperText || requirementsText.join(' • ');\n\n return (\n <div className={`flex flex-col gap-2 ${widthClass}`}>\n <Label htmlFor={fieldId}>\n {label}\n {validation?.required && <span className=\"text-red-500 ml-1\">*</span>}\n </Label>\n\n {/* Hidden file input */}\n <input\n ref={fileInputRef}\n id={fieldId}\n type=\"file\"\n accept={accept}\n disabled={readOnly || isProcessing}\n onBlur={onBlur}\n onChange={(e) => {\n const file = e.target.files?.[0] || null;\n handleFileChange(file, onChange);\n }}\n className=\"hidden\"\n {...getAccessibilityProps({\n id: fieldId,\n hasError,\n isRequired: validation?.required,\n isDisabled: readOnly || isProcessing,\n })}\n />\n\n {/* Drop zone / Upload area */}\n <div\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={(e) => handleDrop(e, onChange)}\n onClick={() => {\n if (!readOnly && !isProcessing && !fileName) {\n fileInputRef.current?.click();\n }\n }}\n className={`\n relative rounded-lg border-2 border-dashed transition-all duration-200\n ${\n isDragOver\n ? 'border-selected bg-selected/5'\n : hasError\n ? 'border-destructive bg-destructive/5'\n : fileName\n ? 'border-border bg-muted/30'\n : 'border-border bg-background hover:border-selected/50 hover:bg-muted/50'\n }\n ${readOnly || isProcessing ? 'cursor-not-allowed opacity-60' : fileName ? 'cursor-default' : 'cursor-pointer'}\n p-6\n `}\n >\n {!fileName ? (\n // Empty state - show upload prompt\n <div className=\"flex flex-col items-center justify-center gap-3 text-center\">\n <div\n className={`rounded-full p-3 transition-colors ${\n isDragOver ? 'bg-selected/10' : 'bg-muted'\n }`}\n >\n <Upload\n className={`h-8 w-8 transition-colors ${\n isDragOver ? 'text-selected' : 'text-muted-foreground'\n }`}\n />\n </div>\n <div className=\"space-y-1\">\n <p className=\"text-sm font-medium\">\n {isDragOver ? 'Drop file here' : placeholder}\n </p>\n {fullHelperText && !isDragOver && (\n <p className=\"text-xs text-muted-foreground\">{fullHelperText}</p>\n )}\n </div>\n </div>\n ) : (\n // File selected state\n <div className=\"flex items-start gap-4\">\n <div\n className={`rounded-lg p-2 ${\n uploadStatus === 'success'\n ? 'bg-success/10'\n : uploadStatus === 'error'\n ? 'bg-destructive/10'\n : 'bg-muted'\n }`}\n >\n <FileIcon\n className={`h-8 w-8 ${\n uploadStatus === 'success'\n ? 'text-success'\n : uploadStatus === 'error'\n ? 'text-destructive'\n : 'text-muted-foreground'\n }`}\n />\n </div>\n <div className=\"flex-1 min-w-0 space-y-1\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium truncate\">{fileName}</p>\n <p className=\"text-xs text-muted-foreground\">\n {formatFileSize(fileSize)}\n {isProcessing && ' • Processing...'}\n </p>\n </div>\n <div className=\"flex items-center gap-2 shrink-0\">\n {uploadStatus === 'success' && !isProcessing && (\n <CheckCircle2 className=\"h-5 w-5 text-success\" />\n )}\n {uploadStatus === 'error' && (\n <AlertCircle className=\"h-5 w-5 text-destructive\" />\n )}\n {!readOnly && !isProcessing && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation();\n clearFile(onChange);\n }}\n className=\"h-8 w-8 p-0\"\n >\n <X className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n </div>\n {!isProcessing && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={readOnly}\n onClick={(e) => {\n e.stopPropagation();\n fileInputRef.current?.click();\n }}\n className=\"mt-2\"\n >\n Change file\n </Button>\n )}\n </div>\n </div>\n )}\n </div>\n\n <ErrorMessage error={error} id={errorId} />\n </div>\n );\n }}\n />\n );\n}\n","import { Plus, X } from 'lucide-react';\nimport React from 'react';\nimport { Controller, FieldValues, useFieldArray, useFormContext, useWatch } from 'react-hook-form';\n\nimport type { FormFieldType } from '@openzeppelin/ui-types';\nimport { getDefaultValueForType } from '@openzeppelin/ui-utils';\n\nimport { Button } from '../../ui/button';\nimport { Label } from '../../ui/label';\nimport { BaseFieldProps } from '../BaseField';\nimport { ErrorMessage, getAccessibilityProps } from '../utils';\nimport {\n computeChildTouched,\n MapEntryRow,\n useDuplicateKeyIndexes,\n useMapFieldSync,\n validateMapStructure,\n} from './index';\n\n/**\n * Helper function to format a label with an optional type hint\n */\nfunction formatLabeledType(baseLabel: string, typeHint?: string): string {\n if (!typeHint) {\n return baseLabel;\n }\n return `${baseLabel} (${typeHint})`;\n}\n\n/**\n * Helper function to create a default map entry with appropriate default values for key and value types\n */\nfunction createDefaultEntry(mapMetadata?: MapFieldProps['mapMetadata']): {\n key: unknown;\n value: unknown;\n} {\n return {\n key: mapMetadata?.keyFieldConfig?.type\n ? getDefaultValueForType(mapMetadata.keyFieldConfig.type)\n : '',\n value: mapMetadata?.valueFieldConfig?.type\n ? getDefaultValueForType(mapMetadata.valueFieldConfig.type)\n : '',\n };\n}\n\n/**\n * MapField component properties\n */\nexport interface MapFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Map metadata containing key and value type information\n */\n mapMetadata?: {\n keyType?: string;\n valueType?: string;\n keyFieldConfig?: Partial<FormFieldType>;\n valueFieldConfig?: Partial<FormFieldType>;\n };\n\n /**\n * Minimum number of map entries\n */\n minItems?: number;\n\n /**\n * Render function for map keys.\n * This allows the parent component to provide appropriate field components\n * based on the key type, maintaining separation of concerns.\n */\n renderKeyField?: (field: FormFieldType, entryIndex: number) => React.ReactNode;\n\n /**\n * Render function for map values.\n * This allows the parent component to provide appropriate field components\n * based on the value type, maintaining separation of concerns.\n */\n renderValueField?: (field: FormFieldType, entryIndex: number) => React.ReactNode;\n}\n\n/**\n * Map (key-value dictionary) input field component specifically designed for React Hook Form integration.\n *\n * This component provides a dynamic interface for managing map/dictionary inputs with:\n * - Add/remove functionality for key-value pairs\n * - Validation for map size constraints\n * - Integration with existing field components for keys and values\n * - Chain-agnostic data format (array of {key, value} objects)\n * - Full accessibility support\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like MapField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles map-specific rendering and validation\n *\n * The component stores data in a chain-agnostic format as an array of {key, value} objects.\n * The adapter is responsible for converting this to the chain-specific format (e.g., SorobanMapEntry[])\n * when submitting to the blockchain.\n */\nexport function MapField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n mapMetadata,\n minItems = 0,\n renderKeyField,\n renderValueField,\n readOnly,\n}: MapFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Get form context for field array operations\n const formContext = useFormContext();\n const effectiveControl = control || formContext.control;\n\n // Use field array for dynamic key-value pairs\n const { fields, append, remove, replace } = useFieldArray({\n control: effectiveControl,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n name: name as any, // Type assertion needed due to generic constraints\n });\n\n // Watch the map field value for duplicate key checking and initialization\n const watchedValue = useWatch({\n control: effectiveControl,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n name: name as any, // Type assertion needed due to generic constraints\n });\n const watchedValueKey = React.useMemo(() => JSON.stringify(watchedValue), [watchedValue]);\n\n // Keep field array synchronized with watched values\n const isReplacingRef = useMapFieldSync(watchedValue, fields.length, replace);\n\n /*\n * Keep the parent MapField error in sync without calling trigger:\n * - If any child has an error and the parent is required -> set a parent error\n * - Else use the structural validation result\n * This avoids re-entrancy loops that can happen when calling trigger during Preview.\n */\n React.useEffect(() => {\n if (!formContext) return;\n if (isReplacingRef.current) return;\n\n const mapArray = Array.isArray(watchedValue)\n ? (watchedValue as Array<{ key?: unknown; value?: unknown }>)\n : [];\n\n let childHasError = false;\n for (let i = 0; i < mapArray.length; i++) {\n const keyPath = `${name}.${i}.key`;\n const valuePath = `${name}.${i}.value`;\n const keyError = (formContext.formState.errors as Record<string, { message?: string }>)[\n keyPath\n ]?.message;\n const valueError = (formContext.formState.errors as Record<string, { message?: string }>)[\n valuePath\n ]?.message;\n if (keyError || valueError) {\n childHasError = true;\n break;\n }\n }\n\n const structural = validateMapStructure({\n value: watchedValue,\n required: !!validation?.required,\n minItems,\n });\n\n let nextMessage: string | undefined;\n if (childHasError && validation?.required) {\n nextMessage = 'This field is required';\n } else if (structural !== true) {\n nextMessage = structural;\n }\n\n const currentMessage = ((formContext.formState.errors as Record<string, { message?: string }>)[\n name as string\n ]?.message || undefined) as string | undefined;\n\n if (nextMessage && nextMessage !== currentMessage) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n formContext.setError(name as any, { type: 'manual', message: nextMessage });\n } else if (!nextMessage && currentMessage) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n formContext.clearErrors(name as any);\n }\n }, [\n formContext,\n name,\n watchedValue,\n watchedValueKey,\n validation?.required,\n minItems,\n isReplacingRef,\n ]);\n\n const duplicateKeyIndexes = useDuplicateKeyIndexes(watchedValue);\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={effectiveControl}\n name={name}\n disabled={readOnly}\n rules={{\n validate: (value) =>\n validateMapStructure({ value, required: !!validation?.required, minItems }),\n }}\n render={({ fieldState: { error, isTouched } }) => {\n // Check if any child fields have been touched to correctly determine\n // when to show the parent validation message.\n const anyChildTouched = computeChildTouched(formContext, name, watchedValue);\n const effectivelyTouched = isTouched || anyChildTouched;\n const hasError = !!error?.message;\n\n // Determine if the error message should be shown.\n // For required fields, we want to show the error immediately if the field is invalid.\n // For other fields, we only show it after the user has interacted with the component.\n const shouldShowError = hasError && (effectivelyTouched || isRequired);\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n // Add new map item\n const handleAddEntry = (): void => {\n // Set flag to prevent sync interference during add operation\n isReplacingRef.current = true;\n append(createDefaultEntry(mapMetadata) as FieldValues[typeof name]);\n\n // Reset flag after operation\n queueMicrotask(() => {\n isReplacingRef.current = false;\n });\n };\n\n // Remove map item\n const handleRemoveEntry = (index: number): void => {\n if (fields.length > minItems) {\n // Set flag to prevent sync interference during remove operation\n isReplacingRef.current = true;\n remove(index);\n\n // Reset flag after operation\n queueMicrotask(() => {\n isReplacingRef.current = false;\n });\n }\n };\n\n return (\n <>\n <div\n className=\"space-y-3\"\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`.trim()}\n >\n {fields.length === 0 ? (\n <div className=\"text-muted-foreground text-sm p-4 border border-dashed border-border rounded-md text-center\">\n No items added yet. Click “Add Item” to begin.\n </div>\n ) : (\n fields.map((field, index) => {\n // Create field configurations for key and value, following ArrayField pattern\n const isDuplicateKey = duplicateKeyIndexes.has(index);\n\n const keyField: FormFieldType = {\n ...mapMetadata?.keyFieldConfig,\n id: `${id}-key-${index}`,\n name: `${name}.${index}.key`,\n label: formatLabeledType(\n 'Key',\n mapMetadata?.keyFieldConfig?.originalParameterType || mapMetadata?.keyType\n ),\n type: mapMetadata?.keyFieldConfig?.type || 'text',\n validation: { required: true, ...mapMetadata?.keyFieldConfig?.validation },\n placeholder: mapMetadata?.keyFieldConfig?.placeholder || 'Enter key',\n width: 'full',\n readOnly: readOnly,\n originalParameterType: mapMetadata?.keyFieldConfig?.originalParameterType,\n };\n\n const valueField: FormFieldType = {\n ...mapMetadata?.valueFieldConfig,\n id: `${id}-value-${index}`,\n name: `${name}.${index}.value`,\n label: formatLabeledType(\n 'Value',\n mapMetadata?.valueFieldConfig?.originalParameterType ||\n mapMetadata?.valueType\n ),\n type: mapMetadata?.valueFieldConfig?.type || 'text',\n validation: { required: true, ...mapMetadata?.valueFieldConfig?.validation },\n placeholder: mapMetadata?.valueFieldConfig?.placeholder || 'Enter value',\n width: 'full',\n readOnly: readOnly,\n originalParameterType: mapMetadata?.valueFieldConfig?.originalParameterType,\n };\n\n return (\n <div\n key={field.id}\n className=\"flex items-start gap-2 p-3 border border-border rounded-md bg-background\"\n >\n <MapEntryRow\n keyField={keyField}\n valueField={valueField}\n isDuplicateKey={isDuplicateKey}\n renderKeyField={renderKeyField}\n renderValueField={renderValueField}\n index={index}\n />\n\n {!readOnly && fields.length > minItems && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => handleRemoveEntry(index)}\n className=\"size-8 p-0\"\n aria-label={`Remove item ${index + 1}`}\n >\n <X className=\"size-4\" />\n </Button>\n )}\n </div>\n );\n })\n )}\n\n {/* Add Item Button */}\n {!readOnly && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full\"\n onClick={handleAddEntry}\n >\n <Plus className=\"h-4 w-4 mr-2\" />\n Add Item\n </Button>\n )}\n </div>\n\n {/* Helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Error message */}\n <ErrorMessage\n message={shouldShowError ? error?.message : undefined}\n error={error}\n id={errorId}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nMapField.displayName = 'MapField';\n","import React from 'react';\n\nimport type { FormFieldType } from '@openzeppelin/ui-types';\n\ninterface Props {\n keyField: FormFieldType;\n valueField: FormFieldType;\n isDuplicateKey: boolean;\n renderKeyField?: (field: FormFieldType, entryIndex: number) => React.ReactNode;\n renderValueField?: (field: FormFieldType, entryIndex: number) => React.ReactNode;\n index: number;\n}\n\n/** Renders a single key-value entry row in a map field. */\nexport function MapEntryRow({\n keyField,\n valueField,\n isDuplicateKey,\n renderKeyField,\n renderValueField,\n index,\n}: Props): React.ReactElement {\n return (\n <div className=\"flex-1 grid grid-cols-1 gap-2 md:grid-cols-2\">\n <div className=\"flex flex-col gap-1\">\n {renderKeyField ? (\n <>\n {renderKeyField(keyField, index)}\n {isDuplicateKey && (\n <div className=\"text-destructive mt-1 text-sm\" role=\"alert\">\n Duplicate keys are not allowed\n </div>\n )}\n </>\n ) : (\n <div className=\"text-sm text-muted-foreground p-2 border border-dashed border-border rounded\">\n Key field type “{keyField.type}” requires a render function\n </div>\n )}\n </div>\n\n <div className=\"flex flex-col gap-1 md:items-center md:justify-center\">\n {renderValueField ? (\n renderValueField(valueField, index)\n ) : (\n <div className=\"text-sm text-muted-foreground p-2 border border-dashed border-border rounded\">\n Value field type “{valueField.type}” requires a render function\n </div>\n )}\n </div>\n </div>\n );\n}\n","import { UseFormReturn } from 'react-hook-form';\n\n/** Computes whether any child field in a map has been touched. */\nexport function computeChildTouched(\n formContext: UseFormReturn | undefined,\n name: string,\n watchedValue: unknown\n): boolean {\n const mapArray = Array.isArray(watchedValue)\n ? (watchedValue as Array<{ key?: unknown; value?: unknown }>)\n : [];\n if (!formContext || mapArray.length === 0) return false;\n\n for (let i = 0; i < mapArray.length; i++) {\n const keyPath = `${name}.${i}.key` as const;\n const valuePath = `${name}.${i}.value` as const;\n const keyState = formContext.getFieldState(keyPath, formContext.formState);\n const valueState = formContext.getFieldState(valuePath, formContext.formState);\n if (keyState.isTouched || valueState.isTouched) return true;\n }\n return false;\n}\n","import React from 'react';\n\n/** Hook that returns indexes of map entries with duplicate keys. */\nexport function useDuplicateKeyIndexes(watchedValue: unknown): Set<number> {\n return React.useMemo(() => {\n const duplicates = new Set<number>();\n if (!Array.isArray(watchedValue)) return duplicates;\n\n const keyCounts = new Map<string, number[]>();\n watchedValue.forEach((item: { key?: unknown }, index: number) => {\n const key = item?.key;\n if (key !== undefined && key !== null && key !== '') {\n const keyStr = String(key);\n if (!keyCounts.has(keyStr)) keyCounts.set(keyStr, []);\n keyCounts.get(keyStr)!.push(index);\n }\n });\n\n for (const [, indexes] of keyCounts) {\n if (indexes.length > 1) {\n indexes.forEach((i) => duplicates.add(i));\n }\n }\n return duplicates;\n }, [watchedValue]);\n}\n","import React from 'react';\n\n/**\n * Keeps a field array synchronized with a watched value's length using replace,\n * while preventing infinite loops via a guard ref.\n */\nexport function useMapFieldSync<TReplaceValue>(\n watchedValue: unknown,\n fieldsLength: number,\n replace: (value: TReplaceValue) => void\n): ReturnType<typeof React.useRef<boolean>> {\n const isReplacingRef = React.useRef(false);\n\n React.useEffect(() => {\n if (isReplacingRef.current) return;\n\n if (Array.isArray(watchedValue) && fieldsLength !== watchedValue.length) {\n isReplacingRef.current = true;\n replace(watchedValue as TReplaceValue);\n queueMicrotask(() => {\n isReplacingRef.current = false;\n });\n }\n }, [fieldsLength, watchedValue, replace]);\n\n return isReplacingRef;\n}\n","import { isMapEntryArray, MapEntry } from '@openzeppelin/ui-types';\n\nimport { validateMapEntries } from '../../utils/validation';\n\ninterface ValidateArgs {\n value: unknown;\n required: boolean;\n minItems?: number;\n}\n\n/** Validates a map field's structure including duplicates and required entries. */\nexport function validateMapStructure({ value, required, minItems }: ValidateArgs): string | true {\n // Validate that the value is actually an array of MapEntry objects\n if (!isMapEntryArray(value)) {\n if (required) return 'This field is required';\n return true;\n }\n\n const mapArray: MapEntry[] = value;\n\n const duplicateError = validateMapEntries(mapArray);\n if (duplicateError) return duplicateError;\n\n const hasPartial = mapArray.some((entry: MapEntry) => {\n const key = entry.key;\n const val = entry.value;\n const keyEmpty = key === '' || key == null;\n const valEmpty = val === '' || val == null;\n return (keyEmpty && !valEmpty) || (!keyEmpty && valEmpty);\n });\n if (hasPartial) return 'All key-value pairs must be completed';\n\n const validEntries = mapArray.filter((entry: MapEntry) => {\n const key = entry.key;\n const val = entry.value;\n return key !== '' && key != null && val !== '' && val != null;\n });\n\n if (required && validEntries.length === 0) return 'This field is required';\n\n if (minItems && validEntries.length < minItems) {\n return `At least ${minItems} item${minItems > 1 ? 's' : ''} required`;\n }\n\n return true;\n}\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n validateField,\n} from './utils';\n\n/**\n * NumberField component properties\n */\nexport interface NumberFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Minimum value validation\n */\n min?: number;\n\n /**\n * Maximum value validation\n */\n max?: number;\n\n /**\n * Step value for increment/decrement\n */\n step?: number;\n\n /**\n * Custom validation function for number values\n */\n validateNumber?: (value: number) => boolean | string;\n}\n\n/**\n * Number input field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like NumberField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles number-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Numeric-specific validations (min, max, step)\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation with arrow keys for numeric increment/decrement\n */\nexport function NumberField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n min,\n max,\n step = 1,\n validateNumber,\n readOnly,\n}: NumberFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Create merged validation that includes min/max from props\n const mergedValidation = {\n ...validation,\n min: validation?.min !== undefined ? validation.min : min,\n max: validation?.max !== undefined ? validation.max : max,\n };\n\n // Regular expressions for number validation\n const NUMBER_REGEX = {\n // Allow optional minus sign, digits, optional decimal point, more digits\n VALID_FORMAT: /^-?\\d*\\.?\\d*$/,\n // Complete number (more strict than the format check)\n COMPLETE_NUMBER: /^-?\\d+\\.?\\d*$/,\n };\n\n // Common validation for numeric values\n const validateNumericValue = (value: number): string | true => {\n // Run standard validation\n const standardValidation = validateField(value, mergedValidation);\n if (standardValidation !== true) return standardValidation as string;\n\n // Run custom validator if provided\n if (validateNumber) {\n const customValidation = validateNumber(value);\n if (customValidation !== true && typeof customValidation === 'string') {\n return customValidation;\n }\n }\n\n return true;\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Skip validation if empty and check required separately\n if (value === undefined || value === null || value === '') {\n return mergedValidation?.required ? 'This field is required' : true;\n }\n\n // Handle incomplete number inputs\n if (value === '-') {\n return 'Please enter a complete number';\n }\n\n // Handle decimal point at the end\n if (typeof value === 'string' && value.endsWith('.')) {\n return 'Please enter a complete decimal number';\n }\n\n // For string values that passed our format check but aren't complete numbers\n if (typeof value === 'string') {\n // Parse the validated string to a number\n const parsedNum = parseFloat(value);\n if (isNaN(parsedNum)) {\n return 'Invalid number'; // Explicitly return error for NaN\n }\n return validateNumericValue(parsedNum);\n }\n\n // For already numeric values\n if (typeof value === 'number') {\n return validateNumericValue(value);\n }\n\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Handle input change\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const rawValue = e.target.value;\n\n // Check if the input matches our valid number format\n const isValidNumberFormat = NUMBER_REGEX.VALID_FORMAT.test(rawValue);\n\n if (!isValidNumberFormat && rawValue !== '') {\n // Don't update the field value for invalid formats\n // This prevents entering invalid characters\n return;\n }\n\n // For valid format or empty string\n if (rawValue === '') {\n // Empty value\n field.onChange('');\n } else if (rawValue === '-') {\n // Allow standalone minus for user to continue typing\n field.onChange(rawValue);\n } else if (rawValue.endsWith('.')) {\n // Allow numbers ending with decimal point for user to continue typing\n field.onChange(rawValue);\n } else {\n // Convert to number for valid numeric values\n const numValue = parseFloat(rawValue);\n field.onChange(isNaN(numValue) ? rawValue : numValue);\n }\n\n // Note: Validation happens naturally when user leaves the field\n // No need to trigger it programmatically on every change\n };\n\n // Handle keyboard events\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n // Allow only numeric characters, backspace, delete, tab, escape, enter, arrows, period, hyphen\n // This is a basic filter; more complex scenarios might need a more robust solution\n const allowedKeys = [\n '0',\n '1',\n '2',\n '3',\n '4',\n '5',\n '6',\n '7',\n '8',\n '9',\n 'Backspace',\n 'Delete',\n 'Tab',\n 'Escape',\n 'Enter',\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n '.',\n '-',\n ];\n\n // Allow Ctrl/Cmd+A, C, V, X, Z for common editing operations\n if (\n (e.ctrlKey || e.metaKey) &&\n ['a', 'c', 'v', 'x', 'z'].includes(e.key.toLowerCase())\n ) {\n return;\n }\n\n if (!allowedKeys.includes(e.key) && !e.ctrlKey && !e.metaKey) {\n e.preventDefault();\n }\n\n // Handle escape key to clear input\n if (e.key === 'Escape') {\n handleEscapeKey(field.onChange, field.value)(e);\n return;\n }\n\n // Handle arrow keys for increment/decrement\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault(); // Prevent default browser behavior\n\n // Get current value as number or default to 0\n let currentValue = 0;\n if (typeof field.value === 'number') {\n currentValue = field.value;\n } else if (\n typeof field.value === 'string' &&\n NUMBER_REGEX.COMPLETE_NUMBER.test(field.value)\n ) {\n currentValue = parseFloat(field.value);\n }\n\n // Calculate new value based on step, respecting min/max\n const increment = e.key === 'ArrowUp' ? step : -step;\n const newValue = Math.min(\n max !== undefined ? max : Infinity,\n Math.max(min !== undefined ? min : -Infinity, currentValue + increment)\n );\n\n // Update the field\n field.onChange(newValue);\n // Note: Validation happens naturally, no need to trigger it programmatically\n }\n };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <Input\n {...field}\n value={field.value ?? ''}\n id={id}\n placeholder={placeholder}\n type=\"text\"\n min={min}\n max={max}\n step={step}\n className={validationClasses}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n onChange={handleInputChange}\n inputMode=\"decimal\"\n pattern=\"-?[0-9]*\\.?[0-9]*\"\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n disabled={readOnly}\n />\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nNumberField.displayName = 'NumberField';\n","import React from 'react';\nimport { Control, Controller, FieldValues, useFormContext } from 'react-hook-form';\n\nimport type {\n ContractSchema,\n FormFieldType,\n FunctionParameter,\n TypeMappingCapability,\n} from '@openzeppelin/ui-types';\n\n// TODO: Consider if FunctionParameter is the most appropriate type for `components` here,\n// or if a UI-specific version of a component/property definition would be more robust.\n\nimport { Card } from '../ui/card';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage, getAccessibilityProps } from './utils';\n\n/**\n * ObjectField component properties\n */\nexport interface ObjectFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * The components/properties of the object.\n * These define the schema for the nested fields within the object.\n */\n components?: FunctionParameter[]; // TODO: As above, review type for `components`.\n\n /**\n * Render function for object properties.\n * This is crucial for rendering complex properties or integrating custom field components.\n */\n // TODO: Explore a fallback rendering mechanism if `renderProperty` is not provided,\n // especially for known simple property types (e.g., 'text', 'number').\n // This could make the component more self-contained for basic object structures.\n renderProperty?: (field: FormFieldType, propertyName: string) => React.ReactNode;\n\n /**\n * Whether to show the object in a card container.\n * Useful for visually grouping object properties.\n */\n // TODO: Consider more advanced layout options beyond a simple card,\n // e.g., tabs, accordions for very complex objects, or grid layouts.\n showCard?: boolean;\n\n /**\n * The type-mapping capability for chain-specific field generation.\n * Essential for correctly determining field types for object properties.\n */\n typeMapping?: TypeMappingCapability;\n\n /**\n * Optional contract schema for nested metadata (structs/enums).\n */\n contractSchema?: ContractSchema;\n}\n\n/**\n * Object (composite/nested) input field component specifically designed for React Hook Form integration.\n *\n * This component provides a structured interface for managing object inputs with:\n * - Nested field rendering based on object components\n * - Validation for required properties (currently, the object itself can be required)\n * - Integration with existing field components for object properties\n * - Full accessibility support\n *\n * The component reuses existing field components for individual properties,\n * maintaining consistency across the form system while supporting complex nested structures.\n */\nexport function ObjectField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n components = [],\n renderProperty,\n showCard = true,\n readOnly,\n typeMapping,\n contractSchema,\n}: ObjectFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Get form context for nested field registration\n const formContext = useFormContext();\n const effectiveControl = control || formContext.control;\n\n // TODO: Consider performance implications for very large/deeply nested objects.\n // For extremely complex objects, virtualization or other rendering strategies might be needed.\n\n return (\n <Controller\n control={effectiveControl as Control<FieldValues>}\n name={name}\n rules={{\n // TODO: Expand validation capabilities for objects.\n // Current validation only checks if the object itself is required.\n // Future: Allow schema-level validation for individual properties within the object,\n // or a custom validate function that receives the whole object value.\n validate: (value) => {\n // Validate object constraints\n if (\n validation?.required &&\n (!value || typeof value !== 'object' || Array.isArray(value))\n ) {\n return 'This field is required';\n }\n\n // Additional object validation can be added here (e.g., based on `components` schema)\n return true;\n },\n }}\n render={({ fieldState: { error } }) => {\n const hasError = !!error;\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n const content = (\n <>\n {/* Object properties */}\n <div className=\"space-y-4\">\n {components.length === 0 ? (\n <div className=\"text-muted-foreground text-sm\">\n No properties defined for this object\n </div>\n ) : (\n components.map((component) => {\n // Generate field using the type-mapping capability to preserve nested array/object metadata.\n if (!typeMapping) {\n throw new Error(\n `ObjectField: No typeMapping capability provided for field generation. Cannot generate field for \"${component.name}\"`\n );\n }\n\n const generatedField = typeMapping.generateDefaultField(\n component,\n contractSchema\n );\n\n // Override with object-specific configuration\n const propertyField: FormFieldType = {\n ...generatedField, // Include elementType and other capability-specific properties\n id: `${id}-${component.name}`,\n name: `${name}.${component.name}`,\n label: component.displayName || component.name,\n // Validation merging precedence:\n // 1. Spread generatedField.validation (adapter-provided bounds, etc.)\n // 2. Override 'required' from parent validation if specified\n // This preserves min/max bounds while allowing parent to control required state\n validation: {\n ...generatedField.validation, // Preserve validation from type mapping (includes min/max bounds)\n required: validation?.required, // Override required from parent\n },\n placeholder: `Enter ${component.displayName || component.name}`,\n helperText:\n component.description ||\n (generatedField.type === 'number' ? 'Numbers only' : undefined),\n width: 'full',\n readOnly,\n // Pass components for nested objects (tuples within a struct)\n ...(component.components && {\n components: component.components,\n }),\n };\n\n return (\n <div key={component.name}>\n {renderProperty ? (\n renderProperty(propertyField, component.name)\n ) : (\n // This fallback is okay, but a more robust solution might attempt to\n // render a default UI field based on `propertyField.type` if it's a known simple type.\n <div className=\"text-sm text-muted-foreground\">\n Property “{component.name}” requires a render function\n </div>\n )}\n </div>\n );\n })\n )}\n </div>\n\n {/* Helper text for the entire object */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm mt-2\">\n {helperText}\n </div>\n )}\n\n {/* Error message for the entire object */}\n <ErrorMessage error={error} id={errorId} />\n </>\n );\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n >\n {/* Label for the entire object */}\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n {/* TODO: Conditional rendering of Card based on `showCard` and `components.length`.\n Perhaps don't render a card if there are no components or if showCard is false.\n Currently, an empty card might be rendered if components is empty but showCard is true. */}\n {showCard ? <Card className=\"p-4\">{content}</Card> : content}\n </div>\n );\n }}\n />\n );\n}\n\n// Set display name for debugging\nObjectField.displayName = 'ObjectField';\n","import { Eye, EyeOff } from 'lucide-react';\nimport React, { useState } from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n validateField,\n} from './utils';\n\n/**\n * PasswordField component properties\n */\nexport interface PasswordFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Placeholder text displayed when the field is empty\n */\n placeholder?: string;\n\n /**\n * Whether to show the password visibility toggle button\n * @default true\n */\n showToggle?: boolean;\n}\n\n/**\n * Password input field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like PasswordField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles password-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Password visibility toggle functionality\n * - Password-specific validations (minLength, maxLength, pattern)\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation\n */\nexport function PasswordField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n readOnly,\n showToggle = true,\n}: PasswordFieldProps<TFieldValues>): React.ReactElement {\n const [showPassword, setShowPassword] = useState(false);\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Function for validating password values\n const validatePasswordValue = (value: string): string | true => {\n const validationResult = validateField(value, validation);\n return validationResult === true ? true : (validationResult as string);\n };\n\n // Toggle password visibility\n const togglePasswordVisibility = (): void => {\n setShowPassword((prev) => !prev);\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Validate password values\n if (typeof value === 'string') {\n return validatePasswordValue(value);\n }\n\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Handle input change with validation for required fields\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const value = e.target.value;\n field.onChange(value);\n\n // Trigger validation if the field is required and empty\n if (isRequired && value === '') {\n setTimeout(() => field.onBlur(), 0);\n }\n };\n\n // Handle keyboard events\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n if (e.key === 'Escape') {\n handleEscapeKey(field.onChange, field.value)(e);\n\n // If required, trigger validation after clearing\n if (isRequired) {\n setTimeout(() => field.onBlur(), 0);\n }\n }\n };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <div className=\"relative\">\n <Input\n {...field}\n id={id}\n type={showPassword ? 'text' : 'password'}\n placeholder={placeholder}\n className={`${validationClasses} ${showToggle ? 'pr-10' : ''}`}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n value={field.value ?? ''}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n disabled={readOnly}\n />\n {showToggle && !readOnly && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent\"\n onClick={togglePasswordVisibility}\n aria-label={showPassword ? 'Hide password' : 'Show password'}\n >\n {showPassword ? (\n <EyeOff className=\"h-4 w-4 text-muted-foreground\" />\n ) : (\n <Eye className=\"h-4 w-4 text-muted-foreground\" />\n )}\n </Button>\n )}\n </div>\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nPasswordField.displayName = 'PasswordField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage, getAccessibilityProps } from './utils';\n\n/**\n * Option item for radio fields\n */\nexport interface RadioOption {\n /**\n * Value to be submitted with the form\n */\n value: string;\n\n /**\n * Display label for the option\n */\n label: string;\n\n /**\n * Whether this option is disabled\n */\n disabled?: boolean;\n}\n\n/**\n * RadioField component properties\n */\nexport interface RadioFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Available options for selection\n */\n options?: RadioOption[];\n\n /**\n * Direction of radio options layout\n */\n layout?: 'horizontal' | 'vertical';\n\n /**\n * Custom validation function for radio values\n */\n validateRadio?: (value: string) => boolean | string;\n}\n\n/**\n * Radio button field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles radio-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Customizable options list\n * - Horizontal or vertical layout options\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n */\nexport function RadioField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n options = [],\n layout = 'vertical',\n validateRadio,\n}: RadioFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n const radioGroupId = `${id}-group`;\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={radioGroupId} className=\"text-sm font-medium\">\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Run custom validation if provided\n if (validateRadio && value) {\n const validation = validateRadio(value);\n if (validation !== true && typeof validation === 'string') {\n return validation;\n }\n }\n\n return true;\n },\n }}\n render={({ field, fieldState: { error } }) => {\n const hasError = !!error;\n\n // Group accessibility attributes\n const groupAccessibilityProps = getAccessibilityProps({\n id: radioGroupId,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <div\n id={radioGroupId}\n role=\"radiogroup\"\n className={`flex ${layout === 'vertical' ? 'flex-col gap-3' : 'flex-row flex-wrap gap-4'}`}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n {...groupAccessibilityProps}\n >\n {options.map((option, index) => {\n const optionId = `${id}-option-${index}`;\n const isSelected = field.value === option.value;\n const isDisabled = option.disabled;\n\n return (\n <label\n key={option.value}\n htmlFor={optionId}\n className={`group relative flex cursor-pointer items-center gap-2 rounded-lg px-3 py-2 transition-all duration-150 ${\n isDisabled ? 'cursor-not-allowed opacity-50' : 'hover:bg-muted/50'\n } ${isSelected && !hasError ? 'bg-selected/5' : ''}`}\n >\n <input\n type=\"radio\"\n id={optionId}\n value={option.value}\n disabled={isDisabled}\n checked={isSelected}\n onChange={() => field.onChange(option.value)}\n className=\"sr-only\"\n aria-describedby={hasError ? errorId : undefined}\n />\n\n {/* Custom Radio Button */}\n <div className=\"relative flex size-4 items-center justify-center\">\n <div\n className={`absolute size-4 rounded-full border-2 transition-all duration-150 ${\n isSelected\n ? hasError\n ? 'border-destructive bg-destructive/10'\n : 'border-selected bg-selected/10'\n : hasError\n ? 'border-destructive/50'\n : 'border-muted-foreground/40 group-hover:border-muted-foreground/60'\n } ${!isDisabled && 'group-hover:scale-105'}`}\n />\n\n {/* Inner dot for selected state */}\n <div\n className={`absolute size-1.5 rounded-full transition-all duration-150 ${\n isSelected\n ? hasError\n ? 'bg-destructive scale-100 opacity-100'\n : 'bg-selected scale-100 opacity-100'\n : 'scale-0 opacity-0'\n }`}\n />\n </div>\n\n {/* Label text */}\n <span\n className={`text-sm transition-colors duration-150 ${\n isDisabled\n ? 'text-muted-foreground'\n : isSelected\n ? hasError\n ? 'text-destructive font-medium'\n : 'text-foreground font-medium'\n : 'text-foreground'\n }`}\n >\n {option.label}\n </span>\n\n {/* Focus ring */}\n <div\n className={`absolute -inset-1 rounded-lg ring-2 ring-selected ring-offset-2 ring-offset-background transition-opacity duration-150 ${\n isSelected && !isDisabled\n ? 'opacity-0 focus-within:opacity-100'\n : 'opacity-0'\n }`}\n />\n </label>\n );\n })}\n </div>\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-sm text-muted-foreground\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage error={error} id={errorId} />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nRadioField.displayName = 'RadioField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Label } from '../ui/label';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage } from './utils';\n\n/**\n * Option item for select fields\n */\nexport interface SelectOption {\n /**\n * Value to be submitted with the form\n */\n value: string;\n\n /**\n * Display label for the option\n */\n label: string;\n\n /**\n * Whether this option is disabled\n */\n disabled?: boolean;\n}\n\n/**\n * SelectField component properties\n */\nexport interface SelectFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Available options for selection\n */\n options?: SelectOption[];\n\n /**\n * Custom validation function for select values\n */\n validateSelect?: (value: string) => boolean | string;\n\n /**\n * Optional default value used when the field has no value yet\n */\n defaultValue?: string;\n}\n\n/**\n * Select dropdown field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles radio-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Customizable options list\n * - Horizontal or vertical layout options\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n */\nexport function SelectField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder = 'Select an option',\n helperText,\n control,\n name,\n width = 'full',\n validation,\n options = [],\n validateSelect,\n defaultValue,\n}: SelectFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Determine width values\n const widthPercentage = width === 'full' ? '100%' : width === 'half' ? '50%' : '33.333%';\n const widthClass = width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3';\n\n return (\n <div className={cn('flex flex-col gap-2', widthClass)} style={{ width: widthPercentage }}>\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n defaultValue={defaultValue as unknown as undefined}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Run custom validation if provided\n if (validateSelect && value) {\n const validation = validateSelect(value);\n if (validation !== true && typeof validation === 'string') {\n return validation;\n }\n }\n\n return true;\n },\n }}\n render={({ field, fieldState: { error } }) => {\n const hasError = !!error;\n\n // Get accessibility attributes\n const accessibilityAttrs = {\n 'aria-invalid': hasError,\n 'aria-required': isRequired,\n 'aria-describedby':\n `${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`.trim(),\n };\n\n // Ensure we properly handle the onValueChange event\n const handleValueChange = (newValue: string): void => {\n field.onChange(newValue);\n };\n\n return (\n <>\n <Select\n defaultValue={field.value}\n onValueChange={handleValueChange}\n value={field.value}\n >\n <SelectTrigger id={id} {...accessibilityAttrs}>\n <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n <SelectContent\n // Ensure dropdown width matches trigger width\n style={{\n width: 'var(--radix-select-trigger-width)',\n maxWidth: 'var(--radix-select-trigger-width)',\n }}\n >\n {options.length === 0 ? (\n <div className=\"px-2 py-1.5 text-sm text-muted-foreground\">\n No options available\n </div>\n ) : (\n options.map((option) => (\n <SelectItem\n key={option.value}\n value={option.value}\n disabled={option.disabled}\n >\n {option.label}\n </SelectItem>\n ))\n )}\n </SelectContent>\n </Select>\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage error={error} id={errorId} />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nSelectField.displayName = 'SelectField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { Label } from '../ui/label';\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n} from '../ui/select';\nimport { BaseFieldProps } from './BaseField';\nimport { ErrorMessage } from './utils';\n\n/**\n * Option item for select fields with visual indicators\n */\nexport interface GroupedSelectOption {\n /**\n * Value to be submitted with the form\n */\n value: string;\n\n /**\n * Display label for the option\n */\n label: string;\n\n /**\n * Whether this option is disabled\n */\n disabled?: boolean;\n\n /**\n * Custom CSS class to apply to the option\n */\n className?: string;\n}\n\n/**\n * Option group structure\n */\nexport interface OptionGroup {\n /**\n * Group label to display\n */\n label: string;\n\n /**\n * Options within this group\n */\n options: GroupedSelectOption[];\n}\n\n/**\n * SelectGroupedField component properties\n */\nexport interface SelectGroupedFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Available option groups for selection\n */\n groups?: OptionGroup[];\n\n /**\n * Custom validation function for select values\n */\n validateSelect?: (value: string) => boolean | string;\n}\n\n/**\n * Select dropdown field component with grouped options specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles radio-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Customizable options list\n * - Horizontal or vertical layout options\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n */\nexport function SelectGroupedField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder = 'Select an option',\n helperText,\n control,\n name,\n width = 'full',\n validation,\n groups = [],\n validateSelect,\n}: SelectGroupedFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Determine width values\n const widthPercentage = width === 'full' ? '100%' : width === 'half' ? '50%' : '33.333%';\n const widthClass = width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3';\n\n return (\n <div className={cn('flex flex-col gap-2', widthClass)} style={{ width: widthPercentage }}>\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Run custom validation if provided\n if (validateSelect && value) {\n const validation = validateSelect(value);\n if (validation !== true && typeof validation === 'string') {\n return validation;\n }\n }\n\n return true;\n },\n }}\n render={({ field, fieldState: { error } }) => {\n const hasError = !!error;\n\n // Get accessibility attributes\n const accessibilityAttrs = {\n 'aria-invalid': hasError,\n 'aria-required': isRequired,\n 'aria-describedby':\n `${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`.trim(),\n };\n\n // Ensure we properly handle the onValueChange event\n const handleValueChange = (newValue: string): void => {\n field.onChange(newValue);\n };\n\n return (\n <>\n <Select\n defaultValue={field.value}\n onValueChange={handleValueChange}\n value={field.value}\n >\n <SelectTrigger id={id} {...accessibilityAttrs}>\n <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n <SelectContent\n // Ensure dropdown width matches trigger width\n style={{\n width: 'var(--radix-select-trigger-width)',\n maxWidth: 'var(--radix-select-trigger-width)',\n }}\n >\n {groups.map((group, groupIndex) => (\n <React.Fragment key={`group-${groupIndex}`}>\n {groupIndex > 0 && <SelectSeparator />}\n <SelectGroup>\n <SelectLabel>{group.label}</SelectLabel>\n {group.options.map((option) => (\n <SelectItem\n key={option.value}\n value={option.value}\n disabled={option.disabled}\n className={cn(option.className, option.disabled && 'opacity-50')}\n >\n <span>{option.label}</span>\n </SelectItem>\n ))}\n </SelectGroup>\n </React.Fragment>\n ))}\n </SelectContent>\n </Select>\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage error={error} id={errorId} />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nSelectGroupedField.displayName = 'SelectGroupedField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n validateField,\n} from './utils';\n\n/**\n * TextField component properties\n */\nexport interface TextFieldProps<TFieldValues extends FieldValues = FieldValues>\n extends BaseFieldProps<TFieldValues> {\n /**\n * Placeholder text displayed when the field is empty\n */\n placeholder?: string;\n\n /**\n * Fired with the new value on USER-originated edits only — keystrokes and the\n * Escape-clear — never on programmatic writes (`setValue`/`reset`). This is\n * the discriminator consumers need to tell \"the user claimed this field\" from\n * \"code seeded this field\" (e.g. the address book's ENS alias suggestion,\n * SF-5 INV-103/INV-105); RHF's `dirtyFields` cannot express it because any\n * form-wide dirty recompute retroactively marks a seeded value dirty.\n */\n onUserEdit?: (value: string) => void;\n}\n\n/**\n * Text input field component specifically designed for React Hook Form integration.\n *\n * Architecture flow:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. TransactionForm renders the overall form structure with React Hook Form\n * 3. DynamicFormField selects the appropriate field component (like TextField) based on field type\n * 4. BaseField provides consistent layout and hook form integration\n * 5. This component handles text-specific rendering and validation\n *\n * The component includes:\n * - Integration with React Hook Form\n * - Text-specific validations (minLength, maxLength, pattern)\n * - Customizable validation through adapter integration\n * - Automatic error handling and reporting\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation\n */\nexport function TextField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n readOnly,\n onUserEdit,\n}: TextFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n // Function for validating text values\n const validateTextValue = (value: string): string | true => {\n const validationResult = validateField(value, validation);\n return validationResult === true ? true : (validationResult as string);\n };\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Handle required validation explicitly\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Validate text values\n if (typeof value === 'string') {\n return validateTextValue(value);\n }\n\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Handle input change with validation for required fields\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const value = e.target.value;\n field.onChange(value);\n onUserEdit?.(value);\n // Note: Validation happens naturally when user leaves the field\n // No need to trigger it programmatically on every change\n };\n\n // Handle keyboard events\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n if (e.key === 'Escape') {\n // Escape-clear is a user edit too — notify with the cleared value.\n handleEscapeKey((value) => {\n field.onChange(value);\n onUserEdit?.(value);\n }, field.value)(e);\n // Note: Validation happens naturally when user leaves the field\n // No need to trigger it programmatically\n }\n };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <Input\n {...field}\n id={id}\n placeholder={placeholder}\n className={validationClasses}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n value={field.value ?? ''}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n disabled={readOnly}\n />\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\n// Set displayName manually for better debugging\nTextField.displayName = 'TextField';\n","import React from 'react';\nimport { Controller, FieldValues } from 'react-hook-form';\n\nimport { getInvalidUrlMessage, isValidUrl } from '@openzeppelin/ui-utils';\n\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\nimport { BaseFieldProps } from './BaseField';\nimport {\n ErrorMessage,\n getAccessibilityProps,\n getValidationStateClasses,\n handleEscapeKey,\n validateField,\n} from './utils';\n\n/**\n * URL input field component specifically designed for React Hook Form integration.\n */\nexport function UrlField<TFieldValues extends FieldValues = FieldValues>({\n id,\n label,\n placeholder,\n helperText,\n control,\n name,\n width = 'full',\n validation,\n readOnly,\n}: BaseFieldProps<TFieldValues>): React.ReactElement {\n const isRequired = !!validation?.required;\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n return (\n <div\n className={`flex flex-col gap-2 ${width === 'full' ? 'w-full' : width === 'half' ? 'w-1/2' : 'w-1/3'}`}\n >\n {label && (\n <Label htmlFor={id}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </Label>\n )}\n\n <Controller\n control={control}\n name={name}\n rules={{\n validate: (value) => {\n // Check required field explicitly first\n if (value === undefined || value === null || value === '') {\n return validation?.required ? 'This field is required' : true;\n }\n\n // Perform standard validations (min, max, pattern, etc.) if they exist\n const standardValidationResult = validateField(value, validation);\n if (standardValidationResult !== true) {\n return standardValidationResult;\n }\n\n // Perform URL-specific validation using the shared validator\n if (typeof value === 'string' && value && !isValidUrl(value)) {\n return getInvalidUrlMessage();\n }\n\n // If all checks pass\n return true;\n },\n }}\n disabled={readOnly}\n render={({ field, fieldState: { error, isTouched } }) => {\n const hasError = !!error;\n const shouldShowError = hasError && isTouched;\n const validationClasses = getValidationStateClasses(error, isTouched);\n\n // Handle input change with validation\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const value = e.target.value;\n field.onChange(value);\n\n // Trigger validation if the field is required and empty\n if (isRequired && value === '') {\n setTimeout(() => field.onBlur(), 0);\n }\n };\n\n // Add keyboard accessibility for clearing the field with Escape\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {\n if (e.key === 'Escape') {\n handleEscapeKey(field.onChange, field.value)(e);\n\n // If required, trigger validation after clearing\n if (isRequired) {\n setTimeout(() => field.onBlur(), 0);\n }\n }\n };\n\n // Get accessibility attributes\n const accessibilityProps = getAccessibilityProps({\n id,\n hasError,\n isRequired,\n hasHelperText: !!helperText,\n });\n\n return (\n <>\n <Input\n {...field}\n id={id}\n type=\"url\"\n placeholder={placeholder || 'https://example.com'}\n className={validationClasses}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n data-slot=\"input\"\n value={field.value ?? ''}\n {...accessibilityProps}\n aria-describedby={`${helperText ? descriptionId : ''} ${hasError ? errorId : ''}`}\n disabled={readOnly}\n />\n\n {/* Display helper text */}\n {helperText && (\n <div id={descriptionId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </div>\n )}\n\n {/* Display error message */}\n <ErrorMessage\n error={error}\n id={errorId}\n message={shouldShowError ? error?.message : undefined}\n />\n </>\n );\n }}\n />\n </div>\n );\n}\n\nUrlField.displayName = 'UrlField';\n","import {\n AlertCircle,\n CheckCircle,\n DollarSign,\n Hash,\n Info,\n Loader2,\n Network,\n Timer,\n} from 'lucide-react';\nimport React from 'react';\n\nimport type { RelayerDetails, RelayerDetailsRich } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { AddressDisplay } from '../ui/address-display';\n\nexport interface RelayerDetailsCardProps {\n details: RelayerDetails;\n enhancedDetails?: RelayerDetailsRich | null;\n loading?: boolean;\n className?: string;\n /** Optional UI labels to override default copy */\n labels?: Partial<{\n detailsTitle: string;\n active: string;\n paused: string;\n systemDisabled: string;\n network: string;\n relayerId: string;\n balance: string;\n nonce: string;\n pending: string;\n lastTransaction: string;\n }>;\n}\n\nexport const RelayerDetailsCard: React.FC<RelayerDetailsCardProps> = ({\n details,\n enhancedDetails,\n loading = false,\n className,\n labels,\n}) => {\n const displayDetails = enhancedDetails || details;\n\n const l = {\n detailsTitle: labels?.detailsTitle || 'Relayer Details',\n active: labels?.active || 'Active',\n paused: labels?.paused || 'Paused',\n systemDisabled: labels?.systemDisabled || 'System Disabled',\n network: labels?.network || 'Network',\n relayerId: labels?.relayerId || 'Relayer ID',\n balance: labels?.balance || 'Balance',\n nonce: labels?.nonce || 'Nonce',\n pending: labels?.pending || 'Pending Transactions',\n lastTransaction: labels?.lastTransaction || 'Last Transaction',\n } as const;\n\n // Format timestamp for display\n const formatTimestamp = (timestamp: string): string => {\n try {\n const date = new Date(timestamp);\n return date.toLocaleString();\n } catch {\n return timestamp;\n }\n };\n\n return (\n <div\n className={cn(\n 'flex flex-col sm:flex-row sm:items-start space-y-3 sm:space-y-0 sm:space-x-3 p-3 bg-slate-50 rounded-md',\n className\n )}\n >\n <Info className=\"size-5 text-primary mt-0.5 flex-shrink-0 hidden sm:block\" />\n <div className=\"space-y-3 flex-1 min-w-0\">\n <div>\n <h4 className=\"text-sm font-medium mb-2\">{l.detailsTitle}</h4>\n\n {/* Relayer Name and Status */}\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-2 space-y-1 sm:space-y-0\">\n <p className=\"text-sm font-medium text-foreground truncate\">{displayDetails.name}</p>\n <span\n className={cn(\n 'inline-flex items-center px-2 py-1 rounded-full text-xs font-medium self-start',\n displayDetails.paused || enhancedDetails?.systemDisabled\n ? 'bg-red-100 text-red-800'\n : 'bg-green-100 text-green-800'\n )}\n >\n {displayDetails.paused || enhancedDetails?.systemDisabled ? (\n <>\n <AlertCircle className=\"size-3 mr-1\" />\n {enhancedDetails?.systemDisabled ? l.systemDisabled : l.paused}\n </>\n ) : (\n <>\n <CheckCircle className=\"size-3 mr-1\" />\n {l.active}\n </>\n )}\n </span>\n </div>\n\n {/* Relayer Address */}\n <div className=\"mb-3\">\n <AddressDisplay\n className=\"w-full sm:w-auto\"\n address={displayDetails.address}\n truncate={true}\n startChars={6}\n endChars={4}\n showCopyButton\n />\n </div>\n\n {/* Additional Details */}\n <div className=\"space-y-1 pt-2 border-t border-slate-200\">\n <div className=\"flex items-center gap-2\">\n <Network className=\"size-3.5 text-muted-foreground flex-shrink-0\" />\n <p className=\"text-xs text-muted-foreground truncate\">\n <span className=\"font-medium\">{l.network}:</span> {displayDetails.network}\n </p>\n </div>\n\n <div className=\"flex items-start gap-2\">\n <Hash className=\"size-3.5 text-muted-foreground flex-shrink-0 mt-0.5\" />\n <div className=\"text-xs text-muted-foreground min-w-0 flex-1\">\n <span className=\"font-medium\">{l.relayerId}:</span>{' '}\n <code className=\"font-mono text-xs bg-slate-100 px-1 py-0.5 rounded break-all\">\n {displayDetails.relayerId}\n </code>\n </div>\n </div>\n </div>\n\n {/* Enhanced Details Section */}\n {loading && (\n <div className=\"mt-3 flex items-center gap-2 text-xs text-muted-foreground\">\n <Loader2 className=\"size-3 animate-spin\" />\n Loading additional details...\n </div>\n )}\n\n {!loading && enhancedDetails && (\n <div className=\"mt-3 pt-3 border-t border-slate-200 space-y-2\">\n {/* Balance */}\n {enhancedDetails.balance && (\n <div className=\"flex items-center gap-2 text-xs\">\n <DollarSign className=\"size-3.5 text-muted-foreground flex-shrink-0\" />\n <div className=\"text-muted-foreground min-w-0 flex-1\">\n <span className=\"font-medium\">{l.balance}:</span>{' '}\n <span className=\"break-all\">{enhancedDetails.balance}</span>\n </div>\n </div>\n )}\n\n {/* Nonce */}\n {enhancedDetails.nonce && (\n <div className=\"flex items-center gap-2 text-xs\">\n <Hash className=\"size-3.5 text-muted-foreground flex-shrink-0\" />\n <span className=\"text-muted-foreground\">\n <span className=\"font-medium\">{l.nonce}:</span> {enhancedDetails.nonce}\n </span>\n </div>\n )}\n\n {/* Pending Transactions */}\n {enhancedDetails.pendingTransactionsCount !== undefined && (\n <div className=\"flex items-center gap-2 text-xs\">\n <Timer className=\"size-3.5 text-muted-foreground flex-shrink-0\" />\n <span className=\"text-muted-foreground\">\n <span className=\"font-medium\">{l.pending}:</span>{' '}\n {enhancedDetails.pendingTransactionsCount}\n </span>\n </div>\n )}\n\n {/* Last Transaction */}\n {enhancedDetails.lastConfirmedTransactionTimestamp && (\n <div className=\"flex items-start gap-2 text-xs\">\n <CheckCircle className=\"size-3.5 text-muted-foreground mt-0.5 flex-shrink-0\" />\n <div className=\"text-muted-foreground min-w-0 flex-1\">\n <span className=\"font-medium\">{l.lastTransaction}:</span>\n <br />\n <span className=\"text-xs break-words\">\n {formatTimestamp(enhancedDetails.lastConfirmedTransactionTimestamp)}\n </span>\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Warning if relayer is paused or system disabled */}\n {(displayDetails.paused || enhancedDetails?.systemDisabled) && (\n <div className=\"bg-red-50 border border-red-200 rounded-md p-2\">\n <p className=\"text-xs text-red-700 flex items-start gap-1\">\n <AlertCircle className=\"size-3 mt-0.5 flex-shrink-0\" />\n <span className=\"min-w-0 flex-1\">\n {enhancedDetails?.systemDisabled\n ? 'This relayer has been disabled by the system and cannot process transactions.'\n : 'This relayer is currently paused and cannot process transactions.'}\n </span>\n </p>\n </div>\n )}\n </div>\n </div>\n );\n};\n","import { createContext } from 'react';\n\nimport type { NetworkErrorContextValue } from './useNetworkErrors';\n\nexport const NetworkErrorContext = createContext<NetworkErrorContextValue | undefined>(undefined);\n","'use client';\n\nimport { toast } from 'sonner';\nimport { useCallback, useMemo, useRef, useState } from 'react';\n\nimport { NetworkErrorContext } from './NetworkErrorContext';\nimport type { NetworkError, NetworkErrorType } from './useNetworkErrors';\n\ninterface NetworkErrorNotificationProviderProps {\n children: React.ReactNode;\n}\n\n/** Provider component for managing and displaying network error notifications. */\nexport function NetworkErrorNotificationProvider({\n children,\n}: NetworkErrorNotificationProviderProps): React.ReactNode {\n const [errors, setErrors] = useState<NetworkError[]>([]);\n const [openNetworkSettingsHandler, setOpenNetworkSettingsHandler] = useState<\n ((networkId: string) => void) | undefined\n >();\n const errorDedupeRef = useRef<Map<string, number>>(new Map());\n\n const reportNetworkError = useCallback(\n (type: NetworkErrorType, networkId: string, networkName: string, message: string) => {\n // Create a unique key for deduplication\n const dedupeKey = `${type}-${networkId}-${message}`;\n const now = Date.now();\n const lastReported = errorDedupeRef.current.get(dedupeKey);\n\n // Dedupe errors that occur within 5 seconds\n if (lastReported && now - lastReported < 5000) {\n return;\n }\n\n errorDedupeRef.current.set(dedupeKey, now);\n\n const error: NetworkError = {\n id: `${type}-${networkId}-${now}`,\n type,\n networkId,\n networkName,\n message,\n timestamp: now,\n };\n\n setErrors((prev) => {\n const newErrors = [...prev, error];\n return newErrors;\n });\n\n // Show toast notification with action button\n const typeLabel = type === 'rpc' ? 'RPC' : 'Explorer';\n toast.error(`${typeLabel} Error - ${networkName}`, {\n description: message,\n duration: 10000, // Show for 10 seconds\n action: openNetworkSettingsHandler\n ? {\n label: 'Configure',\n onClick: (): void => {\n openNetworkSettingsHandler(networkId);\n },\n }\n : undefined,\n });\n\n // Auto-remove error after 1 minute\n setTimeout(() => {\n setErrors((prev) => prev.filter((e) => e.id !== error.id));\n errorDedupeRef.current.delete(dedupeKey);\n }, 60000);\n },\n [openNetworkSettingsHandler]\n );\n\n const clearError = useCallback((id: string) => {\n setErrors((prev) => prev.filter((e) => e.id !== id));\n }, []);\n\n const clearAllErrors = useCallback(() => {\n setErrors([]);\n errorDedupeRef.current.clear();\n }, []);\n\n const stableSetHandler = useCallback((handler: (networkId: string) => void) => {\n setOpenNetworkSettingsHandler(() => handler);\n }, []);\n\n const value = useMemo(\n () => ({\n errors,\n reportNetworkError,\n clearError,\n clearAllErrors,\n onOpenNetworkSettings: openNetworkSettingsHandler,\n setOpenNetworkSettingsHandler: stableSetHandler,\n }),\n [\n errors,\n reportNetworkError,\n clearError,\n clearAllErrors,\n openNetworkSettingsHandler,\n stableSetHandler,\n ]\n );\n\n return <NetworkErrorContext.Provider value={value}>{children}</NetworkErrorContext.Provider>;\n}\n","'use client';\n\nimport { useCallback, useContext } from 'react';\n\nimport type { RuntimeCapability } from '@openzeppelin/ui-types';\n\nimport { NetworkErrorContext } from './NetworkErrorContext';\n\nexport type NetworkErrorType = 'rpc' | 'explorer';\n\nexport interface NetworkError {\n id: string;\n type: NetworkErrorType;\n networkId: string;\n networkName: string;\n message: string;\n timestamp: number;\n}\n\nexport interface NetworkErrorContextValue {\n errors: NetworkError[];\n reportNetworkError: (\n type: NetworkErrorType,\n networkId: string,\n networkName: string,\n message: string\n ) => void;\n clearError: (id: string) => void;\n clearAllErrors: () => void;\n onOpenNetworkSettings?: (networkId: string) => void;\n setOpenNetworkSettingsHandler: (handler: (networkId: string) => void) => void;\n}\n\n/** Hook to access network error reporting and management functions. */\nexport function useNetworkErrors(): NetworkErrorContextValue {\n const context = useContext(NetworkErrorContext);\n if (!context) {\n throw new Error('useNetworkErrors must be used within NetworkErrorNotificationProvider');\n }\n return context;\n}\n\n/**\n * Hook for reporting network errors for a specific runtime-bound capability\n */\nexport function useNetworkErrorReporter(capability: RuntimeCapability | null): {\n reportRpcError: (message: string) => void;\n reportExplorerError: (message: string) => void;\n} {\n const { reportNetworkError } = useNetworkErrors();\n\n const reportRpcError = useCallback(\n (message: string) => {\n if (!capability) return;\n reportNetworkError(\n 'rpc',\n capability.networkConfig.id,\n capability.networkConfig.name,\n message\n );\n },\n [capability, reportNetworkError]\n );\n\n const reportExplorerError = useCallback(\n (message: string) => {\n if (!capability) return;\n reportNetworkError(\n 'explorer',\n capability.networkConfig.id,\n capability.networkConfig.name,\n message\n );\n },\n [capability, reportNetworkError]\n );\n\n return {\n reportRpcError,\n reportExplorerError,\n };\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\n\nimport type { RuntimeCapability } from '@openzeppelin/ui-types';\n\nimport { useNetworkErrors } from './useNetworkErrors';\n\n/**\n * Creates an adapter proxy that intercepts and reports network errors\n */\nexport function useNetworkErrorAwareAdapter<T extends RuntimeCapability>(\n capability: T | null\n): T | null {\n const { reportNetworkError } = useNetworkErrors();\n const wrappedCapabilityRef = useRef<T | null>(null);\n\n useEffect(() => {\n if (!capability) {\n wrappedCapabilityRef.current = null;\n return;\n }\n\n // Create a proxy that wraps the runtime capability to intercept errors\n const wrappedCapability = new Proxy(capability, {\n get(target, prop, receiver): unknown {\n const value = Reflect.get(target, prop, receiver);\n\n // Wrap async methods that might throw network errors\n if (\n typeof value === 'function' &&\n (prop === 'queryViewFunction' || prop === 'loadContract')\n ) {\n return async (...args: unknown[]) => {\n try {\n return await value.apply(target, args);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n\n // Check if it's an RPC error\n if (\n errorMessage.toLowerCase().includes('rpc') ||\n errorMessage.toLowerCase().includes('network') ||\n errorMessage.toLowerCase().includes('timeout') ||\n errorMessage.toLowerCase().includes('fetch') ||\n errorMessage.toLowerCase().includes('connection')\n ) {\n reportNetworkError(\n 'rpc',\n target.networkConfig.id,\n target.networkConfig.name,\n errorMessage\n );\n }\n\n // Check if it's an explorer error\n if (\n errorMessage.toLowerCase().includes('explorer') ||\n errorMessage.toLowerCase().includes('etherscan') ||\n errorMessage.toLowerCase().includes('api key') ||\n errorMessage.toLowerCase().includes('abi') ||\n errorMessage.toLowerCase().includes('verified')\n ) {\n reportNetworkError(\n 'explorer',\n target.networkConfig.id,\n target.networkConfig.name,\n errorMessage\n );\n }\n\n // Re-throw the error to maintain normal error handling\n throw error;\n }\n };\n }\n\n return value;\n },\n }) as T;\n\n wrappedCapabilityRef.current = wrappedCapability;\n }, [capability, reportNetworkError]);\n\n return wrappedCapabilityRef.current;\n}\n","'use client';\n\nimport { CloudOff, Settings } from 'lucide-react';\nimport { useContext } from 'react';\n\nimport type { NetworkConfig } from '@openzeppelin/ui-types';\nimport { getServiceDisplayName } from '@openzeppelin/ui-utils';\n\nimport { Alert, AlertDescription, AlertTitle } from '../ui/alert';\nimport { Button } from '../ui/button';\nimport { NetworkErrorContext } from './NetworkErrorContext';\n\nexport interface NetworkServiceErrorBannerProps {\n /** The network configuration for which the service connection failed */\n networkConfig: NetworkConfig;\n /** The type of service that failed (e.g., 'rpc', 'explorer', 'indexer') */\n serviceType: string;\n /** Optional custom error message to display */\n errorMessage?: string;\n /** Optional custom title override */\n title?: string;\n /** Optional custom description to show below the error message */\n description?: string;\n /**\n * Optional callback to open network settings dialog.\n * If not provided, will try to use the context from NetworkErrorNotificationProvider.\n * If neither is available, the settings button will not be rendered.\n */\n onOpenNetworkSettings?: (networkId: string) => void;\n}\n\n/**\n * User-friendly banner displayed when a network service connection fails.\n * Works with any service type (RPC, Explorer, Indexer, etc.) and provides\n * a clear explanation of the issue with a call-to-action to open the\n * network settings dialog where users can configure an alternative endpoint.\n *\n * This component can be used with or without the NetworkErrorNotificationProvider:\n * - With provider: The settings handler is obtained from context\n * - Without provider: Pass onOpenNetworkSettings prop directly, or the button won't render\n */\nexport function NetworkServiceErrorBanner({\n networkConfig,\n serviceType,\n errorMessage,\n title,\n description,\n onOpenNetworkSettings: onOpenNetworkSettingsProp,\n}: NetworkServiceErrorBannerProps): React.ReactNode {\n // Try to get handler from context (won't throw if not in provider)\n const context = useContext(NetworkErrorContext);\n const onOpenNetworkSettings = onOpenNetworkSettingsProp ?? context?.onOpenNetworkSettings;\n\n const handleOpenSettings = (): void => {\n onOpenNetworkSettings?.(networkConfig.id);\n };\n\n const serviceName = getServiceDisplayName(serviceType);\n const defaultTitle = `Unable to Connect to ${networkConfig.name}`;\n const defaultDescription = onOpenNetworkSettings\n ? `This could be due to network congestion, rate limiting, or the service being temporarily down. You can configure a custom ${serviceName.toLowerCase()} endpoint in the network settings.`\n : `This could be due to network congestion, rate limiting, or the service being temporarily down.`;\n\n return (\n <Alert variant=\"destructive\" className=\"border-red-500/50 bg-red-50 dark:bg-red-950/20\">\n <CloudOff className=\"h-4 w-4 text-red-600 dark:text-red-400\" />\n <AlertTitle className=\"text-red-900 dark:text-red-100\">{title || defaultTitle}</AlertTitle>\n <AlertDescription className=\"text-red-800 dark:text-red-200\">\n <p className=\"mb-2\">\n {errorMessage ||\n `The ${serviceName.toLowerCase()} for ${networkConfig.name} is currently unavailable or not responding.`}\n </p>\n <p className=\"text-sm mb-3\">{description || defaultDescription}</p>\n {onOpenNetworkSettings && (\n <Button\n onClick={handleOpenSettings}\n variant=\"default\"\n size=\"sm\"\n className=\"bg-red-600 hover:bg-red-700 text-white dark:bg-red-500 dark:hover:bg-red-600\"\n >\n <Settings className=\"mr-2 h-4 w-4\" />\n Configure {serviceName} Settings\n </Button>\n )}\n </AlertDescription>\n </Alert>\n );\n}\n","import { Info } from 'lucide-react';\nimport type React from 'react';\n\nimport {\n getHostedNetworkAvailabilityNoticeCopy,\n isNetworkAvailabilityPolicyActive,\n} from '@openzeppelin/ui-utils';\n\nimport { Alert, AlertDescription, AlertTitle } from '../ui/alert';\n\nexport interface NetworkAvailabilityNoticeProps {\n /** Display name of the hosting app, e.g. \"UI Builder\" */\n appName: string;\n /** GitHub repository URL for self-hosting instructions */\n selfHostRepoUrl: string;\n className?: string;\n}\n\n/**\n * Banner shown when the deployment disables mainnet or specific network IDs.\n * Hidden when no network availability policy is active.\n */\nexport function NetworkAvailabilityNotice({\n appName,\n selfHostRepoUrl,\n className,\n}: NetworkAvailabilityNoticeProps): React.ReactElement | null {\n if (!isNetworkAvailabilityPolicyActive()) {\n return null;\n }\n\n const { title, descriptionBeforeLink, descriptionLinkLabel } =\n getHostedNetworkAvailabilityNoticeCopy(appName);\n\n return (\n <Alert className={className}>\n <Info className=\"h-4 w-4\" />\n <AlertTitle>{title}</AlertTitle>\n <AlertDescription>\n {descriptionBeforeLink}\n <a\n href={selfHostRepoUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"font-medium underline underline-offset-4 hover:text-foreground\"\n >\n {descriptionLinkLabel}\n </a>\n .\n </AlertDescription>\n </Alert>\n );\n}\n","import { useTheme } from 'next-themes';\nimport { Toaster as Sonner, ToasterProps } from 'sonner';\nimport { JSX } from 'react';\n\nconst Toaster = ({ ...props }: ToasterProps): JSX.Element => {\n const { theme = 'system' } = useTheme();\n\n return (\n <Sonner\n theme={theme as ToasterProps['theme']}\n className=\"toaster group\"\n toastOptions={{\n classNames: {\n toast:\n 'group toast group-[.toaster]:bg-gray-900 group-[.toaster]:text-gray-50 group-[.toaster]:border-gray-800 group-[.toaster]:shadow-lg',\n description: 'group-[.toast]:text-gray-400',\n actionButton:\n 'group-[.toast]:bg-white group-[.toast]:text-gray-900 group-[.toast]:hover:bg-gray-100 group-[.toast]:font-medium group-[.toast]:border-0',\n cancelButton:\n 'group-[.toast]:bg-gray-800 group-[.toast]:text-gray-300 group-[.toast]:hover:bg-gray-700',\n error:\n 'group-[.toast]:!bg-red-950 group-[.toast]:!text-red-50 group-[.toast]:!border-red-900',\n },\n }}\n {...props}\n />\n );\n};\n\nexport { Toaster };\n"],"mappings":"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"}
|