@petrarca/sonnet-forms 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/FormFieldWrapper.tsx","../src/formFieldUtils.ts","../src/FormInput.tsx","../src/FormTextarea.tsx","../src/FormNumberInput.tsx","../src/FormCheckbox.tsx","../src/FormSelect.tsx","../src/formSelectUtils.ts","../src/FormMultiSelect.tsx","../src/FormTagsInput.tsx","../src/FormQuantityInput.tsx","../src/FormActions.tsx","../src/ExtraPropertiesCard.tsx","../src/JsonSchemaFormRenderer.tsx","../src/widgets/types.ts","../src/widgets/TextInputWidget.tsx","../src/widgets/TextareaWidget.tsx","../src/widgets/NumberWidget.tsx","../src/widgets/CheckboxWidget.tsx","../src/widgets/SelectWidget.tsx","../src/widgets/TagsInputWidget.tsx","../src/widgets/JsonEditorWidget.tsx","../src/widgets/EntitySelectWidget.tsx","../src/widgets/ObjectWidget.tsx","../src/hooks/useNestedFormContext.ts","../src/NestedFormContext.tsx","../src/templates/DefaultObjectContainerTemplate.tsx","../src/widgets/ArrayWidget.tsx","../src/templates/DefaultArrayItemTemplate.tsx","../src/templates/gridUtils.ts","../src/templates/DefaultArrayHeaderTemplate.tsx","../src/widgets/QuantityWidget.tsx","../src/widgets/DateWidget.tsx","../src/widgets/TimeWidget.tsx","../src/widgets/DateTimeWidget.tsx","../src/widgets/DisplayWidget.tsx","../src/widgets/OneOfWidget.tsx","../src/widgets/widgetResolver.ts","../src/widgets/index.ts","../src/templates/HorizontalArrayItemTemplate.tsx","../src/templates/TabsGroupTemplate.tsx","../src/templates/GroupErrorBadge.tsx","../src/templates/StepperGroupTemplate.tsx","../src/templates/SectionsGroupTemplate.tsx","../src/templates/index.ts","../src/FormFieldRenderer.tsx","../src/hooks/useFormEngine.ts","../src/hooks/orderProperties.ts","../src/hooks/useResolvedSchema.ts"],"sourcesContent":["/**\n * FormFieldWrapper - Shared label / description / error chrome for form fields.\n *\n * Eliminates duplication across FormInput, FormNumberInput, FormQuantityInput,\n * etc. Each field component renders its control as `children` and delegates\n * the surrounding chrome here.\n *\n * Supports two modes:\n * - Normal: label, children, description, error displayed vertically\n * - Compact: suppresses label, description, error text (for grid layouts)\n */\n\nimport React from \"react\";\nimport { cn } from \"@petrarca/sonnet-core\";\n\nexport interface FormFieldWrapperProps {\n /** Field id -- wired to the label's htmlFor */\n inputId: string;\n /** Visible label text (false = explicitly hidden) */\n label?: string | false;\n /** Helper text shown below the control */\n description?: string;\n /** Validation error message (takes precedence over description for aria-describedby) */\n error?: string;\n /** Shows a required asterisk next to the label */\n required?: boolean;\n /**\n * Compact mode -- suppresses label, description, and error text so the\n * cell height stays fixed in horizontal grid layouts. Error state is\n * still communicated via the control's own styling (e.g. red border).\n */\n compact?: boolean;\n /**\n * Label placement: \"top\" (default) renders the label above the control;\n * \"start\" renders the label inline on the reading-start side (RTL-safe: left\n * in LTR, right in RTL). Logical values follow the MUI convention.\n */\n labelPlacement?: \"top\" | \"start\";\n /** Additional class name for the outer wrapper div */\n className?: string;\n /** The form control(s) */\n children: React.ReactNode;\n}\n\n/**\n * FormFieldWrapper renders label, children (the control), description, and\n * error in the standard vertical layout used by all form field components.\n */\nexport function FormFieldWrapper({\n inputId,\n label,\n description,\n error,\n required,\n compact,\n labelPlacement = \"top\",\n className,\n children,\n}: FormFieldWrapperProps) {\n if (compact) return <div className={className}>{children}</div>;\n\n const labelEl = !!label && (\n <label\n htmlFor={inputId}\n className=\"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n >\n {label}\n {required && <span className=\"ml-1 text-destructive\">*</span>}\n </label>\n );\n\n const descriptionEl = description && (\n <p id={`${inputId}-description`} className=\"text-sm text-muted-foreground\">\n {description}\n </p>\n );\n\n const errorEl = error && (\n <p id={`${inputId}-error`} className=\"text-sm font-medium text-destructive\">\n {error}\n </p>\n );\n\n // \"start\": label beside the control on the reading-start side, kept tight\n // together. Uses flex so the label flips under dir=rtl. The control box fills\n // its slot (w-full) so an outer x-ui-width wrapper -- or the flow row --\n // governs the width.\n if (labelPlacement === \"start\" && !!label) {\n return (\n <div className={cn(\"flex items-center gap-2\", className)}>\n <div className=\"shrink-0 whitespace-nowrap\">{labelEl}</div>\n <div className=\"w-full min-w-0 space-y-1\">\n {descriptionEl}\n {children}\n {errorEl}\n </div>\n </div>\n );\n }\n\n return (\n <div className={cn(\"space-y-2\", className)}>\n {labelEl}\n {descriptionEl}\n {children}\n {errorEl}\n </div>\n );\n}\n","/**\n * Shared utility functions for form field components.\n * Kept separate from FormFieldWrapper so the wrapper file exports only\n * components (required for React fast-refresh).\n */\n\n/**\n * Returns the correct aria-describedby id for a form control:\n * - error id when there is an error (screen readers announce errors immediately)\n * - description id when there is only a description\n * - undefined when neither is present\n */\nexport function getAriaDescribedBy(\n inputId: string,\n error: string | undefined,\n description: string | undefined,\n): string | undefined {\n if (error) return `${inputId}-error`;\n if (description) return `${inputId}-description`;\n return undefined;\n}\n\n/**\n * Compact-aware version of getAriaDescribedBy.\n * In compact mode, label/description/error text is not rendered, so\n * aria-describedby should be undefined.\n */\nexport function getAriaDescribedByCompact(\n inputId: string,\n error: string | undefined,\n description: string | undefined,\n compact: boolean | undefined,\n): string | undefined {\n if (compact) return undefined;\n return getAriaDescribedBy(inputId, error, description);\n}\n\n/**\n * In compact mode, when label text is hidden, expose it as aria-label\n * so screen readers still announce the field purpose.\n */\nexport function getCompactAriaLabel(\n label: string | false | undefined,\n compact: boolean | undefined,\n): string | undefined {\n if (compact && label) return String(label);\n return undefined;\n}\n\n/**\n * In compact mode, expose the error as a native tooltip so sighted users\n * can hover to see the validation message.\n */\nexport function getCompactTitle(\n error: string | undefined,\n compact: boolean | undefined,\n): string | undefined {\n if (compact && error) return error;\n return undefined;\n}\n\n/**\n * Resolve a `label?: string | false` prop into `string | undefined` for\n * FormFieldWrapper, which does not accept `false` directly.\n * `false` means \"explicitly hidden\"; `undefined` means \"not provided\".\n */\nexport function resolveFieldLabel(\n label: string | false | undefined,\n): string | undefined {\n if (label === false) return undefined;\n return label ?? undefined;\n}\n","/**\n * FormInput - Input wrapper with label, description, and error support\n *\n * Wraps shadcn Input with form field features to match Mantine TextInput API:\n * - Label with required indicator\n * - Description text\n * - Error message display\n * - Proper accessibility attributes\n */\n\nimport React, { useId } from \"react\";\nimport { Input } from \"@petrarca/sonnet-ui\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport {\n getAriaDescribedByCompact,\n getCompactAriaLabel,\n getCompactTitle,\n} from \"./formFieldUtils\";\n\nexport interface FormInputProps\n extends React.ComponentPropsWithoutRef<typeof Input> {\n /** Input label (false = hide label) */\n label?: string | false;\n /** Description text shown below label */\n description?: string;\n /** Error message to display */\n error?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Additional class name for the wrapper */\n wrapperClassName?: string;\n /** Right section content (e.g., icons, buttons) */\n rightSection?: React.ReactNode;\n /** Width of the right section in pixels (for padding adjustment) */\n rightSectionWidth?: number;\n /**\n * Compact mode -- suppresses label, description, and error text so the\n * cell height stays fixed in horizontal grid layouts. Error state is\n * still communicated via a red border on the input.\n */\n compact?: boolean;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n}\n\n/**\n * FormInput component with label, description, and error handling\n */\nexport const FormInput = React.forwardRef<HTMLInputElement, FormInputProps>(\n (\n {\n label,\n description,\n error,\n required,\n wrapperClassName,\n className,\n id,\n rightSection,\n rightSectionWidth,\n compact,\n labelPlacement,\n ...props\n },\n ref,\n ) => {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n\n const paddingStyle = rightSectionWidth\n ? { paddingRight: `${rightSectionWidth}px` }\n : undefined;\n\n return (\n <FormFieldWrapper\n inputId={inputId}\n label={label === false ? undefined : label}\n description={description}\n error={error}\n required={required}\n compact={compact}\n labelPlacement={labelPlacement}\n className={wrapperClassName}\n >\n <div className=\"relative\">\n <Input\n id={inputId}\n ref={ref}\n required={required}\n style={paddingStyle}\n className={cn(\n error && \"border-destructive focus-visible:ring-destructive\",\n className,\n )}\n aria-invalid={error ? \"true\" : \"false\"}\n aria-describedby={getAriaDescribedByCompact(\n inputId,\n error,\n description,\n compact,\n )}\n aria-label={getCompactAriaLabel(label, compact)}\n title={getCompactTitle(error, compact)}\n {...props}\n />\n {rightSection && (\n <div className=\"absolute top-1/2 -translate-y-1/2 right-2 flex items-center gap-1\">\n {rightSection}\n </div>\n )}\n </div>\n </FormFieldWrapper>\n );\n },\n);\n\nFormInput.displayName = \"FormInput\";\n","/**\n * FormTextarea - Textarea wrapper with label, description, error, and autosize support\n *\n * Wraps shadcn Textarea with form field features to match Mantine Textarea API:\n * - Label with required indicator\n * - Description text\n * - Error message display\n * - Auto-resize functionality (via useEffect)\n * - Proper accessibility attributes\n */\n\nimport React, { useEffect, useId, useRef } from \"react\";\nimport { Textarea } from \"@petrarca/sonnet-ui\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport { getAriaDescribedBy } from \"./formFieldUtils\";\n\nexport interface FormTextareaProps\n extends React.ComponentPropsWithoutRef<typeof Textarea> {\n /** Textarea label (false = hide label) */\n label?: string | false;\n /** Description text shown below label */\n description?: string;\n /** Error message to display */\n error?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Additional class name for the wrapper */\n wrapperClassName?: string;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n /** Enable auto-resize behavior (default: false) */\n autosize?: boolean;\n /** Minimum number of rows when autosize is enabled (default: 3) */\n minRows?: number;\n /** Right section content (e.g., action buttons) */\n rightSection?: React.ReactNode;\n /** Width of the right section in pixels (for padding adjustment) */\n rightSectionWidth?: number;\n}\n\n// -- Hooks ----------------------------------------------------------------\n\n/** Merge a forwarded ref with an internal ref. */\nfunction useMergedRef(\n forwardedRef: React.ForwardedRef<HTMLTextAreaElement>,\n internalRef: React.RefObject<HTMLTextAreaElement | null>,\n) {\n return (element: HTMLTextAreaElement | null) => {\n internalRef.current = element;\n if (typeof forwardedRef === \"function\") {\n forwardedRef(element);\n } else if (forwardedRef) {\n forwardedRef.current = element;\n }\n };\n}\n\n/** Auto-resize the textarea to fit its content. */\nfunction useAutoResize(\n ref: React.RefObject<HTMLTextAreaElement | null>,\n value: React.ComponentPropsWithoutRef<typeof Textarea>[\"value\"],\n autosize: boolean,\n minRows: number,\n) {\n useEffect(() => {\n if (!autosize || !ref.current) return;\n const textarea = ref.current;\n textarea.style.height = \"auto\";\n const newHeight = Math.max(textarea.scrollHeight, minRows * 24);\n textarea.style.height = `${newHeight}px`;\n }, [value, autosize, minRows, ref]);\n}\n\n// -- Helpers --------------------------------------------------------------\n\n/** Build the textarea className from state flags. */\nfunction textareaClassName(\n error: string | undefined,\n autosize: boolean,\n className: string | undefined,\n) {\n return cn(\n error && \"border-destructive focus-visible:ring-destructive\",\n autosize && \"resize-none overflow-hidden\",\n \"h-full\",\n className,\n );\n}\n\n// -- FormTextarea ---------------------------------------------------------\n\n/**\n * FormTextarea component with label, description, error, and autosize handling\n */\nexport const FormTextarea = React.forwardRef<\n HTMLTextAreaElement,\n FormTextareaProps\n>((allProps, ref) => {\n const {\n label,\n description,\n error,\n required,\n wrapperClassName,\n labelPlacement,\n className,\n id,\n value,\n onChange,\n rightSection,\n rightSectionWidth,\n // Destructured out so they are not spread onto the DOM textarea below;\n // these are component-level props, not valid HTML attributes.\n autosize: autosizeProp,\n minRows: minRowsProp,\n ...props\n } = allProps;\n const autosize = autosizeProp ?? false;\n const minRows = minRowsProp ?? 3;\n\n const generatedId = useId();\n const textareaId = id ?? generatedId;\n const internalRef = useRef<HTMLTextAreaElement | null>(null);\n const setRefs = useMergedRef(ref, internalRef);\n\n useAutoResize(internalRef, value, autosize, minRows);\n\n const paddingStyle = rightSectionWidth\n ? { paddingRight: `${rightSectionWidth}px` }\n : undefined;\n\n const effectiveRows = autosize ? minRows : props.rows;\n const resolvedLabel = label === false ? undefined : label;\n\n return (\n <FormFieldWrapper\n inputId={textareaId}\n label={resolvedLabel}\n description={description}\n error={error}\n required={required}\n labelPlacement={labelPlacement}\n className={cn(\"flex flex-col\", wrapperClassName)}\n >\n <div className=\"relative flex-1 min-h-0\">\n <Textarea\n id={textareaId}\n ref={setRefs}\n value={value}\n onChange={onChange}\n required={required}\n rows={effectiveRows}\n className={textareaClassName(error, autosize, className)}\n style={paddingStyle}\n aria-invalid={error ? \"true\" : \"false\"}\n aria-describedby={getAriaDescribedBy(textareaId, error, description)}\n {...props}\n />\n {rightSection && (\n <div className=\"absolute top-2 right-2 flex items-start gap-1\">\n {rightSection}\n </div>\n )}\n </div>\n </FormFieldWrapper>\n );\n});\n\nFormTextarea.displayName = \"FormTextarea\";\n","/**\n * FormNumberInput - Number input wrapper with label, description, error, and numeric constraints.\n */\n\nimport React, { useId } from \"react\";\nimport { Input } from \"@petrarca/sonnet-ui\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport { getAriaDescribedBy } from \"./formFieldUtils\";\n\nexport interface FormNumberInputProps {\n /** Input value */\n value?: number | string;\n /** Input label */\n label?: string;\n /** Description text shown below input */\n description?: string;\n /** Error message to display */\n error?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Whether the input is disabled */\n disabled?: boolean;\n /** Whether the input is read-only */\n readOnly?: boolean;\n /** Minimum value */\n min?: number;\n /** Maximum value */\n max?: number;\n /** Step increment/decrement value */\n step?: number;\n /** Allow decimal values (if false, only integers) */\n allowDecimal?: boolean;\n /** Change handler - receives number or undefined */\n onChange?: (value: number | undefined) => void;\n /** Blur handler */\n onBlur?: React.FocusEventHandler<HTMLInputElement>;\n /** Auto-focus on mount */\n autoFocus?: boolean;\n /** Additional class name for the wrapper */\n wrapperClassName?: string;\n /** Additional class name for the input */\n className?: string;\n /** Input ID */\n id?: string;\n /** Input name */\n name?: string;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n}\n\nexport const FormNumberInput = React.forwardRef<\n HTMLInputElement,\n FormNumberInputProps\n>(\n (\n {\n value,\n label,\n description,\n error,\n placeholder,\n required,\n disabled,\n readOnly,\n min,\n max,\n step,\n allowDecimal = true,\n onChange,\n onBlur,\n autoFocus,\n wrapperClassName,\n className,\n id,\n name,\n labelPlacement,\n },\n ref,\n ) => {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!onChange) return;\n const val = e.target.value;\n if (val === \"\" || val === undefined) {\n onChange(undefined);\n } else {\n const numVal = parseFloat(val);\n if (!isNaN(numVal)) onChange(numVal);\n }\n };\n\n const displayValue =\n value !== undefined && value !== null ? String(value) : \"\";\n\n return (\n <FormFieldWrapper\n inputId={inputId}\n label={label}\n description={description}\n error={error}\n required={required}\n labelPlacement={labelPlacement}\n className={wrapperClassName}\n >\n <Input\n id={inputId}\n name={name}\n ref={ref}\n type=\"number\"\n inputMode=\"numeric\"\n value={displayValue}\n onChange={handleChange}\n onBlur={onBlur}\n placeholder={placeholder}\n disabled={disabled}\n readOnly={readOnly}\n autoFocus={autoFocus}\n min={min}\n max={max}\n step={step ?? (allowDecimal ? \"any\" : 1)}\n className={cn(error && \"border-destructive\", className)}\n aria-invalid={error ? \"true\" : \"false\"}\n aria-describedby={getAriaDescribedBy(inputId, error, description)}\n aria-required={required}\n />\n </FormFieldWrapper>\n );\n },\n);\n\nFormNumberInput.displayName = \"FormNumberInput\";\n","/**\n * FormCheckbox - Checkbox wrapper with label, description, error, and indeterminate support\n *\n * Wraps shadcn Checkbox with form field features to match Mantine Checkbox API:\n * - Inline label (checkbox + label on same line)\n * - Description text\n * - Error message display\n * - Indeterminate state support (tri-state)\n * - Proper accessibility attributes\n */\n\nimport React, { useId } from \"react\";\nimport { Checkbox } from \"@petrarca/sonnet-ui\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport {\n getAriaDescribedByCompact,\n getCompactAriaLabel,\n getCompactTitle,\n} from \"./formFieldUtils\";\n\nexport interface FormCheckboxProps {\n /** Checkbox checked state (boolean or 'indeterminate') */\n checked?: boolean | \"indeterminate\";\n /** Checkbox label (displayed inline, false = hide label) */\n label?: string | false;\n /** Description text shown below checkbox */\n description?: string;\n /** Error message to display */\n error?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Whether the checkbox is disabled */\n disabled?: boolean;\n /** Whether the checkbox is read-only */\n readOnly?: boolean;\n /** Change handler */\n onChange?: (checked: boolean | \"indeterminate\") => void;\n /** Blur handler */\n onBlur?: React.FocusEventHandler<HTMLButtonElement>;\n /** Auto-focus on mount */\n autoFocus?: boolean;\n /** Additional class name for the wrapper */\n wrapperClassName?: string;\n /** Additional class name for the checkbox */\n className?: string;\n /** Input ID */\n id?: string;\n /**\n * Compact mode -- suppresses label, description, and error text so the\n * cell height stays fixed in horizontal grid layouts. Error state is\n * still communicated via a red border on the checkbox.\n */\n compact?: boolean;\n}\n\n// -- Sub-components --------------------------------------------------------\n\ninterface CheckboxLabelProps {\n htmlFor: string;\n label: string | false | undefined;\n required: boolean | undefined;\n disabled: boolean | undefined;\n compact: boolean | undefined;\n}\n\nfunction CheckboxLabel({\n htmlFor,\n label,\n required,\n disabled,\n compact,\n}: CheckboxLabelProps) {\n if (compact || !label) return null;\n return (\n <label\n htmlFor={htmlFor}\n className={cn(\n \"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n disabled && \"opacity-70 cursor-not-allowed\",\n )}\n >\n {label}\n {required && <span className=\"text-destructive ml-1\">*</span>}\n </label>\n );\n}\n\ninterface CheckboxChromeProps {\n inputId: string;\n description: string | undefined;\n error: string | undefined;\n compact: boolean | undefined;\n}\n\nfunction CheckboxChrome({\n inputId,\n description,\n error,\n compact,\n}: CheckboxChromeProps) {\n if (compact) return null;\n return (\n <>\n {description && (\n <p\n id={`${inputId}-description`}\n className=\"text-sm text-muted-foreground ml-6\"\n >\n {description}\n </p>\n )}\n {error && (\n <p id={`${inputId}-error`} className=\"text-sm text-destructive ml-6\">\n {error}\n </p>\n )}\n </>\n );\n}\n\n// -- FormCheckbox ----------------------------------------------------------\n\n/**\n * FormCheckbox component with label, description, error, and indeterminate handling\n */\nexport const FormCheckbox = React.forwardRef<\n HTMLButtonElement,\n FormCheckboxProps\n>(\n (\n {\n checked,\n label,\n description,\n error,\n required,\n disabled,\n readOnly,\n onChange,\n onBlur,\n autoFocus,\n wrapperClassName,\n className,\n id,\n compact,\n },\n ref,\n ) => {\n const generatedId = useId();\n const checkboxId = id ?? generatedId;\n\n const handleCheckedChange = (newChecked: boolean | \"indeterminate\") => {\n if (!readOnly && onChange) {\n onChange(newChecked);\n }\n };\n\n return (\n <div className={cn(!compact && \"space-y-2\", wrapperClassName)}>\n <div className=\"flex items-start space-x-2\">\n <Checkbox\n id={checkboxId}\n ref={ref}\n checked={checked}\n onCheckedChange={handleCheckedChange}\n onBlur={onBlur}\n disabled={disabled || readOnly}\n autoFocus={autoFocus}\n className={cn(error && \"border-destructive\", className)}\n aria-invalid={error ? \"true\" : \"false\"}\n aria-describedby={getAriaDescribedByCompact(\n checkboxId,\n error,\n description,\n compact,\n )}\n aria-label={getCompactAriaLabel(label, compact)}\n title={getCompactTitle(error, compact)}\n />\n <CheckboxLabel\n htmlFor={checkboxId}\n label={label}\n required={required}\n disabled={disabled}\n compact={compact}\n />\n </div>\n <CheckboxChrome\n inputId={checkboxId}\n description={description}\n error={error}\n compact={compact}\n />\n </div>\n );\n },\n);\n\nFormCheckbox.displayName = \"FormCheckbox\";\n","/**\n * FormSelect - Searchable single-select dropdown with form field wrapper\n *\n * Composable select component using Popover + Command for searchable,\n * keyboard-navigable dropdown. Follows Form wrapper pattern with\n * label, description, error support.\n */\n\nimport * as React from \"react\";\nimport { Check, ChevronsUpDown, Plus, X } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"@petrarca/sonnet-ui\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@petrarca/sonnet-ui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport {\n getAriaDescribedByCompact,\n getCompactAriaLabel,\n getCompactTitle,\n} from \"./formFieldUtils\";\nimport { canCreateFromSearch } from \"./formSelectUtils\";\nimport type { SelectOption } from \"./widgets/types\";\n\nexport type { SelectOption };\n\nexport interface FormSelectProps {\n // Form wrapper props (consistent with FormInput/FormTextarea)\n label?: string | false;\n description?: string;\n error?: string;\n required?: boolean;\n wrapperClassName?: string;\n /**\n * Compact mode -- suppresses label, description, and error text so the\n * cell height stays fixed in horizontal grid layouts. Error state is\n * still communicated via a red border on the trigger button.\n */\n compact?: boolean;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n\n // Select-specific props\n options: SelectOption[];\n value?: string | null;\n onChange?: (value: string | null) => void;\n onBlur?: () => void;\n placeholder?: string;\n searchPlaceholder?: string;\n emptyMessage?: string;\n clearable?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n loading?: boolean;\n className?: string;\n id?: string;\n name?: string;\n autoFocus?: boolean;\n /**\n * Allow creating a new option from the search text. When set, a\n * `+ Create \"<text>\"` item appears at the bottom of the list whenever the\n * trimmed search matches no existing option label (case-insensitive).\n * Selecting it calls `onCreate(text)`. Requires `onCreate`.\n */\n allowCreate?: boolean;\n /** Called with the trimmed search text when the create item is chosen. */\n onCreate?: (label: string) => void;\n}\n\n// Hook: encapsulate popover state + event handlers.\nfunction useSelectState(\n value: string | null | undefined,\n onChange: ((value: string | null) => void) | undefined,\n onBlur: (() => void) | undefined,\n onCreate: ((label: string) => void) | undefined,\n clearable: boolean,\n) {\n const [open, setOpen] = React.useState(false);\n const [searchQuery, setSearchQuery] = React.useState(\"\");\n\n const handleSelect = (selectedValue: string) => {\n // Re-clicking the selected value deselects it, but only when clearable.\n const next = clearable && selectedValue === value ? null : selectedValue;\n onChange?.(next);\n setOpen(false);\n setSearchQuery(\"\");\n };\n\n const handleCreate = (label: string) => {\n onCreate?.(label);\n setOpen(false);\n setSearchQuery(\"\");\n };\n\n const handleClear = (e: React.MouseEvent) => {\n e.stopPropagation();\n onChange?.(null);\n };\n\n const handleOpenChange = (newOpen: boolean) => {\n setOpen(newOpen);\n if (newOpen) return;\n setSearchQuery(\"\");\n onBlur?.();\n };\n\n return {\n open,\n searchQuery,\n setSearchQuery,\n handleSelect,\n handleCreate,\n handleClear,\n handleOpenChange,\n };\n}\n\n// Trigger trailing icons (clear + chevron).\nfunction TriggerIcons({\n showClear,\n onClear,\n}: {\n showClear: boolean;\n onClear: (e: React.MouseEvent) => void;\n}) {\n return (\n <div className=\"flex items-center gap-1\">\n {showClear && (\n <X className=\"h-4 w-4 opacity-50 hover:opacity-100\" onClick={onClear} />\n )}\n <ChevronsUpDown className=\"h-4 w-4 shrink-0 opacity-50\" />\n </div>\n );\n}\n\n// Dropdown content extracted to keep FormSelect under complexity 10.\n// Not a Radix trigger -- no ref forwarding needed.\nfunction SelectDropdown({\n searchPlaceholder,\n searchQuery,\n onSearchChange,\n loading,\n emptyMessage,\n options,\n value,\n onSelect,\n allowCreate = false,\n onCreate,\n}: {\n searchPlaceholder: string;\n searchQuery: string;\n onSearchChange: (value: string) => void;\n loading: boolean;\n emptyMessage: string;\n options: SelectOption[];\n value: string | null | undefined;\n onSelect: (value: string) => void;\n allowCreate?: boolean;\n onCreate?: (label: string) => void;\n}) {\n const showCreate = canCreateFromSearch(allowCreate, searchQuery, options);\n return (\n <Command shouldFilter={false}>\n <CommandInput\n placeholder={searchPlaceholder}\n value={searchQuery}\n onValueChange={onSearchChange}\n />\n <CommandList>\n {!showCreate && (\n <CommandEmpty>{loading ? \"Loading...\" : emptyMessage}</CommandEmpty>\n )}\n <CommandGroup>\n {options\n .filter((option) =>\n option.label.toLowerCase().includes(searchQuery.toLowerCase()),\n )\n .map((option) => (\n <CommandItem\n key={option.value}\n value={option.value}\n onSelect={onSelect}\n >\n <Check\n className={cn(\n \"mr-2 h-4 w-4\",\n value === option.value ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n {option.label}\n </CommandItem>\n ))}\n {showCreate && (\n <CommandItem\n key=\"__create__\"\n value={`__create__${searchQuery}`}\n onSelect={() => onCreate?.(searchQuery.trim())}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n Create &ldquo;{searchQuery.trim()}&rdquo;\n </CommandItem>\n )}\n </CommandGroup>\n </CommandList>\n </Command>\n );\n}\n\n// Resolve optional props to concrete values.\nfunction resolveDefaults(props: FormSelectProps) {\n return {\n placeholder: props.placeholder ?? \"Select...\",\n searchPlaceholder: props.searchPlaceholder ?? \"Search...\",\n emptyMessage: props.emptyMessage ?? \"No results found\",\n clearable: props.clearable ?? true,\n disabled: props.disabled ?? false,\n readOnly: props.readOnly ?? false,\n loading: props.loading ?? false,\n };\n}\n\nexport function FormSelect(props: FormSelectProps) {\n const {\n label,\n description,\n error,\n required,\n wrapperClassName,\n compact,\n labelPlacement,\n options,\n value,\n onChange,\n onBlur,\n className,\n id,\n autoFocus,\n allowCreate,\n onCreate,\n } = props;\n const {\n placeholder,\n searchPlaceholder,\n emptyMessage,\n clearable,\n disabled,\n readOnly,\n loading,\n } = resolveDefaults(props);\n\n const generatedId = React.useId();\n const selectId = id ?? generatedId;\n\n const {\n open,\n searchQuery,\n setSearchQuery,\n handleSelect,\n handleCreate,\n handleClear,\n handleOpenChange,\n } = useSelectState(value, onChange, onBlur, onCreate, clearable);\n\n const selectedOption = options.find((opt) => opt.value === value);\n const isDisabled = disabled || readOnly || loading;\n\n return (\n <FormFieldWrapper\n inputId={selectId}\n label={label}\n description={description}\n error={error}\n required={required}\n compact={compact}\n labelPlacement={labelPlacement}\n className={wrapperClassName}\n >\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <Button\n id={selectId}\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n aria-invalid={error ? \"true\" : \"false\"}\n aria-describedby={getAriaDescribedByCompact(\n selectId,\n error,\n description,\n compact,\n )}\n aria-label={getCompactAriaLabel(label, compact)}\n title={getCompactTitle(error, compact)}\n className={cn(\n \"w-full justify-between\",\n !selectedOption && \"text-muted-foreground\",\n error && \"border-destructive\",\n className,\n )}\n disabled={isDisabled}\n autoFocus={autoFocus}\n >\n <span className=\"truncate\">\n {selectedOption ? selectedOption.label : placeholder}\n </span>\n <TriggerIcons\n showClear={clearable && !!value && !isDisabled}\n onClear={handleClear}\n />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className=\"w-[--radix-popover-trigger-width] p-0\"\n align=\"start\"\n >\n <SelectDropdown\n searchPlaceholder={searchPlaceholder}\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n loading={loading}\n emptyMessage={emptyMessage}\n options={options}\n value={value}\n onSelect={handleSelect}\n allowCreate={allowCreate}\n onCreate={handleCreate}\n />\n </PopoverContent>\n </Popover>\n </FormFieldWrapper>\n );\n}\n","/**\n * Pure helpers for FormSelect, kept separate from the component module so they\n * can be unit-tested and shared without tripping react-refresh's\n * component-only-export rule.\n */\n\nimport type { SelectOption } from \"./widgets/types\";\n\n/**\n * Whether to offer a \"create\" item in a creatable select: creation is enabled,\n * the trimmed search is non-empty, and no existing option's label matches the\n * search (case-insensitive).\n */\nexport function canCreateFromSearch(\n allowCreate: boolean,\n searchQuery: string,\n options: SelectOption[],\n): boolean {\n const trimmed = searchQuery.trim();\n if (!allowCreate || trimmed.length === 0) return false;\n const lower = trimmed.toLowerCase();\n return !options.some((o) => o.label.toLowerCase() === lower);\n}\n","/**\n * FormMultiSelect - Searchable multi-select dropdown with badges\n *\n * Multi-select component using Popover + Command with badge display\n * for selected items. Follows Form wrapper pattern with label,\n * description, error support.\n */\n\nimport * as React from \"react\";\nimport { Check, ChevronsUpDown, X } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport { Badge, badgeVariants } from \"@petrarca/sonnet-ui\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"@petrarca/sonnet-ui\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@petrarca/sonnet-ui\";\nimport type { VariantProps } from \"class-variance-authority\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport { resolveFieldLabel } from \"./formFieldUtils\";\nimport type { SelectOption } from \"./widgets/types\";\n\ntype BadgeColor = NonNullable<VariantProps<typeof badgeVariants>[\"badgeColor\"]>;\n\nexport type { SelectOption };\n\nexport interface FormMultiSelectProps {\n // Form wrapper props (consistent with FormInput/FormTextarea)\n label?: string | false;\n description?: string;\n error?: string;\n required?: boolean;\n wrapperClassName?: string;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n\n // Multi-select specific props\n options: SelectOption[];\n value?: string[];\n onChange?: (value: string[]) => void;\n onBlur?: () => void;\n placeholder?: string;\n searchPlaceholder?: string;\n emptyMessage?: string;\n clearable?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n loading?: boolean;\n className?: string;\n id?: string;\n name?: string;\n autoFocus?: boolean;\n maxDisplay?: number; // Max badges to display before showing \"+X more\"\n badgeColor?: BadgeColor;\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\ninterface RemovableBadgeProps {\n option: SelectOption;\n isDisabled: boolean;\n badgeColor: BadgeColor | undefined;\n onRemove: (value: string, e: React.MouseEvent | React.KeyboardEvent) => void;\n}\n\nfunction RemovableBadge({\n option,\n isDisabled,\n badgeColor,\n onRemove,\n}: RemovableBadgeProps) {\n return (\n <Badge variant=\"secondary\" badgeColor={badgeColor} className=\"mr-1\">\n {option.label}\n {!isDisabled && (\n // Rendered as a role=\"button\" span, not a <button>: this badge lives\n // inside the combobox trigger <button>, and a button cannot be nested\n // in a button (invalid HTML / hydration error). The span keeps click +\n // Enter/Space activation and a focus ring.\n <span\n role=\"button\"\n tabIndex={0}\n aria-label={`Remove ${option.label}`}\n className=\"ml-1 inline-flex cursor-pointer ring-offset-background rounded-full outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\"\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onRemove(option.value, e);\n }\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}\n onClick={(e) => onRemove(option.value, e)}\n >\n <X className=\"h-3 w-3 text-muted-foreground hover:text-foreground\" />\n </span>\n )}\n </Badge>\n );\n}\n\ninterface SelectedBadgesProps {\n selectedOptions: SelectOption[];\n effectiveMaxDisplay: number;\n expanded: boolean;\n maxDisplay: number;\n isDisabled: boolean;\n badgeColor: BadgeColor | undefined;\n placeholder: string;\n onRemove: (value: string, e: React.MouseEvent | React.KeyboardEvent) => void;\n onExpand: (e: React.MouseEvent) => void;\n onCollapse: (e: React.MouseEvent) => void;\n}\n\nfunction SelectedBadges({\n selectedOptions,\n effectiveMaxDisplay,\n expanded,\n maxDisplay,\n isDisabled,\n badgeColor,\n placeholder,\n onRemove,\n onExpand,\n onCollapse,\n}: SelectedBadgesProps) {\n if (selectedOptions.length === 0) {\n return <span className=\"text-muted-foreground\">{placeholder}</span>;\n }\n\n const displayedBadges = selectedOptions.slice(0, effectiveMaxDisplay);\n const remainingCount = selectedOptions.length - effectiveMaxDisplay;\n const showCollapse =\n expanded && remainingCount <= 0 && selectedOptions.length > maxDisplay;\n\n return (\n <>\n {displayedBadges.map((option) => (\n <RemovableBadge\n key={option.value}\n option={option}\n isDisabled={isDisabled}\n badgeColor={badgeColor}\n onRemove={onRemove}\n />\n ))}\n {remainingCount > 0 && (\n <Badge\n variant=\"secondary\"\n badgeColor={badgeColor}\n className=\"mr-1 cursor-pointer hover:bg-secondary/80\"\n onClick={onExpand}\n >\n +{remainingCount} more\n </Badge>\n )}\n {showCollapse && (\n <Badge\n variant=\"secondary\"\n badgeColor={badgeColor}\n className=\"mr-1 cursor-pointer hover:bg-secondary/80\"\n onClick={onCollapse}\n >\n Show less\n </Badge>\n )}\n </>\n );\n}\n\ninterface MultiSelectDropdownProps {\n searchPlaceholder: string;\n searchQuery: string;\n onSearchChange: (value: string) => void;\n loading: boolean;\n emptyMessage: string;\n options: SelectOption[];\n value: string[];\n onSelect: (value: string) => void;\n}\n\nfunction MultiSelectDropdown({\n searchPlaceholder,\n searchQuery,\n onSearchChange,\n loading,\n emptyMessage,\n options,\n value,\n onSelect,\n}: MultiSelectDropdownProps) {\n return (\n <Command shouldFilter={false}>\n <CommandInput\n placeholder={searchPlaceholder}\n value={searchQuery}\n onValueChange={onSearchChange}\n />\n <CommandList>\n <CommandEmpty>{loading ? \"Loading...\" : emptyMessage}</CommandEmpty>\n <CommandGroup>\n {options\n .filter((option) =>\n option.label.toLowerCase().includes(searchQuery.toLowerCase()),\n )\n .map((option) => (\n <CommandItem\n key={option.value}\n value={option.value}\n onSelect={onSelect}\n >\n <Check\n className={cn(\n \"mr-2 h-4 w-4\",\n value.includes(option.value) ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n {option.label}\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Hook: encapsulate popover state + handlers\n// ---------------------------------------------------------------------------\n\nfunction useMultiSelectState(\n value: string[],\n onChange: ((value: string[]) => void) | undefined,\n onBlur: (() => void) | undefined,\n) {\n const [open, setOpen] = React.useState(false);\n const [searchQuery, setSearchQuery] = React.useState(\"\");\n const [expanded, setExpanded] = React.useState(false);\n\n const handleSelect = (selectedValue: string) => {\n const newValue = value.includes(selectedValue)\n ? value.filter((v) => v !== selectedValue)\n : [...value, selectedValue];\n onChange?.(newValue);\n };\n\n const handleRemove = (\n valueToRemove: string,\n e: React.MouseEvent | React.KeyboardEvent,\n ) => {\n e.stopPropagation();\n onChange?.(value.filter((v) => v !== valueToRemove));\n };\n\n const handleClearAll = (e: React.MouseEvent) => {\n e.stopPropagation();\n onChange?.([]);\n };\n\n const handleOpenChange = (newOpen: boolean) => {\n setOpen(newOpen);\n if (newOpen) return;\n setSearchQuery(\"\");\n setExpanded(false);\n onBlur?.();\n };\n\n const handleExpand = (e: React.MouseEvent) => {\n e.stopPropagation();\n setExpanded(true);\n };\n\n const handleCollapse = (e: React.MouseEvent) => {\n e.stopPropagation();\n setExpanded(false);\n };\n\n return {\n open,\n searchQuery,\n setSearchQuery,\n expanded,\n handleSelect,\n handleRemove,\n handleClearAll,\n handleOpenChange,\n handleExpand,\n handleCollapse,\n };\n}\n\n// ---------------------------------------------------------------------------\n// FormMultiSelect\n// ---------------------------------------------------------------------------\n\n/** Resolve optional props to concrete values outside the component to reduce branching. */\nfunction resolveMultiSelectDefaults(props: FormMultiSelectProps) {\n return {\n placeholder: props.placeholder ?? \"Select...\",\n searchPlaceholder: props.searchPlaceholder ?? \"Search...\",\n emptyMessage: props.emptyMessage ?? \"No results found\",\n clearable: props.clearable ?? true,\n disabled: props.disabled ?? false,\n readOnly: props.readOnly ?? false,\n loading: props.loading ?? false,\n maxDisplay: props.maxDisplay ?? Infinity,\n };\n}\n\n// Trigger trailing icons (clear + chevron).\nfunction TriggerIcons({\n showClear,\n onClear,\n}: {\n showClear: boolean;\n onClear: (e: React.MouseEvent) => void;\n}) {\n return (\n <div className=\"flex items-center gap-1 ml-2\">\n {showClear && (\n <X className=\"h-4 w-4 opacity-50 hover:opacity-100\" onClick={onClear} />\n )}\n <ChevronsUpDown className=\"h-4 w-4 shrink-0 opacity-50\" />\n </div>\n );\n}\n\nexport function FormMultiSelect(props: FormMultiSelectProps) {\n const {\n label,\n description,\n error,\n required,\n wrapperClassName,\n labelPlacement,\n options,\n onChange,\n onBlur,\n className,\n id,\n name,\n autoFocus,\n badgeColor,\n } = props;\n const value = props.value ?? [];\n const generatedId = React.useId();\n const fieldId = id ?? generatedId;\n const {\n placeholder,\n searchPlaceholder,\n emptyMessage,\n clearable,\n disabled,\n readOnly,\n loading,\n maxDisplay,\n } = resolveMultiSelectDefaults(props);\n\n const selectedOptions = options.filter((opt) => value.includes(opt.value));\n const isDisabled = disabled || readOnly || loading;\n\n const {\n open,\n searchQuery,\n setSearchQuery,\n expanded,\n handleSelect,\n handleRemove,\n handleClearAll,\n handleOpenChange,\n handleExpand,\n handleCollapse,\n } = useMultiSelectState(value, onChange, onBlur);\n\n const effectiveMaxDisplay = expanded ? Infinity : maxDisplay;\n\n return (\n <FormFieldWrapper\n inputId={fieldId}\n label={resolveFieldLabel(label)}\n description={description}\n error={error}\n required={required}\n labelPlacement={labelPlacement}\n className={wrapperClassName}\n >\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <Button\n id={fieldId}\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n className={cn(\n \"w-full justify-between min-h-10 h-auto\",\n error && \"border-destructive\",\n className,\n )}\n disabled={isDisabled}\n autoFocus={autoFocus}\n >\n <div className=\"flex flex-wrap gap-1 flex-1\">\n <SelectedBadges\n selectedOptions={selectedOptions}\n effectiveMaxDisplay={effectiveMaxDisplay}\n expanded={expanded}\n maxDisplay={maxDisplay}\n isDisabled={isDisabled}\n badgeColor={badgeColor}\n placeholder={placeholder}\n onRemove={handleRemove}\n onExpand={handleExpand}\n onCollapse={handleCollapse}\n />\n </div>\n <TriggerIcons\n showClear={clearable && value.length > 0 && !isDisabled}\n onClear={handleClearAll}\n />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className=\"w-[--radix-popover-trigger-width] p-0\"\n align=\"start\"\n >\n <MultiSelectDropdown\n searchPlaceholder={searchPlaceholder}\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n loading={loading}\n emptyMessage={emptyMessage}\n options={options}\n value={value}\n onSelect={handleSelect}\n />\n </PopoverContent>\n </Popover>\n\n {/* Hidden inputs for form submission */}\n {name &&\n value.map((v) => <input key={v} type=\"hidden\" name={name} value={v} />)}\n </FormFieldWrapper>\n );\n}\n","/**\n * FormTagsInput - Input field for managing tags with badges\n *\n * Allows adding tags by pressing Enter or comma, removing tags via X button\n * or backspace. Displays tags as badges. Follows Form wrapper pattern with\n * label, description, error support.\n */\n\nimport * as React from \"react\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { Input } from \"@petrarca/sonnet-ui\";\nimport { Badge } from \"@petrarca/sonnet-ui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport { resolveFieldLabel } from \"./formFieldUtils\";\n\nexport interface FormTagsInputProps {\n // Form wrapper props (consistent with FormInput/FormTextarea)\n label?: string | false;\n description?: string;\n error?: string;\n required?: boolean;\n wrapperClassName?: string;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n\n // TagsInput specific props\n id?: string;\n name?: string;\n value: string[];\n onChange?: (tags: string[]) => void;\n placeholder?: string;\n disabled?: boolean;\n readOnly?: boolean;\n maxTags?: number;\n splitKeys?: string[]; // Keys that trigger tag creation (default: ['Enter', ','])\n allowDuplicates?: boolean;\n}\n\n// -- Sub-component --------------------------------------------------------\n\ninterface TagBadgeProps {\n tag: string;\n index: number;\n isDisabled: boolean;\n onRemove: (index: number) => void;\n}\n\nfunction TagBadge({ tag, index, isDisabled, onRemove }: TagBadgeProps) {\n return (\n <Badge variant=\"secondary\" className=\"gap-1\">\n {tag}\n {!isDisabled && (\n <button\n type=\"button\"\n className=\"ml-1 ring-offset-background rounded-full outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\"\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n onRemove(index);\n }\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}\n onClick={(e) => {\n e.stopPropagation();\n onRemove(index);\n }}\n >\n <X className=\"h-3 w-3 text-muted-foreground hover:text-foreground\" />\n </button>\n )}\n </Badge>\n );\n}\n\n// -- Hook: tag management -------------------------------------------------\n\nfunction useTagManagement(\n value: string[],\n onChange: ((tags: string[]) => void) | undefined,\n allowDuplicates: boolean,\n maxTags: number | undefined,\n splitKeys: string[],\n) {\n const [inputValue, setInputValue] = React.useState(\"\");\n\n const addTag = React.useCallback(\n (tag: string) => {\n const trimmedTag = tag.trim();\n if (!trimmedTag) return;\n if (!allowDuplicates && value.includes(trimmedTag)) return;\n if (maxTags && value.length >= maxTags) return;\n onChange?.([...value, trimmedTag]);\n setInputValue(\"\");\n },\n [value, onChange, allowDuplicates, maxTags],\n );\n\n const removeTag = React.useCallback(\n (indexToRemove: number) => {\n onChange?.(value.filter((_, index) => index !== indexToRemove));\n },\n [value, onChange],\n );\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (splitKeys.includes(e.key)) {\n e.preventDefault();\n addTag(inputValue);\n return;\n }\n if (e.key === \"Backspace\" && !inputValue && value.length > 0) {\n e.preventDefault();\n removeTag(value.length - 1);\n }\n },\n [splitKeys, inputValue, value.length, addTag, removeTag],\n );\n\n const handleInputChange = React.useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n if (!splitKeys.includes(\",\") || !newValue.includes(\",\")) {\n setInputValue(newValue);\n return;\n }\n const parts = newValue.split(\",\");\n parts.slice(0, -1).forEach((tag) => addTag(tag));\n setInputValue(parts[parts.length - 1]);\n },\n [splitKeys, addTag],\n );\n\n return { inputValue, addTag, removeTag, handleKeyDown, handleInputChange };\n}\n\n// -- FormTagsInput --------------------------------------------------------\n\n/** Resolve optional props with defaults outside the component scope. */\nfunction resolveTagsDefaults(props: FormTagsInputProps) {\n return {\n required: props.required ?? false,\n placeholder: props.placeholder ?? \"Enter tag and press Enter\",\n splitKeys: props.splitKeys ?? [\"Enter\", \",\"],\n allowDuplicates: props.allowDuplicates ?? false,\n };\n}\n\nexport const FormTagsInput = React.forwardRef<\n HTMLInputElement,\n FormTagsInputProps\n>((props, ref) => {\n const {\n label,\n description,\n error,\n wrapperClassName,\n labelPlacement,\n id,\n name,\n value = [],\n onChange,\n disabled,\n readOnly,\n maxTags,\n } = props;\n const { required, placeholder, splitKeys, allowDuplicates } =\n resolveTagsDefaults(props);\n\n const generatedId = React.useId();\n const fieldId = id ?? generatedId;\n const inputRef = React.useRef<HTMLInputElement>(null);\n React.useImperativeHandle(ref, () => inputRef.current!);\n\n const isDisabled = disabled || readOnly;\n const { inputValue, removeTag, handleKeyDown, handleInputChange } =\n useTagManagement(value, onChange, allowDuplicates, maxTags, splitKeys);\n\n const handleContainerClick = () => {\n inputRef.current?.focus();\n };\n\n return (\n <FormFieldWrapper\n inputId={fieldId}\n label={resolveFieldLabel(label)}\n description={description}\n error={error}\n required={required}\n labelPlacement={labelPlacement}\n className={wrapperClassName}\n >\n <div\n className={cn(\n \"flex min-h-10 w-full flex-wrap gap-1.5 rounded-md border border-input bg-background px-3 py-2 text-sm\",\n isDisabled && \"cursor-not-allowed opacity-50\",\n error && \"border-destructive\",\n )}\n onClick={handleContainerClick}\n >\n {value.map((tag, index) => (\n <TagBadge\n key={index}\n tag={tag}\n index={index}\n isDisabled={!!isDisabled}\n onRemove={removeTag}\n />\n ))}\n <Input\n ref={inputRef}\n id={fieldId}\n name={name}\n value={inputValue}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n placeholder={value.length === 0 ? placeholder : \"\"}\n disabled={!!isDisabled}\n className=\"flex-1 min-w-[120px] border-0 p-0 h-auto focus-visible:ring-0 focus-visible:ring-offset-0\"\n />\n </div>\n </FormFieldWrapper>\n );\n});\n\nFormTagsInput.displayName = \"FormTagsInput\";\n","/**\n * FormQuantityInput - Compound input for a numeric value paired with a unit selector.\n *\n * Renders as a single visual control using InputGroup: the numeric input fills\n * the left side; the unit selector (or static text) sits inside the right (or\n * left) edge of the same border as an inline addon.\n *\n * Value shape: { value: number | undefined, unit: string }\n *\n * Decimal handling: uses inputMode=\"decimal\" with type=\"text\" to support\n * international decimal separators (comma and period). Input is validated and\n * normalized on blur, not on every keystroke, to allow intermediate states\n * such as \"37.\" or \"-\".\n *\n * NOTE on precision: toFixed() uses IEEE 754 rounding. For values where exact\n * decimal representation matters (e.g. financial amounts), the caller should\n * round the emitted number independently before storing it.\n */\n\nimport React, { useCallback, useEffect, useId, useMemo, useState } from \"react\";\nimport { ChevronsUpDown } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n} from \"@petrarca/sonnet-ui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport { getAriaDescribedBy } from \"./formFieldUtils\";\nimport type { SelectOption } from \"./widgets/types\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/** Compound quantity value: numeric value + unit code */\nexport interface QuantityValue {\n value: number | undefined;\n unit: string;\n}\n\n/** Where the unit label renders relative to the numeric input */\nexport type UnitPosition = \"prefix\" | \"suffix\";\n\n/** A unit option with optional per-unit validation constraints and position */\nexport interface UnitOption extends SelectOption {\n /** Minimum allowed value for this unit */\n min?: number;\n /** Maximum allowed value for this unit */\n max?: number;\n /** Where to render this unit relative to the value (default: \"suffix\") */\n position?: UnitPosition;\n}\n\nexport interface FormQuantityInputProps {\n /** Controlled compound value */\n value?: QuantityValue;\n /** Change handler -- receives the updated quantity */\n onChange?: (value: QuantityValue) => void;\n /** Blur handler */\n onBlur?: () => void;\n\n /** Available unit options. Single = static text, 2+ = dropdown, none = no addon. */\n units?: UnitOption[];\n /**\n * Default position for all units. Individual UnitOption.position overrides\n * this. Default: \"suffix\".\n */\n unitPosition?: UnitPosition;\n /**\n * Decimal places to format on blur (undefined = no formatting).\n * Uses toFixed() -- see IEEE 754 note in file header.\n */\n precision?: number;\n /** Arrow-key step increment */\n step?: number;\n /** Global minimum (overridden by per-unit min when present) */\n min?: number;\n /** Global maximum (overridden by per-unit max when present) */\n max?: number;\n\n /** Visible label */\n label?: string;\n /** Helper text shown below the control */\n description?: string;\n /** Validation error message */\n error?: string;\n /** Placeholder for the numeric input */\n placeholder?: string;\n /** Shows a required asterisk */\n required?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n autoFocus?: boolean;\n /** Additional class name for the outer wrapper */\n wrapperClassName?: string;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n /** Additional class name for the numeric input */\n className?: string;\n id?: string;\n name?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Pure helpers\n// ---------------------------------------------------------------------------\n\n// Allows in-progress numeric strings: optional leading minus, digits,\n// at most one decimal separator (comma or period).\nconst VALID_NUMERIC_INPUT = /^-?\\d*[.,]?\\d*$/;\n\n/** Sentinel values that represent incomplete but valid in-progress entries. */\nconst INCOMPLETE_SENTINELS = new Set([\"\", \".\", \"-\", \"-.\"]);\n\n/**\n * Round n to p decimal places using integer scaling.\n *\n * Avoids the IEEE 754 trap in toFixed() (e.g. (1.005).toFixed(2) === \"1.00\").\n * The Number.EPSILON nudge shifts values that land exactly halfway between two\n * representable floats (e.g. 1.005, 0.045) to the correct side before rounding.\n * Safe for all values within Number.MAX_SAFE_INTEGER / 10^p, which covers every\n * practical clinical and financial quantity this widget handles (see ADR-0010).\n */\nfunction roundToPrecision(n: number, p: number): number {\n const factor = Math.pow(10, p);\n return Math.round((n + Number.EPSILON) * factor) / factor;\n}\n\n/** Pure validation -- returns an error string or empty string. */\nfunction validateQuantity(\n numValue: number,\n lo: number | undefined,\n hi: number | undefined,\n unitLabel: string,\n): string {\n if (lo !== undefined && numValue < lo) {\n return `Value must be at least ${lo}${unitLabel ? ` ${unitLabel}` : \"\"}`;\n }\n if (hi !== undefined && numValue > hi) {\n return `Value must be at most ${hi}${unitLabel ? ` ${unitLabel}` : \"\"}`;\n }\n return \"\";\n}\n\n/** Round and format a parsed number. Returns { rounded, formatted }. */\nfunction roundAndFormat(\n numValue: number,\n precision: number | undefined,\n): { rounded: number; formatted: string } {\n const rounded =\n precision !== undefined ? roundToPrecision(numValue, precision) : numValue;\n const formatted =\n precision !== undefined ? rounded.toFixed(precision) : String(rounded);\n return { rounded, formatted };\n}\n\n// ---------------------------------------------------------------------------\n// UnitAddon sub-component (named for React DevTools visibility)\n// ---------------------------------------------------------------------------\n\ninterface UnitAddonProps {\n units: UnitOption[];\n currentUnit: string;\n addonAlign: \"inline-start\" | \"inline-end\";\n disabled?: boolean;\n readOnly?: boolean;\n onChange: (e: React.ChangeEvent<HTMLSelectElement>) => void;\n}\n\nfunction UnitAddon({\n units,\n currentUnit,\n addonAlign,\n disabled,\n readOnly,\n onChange,\n}: UnitAddonProps) {\n if (units.length === 0) return null;\n\n if (units.length === 1) {\n return (\n <InputGroupAddon align={addonAlign}>\n <span className=\"text-sm text-muted-foreground\">{units[0].label}</span>\n </InputGroupAddon>\n );\n }\n\n return (\n <InputGroupAddon align={addonAlign}>\n <div className=\"relative flex items-center\">\n <select\n value={currentUnit}\n onChange={onChange}\n disabled={disabled || readOnly}\n className=\"cursor-pointer appearance-none border-0 bg-transparent py-0 pr-5 pl-1 text-sm text-muted-foreground outline-none hover:text-foreground focus:text-foreground\"\n aria-label=\"Unit\"\n >\n {units.map((u) => (\n <option key={u.value} value={u.value}>\n {u.label}\n </option>\n ))}\n </select>\n <ChevronsUpDown className=\"pointer-events-none absolute right-0 h-3.5 w-3.5 text-muted-foreground/60\" />\n </div>\n </InputGroupAddon>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Hooks\n// ---------------------------------------------------------------------------\n\n/** Derive current unit, position, and effective min/max from props. */\nfunction useUnitState(\n value: QuantityValue | undefined,\n units: UnitOption[],\n unitPosition: UnitPosition,\n min: number | undefined,\n max: number | undefined,\n) {\n const currentUnit = useMemo(() => {\n const preferred = value?.unit;\n if (preferred && units.some((u) => u.value === preferred)) return preferred;\n return units[0]?.value ?? \"\";\n }, [value?.unit, units]);\n\n const unitMeta = useMemo(\n () => units.find((u) => u.value === currentUnit),\n [units, currentUnit],\n );\n\n const effectiveMin = unitMeta?.min ?? min;\n const effectiveMax = unitMeta?.max ?? max;\n const effectivePosition = unitMeta?.position ?? unitPosition;\n const addonAlign: \"inline-start\" | \"inline-end\" =\n effectivePosition === \"prefix\" ? \"inline-start\" : \"inline-end\";\n\n return { currentUnit, effectiveMin, effectiveMax, addonAlign };\n}\n\n/** Manage raw text input, validation, and handlers for numeric entry. */\nfunction useQuantityInput(\n value: QuantityValue | undefined,\n onChange: ((value: QuantityValue) => void) | undefined,\n onBlur: (() => void) | undefined,\n currentUnit: string,\n precision: number | undefined,\n effectiveMin: number | undefined,\n effectiveMax: number | undefined,\n externalError: string | undefined,\n) {\n const [rawInput, setRawInput] = useState<string>(\n value?.value !== undefined ? String(value.value) : \"\",\n );\n const [validationError, setValidationError] = useState<string>(\"\");\n\n // Sync rawInput when the controlled value changes from outside.\n useEffect(() => {\n const external = value?.value !== undefined ? String(value.value) : \"\";\n setRawInput((prev) => {\n const parsed = parseFloat(prev.replace(\",\", \".\"));\n if (!isNaN(parsed) && parsed === value?.value) return prev;\n return external;\n });\n }, [value?.value]);\n\n const error = externalError || validationError;\n\n const emit = useCallback(\n (numValue: number | undefined, unitValue: string) => {\n onChange?.({ value: numValue, unit: unitValue });\n },\n [onChange],\n );\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const raw = e.target.value;\n if (raw !== \"\" && !VALID_NUMERIC_INPUT.test(raw)) return;\n setRawInput(raw);\n setValidationError(\"\");\n },\n [],\n );\n\n const handleInputBlur = useCallback(() => {\n const normalized = rawInput.replace(\",\", \".\");\n\n // Handle incomplete entries (empty, just a dot/minus/minus-dot).\n if (INCOMPLETE_SENTINELS.has(normalized)) {\n if (normalized !== \"\") setRawInput(\"\");\n emit(undefined, currentUnit);\n setValidationError(\"\");\n onBlur?.();\n return;\n }\n\n const numValue = parseFloat(normalized);\n if (isNaN(numValue)) {\n setRawInput(\"\");\n emit(undefined, currentUnit);\n onBlur?.();\n return;\n }\n\n const { rounded, formatted } = roundAndFormat(numValue, precision);\n setRawInput(formatted);\n setValidationError(\n validateQuantity(rounded, effectiveMin, effectiveMax, currentUnit),\n );\n emit(rounded, currentUnit);\n onBlur?.();\n }, [\n rawInput,\n currentUnit,\n precision,\n effectiveMin,\n effectiveMax,\n emit,\n onBlur,\n ]);\n\n return {\n rawInput,\n error,\n handleInputChange,\n handleInputBlur,\n emit,\n setValidationError,\n };\n}\n\n// ---------------------------------------------------------------------------\n// FormQuantityInput\n// ---------------------------------------------------------------------------\n\n/**\n * FormQuantityInput -- controlled compound numeric + unit input in a single\n * InputGroup border. See file header for behavioural notes.\n */\nexport const FormQuantityInput = React.forwardRef<\n HTMLInputElement,\n FormQuantityInputProps\n>((allProps, ref) => {\n const {\n value,\n onChange,\n onBlur,\n precision,\n step,\n min,\n max,\n label,\n description,\n placeholder,\n required,\n disabled,\n readOnly,\n autoFocus,\n wrapperClassName,\n labelPlacement,\n className,\n name,\n } = allProps;\n const units = useMemo(() => allProps.units ?? [], [allProps.units]);\n const unitPosition = allProps.unitPosition ?? \"suffix\";\n const error = allProps.error;\n\n const generatedId = useId();\n const inputId = allProps.id ?? generatedId;\n\n const { currentUnit, effectiveMin, effectiveMax, addonAlign } = useUnitState(\n value,\n units,\n unitPosition,\n min,\n max,\n );\n\n const {\n rawInput,\n error: resolvedError,\n handleInputChange,\n handleInputBlur,\n emit,\n setValidationError,\n } = useQuantityInput(\n value,\n onChange,\n onBlur,\n currentUnit,\n precision,\n effectiveMin,\n effectiveMax,\n error,\n );\n\n // Unit change handler\n const handleUnitChange = useCallback(\n (e: React.ChangeEvent<HTMLSelectElement>) => {\n const unitValue = e.target.value;\n setValidationError(\"\");\n const normalized = rawInput.replace(\",\", \".\");\n const numValue = parseFloat(normalized);\n if (isNaN(numValue)) return;\n const um = units.find((u) => u.value === unitValue);\n const lo = um?.min ?? min;\n const hi = um?.max ?? max;\n setValidationError(validateQuantity(numValue, lo, hi, unitValue));\n emit(numValue, unitValue);\n },\n [rawInput, units, min, max, emit, setValidationError],\n );\n\n const unitAddon = useMemo(\n () => (\n <UnitAddon\n units={units}\n currentUnit={currentUnit}\n addonAlign={addonAlign}\n disabled={disabled}\n readOnly={readOnly}\n onChange={handleUnitChange}\n />\n ),\n [units, currentUnit, addonAlign, disabled, readOnly, handleUnitChange],\n );\n\n return (\n <FormFieldWrapper\n inputId={inputId}\n label={label}\n description={description}\n error={resolvedError}\n required={required}\n labelPlacement={labelPlacement}\n className={wrapperClassName}\n >\n <InputGroup\n data-disabled={disabled || undefined}\n className={cn(resolvedError && \"border-destructive\")}\n >\n <InputGroupInput\n id={inputId}\n name={name}\n ref={ref}\n type=\"text\"\n inputMode=\"decimal\"\n value={rawInput}\n onChange={handleInputChange}\n onBlur={handleInputBlur}\n placeholder={placeholder}\n disabled={disabled}\n readOnly={readOnly}\n autoFocus={autoFocus}\n step={step}\n className={className}\n aria-invalid={resolvedError ? \"true\" : \"false\"}\n aria-describedby={getAriaDescribedBy(\n inputId,\n resolvedError,\n description,\n )}\n aria-required={required}\n aria-valuemin={effectiveMin}\n aria-valuemax={effectiveMax}\n />\n {unitAddon}\n </InputGroup>\n </FormFieldWrapper>\n );\n});\n\nFormQuantityInput.displayName = \"FormQuantityInput\";\n","/**\n * FormActions - Save / Cancel button row for buffered forms\n *\n * Rendered only when the parent JsonSchemaFormRenderer is in buffered mode\n * (showActions=true). Keeps button logic out of the orchestrator.\n *\n * @module components/Forms/FormActions\n */\n\nimport type { ReactNode } from \"react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport { SimpleGroup } from \"@petrarca/sonnet-ui\";\nimport type { SaveWhenInvalid } from \"@petrarca/sonnet-core/config\";\n\nexport interface FormActionsProps {\n onSave: () => void;\n onCancel: () => void;\n disabled?: boolean;\n hasChanges: boolean;\n isValid: boolean;\n /**\n * Whether Save is available while invalid. `reveal` (default) keeps it\n * enabled -- an invalid click reveals errors and does not submit; `disable`\n * greys it out while invalid.\n */\n saveWhenInvalid?: SaveWhenInvalid;\n saveLabel?: string;\n cancelLabel?: string;\n showCancel?: boolean;\n /**\n * Optional content rendered left-aligned in the action row (e.g. a secondary\n * action like \"Test connection\"). Cancel/Save stay grouped on the right.\n */\n leadingActions?: ReactNode;\n}\n\nexport function FormActions({\n onSave,\n onCancel,\n disabled = false,\n hasChanges,\n isValid,\n saveWhenInvalid = \"reveal\",\n saveLabel = \"Save\",\n cancelLabel = \"Cancel\",\n showCancel = true,\n leadingActions,\n}: FormActionsProps) {\n // \"reveal\": Save stays enabled while invalid; the click reveals errors and\n // handleSave declines to submit. \"disable\": greyed out while invalid.\n const saveDisabled =\n disabled || !hasChanges || (saveWhenInvalid === \"disable\" && !isValid);\n return (\n <div className=\"flex items-center justify-between mt-4\">\n <div className=\"flex items-center gap-2\">{leadingActions}</div>\n <SimpleGroup justify=\"flex-end\">\n {showCancel && (\n <Button variant=\"outline\" onClick={onCancel} disabled={disabled}>\n {cancelLabel}\n </Button>\n )}\n <Button onClick={onSave} disabled={saveDisabled}>\n {saveLabel}\n </Button>\n </SimpleGroup>\n </div>\n );\n}\n","import { useMemo } from \"react\";\nimport { ChevronDown, ChevronRight } from \"lucide-react\";\nimport { Card } from \"@petrarca/sonnet-ui\";\nimport { useDisclosure } from \"@petrarca/sonnet-core/hooks\";\nimport { JsonSchema } from \"@petrarca/sonnet-core/schema\";\nimport { Collapsible, CollapsibleContent } from \"@petrarca/sonnet-ui\";\n\ntype Props = {\n properties: Record<string, any>;\n schema: JsonSchema | null;\n};\n\n/**\n * Displays properties that are not defined in the JSON Schema.\n * Shown as a collapsible card, closed by default.\n *\n * This is a generic component that can be used anywhere a schema and properties\n * need to be compared to show additional/extra properties.\n */\nfunction ExtraPropertiesCard({ properties, schema }: Props) {\n const [opened, { toggle }] = useDisclosure(false);\n\n const extraProperties = useMemo(() => {\n if (!schema) return null;\n const schemaProps = schema.properties ?? {};\n const extra = Object.fromEntries(\n Object.entries(properties).filter(([k]) => !(k in schemaProps)),\n );\n return Object.keys(extra).length > 0 ? extra : null;\n }, [properties, schema]);\n\n if (!extraProperties) return null;\n\n return (\n <Card className=\"border p-3\">\n <p\n className={`flex items-center gap-1 text-sm font-medium cursor-pointer select-none ${opened ? \"mb-1\" : \"\"}`}\n onClick={toggle}\n >\n {opened ? (\n <ChevronDown className=\"h-3.5 w-3.5\" />\n ) : (\n <ChevronRight className=\"h-3.5 w-3.5\" />\n )}\n Extra Properties (not in schema)\n </p>\n <Collapsible open={opened}>\n <CollapsibleContent>\n <pre className=\"text-xs bg-muted p-2 rounded overflow-x-auto\">\n <code>{JSON.stringify(extraProperties, null, 2)}</code>\n </pre>\n </CollapsibleContent>\n </Collapsible>\n </Card>\n );\n}\n\nexport default ExtraPropertiesCard;\n","/**\n * JsonSchemaFormRenderer - Generic form renderer based on JSON Schema\n *\n * Thin orchestrator: composes useFormEngine, FormFieldRenderer, and FormActions.\n *\n * Supports three update modes:\n * 1. Real-time (default) — onChange on every field change\n * 2. Deferred (deferChanges=true) — onChange on blur for text fields\n * 3. Buffered (showActions=true) — Save/Cancel managed by form; onUpdate on Save\n *\n * When rendered inside a HorizontalArrayItemTemplate (via ObjectWidget in an\n * array row), the caller sets `displayContents=true` so this renderer's\n * wrapper uses `display: contents`, making each field div a direct grid cell\n * in the parent row grid.\n *\n * @module components/Forms/JsonSchemaFormRenderer\n */\n\nimport React, { useCallback, useContext, useMemo } from \"react\";\nimport { SimpleStack } from \"@petrarca/sonnet-ui\";\nimport { AlertCircle } from \"lucide-react\";\nimport {\n JsonSchema,\n UILayoutConfig,\n UILayoutRowConfig,\n UILayoutGroupConfig,\n WidthToken,\n WIDTH_TOKEN_REMS,\n} from \"@petrarca/sonnet-core/schema\";\nimport type {\n FormDiff,\n RefResolver,\n FieldError,\n} from \"@petrarca/sonnet-core/schema\";\nimport { isFieldRequired, evaluateUiRule } from \"@petrarca/sonnet-core/schema\";\nimport { FORM_ITEM_ID_FIELD } from \"@petrarca/sonnet-core\";\nimport ExtraPropertiesCard from \"./ExtraPropertiesCard\";\nimport { DEFAULT_WIDGETS, WidgetRegistry, UISchema } from \"./widgets\";\nimport { TemplateRegistry, UISchemaOptions } from \"./widgets/types\";\nimport type { FieldGroup, GroupLayoutTemplate } from \"./widgets/types\";\nimport { DEFAULT_TEMPLATES, groupTemplateKey } from \"./templates\";\nimport { FormFieldRenderer } from \"./FormFieldRenderer\";\nimport { FormActions } from \"./FormActions\";\nimport { useFormEngine } from \"./hooks/useFormEngine\";\nimport {\n useValidationDisplay,\n useSaveWhenInvalid,\n type ValidationDisplay,\n type SaveWhenInvalid,\n} from \"@petrarca/sonnet-core/config\";\nimport { NestedFormContext, NestedRenderer } from \"./NestedFormContext\";\n\n/**\n * Recursively remove FORM_ITEM_ID_FIELD from all array items in a data object.\n * This is the single boundary where _fid is stripped -- it never leaves the renderer.\n */\nfunction stripFids(data: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (Array.isArray(value)) {\n result[key] = value.map((item: unknown) => {\n if (item !== null && typeof item === \"object\" && !Array.isArray(item)) {\n const rest = Object.fromEntries(\n Object.entries(item as Record<string, unknown>).filter(\n ([k]) => k !== FORM_ITEM_ID_FIELD,\n ),\n );\n return stripFids(rest);\n }\n return item;\n });\n } else if (value !== null && typeof value === \"object\") {\n result[key] = stripFids(value as Record<string, unknown>);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\n/** Resolve boolean/flag default values for optional props. */\nfunction resolveFlagDefaults(props: JsonSchemaFormRendererProps) {\n return {\n disabled: props.disabled ?? false,\n readOnly: props.readOnly ?? false,\n showActions: props.showActions ?? false,\n deferChanges: props.deferChanges ?? false,\n deferStateUpdates: props.deferStateUpdates ?? false,\n showCancel: props.showCancel ?? true,\n showExtraProperties: props.showExtraProperties ?? true,\n displayContents: props.displayContents ?? false,\n allowPristineSave: props.allowPristineSave ?? false,\n };\n}\n\n/** Resolve non-boolean default values for optional props. */\nfunction resolveValueDefaults(props: JsonSchemaFormRendererProps) {\n return {\n saveLabel: props.saveLabel ?? \"Save\",\n cancelLabel: props.cancelLabel ?? \"Cancel\",\n widgets: props.widgets ?? DEFAULT_WIDGETS,\n uiSchema: props.uiSchema ?? ({} as { [fieldName: string]: UISchema }),\n };\n}\n\n/**\n * Wrap outbound callbacks to strip _fid before data crosses the renderer\n * boundary. Each callback is memoised individually.\n */\nfunction useWrappedCallbacks(\n onChange: JsonSchemaFormRendererProps[\"onChange\"],\n onBlur: JsonSchemaFormRendererProps[\"onBlur\"],\n onUpdate: JsonSchemaFormRendererProps[\"onUpdate\"],\n) {\n const wrappedOnChange = useCallback(\n (d: Record<string, any>) => onChange?.(stripFids(d)),\n [onChange],\n );\n\n const wrappedOnBlur = useCallback(\n (fieldName: string, d: Record<string, any>) =>\n onBlur?.(fieldName, stripFids(d)),\n [onBlur],\n );\n\n const wrappedOnUpdate = useCallback(\n (d: Record<string, any>, changed: Record<string, any>, diff: FormDiff) =>\n onUpdate?.(stripFids(d), stripFids(changed), diff),\n [onUpdate],\n );\n\n return {\n wrappedOnChange: onChange ? wrappedOnChange : undefined,\n wrappedOnBlur: onBlur ? wrappedOnBlur : undefined,\n wrappedOnUpdate: onUpdate ? wrappedOnUpdate : undefined,\n };\n}\n\n/** Index field elements by their React key for O(1) lookup. */\nfunction buildFieldMap(\n fields: React.ReactElement[],\n): Map<string, React.ReactElement> {\n const map = new Map<string, React.ReactElement>();\n for (const field of fields) {\n if (React.isValidElement(field) && field.key != null) {\n map.set(String(field.key), field);\n }\n }\n return map;\n}\n\n/** Build a single CSS grid row element from a row definition. */\n// Column-width tokens re-use the shared WIDTH_TOKEN_REMS from sonnet-core\n// (single source of truth for token -> size; see types.ts).\nconst COLUMN_TRACK: Record<WidthToken, string> = WIDTH_TOKEN_REMS;\n\n/**\n * Resolve a row's grid-template-columns. Precedence: raw `columns` (escape\n * hatch) -> semantic `widths` tokens -> equal 1fr per field.\n */\nfunction resolveGridColumns(\n row: UILayoutRowConfig,\n fieldCount: number,\n): string {\n if (row.columns) return row.columns;\n if (row.widths && row.widths.length > 0) {\n return Array.from(\n { length: fieldCount },\n (_, i) => COLUMN_TRACK[row.widths?.[i] ?? \"full\"],\n ).join(\" \");\n }\n return `repeat(${fieldCount}, 1fr)`;\n}\n\n/**\n * Wrap row content in a titled fieldset when `group` is set. Composable: the\n * fieldset holds arbitrary content, so nesting (groups of rows, tabs)\n * layers on without changing callers.\n */\nfunction wrapInGroup(\n group: string | undefined,\n key: string,\n content: React.ReactElement,\n): React.ReactElement {\n if (!group) return content;\n return (\n <fieldset\n key={`group:${key}`}\n className=\"rounded-md border border-border/60 px-3 pb-3 pt-1\"\n >\n <legend className=\"px-1 text-sm font-medium text-muted-foreground\">\n {group}\n </legend>\n {content}\n </fieldset>\n );\n}\n\nfunction buildRowElement(\n row: UILayoutRowConfig,\n fieldMap: Map<string, React.ReactElement>,\n defaultRowGap: number,\n): { element: React.ReactElement; placed: string[] } | null {\n const rowFields = row.fields\n .map((name) => fieldMap.get(name))\n .filter((el): el is React.ReactElement => el != null);\n if (rowFields.length === 0) return null;\n\n const rowGap = row.gap ?? defaultRowGap;\n const rowKey = row.fields.join(\",\");\n\n // \"flow\": flex row, fields at natural width, left-to-right, wrapping.\n // \"grid\" (default): CSS grid using columns/widths (equal 1fr by default).\n const style: React.CSSProperties =\n row.arrange === \"flow\"\n ? {\n display: \"flex\",\n flexWrap: \"wrap\",\n alignItems: \"center\",\n gap: `${rowGap}px`,\n }\n : {\n display: \"grid\",\n gridTemplateColumns: resolveGridColumns(row, rowFields.length),\n gap: `${rowGap}px`,\n };\n\n const inner = (\n <div key={`row:${rowKey}`} style={style}>\n {rowFields}\n </div>\n );\n\n return {\n element: wrapInGroup(row.group, rowKey, inner),\n placed: row.fields,\n };\n}\n\n/** Collect fields not present in the placed set, preserving source order. */\nfunction collectUnplacedFields(\n fields: React.ReactElement[],\n placed: Set<string>,\n): React.ReactElement[] {\n const result: React.ReactElement[] = [];\n for (const field of fields) {\n if (\n React.isValidElement(field) &&\n field.key != null &&\n !placed.has(String(field.key))\n ) {\n result.push(field);\n }\n }\n return result;\n}\n\n/**\n * Build a list of rows, recording into `placed` every field they declare.\n * Placement is recorded even for a row that renders nothing, so a field named\n * by the layout never also turns up in the unplaced stack.\n */\nfunction buildRows(\n rowDefs: UILayoutRowConfig[],\n fieldMap: Map<string, React.ReactElement>,\n defaultRowGap: number,\n placed: Set<string>,\n): React.ReactElement[] {\n const elements: React.ReactElement[] = [];\n for (const row of rowDefs) {\n const result = buildRowElement(row, fieldMap, defaultRowGap);\n for (const name of row.fields) placed.add(name);\n if (result != null) elements.push(result.element);\n }\n return elements;\n}\n\n/**\n * Arrange field elements into CSS grid rows according to row definitions.\n * Fields not mentioned in any row are appended in source order.\n */\nfunction layoutFieldsInRows(\n fields: React.ReactElement[],\n rowDefs: UILayoutRowConfig[],\n defaultRowGap: number,\n): React.ReactElement[] {\n const placed = new Set<string>();\n const elements = buildRows(\n rowDefs,\n buildFieldMap(fields),\n defaultRowGap,\n placed,\n );\n return elements.concat(collectUnplacedFields(fields, placed));\n}\n\n/**\n * Whether a field must be given a blur handler.\n *\n * Four independent reasons, any one of which is sufficient: the two deferred\n * modes flush on blur, a consumer onBlur must be forwarded, and `onTouched`\n * error display needs blur to record that a field was touched.\n */\n/**\n * The data an `x-ui-rule` scope resolves against: the whole form, not the\n * renderer's own slice.\n *\n * A nested renderer inherits the root from the enclosing one; the outermost\n * renderer has no enclosing context, so its own data *is* the root. This is\n * what lets a rule on a nested field reference any field by its pointer from\n * the top of the form -- consistent with every other JSON Pointer in the\n * vocabulary (`editablePaths`, validation error pointers).\n */\nfunction useRootFormData(\n ownData: Record<string, unknown>,\n): Record<string, unknown> {\n return useContext(NestedFormContext)?.rootData ?? ownData;\n}\n\nfunction blurHandlerNeeded({\n deferStateUpdates,\n deferChanges,\n hasOnBlur,\n validationDisplay,\n}: {\n deferStateUpdates: boolean;\n deferChanges: boolean;\n hasOnBlur: boolean;\n validationDisplay: ValidationDisplay;\n}): boolean {\n return (\n deferStateUpdates ||\n deferChanges ||\n hasOnBlur ||\n validationDisplay === \"onTouched\"\n );\n}\n\n/** Whether a field's validation errors are shown yet, per the display policy. */\nfunction fieldErrorsVisible(\n validationDisplay: ValidationDisplay,\n submitAttempted: boolean,\n isTouched: boolean | undefined,\n): boolean {\n if (validationDisplay === \"always\") return true;\n if (submitAttempted) return true;\n return validationDisplay === \"onTouched\" && !!isTouched;\n}\n\n// The root field name a JSON Pointer refers to, un-escaped (RFC 6901).\n// \"/contact/email\" -> \"contact\"; \"/a~1b\" -> \"a/b\".\nfunction pointerRoot(pointer: string): string {\n const token = pointer.split(\"/\")[1] ?? \"\";\n return token.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n}\n\n// How many validation errors belong to the fields declared in a tab.\nfunction groupErrorCount(\n tab: UILayoutGroupConfig,\n fieldErrors: FieldError[],\n): number {\n if (fieldErrors.length === 0) return 0;\n const owned = new Set(tab.rows.flatMap((row) => row.fields));\n return fieldErrors.filter((e) => owned.has(pointerRoot(e.pointer))).length;\n}\n\n/**\n * Which groups their rules currently show. The single source of truth for\n * group visibility -- both the layout and the hidden-error summary read it, so\n * they cannot disagree about what is on screen.\n *\n * `allHidden` matters because the renderer then falls back to a flat layout,\n * which means nothing is actually hidden from the user.\n */\nfunction groupVisibility(\n groupDefs: UILayoutGroupConfig[],\n formData: Record<string, unknown>,\n): { visible: boolean[]; allHidden: boolean } {\n const visible = groupDefs.map(\n (tab) => evaluateUiRule(tab.rule, formData).visible,\n );\n return { visible, allHidden: !visible.some(Boolean) };\n}\n\n// Field names declared in groups that are hidden, and so are not on screen.\nfunction hiddenGroupFieldNames(\n groupDefs: UILayoutGroupConfig[],\n formData: Record<string, unknown>,\n): Set<string> {\n const hidden = new Set<string>();\n const { visible, allHidden } = groupVisibility(groupDefs, formData);\n if (allHidden) return hidden; // rendered flat: nothing is hidden\n groupDefs.forEach((tab, i) => {\n if (visible[i]) return;\n for (const row of tab.rows) for (const f of row.fields) hidden.add(f);\n });\n return hidden;\n}\n\n// The presentation for a grouped layout: \"tabs\" (default), \"stepper\",\n// \"sections\", or any template a consumer registered under the matching name.\nfunction resolveGroupTemplate(\n templates: TemplateRegistry,\n variant: string | undefined,\n): GroupLayoutTemplate {\n const registered = templates[groupTemplateKey(variant)];\n if (typeof registered === \"function\") {\n return registered as GroupLayoutTemplate;\n }\n return DEFAULT_TEMPLATES.TabsGroupTemplate as GroupLayoutTemplate;\n}\n\n/**\n * Summary of validation errors that belong to fields the user cannot currently\n * see (they sit in a hidden group). Without this the form is a dead end: Save\n * is disabled, and no on-screen field explains why.\n */\nfunction HiddenErrorNotice({\n count,\n}: {\n count: number;\n}): React.ReactElement | null {\n if (count === 0) return null;\n return (\n <p className=\"flex items-center gap-1.5 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0\" />\n {count === 1\n ? \"1 required field is in a section that is not currently shown.\"\n : `${count} required fields are in sections that are not currently shown.`}\n </p>\n );\n}\n\n/**\n * Arrange field elements into groups and hand them to the registered group\n * template (tabs by default; stepper, sections or a consumer's own via\n * `x-ui-layout.variant`). This function owns the layout; the template owns the\n * presentation and navigation.\n *\n * Fields declared in a group hidden by its rule are consumed (not rendered);\n * fields in no group at all are appended below so nothing is hidden by accident.\n */\nfunction layoutFieldsInGroups(\n fields: React.ReactElement[],\n groupDefs: UILayoutGroupConfig[],\n defaultRowGap: number,\n fieldErrors: FieldError[],\n formData: Record<string, unknown>,\n GroupTemplate: GroupLayoutTemplate,\n): React.ReactElement[] {\n const fieldMap = buildFieldMap(fields);\n const placed = new Set<string>();\n const { visible, allHidden } = groupVisibility(groupDefs, formData);\n\n // Build every group's rows: a hidden group still consumes its fields so they\n // cannot leak into the unplaced stack below.\n const built = groupDefs.map((tab, index) => ({\n index,\n rows: buildRows(tab.rows, fieldMap, defaultRowGap, placed),\n }));\n const unplaced = collectUnplacedFields(fields, placed);\n\n // Every group hidden: fall back to rendering their rows flat rather than\n // silently dropping the fields they declare.\n if (allHidden) {\n return [...built.flatMap((b) => b.rows), ...unplaced];\n }\n\n const groups: FieldGroup[] = built\n .filter((b) => visible[b.index])\n .map((b) => ({\n key: `group-${b.index}`,\n label: groupDefs[b.index].label,\n content: b.rows,\n errorCount: groupErrorCount(groupDefs[b.index], fieldErrors),\n }));\n\n return [<GroupTemplate key=\"form:groups\" groups={groups} />, ...unplaced];\n}\n\ninterface FormContainerProps {\n displayContents: boolean;\n showExtraProperties: boolean;\n showActions: boolean;\n formData: Record<string, any>;\n resolvedSchema: JsonSchema;\n handleSave: () => void;\n handleCancel: () => void;\n disabled: boolean;\n hasChanges: boolean;\n isValid: boolean;\n saveWhenInvalid: SaveWhenInvalid;\n saveLabel: string;\n cancelLabel: string;\n showCancel: boolean;\n leadingActions?: React.ReactNode;\n /** Errors owned by fields inside a currently hidden tab. */\n hiddenErrorCount: number;\n children: React.ReactNode;\n}\n\n/** Container that renders either display:contents or a SimpleStack with actions. */\nfunction FormContainer({\n displayContents,\n showExtraProperties,\n showActions,\n formData,\n resolvedSchema,\n handleSave,\n handleCancel,\n disabled,\n hasChanges,\n isValid,\n saveWhenInvalid,\n saveLabel,\n cancelLabel,\n showCancel,\n leadingActions,\n hiddenErrorCount,\n children,\n}: FormContainerProps): React.ReactElement {\n if (displayContents) {\n return <div style={{ display: \"contents\" }}>{children}</div>;\n }\n return (\n <SimpleStack gap=\"md\">\n {children}\n {showExtraProperties && (\n <ExtraPropertiesCard properties={formData} schema={resolvedSchema} />\n )}\n <HiddenErrorNotice count={hiddenErrorCount} />\n {showActions && (\n <FormActions\n onSave={handleSave}\n onCancel={handleCancel}\n disabled={disabled}\n hasChanges={hasChanges}\n isValid={isValid}\n saveWhenInvalid={saveWhenInvalid}\n saveLabel={saveLabel}\n cancelLabel={cancelLabel}\n showCancel={showCancel}\n leadingActions={leadingActions}\n />\n )}\n </SimpleStack>\n );\n}\n\nexport type JsonSchemaFormRendererProps = {\n /** JSON Schema defining the form fields */\n schema: JsonSchema;\n\n /** Current form data */\n data: Record<string, any>;\n\n /** Callback when any field changes (real-time updates) */\n onChange?: (data: Record<string, any>) => void;\n\n /** Callback when a field loses focus */\n onBlur?: (fieldName: string, data: Record<string, any>) => void;\n\n /** Optional callback for validation state changes */\n onValidationChange?: (errors: string[], isValid: boolean) => void;\n\n /**\n * Defer onChange to blur for text fields (default: false).\n * Checkboxes and selects always trigger immediately.\n */\n deferChanges?: boolean;\n\n /**\n * Defer internal state updates to blur for text fields (default: false).\n * Only applies when showActions=true. The Save button enables only after\n * leaving a modified text field.\n */\n deferStateUpdates?: boolean;\n\n /**\n * Callback when user saves changes -- only fired if data actually changed.\n *\n * - `data`: complete form data (all fields, _fid stripped)\n * - `changedFields`: only fields that differ from the original baseline,\n * useful for PATCH-style APIs with exclude_unset semantics (_fid stripped)\n * - `diff`: structured diff classifying each change as value/array add/remove/move/modify.\n * Array item changes carry `fid` tokens for correlation; these are form-internal\n * and are never sent to the server.\n */\n onUpdate?: (\n data: Record<string, any>,\n changedFields: Record<string, any>,\n diff: FormDiff,\n ) => void;\n\n /** Callback when user clicks Cancel */\n onCancel?: () => void;\n\n /** Disable all fields */\n disabled?: boolean;\n\n /** Read-only mode — fields are not editable */\n readOnly?: boolean;\n\n /** Show Save/Cancel action buttons */\n showActions?: boolean;\n\n /**\n * Allow Save when the form is pristine (no changes vs the baseline). Set for\n * CREATE forms, where submitting default / empty values is valid -- the\n * \"must have changed something\" dirty-check is an edit-only concept. Required-\n * field validation still applies. Default false (edit semantics).\n */\n allowPristineSave?: boolean;\n\n /**\n * Optional resolver for non-local `$ref`s (schema-registry id / canonical\n * URI). Tried before the in-document `$defs` fallback. Synchronous -- the\n * caller pre-loads referenced schemas into a map and passes a lookup.\n */\n refResolver?: RefResolver;\n\n /**\n * When to reveal field validation errors. Overrides the app-wide default set\n * in SonnetConfigProvider globals. Defaults to `onSubmit`.\n */\n validationDisplay?: ValidationDisplay;\n\n /**\n * Whether Save is available while the form is invalid. Overrides the app-wide\n * default set in SonnetConfigProvider globals. Defaults to `reveal` (Save\n * stays enabled; an invalid click reveals errors and does not submit).\n */\n saveWhenInvalid?: SaveWhenInvalid;\n\n /** Label for Save button (default: \"Save\") */\n saveLabel?: string;\n\n /** Label for Cancel button (default: \"Cancel\") */\n cancelLabel?: string;\n\n /** Show the Cancel button (default: true) */\n showCancel?: boolean;\n\n /**\n * Optional content rendered left-aligned in the Save/Cancel action row\n * (only when showActions=true), e.g. a secondary action like \"Test connection\".\n */\n leadingActions?: React.ReactNode;\n\n /** Show extra properties card (default: true) */\n showExtraProperties?: boolean;\n\n /** Widget registry for custom widgets (default: DEFAULT_WIDGETS) */\n widgets?: WidgetRegistry;\n\n /**\n * Template registry for custom layout templates (default: DEFAULT_TEMPLATES).\n *\n * Templates control structural rendering (array item rows, object containers).\n * Widgets control input rendering. Override specific templates by providing\n * a partial registry -- unspecified keys fall back to DEFAULT_TEMPLATES.\n */\n templates?: TemplateRegistry;\n\n /**\n * When true, renders with `display: contents` instead of a SimpleStack.\n *\n * Used by ObjectWidget when it is a direct child of a HorizontalArrayItemTemplate\n * row grid. `display: contents` makes this renderer's wrapper invisible to the\n * layout algorithm so each field div becomes a direct grid cell in the row.\n */\n displayContents?: boolean;\n\n /**\n * UISchema for customizing widget behavior and appearance.\n *\n * @example\n * ```typescript\n * uiSchema={{\n * 'x-ui-globalOptions': { label: false },\n * 'x-ui-order': ['email', 'name'],\n * name: { 'x-ui-widget': 'textarea' },\n * }}\n * ```\n */\n uiSchema?: { [fieldName: string]: UISchema };\n\n /**\n * Prefix for generated field control ids: `<idPrefix>-<fieldName>` (default\n * \"field\"). Set a distinct prefix per form when rendering multiple forms on\n * one page to avoid duplicate DOM ids.\n */\n idPrefix?: string;\n};\n\nexport function JsonSchemaFormRenderer(\n props: JsonSchemaFormRendererProps,\n): React.ReactElement {\n const {\n schema,\n data,\n onChange,\n onBlur,\n onValidationChange,\n onUpdate,\n onCancel,\n templates,\n leadingActions,\n idPrefix = \"field\",\n } = props;\n\n const {\n disabled,\n readOnly,\n showActions,\n deferChanges,\n deferStateUpdates,\n showCancel,\n showExtraProperties,\n displayContents,\n allowPristineSave,\n } = resolveFlagDefaults(props);\n\n const { saveLabel, cancelLabel, widgets, uiSchema } =\n resolveValueDefaults(props);\n\n const { wrappedOnChange, wrappedOnBlur, wrappedOnUpdate } =\n useWrappedCallbacks(onChange, onBlur, onUpdate);\n\n const {\n formData,\n displayData,\n resolvedSchema,\n orderedProperties,\n hasChanges,\n isValid,\n fieldErrors,\n touched,\n submitAttempted,\n handleFieldChange,\n handleFieldBlur,\n handleSave,\n handleCancel,\n } = useFormEngine({\n schema,\n data,\n uiSchema,\n onChange: wrappedOnChange,\n onBlur: wrappedOnBlur,\n onValidationChange,\n onUpdate: wrappedOnUpdate,\n onCancel,\n readOnly,\n showActions,\n deferChanges,\n deferStateUpdates,\n allowPristineSave,\n refResolver: props.refResolver,\n });\n\n // Global options for all fields. A container-level x-ui-layout.labelPlacement\n // is folded in here so it is inherited by the container's fields (a field's\n // own x-ui-options.labelPlacement still wins via mergeFieldOptions).\n const layoutLabelPlacement = (\n uiSchema[\"x-ui-layout\"] as UILayoutConfig | undefined\n )?.labelPlacement;\n const globalOptions: UISchemaOptions = useMemo(\n () => ({\n ...(layoutLabelPlacement ? { labelPlacement: layoutLabelPlacement } : {}),\n ...((uiSchema[\"x-ui-globalOptions\"] as UISchemaOptions) || {}),\n }),\n [layoutLabelPlacement, uiSchema],\n );\n\n // Merge caller-supplied templates over the defaults. Callers only need\n // to provide the templates they want to override.\n const resolvedTemplates = useMemo(\n () => ({ ...DEFAULT_TEMPLATES, ...templates }),\n [templates],\n );\n\n // Provide renderer + templates to nested widgets via context so they can\n // render sub-forms and resolve layout templates without circular imports.\n // The `displayContents` prop is forwarded from the call site (ObjectWidget)\n // when this renderer is inside a horizontal array row grid.\n const nestedRenderer = useCallback<NestedRenderer>(\n (props) => (\n <JsonSchemaFormRenderer\n {...props}\n templates={resolvedTemplates}\n showActions={false}\n showExtraProperties={false}\n />\n ),\n [resolvedTemplates],\n );\n\n const rootData = useRootFormData(displayData);\n\n const contextValue = useMemo(\n () => ({\n renderer: nestedRenderer,\n templates: resolvedTemplates,\n rootData,\n }),\n [nestedRenderer, resolvedTemplates, rootData],\n );\n\n const validationDisplay = useValidationDisplay(props.validationDisplay);\n const saveWhenInvalid = useSaveWhenInvalid(props.saveWhenInvalid);\n const needsBlurHandler = blurHandlerNeeded({\n deferStateUpdates,\n deferChanges,\n hasOnBlur: !!onBlur,\n validationDisplay,\n });\n const showFieldErrors = useCallback(\n (fieldName: string): boolean =>\n fieldErrorsVisible(\n validationDisplay,\n submitAttempted,\n touched[fieldName],\n ),\n [validationDisplay, submitAttempted, touched],\n );\n\n // Memoize the rendered field list so the row-layout memo below has a stable\n // dependency. orderedProperties changes only when schema/uiSchema/data change.\n const fields = useMemo(\n () =>\n orderedProperties.flatMap(([fieldName, property]) => {\n // Declarative presentation rule (x-ui-rule): uiSchema entry wins over\n // the schema property. Evaluated against the ROOT form data, so a\n // nested field's rule may reference any field by its pointer from the\n // top of the form -- not merely its own object's slice.\n const rule =\n uiSchema[fieldName]?.[\"x-ui-rule\"] ?? property[\"x-ui-rule\"];\n const { visible, enabled } = evaluateUiRule(rule, rootData);\n if (!visible) return [];\n return [\n <FormFieldRenderer\n key={fieldName}\n fieldName={fieldName}\n property={property}\n value={displayData[fieldName]}\n onChange={(v) => handleFieldChange(fieldName, v)}\n onBlur={\n needsBlurHandler ? () => handleFieldBlur(fieldName) : undefined\n }\n required={isFieldRequired(resolvedSchema, fieldName)}\n disabled={disabled || !enabled}\n readOnly={readOnly}\n schema={schema}\n uiSchema={uiSchema[fieldName]}\n registry={widgets}\n globalOptions={globalOptions}\n formData={displayData}\n idPrefix={idPrefix}\n rawErrors={\n showFieldErrors(fieldName)\n ? fieldErrors\n .filter((e) => pointerRoot(e.pointer) === fieldName)\n .map((e) => e.message)\n : undefined\n }\n />,\n ];\n }),\n [\n orderedProperties,\n displayData,\n rootData,\n resolvedSchema,\n disabled,\n readOnly,\n schema,\n uiSchema,\n widgets,\n globalOptions,\n idPrefix,\n needsBlurHandler,\n showFieldErrors,\n fieldErrors,\n handleFieldChange,\n handleFieldBlur,\n ],\n );\n\n // Read row/tab layout config from the uiSchema.\n const layoutConfig = uiSchema[\"x-ui-layout\"] as UILayoutConfig | undefined;\n const rowDefs = layoutConfig?.rows;\n const groupDefs = layoutConfig?.groups;\n // Default gap used within rows when no per-row gap is specified.\n const defaultRowGap = layoutConfig?.gap ?? 24;\n\n const groupTemplate = resolveGroupTemplate(\n resolvedTemplates,\n layoutConfig?.variant,\n );\n\n // Groups take precedence over flat rows (each group carries its own rows).\n // When neither is configured, fields render as a plain vertical stack. Fields\n // not placed by the active layout are appended so nothing is hidden.\n const layoutFields = useMemo(() => {\n if (groupDefs && groupDefs.length > 0) {\n return layoutFieldsInGroups(\n fields,\n groupDefs,\n defaultRowGap,\n fieldErrors,\n // Tab rules are x-ui-rule too: root-anchored like field rules.\n rootData,\n groupTemplate,\n );\n }\n if (rowDefs && rowDefs.length > 0) {\n return layoutFieldsInRows(fields, rowDefs, defaultRowGap);\n }\n return fields;\n }, [\n fields,\n rowDefs,\n groupDefs,\n defaultRowGap,\n fieldErrors,\n rootData,\n groupTemplate,\n ]);\n\n // Errors the user cannot see because their tab is hidden. Surfaced next to\n // the actions so a disabled Save always has a visible explanation.\n const hiddenErrorCount = useMemo(() => {\n if (!groupDefs?.length || fieldErrors.length === 0) return 0;\n const hidden = hiddenGroupFieldNames(groupDefs, rootData);\n if (hidden.size === 0) return 0;\n return fieldErrors.filter((e) => hidden.has(pointerRoot(e.pointer))).length;\n }, [groupDefs, fieldErrors, rootData]);\n\n return (\n <NestedFormContext.Provider value={contextValue}>\n <FormContainer\n displayContents={displayContents}\n showExtraProperties={showExtraProperties}\n showActions={showActions}\n formData={formData}\n resolvedSchema={resolvedSchema}\n handleSave={handleSave}\n handleCancel={handleCancel}\n disabled={disabled}\n hasChanges={hasChanges || allowPristineSave}\n isValid={isValid}\n saveWhenInvalid={saveWhenInvalid}\n saveLabel={saveLabel}\n cancelLabel={cancelLabel}\n showCancel={showCancel}\n leadingActions={leadingActions}\n hiddenErrorCount={hiddenErrorCount}\n >\n {layoutFields}\n </FormContainer>\n </NestedFormContext.Provider>\n );\n}\n","/**\n * Widget Type System\n *\n * Type definitions for the JSON Schema Form widget architecture.\n * Based on react-jsonschema-form patterns with simplified Mantine-focused implementation.\n */\n\nimport {\n JsonSchema,\n JsonSchemaProperty,\n UISchema,\n UILayoutConfig,\n UISchemaOptions,\n} from \"@petrarca/sonnet-core/schema\";\nimport { ComponentType } from \"react\";\n\n// Re-export for convenience\nexport type {\n UISchema,\n UISchemaOptions,\n UILayoutConfig,\n} from \"@petrarca/sonnet-core/schema\";\n\n/**\n * WidgetRegistry - Map of widget name to component\n *\n * @example\n * ```typescript\n * const registry: WidgetRegistry = {\n * TextWidget: TextWidget,\n * SelectWidget: SelectWidget,\n * CustomWidget: MyCustomWidget\n * }\n * ```\n */\nexport type WidgetRegistry = {\n [widgetName: string]: Widget;\n};\n\n/**\n * WidgetProps - Props passed to every widget\n *\n * Widgets receive comprehensive context to make intelligent decisions.\n * All widgets must accept these props.\n *\n * @example\n * ```typescript\n * export function MyWidget({\n * id,\n * value,\n * onChange,\n * label,\n * propertySchema,\n * options\n * }: WidgetProps) {\n * const customOption = options?.myCustomOption ?? 'default';\n * // ...\n * }\n * ```\n */\nexport interface WidgetProps {\n // Identification\n /** Unique field ID */\n id: string;\n /** Field name */\n name: string;\n\n // Schema Context - Full access to make informed decisions\n /** Full form schema */\n schema: JsonSchema;\n /** This field's schema */\n propertySchema: JsonSchemaProperty;\n /** UI configuration for this field */\n uiSchema?: UISchema;\n /** Access to all widgets */\n registry: WidgetRegistry;\n\n // Data & Events\n /** Current field value */\n value: unknown;\n /** Called when value changes */\n onChange: (value: unknown) => void;\n /** Called when field loses focus */\n onBlur?: (id: string, value: unknown) => void;\n /** Called when field gains focus */\n onFocus?: (id: string, value: unknown) => void;\n\n // Form Context\n /** Current form data - all field values (for dependent/cascading widgets) */\n formData?: Record<string, unknown>;\n\n // Display\n /** Field label (empty string = hidden) */\n label: string;\n /** Field description */\n description?: string;\n /** Placeholder text */\n placeholder?: string;\n\n // State\n /** Is field required */\n required?: boolean;\n /** Is field disabled */\n disabled?: boolean;\n /** Is field readonly */\n readonly?: boolean;\n /** Should field autofocus */\n autofocus?: boolean;\n\n // Validation\n /** Raw validation errors */\n rawErrors?: string[];\n\n // Options - Widget accesses x-ui-options for any configuration it needs\n /** Widget-specific options from x-ui-options */\n options?: UISchemaOptions;\n}\n\n/**\n * Widget - React component type for form widgets\n *\n * @example\n * ```typescript\n * const TextWidget: Widget = ({ id, value, onChange, label }) => (\n * <TextInput id={id} value={value} onChange={e => onChange(e.target.value)} label={label} />\n * );\n * ```\n */\nexport type Widget = ComponentType<WidgetProps>;\n\n/**\n * WidgetDescriptor - Extended information for widget registration\n *\n * Allows providing metadata along with the widget component.\n *\n * @example\n * ```typescript\n * const descriptor: WidgetDescriptor = {\n * component: MyWidget,\n * displayName: 'My Custom Widget',\n * description: 'A widget for custom input',\n * defaultOptions: { rows: 3 }\n * }\n * ```\n */\nexport interface WidgetDescriptor {\n /** The widget component */\n component: Widget;\n /** Display name for debugging */\n displayName?: string;\n /** Description of what the widget does */\n description?: string;\n /** Default options to apply */\n defaultOptions?: UISchemaOptions;\n}\n\n/**\n * WidgetMap - Type/format to widget name mapping\n *\n * Defines the default widget to use for each schema type and format.\n *\n * @example\n * ```typescript\n * const map: WidgetMap = {\n * string: {\n * default: 'TextWidget',\n * email: 'EmailWidget',\n * textarea: 'TextareaWidget'\n * }\n * }\n * ```\n */\nexport type WidgetMap = {\n [schemaType: string]: {\n [variantOrFormat: string]: string;\n };\n};\n\n/**\n * Return the first validation error message, or undefined if there are none.\n * Avoids repeating `rawErrors && rawErrors.length > 0 ? rawErrors[0] : undefined`\n * in every widget.\n */\nexport function firstError(rawErrors?: string[]): string | undefined {\n return rawErrors && rawErrors.length > 0 ? rawErrors[0] : undefined;\n}\n\n/**\n * SelectOption - Single option in a select dropdown\n */\nexport interface SelectOption {\n value: string;\n label: string;\n}\n\n// Templates -- rendering functions for structural layout concerns.\n// Separate from widgets (which render input controls).\n// Injected via JsonSchemaFormRenderer's `templates` prop or per-field\n// via x-ui-options.itemTemplate / x-ui-options.containerTemplate.\n\n/** Props passed to an ArrayItemTemplate */\nexport interface ArrayItemTemplateProps {\n children: React.ReactNode;\n index: number;\n total: number;\n canRemove: boolean;\n orderable: boolean;\n disabled?: boolean;\n layout: UILayoutConfig;\n fieldCount: number;\n /**\n * Stable form-internal item id (_fid). Rendered as `data-fid` on the item\n * container so tests can target a specific item across reorders (the\n * positional `index` is not stable).\n */\n fid?: string;\n onRemove: () => void;\n onMoveUp?: () => void;\n onMoveDown?: () => void;\n}\n\n/** Props passed to an ArrayHeaderTemplate */\nexport interface ArrayHeaderTemplateProps {\n itemSchema: JsonSchemaProperty;\n layout: UILayoutConfig;\n canRemove: boolean;\n orderable: boolean;\n fieldCount: number;\n}\n\n/** Props passed to an ObjectContainerTemplate */\nexport interface ObjectContainerTemplateProps {\n children: React.ReactNode;\n label: string;\n description?: string;\n variant?: string;\n defaultOpen?: boolean;\n}\n\n/**\n * One group of fields in a grouped layout (a tab, a wizard step, a section).\n * `content` is already laid out -- the template only decides how groups are\n * presented and navigated.\n */\nexport interface FieldGroup {\n /** Stable key for React and for the template's own selection state. */\n key: string;\n /** Label shown on the group's trigger, step header or section legend. */\n label: string;\n /** The group's rendered rows. */\n content: React.ReactNode;\n /** Validation errors owned by this group's fields (for a badge). */\n errorCount: number;\n}\n\n/** Props passed to a GroupLayoutTemplate */\nexport interface GroupLayoutTemplateProps {\n /** The visible groups, in declaration order. Never empty. */\n groups: FieldGroup[];\n}\n\n/**\n * Presents a set of field groups: as tabs, as a wizard, as an accordion --\n * whatever the registered template renders. Selected by\n * `x-ui-layout.variant`, which maps to a TemplateRegistry key, so consumers\n * can register their own presentation without changing the renderer.\n */\nexport type GroupLayoutTemplate = (\n props: GroupLayoutTemplateProps,\n) => React.ReactElement;\n\nexport type ArrayItemTemplate = (\n props: ArrayItemTemplateProps,\n) => React.ReactElement;\n\nexport type ArrayHeaderTemplate = (\n props: ArrayHeaderTemplateProps,\n) => React.ReactElement | null;\n\nexport type ObjectContainerTemplate = (\n props: ObjectContainerTemplateProps,\n) => React.ReactElement;\n\n/**\n * TemplateRegistry -- named rendering functions for structural layout.\n *\n * Built-in keys: ArrayItemTemplate, ArrayHeaderTemplate, ObjectContainerTemplate.\n * Custom keys are allowed for per-field template overrides (looked up by name).\n * The index signature uses `unknown` to avoid TypeScript variance conflicts with\n * the specifically-typed named properties.\n */\nexport type TemplateRegistry = {\n ArrayItemTemplate?: ArrayItemTemplate;\n HorizontalArrayItemTemplate?: ArrayItemTemplate;\n ArrayHeaderTemplate?: ArrayHeaderTemplate;\n ObjectContainerTemplate?: ObjectContainerTemplate;\n /** Group presentations, selected by x-ui-layout.variant (default \"tabs\"). */\n TabsGroupTemplate?: GroupLayoutTemplate;\n StepperGroupTemplate?: GroupLayoutTemplate;\n SectionsGroupTemplate?: GroupLayoutTemplate;\n [templateName: string]: unknown;\n};\n","/**\n * TextInputWidget - Standard text input widget\n *\n * Renders a single-line text input field using FormInput.\n * Supports various input types via format (email, url, text).\n */\n\nimport { FormInput } from \"../FormInput\";\nimport { WidgetProps, firstError } from \"./types\";\n\n// Determine HTML input type based on JSON Schema format.\nfunction inputTypeFromFormat(format: string | undefined): string {\n if (format === \"email\") return \"email\";\n if (format === \"uri\" || format === \"url\") return \"url\";\n return \"text\";\n}\n\n/**\n * TextInputWidget renders a standard text input field.\n *\n * Supports:\n * - Basic string input\n * - Email input (format: 'email')\n * - URL input (format: 'uri' or 'url')\n * - Validation constraints (minLength, maxLength, pattern)\n */\nexport function TextInputWidget({\n id,\n name,\n value,\n onChange,\n onBlur,\n propertySchema,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n placeholder,\n autofocus,\n options,\n}: WidgetProps): React.ReactElement {\n const error = firstError(rawErrors);\n const compact = options?.compact;\n\n return (\n <FormInput\n id={id}\n name={name}\n value={value !== undefined && value !== null ? String(value) : \"\"}\n onChange={(event) => onChange(event.currentTarget.value)}\n onBlur={() => onBlur?.(id, value)}\n label={label}\n labelPlacement={options?.labelPlacement}\n description={description}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n type={options?.inputType ?? inputTypeFromFormat(propertySchema.format)}\n minLength={propertySchema.minLength}\n maxLength={propertySchema.maxLength}\n autoFocus={autofocus}\n compact={compact as boolean | undefined}\n className={compact ? \"h-8 text-xs\" : undefined}\n />\n );\n}\n","/**\n * TextareaWidget - Multi-line text input\n *\n * Renders a multi-line textarea field using FormTextarea.\n * Supports autosize and configurable rows.\n */\n\nimport { FormTextarea } from \"../FormTextarea\";\nimport { WidgetProps, firstError } from \"./types\";\n\n/**\n * TextareaWidget renders a multi-line text input field.\n *\n * Supports:\n * - Multi-line text input\n * - Autosize functionality\n * - Configurable minimum rows via x-ui-options\n * - Validation constraints (minLength, maxLength)\n *\n * @param props - WidgetProps\n */\nexport function TextareaWidget({\n id,\n name,\n value,\n onChange,\n onBlur,\n propertySchema,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n placeholder,\n autofocus,\n options = {},\n}: WidgetProps) {\n const minRows = options.rows || options.minRows || 3;\n const autosize = options.autosize !== false; // Default to true\n\n const error = firstError(rawErrors);\n\n return (\n <FormTextarea\n id={id}\n name={name}\n value={value !== undefined && value !== null ? String(value) : \"\"}\n onChange={(event) => onChange(event.currentTarget.value)}\n onBlur={() => onBlur?.(id, value)}\n label={label}\n labelPlacement={options?.labelPlacement}\n description={description}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n minRows={minRows}\n autosize={autosize}\n minLength={propertySchema.minLength}\n maxLength={propertySchema.maxLength}\n autoFocus={autofocus}\n />\n );\n}\n","/**\n * NumberWidget - Number/Integer input widget\n *\n * Renders a number input field using FormNumberInput.\n * Handles both number and integer types with appropriate step values.\n */\n\nimport { FormNumberInput } from \"../FormNumberInput\";\nimport { WidgetProps, firstError } from \"./types\";\n\n/**\n * NumberWidget renders a number input field.\n *\n * Supports:\n * - Number input (decimal allowed)\n * - Integer input (step = 1, no decimals)\n * - Min/max constraints from schema\n * - Step configuration via x-ui-options\n *\n * @param props - WidgetProps\n */\nexport function NumberWidget({\n id,\n name,\n value,\n onChange,\n onBlur,\n propertySchema,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n placeholder,\n autofocus,\n options = {},\n}: WidgetProps) {\n const isInteger = propertySchema.type === \"integer\";\n const step = options.step ?? (isInteger ? 1 : undefined);\n const allowDecimal = options.allowDecimal ?? !isInteger;\n\n const error = firstError(rawErrors);\n\n return (\n <FormNumberInput\n id={id}\n name={name}\n value={value !== undefined && value !== null ? Number(value) : undefined}\n onChange={(val) => onChange(val)}\n onBlur={() => onBlur?.(id, value)}\n label={label}\n labelPlacement={options.labelPlacement}\n description={description}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n min={propertySchema.minimum}\n max={propertySchema.maximum}\n step={step}\n allowDecimal={allowDecimal}\n autoFocus={autofocus}\n />\n );\n}\n","/**\n * CheckboxWidget - Boolean checkbox widget\n *\n * Renders a checkbox input using FormCheckbox.\n * Used for boolean type fields.\n *\n * Supports tri-state behavior for nullable boolean fields (anyOf[boolean, null]):\n * - null (indeterminate) -> true (checked) -> false (unchecked) -> null\n */\n\nimport { useCallback } from \"react\";\nimport { FormCheckbox } from \"../FormCheckbox\";\nimport { isNullableBoolean } from \"@petrarca/sonnet-core/schema\";\nimport { WidgetProps, firstError } from \"./types\";\n\n/**\n * CheckboxWidget renders a checkbox for boolean values.\n *\n * Supports:\n * - Boolean true/false values (standard checkbox)\n * - Tri-state true/false/null values (indeterminate checkbox)\n * - Custom labels from schema or UISchema\n * - Description text\n *\n * Tri-state behavior (when anyOf[boolean, null] is detected):\n * - Click on null -> becomes true\n * - Click on true -> becomes false\n * - Click on false -> becomes null\n */\nexport function CheckboxWidget({\n id,\n value,\n onChange,\n onBlur,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n autofocus,\n propertySchema,\n options,\n}: WidgetProps): React.ReactElement {\n const error = firstError(rawErrors);\n const compact = options?.compact;\n\n // Detect if this is a nullable boolean (tri-state)\n const isTriState = isNullableBoolean(propertySchema);\n\n // Determine checkbox state\n const isChecked = value === true;\n const isIndeterminate = isTriState && value === null;\n const checkedState: boolean | \"indeterminate\" = isIndeterminate\n ? \"indeterminate\"\n : isChecked;\n\n // Handle change with tri-state logic\n const handleChange = useCallback(\n (_newChecked: boolean | \"indeterminate\") => {\n if (isTriState) {\n if (value === null) {\n onChange(true);\n } else if (value === true) {\n onChange(false);\n } else {\n onChange(null);\n }\n } else {\n onChange(_newChecked === true);\n }\n },\n [isTriState, value, onChange],\n );\n\n return (\n <FormCheckbox\n id={id}\n checked={checkedState}\n onChange={handleChange}\n onBlur={() => onBlur?.(id, value)}\n label={label}\n description={description}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n autoFocus={autofocus}\n compact={compact as boolean | undefined}\n />\n );\n}\n","/**\n * SelectWidget - Dropdown selection widget\n *\n * Renders a dropdown select field using FormSelect or FormMultiSelect.\n * Used for enum fields with a list of predefined options.\n * Supports both single-select (returns string) and multi-select (returns array) modes.\n */\n\nimport { useRef } from \"react\";\nimport { FormSelect } from \"../FormSelect\";\nimport { FormMultiSelect } from \"../FormMultiSelect\";\nimport { extractEnumValues } from \"@petrarca/sonnet-core/schema\";\nimport { badgeVariants } from \"@petrarca/sonnet-ui\";\nimport type { VariantProps } from \"class-variance-authority\";\nimport { WidgetProps, firstError } from \"./types\";\n\ntype BadgeColor = NonNullable<VariantProps<typeof badgeVariants>[\"badgeColor\"]>;\n\n/**\n * SelectWidget renders a dropdown select for enum values.\n *\n * Supports:\n * - Enum values from schema\n * - Custom display names via x-ui-options.enumNames\n * - Searchable dropdown\n * - Clearable option (when not required)\n * - Multi-select mode (auto-detected from schema type='array' or explicit multiple option)\n * - Custom badge colors for multi-select mode\n *\n * @param props - WidgetProps\n */\n/** Build select options from enum values with optional display names. */\nfunction buildSelectOptions(\n propertySchema: WidgetProps[\"propertySchema\"],\n enumNames: Record<string | number, string>,\n) {\n const enumValues = extractEnumValues(propertySchema);\n return enumValues.map((val) => {\n const key = String(val);\n return { value: key, label: enumNames[key] || key };\n });\n}\n\n/** Normalize a value into a string array for multi-select. */\nfunction normalizeMultiValue(value: unknown): string[] {\n if (Array.isArray(value)) return value.map(String);\n if (value) return [String(value)];\n return [];\n}\n\n/** Normalize a value into a string or null for single-select. */\nfunction normalizeSingleValue(value: unknown): string | null {\n if (value !== undefined && value !== null) return String(value);\n return null;\n}\n\nexport function SelectWidget(props: WidgetProps) {\n const {\n id,\n name,\n value,\n onChange,\n onBlur,\n propertySchema,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n placeholder,\n autofocus,\n } = props;\n const widgetOptions = props.options ?? {};\n\n const valueRef = useRef(value);\n valueRef.current = value;\n\n const enumNames = widgetOptions.enumNames || {};\n const clearable = widgetOptions.clearable !== false && !required;\n const isMultiple = widgetOptions.multiple ?? propertySchema.type === \"array\";\n const creatable = !!widgetOptions.creatable;\n const selectOptions = buildSelectOptions(propertySchema, enumNames);\n const error = firstError(rawErrors);\n const compact = widgetOptions?.compact;\n const triggerClassName = compact ? \"h-8 text-xs\" : undefined;\n const handleBlur = () => onBlur?.(id, valueRef.current);\n\n if (isMultiple) {\n return (\n <FormMultiSelect\n id={id}\n name={name}\n options={selectOptions}\n value={normalizeMultiValue(value)}\n onChange={(newValue) => onChange(newValue || [])}\n label={label}\n labelPlacement={widgetOptions.labelPlacement}\n description={description}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n clearable={clearable}\n autoFocus={autofocus}\n badgeColor={widgetOptions.badgeColor as BadgeColor | undefined}\n onBlur={handleBlur}\n className={triggerClassName}\n />\n );\n }\n\n return (\n <FormSelect\n id={id}\n name={name}\n options={selectOptions}\n value={normalizeSingleValue(value)}\n onChange={(val) => onChange(val || \"\")}\n label={label}\n labelPlacement={widgetOptions.labelPlacement}\n description={description}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n clearable={clearable}\n autoFocus={autofocus}\n onBlur={handleBlur}\n className={triggerClassName}\n compact={compact}\n allowCreate={creatable}\n onCreate={(label) => onChange(label)}\n />\n );\n}\n","/**\n * TagsInputWidget - Free-text tag input widget\n *\n * Renders FormTagsInput for array-of-string fields where the user types\n * free-text values (no predefined enum). Tags are entered by pressing\n * Enter or comma and displayed as dismissible badges. Duplicates are\n * rejected by default.\n *\n * Use via x-ui-widget: \"tags\" in a JSON Schema or Zod .meta().\n */\n\nimport React from \"react\";\nimport { FormTagsInput } from \"../FormTagsInput\";\nimport { type WidgetProps, firstError } from \"./types\";\n\n/**\n * TagsInputWidget renders a free-text tag input field.\n *\n * Supports:\n * - Free-text tag creation (Enter or comma)\n * - Duplicate rejection (default)\n * - Max tags limit (via x-ui-options.maxTags)\n * - Custom split keys (via x-ui-options.splitKeys)\n */\nexport function TagsInputWidget({\n id,\n name,\n value,\n onChange,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n placeholder,\n options,\n}: WidgetProps): React.ReactElement {\n const error = firstError(rawErrors);\n const tags = Array.isArray(value) ? value.map(String) : [];\n\n return (\n <FormTagsInput\n id={id}\n name={name}\n value={tags}\n onChange={(newTags) => onChange(newTags)}\n label={label}\n labelPlacement={options?.labelPlacement}\n description={description}\n placeholder={placeholder ?? \"Type and press Enter\"}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n maxTags={options?.maxTags as number | undefined}\n splitKeys={options?.splitKeys as string[] | undefined}\n allowDuplicates={false}\n />\n );\n}\n","/**\n * JsonEditorWidget - JSON document editor widget.\n *\n * Renders JsonEditor for object/any fields where the user authors raw JSON.\n * The full document is editable. Invalid JSON is not propagated -- the last\n * valid value is retained until the user fixes the syntax error.\n *\n * Use via x-ui-widget: \"json-editor\" in a JSON Schema or Zod .meta().\n */\n\nimport React, { useCallback, useState } from \"react\";\nimport { JsonEditor } from \"@petrarca/sonnet-ui/json-editor\";\nimport { type WidgetProps } from \"./types\";\n\n// Single editable path covering the full document.\nconst FULL_DOCUMENT: string[] = [\"/\"];\n\n/**\n * JsonEditorWidget renders a full-document JSON editor.\n *\n * Supports:\n * - Full document editing (no readonly regions)\n * - Invalid JSON is silently retained until fixed\n * - Height configurable via x-ui-options.height (default: \"240px\")\n */\nexport function JsonEditorWidget({\n id,\n value,\n onChange,\n label,\n description,\n required,\n options,\n}: WidgetProps): React.ReactElement {\n const [raw, setRaw] = useState(\n value != null ? JSON.stringify(value, null, 2) : \"\",\n );\n\n const height = (options?.height as string | undefined) ?? \"240px\";\n\n const handleChange = useCallback(\n (val: string) => {\n setRaw(val);\n try {\n const parsed: unknown = JSON.parse(val);\n onChange(parsed);\n } catch {\n // Hold the last valid value -- do not propagate invalid JSON.\n }\n },\n [onChange],\n );\n\n return (\n <div className=\"space-y-2\">\n {label && (\n <label htmlFor={id} className=\"text-sm font-medium leading-none\">\n {label}\n {required && <span className=\"text-destructive ml-1\">*</span>}\n </label>\n )}\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n <JsonEditor\n value={raw}\n editablePaths={FULL_DOCUMENT}\n onChange={handleChange}\n height={height}\n className=\"rounded-md border overflow-hidden\"\n />\n </div>\n );\n}\n","/**\n * EntitySelectWidget -- form widget for async entity reference selection.\n *\n * Wraps EntitySelect and adapts it to the WidgetProps contract. Reads\n * x-ui-options for fetcher configuration (REST or GraphQL) and uses the\n * FetcherProvider context to create the appropriate fetcher.\n *\n * Schema usage:\n * x-ui-widget: \"entity-select\"\n * x-ui-options: {\n * endpoint: \"/organizations\", // REST: relative to API base\n * valueKey: \"org_id\",\n * labelKey: \"name\",\n * }\n * -- or --\n * x-ui-options: {\n * query: \"query Orgs($search: String, $limit: Int) { ... }\",\n * dataPath: \"organizations\",\n * valueKey: \"org_id\",\n * labelKey: \"name\",\n * }\n */\n\nimport React, { useMemo } from \"react\";\nimport { EntitySelect } from \"@petrarca/sonnet-ui\";\nimport { useFetcherFactory } from \"@petrarca/sonnet-core/entityOptions\";\nimport type { EntitySelectMode } from \"@petrarca/sonnet-core/hooks\";\nimport type { WidgetProps, UISchemaOptions } from \"./types\";\nimport { firstError } from \"./types\";\nimport type {\n RestFetcherConfig,\n GraphqlFetcherConfig,\n} from \"@petrarca/sonnet-core/entityOptions\";\n\n// ---------------------------------------------------------------------------\n// Pure helpers\n// ---------------------------------------------------------------------------\n\nconst VALID_MODES: EntitySelectMode[] = [\"eager\", \"typeahead\", \"explicit\"];\n\n/** Resolve the select mode from widget options. */\nfunction resolveSelectMode(\n options: UISchemaOptions | undefined,\n): EntitySelectMode {\n const rawMode = options?.mode;\n if (\n typeof rawMode === \"string\" &&\n VALID_MODES.includes(rawMode as EntitySelectMode)\n ) {\n return rawMode as EntitySelectMode;\n }\n return \"eager\";\n}\n\n/** Resolve the minimum character threshold. */\nfunction resolveMinChars(options: UISchemaOptions | undefined): number {\n const rawMinChars = options?.minChars;\n if (typeof rawMinChars === \"number\" && rawMinChars >= 1) return rawMinChars;\n return 1;\n}\n\n/** Build a REST fetcher config from options. */\nfunction buildRestConfig(options: UISchemaOptions): RestFetcherConfig | null {\n if (!(\"endpoint\" in options) || !options.endpoint) return null;\n const rawExtra = options.extraParams;\n const extraParams =\n rawExtra && typeof rawExtra === \"object\"\n ? (rawExtra as Record<string, string>)\n : undefined;\n return {\n endpoint: String(options.endpoint),\n valueKey: String(options.valueKey ?? \"id\"),\n labelKey: String(options.labelKey ?? \"name\"),\n searchKey: options.searchKey ? String(options.searchKey) : undefined,\n extraParams,\n };\n}\n\n/** Build a GraphQL fetcher config from options. */\nfunction buildGraphqlConfig(\n options: UISchemaOptions,\n): GraphqlFetcherConfig | null {\n if (!(\"query\" in options) || !options.query) return null;\n return {\n query: String(options.query),\n dataPath: String(options.dataPath ?? \"\"),\n valueKey: String(options.valueKey ?? \"id\"),\n labelKey: String(options.labelKey ?? \"name\"),\n };\n}\n\n/** Build fetcher config from widget options. Returns null if insufficient config. */\nfunction buildFetcherConfig(\n options: UISchemaOptions | undefined,\n): RestFetcherConfig | GraphqlFetcherConfig | null {\n if (!options) return null;\n return buildRestConfig(options) ?? buildGraphqlConfig(options);\n}\n\n/** Derive a stable query key from the fetcher config. */\nfunction deriveQueryKey(\n config: RestFetcherConfig | GraphqlFetcherConfig | null,\n fallbackName: string,\n): string {\n if (!config) return fallbackName;\n if (\"endpoint\" in config) return config.endpoint;\n return `graphql:${config.dataPath}`;\n}\n\n// ---------------------------------------------------------------------------\n// EntitySelectWidget\n// ---------------------------------------------------------------------------\n\nexport function EntitySelectWidget({\n id,\n name,\n value,\n onChange,\n onBlur,\n label,\n description,\n placeholder,\n required,\n disabled,\n readonly,\n rawErrors,\n options,\n}: WidgetProps): React.ReactElement {\n const createFetcher = useFetcherFactory();\n\n const selectMode = resolveSelectMode(options);\n const selectMinChars = resolveMinChars(options);\n\n const fetcherConfig = useMemo(() => buildFetcherConfig(options), [options]);\n const fetcher = useMemo(() => {\n if (!fetcherConfig) return null;\n return createFetcher(fetcherConfig);\n }, [createFetcher, fetcherConfig]);\n const queryKey = useMemo(\n () => deriveQueryKey(fetcherConfig, name ?? \"\"),\n [fetcherConfig, name],\n );\n\n if (!fetcher) {\n return (\n <div className=\"text-sm text-destructive\">\n EntitySelectWidget: missing endpoint or query in x-ui-options for field\n &quot;{name}&quot;\n </div>\n );\n }\n\n return (\n <EntitySelect\n id={id}\n fetcher={fetcher}\n queryKey={queryKey}\n mode={selectMode}\n minChars={selectMinChars}\n value={typeof value === \"string\" ? value : null}\n onChange={(v) => onChange(v ?? null)}\n onBlur={() => onBlur?.(id, value)}\n label={label || false}\n description={description}\n placeholder={placeholder}\n required={required}\n clearable={!required}\n disabled={disabled || readonly}\n error={firstError(rawErrors)}\n />\n );\n}\n","/**\n * ObjectWidget -- renders a nested sub-form for type: \"object\" properties.\n *\n * Composes a JsonSchemaFormRenderer scoped to the sub-schema. The renderer\n * is injected via NestedFormContext so there is no circular import.\n *\n * Presentation is delegated to ObjectContainerTemplate (resolved from context,\n * defaulting to DefaultObjectContainerTemplate). The variant passed via\n * options controls which container is used (section, card, collapsible,\n * inline, borderless).\n *\n * When options.displayContents is true (set by ArrayWidget in horizontal mode)\n * the sub-renderer uses display:contents so its field divs become direct grid\n * cells in the parent row grid.\n *\n * When options.globalOptions is set, it is forwarded to the sub-renderer so\n * compact / label suppression propagates to all nested widgets.\n */\n\nimport { useMemo } from \"react\";\nimport type {\n JsonSchema,\n JsonSchemaProperty,\n UILayoutConfig,\n UISchema,\n} from \"@petrarca/sonnet-core/schema\";\nimport { useNestedFormContext } from \"../hooks/useNestedFormContext\";\nimport { DefaultObjectContainerTemplate } from \"../templates/DefaultObjectContainerTemplate\";\nimport type { WidgetProps } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Pure helpers\n// ---------------------------------------------------------------------------\n\n/** Build a JsonSchema from the property's nested structure. */\nfunction buildSubSchema(prop: JsonSchemaProperty): JsonSchema | null {\n const properties = prop.properties;\n if (!properties) return null;\n return {\n title: prop.title || \"\",\n type: \"object\",\n properties,\n required: prop.required,\n ...(prop.allOf ? { allOf: prop.allOf } : {}),\n ...(prop.if ? { if: prop.if } : {}),\n ...(prop.then ? { then: prop.then } : {}),\n ...(prop.else ? { else: prop.else } : {}),\n ...(prop[\"x-ui-order\"] ? { \"x-ui-order\": prop[\"x-ui-order\"] } : {}),\n };\n}\n\n/** Merge field-level uiSchema with globalOptions and layout for sub-renderer. */\nfunction buildEffectiveUiSchema(\n subUiSchema: { [fieldName: string]: UISchema },\n globalOptions: Record<string, unknown> | undefined,\n layout: UILayoutConfig | undefined,\n): { [fieldName: string]: UISchema } {\n return {\n ...subUiSchema,\n ...(globalOptions\n ? { \"x-ui-globalOptions\": globalOptions as UISchema }\n : {}),\n ...(layout ? { \"x-ui-layout\": layout as unknown as UISchema } : {}),\n };\n}\n\n/** Extract typed options from the generic options bag. */\nfunction resolveObjectOptions(options: WidgetProps[\"options\"]) {\n return {\n variant: (options?.variant as string) || \"section\",\n defaultOpen: options?.defaultOpen !== false,\n displayContents: (options?.displayContents as boolean) ?? false,\n globalOptions: options?.globalOptions as\n | Record<string, unknown>\n | undefined,\n };\n}\n\n/** Resolve layout from uiSchema and property schema. */\nfunction resolveLayout(\n uiSchema: WidgetProps[\"uiSchema\"],\n propertySchema: JsonSchemaProperty,\n): UILayoutConfig | undefined {\n return (\n (uiSchema?.[\"x-ui-layout\"] as UILayoutConfig | undefined) ??\n propertySchema[\"x-ui-layout\"]\n );\n}\n\n// ---------------------------------------------------------------------------\n// ObjectWidget\n// ---------------------------------------------------------------------------\n\nexport function ObjectWidget({\n id,\n propertySchema,\n value,\n onChange,\n onBlur,\n registry,\n uiSchema,\n disabled,\n readonly,\n label,\n description,\n options,\n}: WidgetProps): React.ReactElement | null {\n const { renderer: Renderer, templates } = useNestedFormContext();\n const ContainerTemplate =\n templates.ObjectContainerTemplate ?? DefaultObjectContainerTemplate;\n\n const subSchema = useMemo(\n () => buildSubSchema(propertySchema),\n [propertySchema],\n );\n\n const subUiSchema = useMemo(\n () =>\n (uiSchema?.[\"x-ui-fields\"] ?? {}) as { [fieldName: string]: UISchema },\n [uiSchema],\n );\n\n if (!subSchema) return null;\n\n const { variant, defaultOpen, displayContents, globalOptions } =\n resolveObjectOptions(options);\n const layout = resolveLayout(uiSchema, propertySchema);\n const effectiveUiSchema = buildEffectiveUiSchema(\n subUiSchema,\n globalOptions,\n layout,\n );\n\n const content = (\n <Renderer\n schema={subSchema}\n data={(value as Record<string, unknown>) || {}}\n onChange={onChange}\n disabled={disabled}\n readOnly={readonly}\n widgets={registry}\n uiSchema={effectiveUiSchema}\n displayContents={displayContents}\n // Scope the sub-form's control ids to this object. Without it every\n // array item's fields share the sub-renderer's default prefix, so\n // `htmlFor` and `aria-describedby` bind to the first item's controls.\n idPrefix={id}\n // Bridge a nested field's blur up to this object's own field blur. The\n // parent holds a deferred change until its field blurs; without this the\n // blur never arrives and the change is stranded.\n onBlur={onBlur ? () => onBlur(id, value) : undefined}\n />\n );\n\n if (displayContents) return <>{content}</>;\n\n return (\n <ContainerTemplate\n label={label}\n description={description}\n variant={variant}\n defaultOpen={defaultOpen}\n >\n {content}\n </ContainerTemplate>\n );\n}\n","/**\n * useNestedFormContext -- returns the renderer and templates injected by\n * the nearest JsonSchemaFormRenderer via NestedFormContext.\n *\n * Used by ObjectWidget and ArrayWidget to render nested sub-forms and\n * resolve layout templates without a circular import.\n *\n * Throws if called outside a JsonSchemaFormRenderer tree. This is\n * intentional: ObjectWidget and ArrayWidget cannot function without\n * the renderer context, and a clear error is better than a silent null.\n */\n\nimport { useContext } from \"react\";\nimport { NestedFormContext } from \"../NestedFormContext\";\nimport type { NestedFormContextValue } from \"../NestedFormContext\";\n\nexport function useNestedFormContext(): NestedFormContextValue {\n const ctx = useContext(NestedFormContext);\n if (!ctx) {\n throw new Error(\n \"useNestedFormContext must be used inside a JsonSchemaFormRenderer.\",\n );\n }\n return ctx;\n}\n","/**\n * NestedFormContext -- provides the JsonSchemaFormRenderer and the active\n * TemplateRegistry to nested widgets (ObjectWidget, ArrayWidget) without\n * creating a circular import.\n *\n * JsonSchemaFormRenderer sets this context on mount. Nested widgets read\n * it via useNestedFormContext() to render sub-forms and resolve templates.\n */\n\nimport { createContext } from \"react\";\nimport type { JsonSchemaFormRendererProps } from \"./JsonSchemaFormRenderer\";\nimport type { TemplateRegistry } from \"./widgets/types\";\n\nexport type NestedRenderer = (\n props: Omit<\n JsonSchemaFormRendererProps,\n \"onUpdate\" | \"onCancel\" | \"showActions\" | \"showExtraProperties\"\n >,\n) => React.ReactElement | null;\n\nexport interface NestedFormContextValue {\n renderer: NestedRenderer;\n templates: TemplateRegistry;\n /**\n * The whole form's data, carried down so a nested renderer can evaluate an\n * `x-ui-rule` scope against the form root rather than its own slice.\n *\n * Every other JSON Pointer in the vocabulary (`editablePaths`, validation\n * error pointers) is root-anchored; without this, a rule on a nested field\n * could only ever see its immediate object, so a rule referencing a\n * top-level field silently never fired.\n *\n * The outermost renderer sets this to its own data; nested renderers inherit\n * it unchanged.\n */\n rootData: Record<string, unknown>;\n}\n\nexport const NestedFormContext = createContext<NestedFormContextValue | null>(\n null,\n);\n","/**\n * DefaultObjectContainerTemplate -- wraps an ObjectWidget sub-form with\n * the appropriate presentation based on the variant option.\n *\n * Variants: section (default), card, collapsible, inline, borderless.\n * Extracted from ObjectWidget so ObjectWidget can delegate to this template\n * or to a caller-supplied replacement.\n */\n\nimport { useState } from \"react\";\nimport { ChevronDown, ChevronRight } from \"lucide-react\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@petrarca/sonnet-ui\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@petrarca/sonnet-ui\";\nimport type { ObjectContainerTemplateProps } from \"../widgets/types\";\n\n// -- Variant sub-components -----------------------------------------------\n\nfunction CardVariant({\n children,\n label,\n description,\n}: {\n children: React.ReactNode;\n label?: string;\n description?: string;\n}) {\n return (\n <Card>\n {label && (\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"text-base\">{label}</CardTitle>\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </CardHeader>\n )}\n <CardContent>{children}</CardContent>\n </Card>\n );\n}\n\nfunction SectionVariant({\n children,\n label,\n description,\n}: {\n children: React.ReactNode;\n label?: string;\n description?: string;\n}) {\n return (\n <div className=\"space-y-3\">\n {label && (\n <div>\n <h4 className=\"text-sm font-medium\">{label}</h4>\n {description && (\n <p className=\"text-xs text-muted-foreground\">{description}</p>\n )}\n </div>\n )}\n <div className=\"pl-3 border-l-2 border-muted\">{children}</div>\n </div>\n );\n}\n\n// -- DefaultObjectContainerTemplate ----------------------------------------\n\nexport function DefaultObjectContainerTemplate({\n children,\n label,\n description,\n variant = \"section\",\n defaultOpen = true,\n}: ObjectContainerTemplateProps): React.ReactElement {\n switch (variant) {\n case \"card\":\n return (\n <CardVariant label={label} description={description}>\n {children}\n </CardVariant>\n );\n\n case \"collapsible\":\n if (!label) return <SectionVariant>{children}</SectionVariant>;\n return (\n <CollapsibleVariant\n label={label}\n description={description}\n defaultOpen={defaultOpen}\n >\n {children}\n </CollapsibleVariant>\n );\n\n case \"inline\":\n return <div>{children}</div>;\n\n case \"borderless\":\n return <div className=\"space-y-4\">{children}</div>;\n\n case \"section\":\n default:\n return (\n <SectionVariant label={label} description={description}>\n {children}\n </SectionVariant>\n );\n }\n}\n\n// Extracted to its own component so Collapsible state is isolated.\nfunction CollapsibleVariant({\n label,\n description,\n defaultOpen,\n children,\n}: {\n label: string;\n description?: string;\n defaultOpen: boolean;\n children: React.ReactNode;\n}): React.ReactElement {\n const [open, setOpen] = useState(defaultOpen);\n\n return (\n <Collapsible open={open} onOpenChange={setOpen}>\n <CollapsibleTrigger asChild>\n <button\n type=\"button\"\n className=\"flex w-full items-center gap-2 text-sm font-medium hover:text-foreground/80\"\n >\n {open ? (\n <ChevronDown className=\"h-4 w-4\" />\n ) : (\n <ChevronRight className=\"h-4 w-4\" />\n )}\n {label}\n </button>\n </CollapsibleTrigger>\n {description && (\n <p className=\"text-xs text-muted-foreground ml-6\">{description}</p>\n )}\n <CollapsibleContent className=\"mt-2 pl-3 border-l-2 border-muted\">\n {children}\n </CollapsibleContent>\n </Collapsible>\n );\n}\n","/**\n * ArrayWidget -- renders a repeatable list of sub-forms for\n * type: \"array\" properties whose items have type: \"object\".\n *\n * Layout is template-driven. The active templates are resolved from\n * NestedFormContext (injected by JsonSchemaFormRenderer):\n * - ArrayItemTemplate -- how each item is wrapped (default: vertical card)\n * - ArrayHeaderTemplate -- column headers for horizontal mode (default: none)\n *\n * Horizontal layout is activated by x-ui-layout.direction: \"horizontal\" on\n * the array property or UISchema. The HorizontalArrayItemTemplate renders a\n * CSS grid row; ObjectWidget sets displayContents=true on the sub-renderer so\n * field divs become direct grid cells.\n *\n * Each item carries a stable form-internal ID (_fid) assigned via generateId().\n * IDs are used as React keys and for structural diffing at save time. They\n * never leave the renderer boundary.\n */\n\nimport { useCallback, useMemo } from \"react\";\nimport { Plus } from \"lucide-react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport { useNestedFormContext } from \"../hooks/useNestedFormContext\";\nimport type { UILayoutConfig } from \"@petrarca/sonnet-core/schema\";\nimport { applySchemaDefaults } from \"@petrarca/sonnet-core/schema\";\nimport { FORM_ITEM_ID_FIELD, generateId } from \"@petrarca/sonnet-core\";\nimport type { WidgetProps, UISchemaOptions } from \"./types\";\nimport { ObjectWidget } from \"./ObjectWidget\";\nimport { DefaultArrayItemTemplate } from \"../templates/DefaultArrayItemTemplate\";\nimport { DefaultArrayHeaderTemplate } from \"../templates/DefaultArrayHeaderTemplate\";\n\n// ---------------------------------------------------------------------------\n// Pure helpers\n// ---------------------------------------------------------------------------\n\nfunction countFields(itemSchema: WidgetProps[\"propertySchema\"]): number {\n return Object.keys(itemSchema.properties ?? {}).length;\n}\n\nfunction allItemsComplete(\n items: Record<string, unknown>[],\n requiredFields: string[],\n): boolean {\n if (requiredFields.length === 0) return true;\n return items.every((item) =>\n requiredFields.every((field) => {\n const v = item[field];\n return v !== undefined && v !== null && v !== \"\";\n }),\n );\n}\n\n/** Ensure every item has a stable _fid. */\nfunction ensureItemIds(value: unknown): Record<string, unknown>[] {\n return (Array.isArray(value) ? value : []).map((item) =>\n item[FORM_ITEM_ID_FIELD]\n ? item\n : { ...item, [FORM_ITEM_ID_FIELD]: generateId() },\n );\n}\n\n/** Strip the _fid from an item for passing to sub-renderer. */\nfunction stripItemId(item: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(item).filter(([k]) => k !== FORM_ITEM_ID_FIELD),\n );\n}\n\n/** Resolve layout config from UISchema and property schema. */\nfunction resolveLayout(\n uiSchema: WidgetProps[\"uiSchema\"],\n propertySchema: WidgetProps[\"propertySchema\"],\n): UILayoutConfig {\n const schemaLayout = propertySchema[\"x-ui-layout\"];\n const uiLayout = uiSchema?.[\"x-ui-layout\"];\n return { ...schemaLayout, ...uiLayout };\n}\n\n/** Build global options for sub-form (compact / label suppression). */\nfunction buildSubGlobalOptions(\n layout: UILayoutConfig,\n isHorizontal: boolean,\n): Record<string, unknown> | undefined {\n const compactOptions = layout.compact ? { compact: true } : undefined;\n const labelsOption =\n layout.labels !== undefined\n ? layout.labels\n : isHorizontal\n ? false\n : undefined;\n if (!compactOptions && labelsOption !== false) return undefined;\n return {\n ...(compactOptions ?? {}),\n ...(labelsOption === false ? { label: false } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\ninterface ArrayHeaderProps {\n label: string | undefined;\n description: string | undefined;\n}\n\nfunction ArrayHeader({ label, description }: ArrayHeaderProps) {\n if (!label) return null;\n return (\n <div>\n <h4 className=\"text-sm font-medium\">{label}</h4>\n {description && (\n <p className=\"text-xs text-muted-foreground\">{description}</p>\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Hooks\n// ---------------------------------------------------------------------------\n\nfunction useArrayHandlers(\n items: Record<string, unknown>[],\n onChange: (v: unknown) => void,\n propertySchema: WidgetProps[\"propertySchema\"],\n) {\n const handleItemChange = useCallback(\n (index: number, data: Record<string, unknown>) => {\n const next = [...items];\n next[index] = {\n ...data,\n [FORM_ITEM_ID_FIELD]: items[index][FORM_ITEM_ID_FIELD],\n };\n onChange(next);\n },\n [items, onChange],\n );\n\n const handleAdd = useCallback(() => {\n const base = propertySchema.items\n ? applySchemaDefaults({}, propertySchema.items)\n : {};\n onChange([...items, { ...base, [FORM_ITEM_ID_FIELD]: generateId() }]);\n }, [items, onChange, propertySchema.items]);\n\n const handleRemove = useCallback(\n (index: number) => {\n onChange(items.filter((_, i) => i !== index));\n },\n [items, onChange],\n );\n\n const handleMove = useCallback(\n (from: number, to: number) => {\n const next = [...items];\n const [movedItem] = next.splice(from, 1);\n next.splice(to, 0, movedItem);\n onChange(next);\n },\n [items, onChange],\n );\n\n return { handleItemChange, handleAdd, handleRemove, handleMove };\n}\n\n// ---------------------------------------------------------------------------\n// ArrayWidget\n// ---------------------------------------------------------------------------\n\nexport function ArrayWidget({\n propertySchema,\n value,\n onChange,\n registry,\n uiSchema,\n disabled,\n readonly,\n label,\n description,\n options,\n schema,\n name,\n}: WidgetProps): React.ReactElement {\n const { templates } = useNestedFormContext();\n\n const items = useMemo(() => ensureItemIds(value), [value]);\n const { handleItemChange, handleAdd, handleRemove, handleMove } =\n useArrayHandlers(items, onChange, propertySchema);\n\n const itemSchema = propertySchema.items;\n if (!itemSchema?.properties) {\n return (\n <p className=\"text-sm text-destructive\">\n ArrayWidget requires items with type &quot;object&quot; and properties.\n </p>\n );\n }\n\n const layout = resolveLayout(uiSchema, propertySchema);\n const isHorizontal = layout.direction === \"horizontal\";\n const subGlobalOptions = buildSubGlobalOptions(layout, isHorizontal);\n\n return (\n <ArrayWidgetInner\n items={items}\n propertySchema={propertySchema}\n itemSchema={itemSchema}\n schema={schema}\n name={name ?? \"\"}\n registry={registry}\n uiSchema={uiSchema}\n disabled={disabled}\n readonly={readonly}\n label={label}\n description={description}\n options={options}\n layout={layout}\n isHorizontal={isHorizontal}\n subGlobalOptions={subGlobalOptions}\n templates={templates}\n onItemChange={handleItemChange}\n onAdd={handleAdd}\n onRemove={handleRemove}\n onMove={handleMove}\n />\n );\n}\n\n// ---------------------------------------------------------------------------\n// Inner renderer (split to keep each function below complexity threshold)\n// ---------------------------------------------------------------------------\n\ninterface ArrayWidgetInnerProps {\n items: Record<string, unknown>[];\n propertySchema: WidgetProps[\"propertySchema\"];\n itemSchema: WidgetProps[\"propertySchema\"];\n schema: WidgetProps[\"schema\"];\n name: string;\n registry: WidgetProps[\"registry\"];\n uiSchema: WidgetProps[\"uiSchema\"];\n disabled?: boolean;\n readonly?: boolean;\n label?: string;\n description?: string;\n options?: UISchemaOptions;\n layout: UILayoutConfig;\n isHorizontal: boolean;\n subGlobalOptions: Record<string, unknown> | undefined;\n templates: ReturnType<typeof useNestedFormContext>[\"templates\"];\n onItemChange: (index: number, data: Record<string, unknown>) => void;\n onAdd: () => void;\n onRemove: (index: number) => void;\n onMove: (from: number, to: number) => void;\n}\n\n/** Resolve array schema constraints. */\nfunction resolveConstraints(\n arraySchema: WidgetProps[\"propertySchema\"],\n itemSchema: WidgetProps[\"propertySchema\"],\n readonly: boolean | undefined,\n disabled: boolean | undefined,\n itemCount: number,\n) {\n const minItems = arraySchema.minItems ?? 0;\n const maxItems = arraySchema.maxItems ?? Infinity;\n const requiredFields = itemSchema.required ?? [];\n const isEditable = !readonly && !disabled;\n return {\n canRemove: isEditable && itemCount > minItems,\n canAddBase: isEditable && itemCount < maxItems,\n requiredFields,\n };\n}\n\n/** Resolve display options from widget options. */\nfunction resolveDisplayOptions(\n options: UISchemaOptions | undefined,\n itemCount: number,\n) {\n return {\n addLabel: (options?.addLabel as string) ?? \"Add item\",\n itemTitle: options?.itemTitle as string | undefined,\n orderable: !!options?.orderable && itemCount > 1,\n emptyMessage: options?.emptyMessage as string | undefined,\n };\n}\n\n/** Resolve the active templates from context with defaults. */\nfunction resolveTemplates(\n templates: ReturnType<typeof useNestedFormContext>[\"templates\"],\n isHorizontal: boolean,\n) {\n const ItemTemplate = templates.ArrayItemTemplate ?? DefaultArrayItemTemplate;\n const HorizontalItemTemplate =\n templates.HorizontalArrayItemTemplate ?? undefined;\n const HeaderTemplate =\n templates.ArrayHeaderTemplate ?? DefaultArrayHeaderTemplate;\n const ActiveItemTemplate =\n isHorizontal && HorizontalItemTemplate\n ? HorizontalItemTemplate\n : ItemTemplate;\n return { ActiveItemTemplate, HeaderTemplate };\n}\n\n/** Build ObjectWidget options for a sub-item. */\nfunction buildItemOptions(\n isHorizontal: boolean,\n subGlobalOptions: Record<string, unknown> | undefined,\n): UISchemaOptions {\n return {\n variant: \"borderless\",\n displayContents: isHorizontal,\n ...(subGlobalOptions ? { globalOptions: subGlobalOptions } : {}),\n };\n}\n\n/** Resolve the label for an array item. */\nfunction resolveItemLabel(\n itemTitle: string | undefined,\n index: number,\n): string {\n return itemTitle ? itemTitle.replace(\"{index}\", String(index + 1)) : \"\";\n}\n\nfunction ArrayWidgetInner({\n items,\n propertySchema,\n itemSchema,\n schema,\n name,\n registry,\n uiSchema,\n disabled,\n readonly,\n label,\n description,\n options,\n layout,\n isHorizontal,\n subGlobalOptions,\n templates,\n onItemChange,\n onAdd,\n onRemove,\n onMove,\n}: ArrayWidgetInnerProps) {\n const constraints = resolveConstraints(\n propertySchema,\n itemSchema,\n readonly,\n disabled,\n items.length,\n );\n const display = resolveDisplayOptions(options, items.length);\n const canAdd =\n constraints.canAddBase &&\n allItemsComplete(items, constraints.requiredFields);\n const { ActiveItemTemplate, HeaderTemplate } = resolveTemplates(\n templates,\n isHorizontal,\n );\n const fieldCount = countFields(itemSchema);\n const itemOptions = buildItemOptions(isHorizontal, subGlobalOptions);\n\n return (\n <div className={isHorizontal ? \"space-y-1\" : \"space-y-3\"}>\n <ArrayHeader label={label} description={description} />\n\n {items.length === 0 && display.emptyMessage && (\n <p className=\"text-sm text-muted-foreground italic\">\n {display.emptyMessage}\n </p>\n )}\n\n {items.length > 0 && (\n <HeaderTemplate\n itemSchema={itemSchema}\n layout={layout}\n canRemove={constraints.canRemove}\n orderable={display.orderable}\n fieldCount={fieldCount}\n />\n )}\n\n {items.map((item, index) => (\n <ActiveItemTemplate\n key={item[FORM_ITEM_ID_FIELD] as string}\n index={index}\n total={items.length}\n canRemove={constraints.canRemove}\n orderable={display.orderable}\n disabled={disabled}\n layout={layout}\n fieldCount={fieldCount}\n fid={item[FORM_ITEM_ID_FIELD] as string}\n onRemove={() => onRemove(index)}\n onMoveUp={index > 0 ? () => onMove(index, index - 1) : undefined}\n onMoveDown={\n index < items.length - 1\n ? () => onMove(index, index + 1)\n : undefined\n }\n >\n <ObjectWidget\n id={`field-${name}-${index}`}\n name={`${name}[${index}]`}\n schema={schema}\n propertySchema={itemSchema}\n uiSchema={uiSchema}\n registry={registry}\n value={stripItemId(item)}\n onChange={(data: unknown) =>\n onItemChange(index, data as Record<string, unknown>)\n }\n label={resolveItemLabel(display.itemTitle, index)}\n description={undefined}\n disabled={disabled}\n readonly={readonly}\n options={itemOptions}\n />\n </ActiveItemTemplate>\n ))}\n\n {canAdd && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={onAdd}\n disabled={disabled}\n className=\"gap-1.5\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n {display.addLabel}\n </Button>\n )}\n </div>\n );\n}\n","/**\n * DefaultArrayItemTemplate -- vertical card layout for array items.\n *\n * Renders the item content with optional remove, move-up, and move-down\n * controls in a column on the right. This is the default (vertical) layout;\n * HorizontalArrayItemTemplate handles the grid-row case.\n */\n\nimport { Trash2, ChevronUp, ChevronDown } from \"lucide-react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport type { ArrayItemTemplateProps } from \"../widgets/types\";\n\nexport function DefaultArrayItemTemplate({\n children,\n index,\n total,\n canRemove,\n orderable,\n disabled,\n fid,\n onRemove,\n onMoveUp,\n onMoveDown,\n}: ArrayItemTemplateProps): React.ReactElement {\n const showControls = canRemove || orderable;\n\n return (\n <div\n data-fid={fid}\n className=\"relative flex gap-2 rounded-md border border-border/50 bg-muted/20 p-3\"\n >\n <div className=\"flex-1 min-w-0\">{children}</div>\n {showControls && (\n <div className=\"flex flex-col gap-1 pt-0.5\">\n {orderable && index > 0 && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"compact\"\n disabled={disabled}\n onClick={onMoveUp}\n title=\"Move up\"\n >\n <ChevronUp className=\"h-3.5 w-3.5\" />\n </Button>\n )}\n {orderable && index < total - 1 && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"compact\"\n disabled={disabled}\n onClick={onMoveDown}\n title=\"Move down\"\n >\n <ChevronDown className=\"h-3.5 w-3.5\" />\n </Button>\n )}\n {canRemove && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"compact\"\n disabled={disabled}\n onClick={onRemove}\n title=\"Remove item\"\n className=\"text-muted-foreground hover:text-destructive\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n )}\n </div>\n )}\n </div>\n );\n}\n","/**\n * Utility for building CSS grid-template-columns strings for array item rows.\n */\n\nimport type { UILayoutConfig } from \"@petrarca/sonnet-core/schema\";\n\n/** Build the CSS grid-template-columns string for a horizontal item row. */\nexport function buildGridTemplate(\n layout: UILayoutConfig,\n canRemove: boolean,\n fieldCount: number,\n orderable: boolean = false,\n): string {\n const base = layout.columns ?? `repeat(${fieldCount}, 1fr)`;\n const withOrder = orderable ? `${base} 32px` : base;\n return canRemove ? `${withOrder} 32px` : withOrder;\n}\n","/**\n * DefaultArrayHeaderTemplate -- column header row for horizontal array layout.\n *\n * Rendered once above all items by ArrayWidget when direction is \"horizontal\".\n * Returns null in vertical mode (no headers needed).\n */\n\nimport type { ArrayHeaderTemplateProps } from \"../widgets/types\";\nimport { buildGridTemplate } from \"./gridUtils\";\n\nexport function DefaultArrayHeaderTemplate({\n itemSchema,\n layout,\n canRemove,\n orderable,\n fieldCount,\n}: ArrayHeaderTemplateProps): React.ReactElement | null {\n if (layout.direction !== \"horizontal\") return null;\n\n const template = buildGridTemplate(layout, canRemove, fieldCount, orderable);\n const gap = layout.gap ?? 8;\n\n const properties = itemSchema.properties ?? {};\n const order = itemSchema[\"x-ui-order\"];\n const fieldNames = order\n ? order.filter((k) => k in properties)\n : Object.keys(properties);\n\n return (\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: template,\n gap: `${gap}px`,\n }}\n >\n {fieldNames.map((name) => (\n <span key={name} className=\"text-xs font-medium text-muted-foreground\">\n {properties[name]?.title ?? name}\n </span>\n ))}\n {orderable && <span />}\n {canRemove && <span />}\n </div>\n );\n}\n","/**\n * QuantityWidget - JSON-Schema-aware widget for compound value + unit input.\n *\n * Reads unit options from x-ui-options.units (static array) and delegates\n * rendering to FormQuantityInput. Registered as x-ui-widget: \"quantity\".\n *\n * x-ui-options:\n * units - Array of { value, label, min?, max?, position? } unit options\n * unitPosition - Default position for all units: \"prefix\" | \"suffix\"\n * precision - Number of decimal places to format on blur\n * step - Arrow-key increment\n *\n * Schema-level min/max come from propertySchema.minimum / propertySchema.maximum.\n *\n * Form value shape: { value: number | undefined, unit: string }\n */\n\nimport { useCallback, useRef } from \"react\";\nimport {\n FormQuantityInput,\n type QuantityValue,\n type UnitOption,\n type UnitPosition,\n} from \"../FormQuantityInput\";\nimport { WidgetProps, firstError } from \"./types\";\n\n/** Runtime shape guard for a single unit option from x-ui-options. */\nfunction isUnitOption(u: unknown): u is UnitOption {\n return (\n typeof u === \"object\" &&\n u !== null &&\n typeof (u as UnitOption).value === \"string\" &&\n typeof (u as UnitOption).label === \"string\"\n );\n}\n\ninterface ParsedQuantityOptions {\n units: UnitOption[];\n precision: number | undefined;\n step: number | undefined;\n unitPosition: UnitPosition | undefined;\n}\n\n/** Parse and validate x-ui-options for the quantity widget. */\nfunction parseQuantityOptions(\n options: Record<string, unknown>,\n): ParsedQuantityOptions {\n const units = Array.isArray(options.units)\n ? (options.units as unknown[]).filter(isUnitOption)\n : [];\n const precision =\n typeof options.precision === \"number\" ? options.precision : undefined;\n const step = typeof options.step === \"number\" ? options.step : undefined;\n const unitPosition =\n options.unitPosition === \"prefix\" || options.unitPosition === \"suffix\"\n ? options.unitPosition\n : undefined;\n return { units, precision, step, unitPosition };\n}\n\nexport function QuantityWidget({\n id,\n name,\n value,\n onChange,\n onBlur,\n propertySchema,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n placeholder,\n autofocus,\n options = {},\n}: WidgetProps) {\n const error = firstError(rawErrors);\n const {\n units,\n precision,\n step,\n unitPosition: unitPositionOpt,\n } = parseQuantityOptions(options);\n\n // Coerce incoming value to QuantityValue (unknown -> typed).\n const quantityValue: QuantityValue | undefined =\n value != null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as QuantityValue)\n : undefined;\n\n // L5: We store the current value in a ref so the onBlur handler can pass it\n // to the form engine without capturing a stale snapshot in a useCallback\n // closure. Adding `value` to the useCallback dep array would cause the\n // handler to be recreated on every value change, which in turn makes\n // FormQuantityInput recreate its own blur handler -- unnecessary churn.\n const valueRef = useRef(value);\n valueRef.current = value;\n\n const handleBlur = useCallback(() => {\n onBlur?.(id, valueRef.current);\n }, [id, onBlur]);\n\n // M4: onChange is passed directly -- no wrapper needed. FormQuantityInput\n // calls onChange with a QuantityValue, which satisfies (value: unknown) => void.\n return (\n <FormQuantityInput\n id={id}\n name={name}\n value={quantityValue}\n onChange={onChange as (v: QuantityValue) => void}\n onBlur={handleBlur}\n units={units}\n unitPosition={unitPositionOpt}\n precision={precision}\n step={step}\n min={propertySchema.minimum}\n max={propertySchema.maximum}\n label={label}\n labelPlacement={options?.labelPlacement}\n description={description}\n error={error}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n autoFocus={autofocus}\n />\n );\n}\n","/**\n * DateWidget - date field widget backed by the DateInput primitive.\n *\n * Renders a text input with calendar popover. Value is a partial ISO 8601 date\n * string (`YYYY`, `YYYY-MM`, or `YYYY-MM-DD`). Auto-resolves from schema\n * `format: \"date\"`, or `x-ui-widget: \"date\"`.\n *\n * x-ui-options:\n * precision - \"year\" | \"month\" | \"day\" (default \"day\")\n * locale - BCP-47 locale override (defaults to the app locale)\n *\n * The label/description chrome comes from FormFieldWrapper; the primitive owns\n * the inline error message and invalid border.\n */\n\nimport { DateInput } from \"@petrarca/sonnet-ui\";\nimport type { DatePrecision } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"../FormFieldWrapper\";\nimport { WidgetProps, firstError } from \"./types\";\n\nfunction resolvePrecision(value: unknown): DatePrecision {\n return value === \"year\" || value === \"month\" ? value : \"day\";\n}\n\nexport function DateWidget({\n id,\n value,\n onChange,\n onBlur,\n required,\n disabled,\n rawErrors,\n label,\n description,\n placeholder,\n options,\n}: WidgetProps): React.ReactElement {\n const error = firstError(rawErrors);\n const precision = resolvePrecision(options?.precision);\n const locale =\n typeof options?.locale === \"string\" ? options.locale : undefined;\n\n return (\n <FormFieldWrapper\n inputId={id}\n label={label}\n description={description}\n required={required}\n labelPlacement={options?.labelPlacement}\n >\n <DateInput\n id={id}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={onChange}\n onBlur={() => onBlur?.(id, value)}\n precision={precision}\n locale={locale}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n error={error}\n />\n </FormFieldWrapper>\n );\n}\n","/**\n * TimeWidget - time-of-day field widget backed by the TimeInput primitive.\n *\n * Zone-free time value as a normalized ISO string (`HH:mm` or `HH:mm:ss`).\n * Auto-resolves from schema `format: \"time\"`, or `x-ui-widget: \"time\"`.\n *\n * x-ui-options:\n * granularity - \"minute\" | \"second\" (default \"minute\")\n *\n * The label/description chrome comes from FormFieldWrapper; the primitive owns\n * the inline error message and invalid border.\n */\n\nimport { TimeInput } from \"@petrarca/sonnet-ui\";\nimport type { TimeGranularity } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"../FormFieldWrapper\";\nimport { WidgetProps, firstError } from \"./types\";\n\nfunction resolveGranularity(value: unknown): TimeGranularity {\n return value === \"second\" ? \"second\" : \"minute\";\n}\n\nexport function TimeWidget({\n id,\n value,\n onChange,\n onBlur,\n required,\n disabled,\n rawErrors,\n label,\n description,\n placeholder,\n options,\n}: WidgetProps): React.ReactElement {\n const error = firstError(rawErrors);\n const granularity = resolveGranularity(options?.granularity);\n\n return (\n <FormFieldWrapper\n inputId={id}\n label={label}\n description={description}\n required={required}\n labelPlacement={options?.labelPlacement}\n >\n <TimeInput\n id={id}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={onChange}\n onBlur={() => onBlur?.(id, value)}\n granularity={granularity}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n error={error}\n />\n </FormFieldWrapper>\n );\n}\n","/**\n * DateTimeWidget - date + time field widget backed by the DateTimeInput primitive.\n *\n * Plain wall-clock value as an ISO string (`YYYY-MM-DDTHH:mm[:ss]`), no\n * timezone. Auto-resolves from schema `format: \"date-time\"`, or\n * `x-ui-widget: \"date-time\"`.\n *\n * x-ui-options:\n * granularity - \"minute\" | \"second\" (default \"minute\")\n * timeZone - IANA id shown as a display-only hint (never applied)\n * locale - BCP-47 locale override for the date part\n *\n * The label/description chrome comes from FormFieldWrapper; the primitive owns\n * the inline error message and invalid border.\n */\n\nimport { DateTimeInput } from \"@petrarca/sonnet-ui\";\nimport type { TimeGranularity } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"../FormFieldWrapper\";\nimport { WidgetProps, firstError } from \"./types\";\n\nfunction resolveGranularity(value: unknown): TimeGranularity {\n return value === \"second\" ? \"second\" : \"minute\";\n}\n\nexport function DateTimeWidget({\n id,\n value,\n onChange,\n onBlur,\n required,\n disabled,\n rawErrors,\n label,\n description,\n options,\n}: WidgetProps): React.ReactElement {\n const error = firstError(rawErrors);\n const granularity = resolveGranularity(options?.granularity);\n const timeZone =\n typeof options?.timeZone === \"string\" ? options.timeZone : undefined;\n const locale =\n typeof options?.locale === \"string\" ? options.locale : undefined;\n\n return (\n <FormFieldWrapper\n inputId={id}\n label={label}\n description={description}\n required={required}\n labelPlacement={options?.labelPlacement}\n >\n <DateTimeInput\n idPrefix={id}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={onChange}\n onBlur={() => onBlur?.(id, value)}\n granularity={granularity}\n timeZone={timeZone}\n locale={locale}\n required={required}\n disabled={disabled}\n error={error}\n />\n </FormFieldWrapper>\n );\n}\n","/**\n * DisplayWidget - read-only text block, no data binding.\n *\n * Renders a property's title (and optional description) as static text --\n * instructions, notes, disclaimers placed between fields. Collects no value.\n * Auto-resolves from `type: \"null\"`, or `x-ui-widget: \"display\"`.\n *\n * Modeled as a value-less property so it participates in field ordering and\n * layout (appears exactly where placed). It never contributes to form data.\n */\n\nimport { WidgetProps } from \"./types\";\n\nexport function DisplayWidget({\n label,\n description,\n}: WidgetProps): React.ReactElement | null {\n if (!label && !description) return null;\n return (\n <div className=\"space-y-1\">\n {label && <p className=\"text-sm text-foreground\">{label}</p>}\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n );\n}\n","/**\n * OneOfWidget -- renders a discriminated union (oneOf).\n *\n * A branch selector (reusing the Select primitive) chooses one of the property's\n * `oneOf` branches; the selected branch's object sub-schema is then rendered as\n * a nested sub-form (same pattern as ObjectWidget). The active branch is tracked\n * by the discriminator property (see the oneOf helpers in\n * @petrarca/sonnet-core/schema).\n *\n * Auto-resolves when a property has `oneOf`, or via `x-ui-widget: \"one-of\"`.\n */\n\nimport { useMemo } from \"react\";\nimport type {\n JsonSchema,\n JsonSchemaProperty,\n UISchema,\n} from \"@petrarca/sonnet-core/schema\";\nimport {\n getDiscriminator,\n getBranchValue,\n getBranchLabel,\n findActiveBranch,\n} from \"@petrarca/sonnet-core/schema\";\nimport {\n Label,\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n} from \"@petrarca/sonnet-ui\";\nimport { useNestedFormContext } from \"../hooks/useNestedFormContext\";\nimport { DefaultObjectContainerTemplate } from \"../templates/DefaultObjectContainerTemplate\";\nimport type { WidgetProps } from \"./types\";\n\ninterface BranchChoice {\n index: number;\n value: string;\n label: string;\n}\n\n// Build the selectable branch list from the property's oneOf.\nfunction buildChoices(\n branches: JsonSchemaProperty[],\n discriminator: string | undefined,\n): BranchChoice[] {\n return branches.map((branch, index) => {\n const raw = discriminator\n ? getBranchValue(branch, discriminator)\n : undefined;\n return {\n index,\n value: raw !== undefined ? String(raw) : String(index),\n label: getBranchLabel(branch, discriminator, index),\n };\n });\n}\n\n// Build a renderable object sub-schema from a branch.\nfunction buildBranchSchema(branch: JsonSchemaProperty): JsonSchema | null {\n if (!branch.properties) return null;\n return {\n title: branch.title || \"\",\n type: \"object\",\n properties: branch.properties,\n required: branch.required,\n ...(branch[\"x-ui-order\"] ? { \"x-ui-order\": branch[\"x-ui-order\"] } : {}),\n };\n}\n\n// Reset data to just the new discriminator value so stale branch-specific\n// fields do not leak across branches.\nfunction branchChangeData(\n choices: BranchChoice[],\n branches: JsonSchemaProperty[],\n discriminator: string | undefined,\n selected: string,\n): Record<string, unknown> {\n const choice = choices.find((c) => c.value === selected);\n if (!choice || !discriminator) return {};\n const discValue =\n getBranchValue(branches[choice.index], discriminator) ?? selected;\n return { [discriminator]: discValue };\n}\n\nfunction BranchSelector({\n id,\n label,\n description,\n choices,\n activeValue,\n disabled,\n onSelect,\n}: {\n id?: string;\n label?: string;\n description?: string;\n choices: BranchChoice[];\n activeValue: string;\n disabled?: boolean;\n onSelect: (value: string) => void;\n}): React.ReactElement {\n return (\n <div className=\"space-y-1\">\n {label && <Label htmlFor={id}>{label}</Label>}\n <Select value={activeValue} onValueChange={onSelect} disabled={disabled}>\n <SelectTrigger id={id}>\n <SelectValue placeholder=\"Select an option\" />\n </SelectTrigger>\n <SelectContent>\n {choices.map((c) => (\n <SelectItem key={c.value} value={c.value}>\n {c.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n );\n}\n\n// Resolve which branch is active for the current data, with its label + schema.\nfunction resolveActive(\n propertySchema: JsonSchemaProperty,\n branches: JsonSchemaProperty[],\n choices: BranchChoice[],\n discriminator: string | undefined,\n data: Record<string, unknown>,\n): { value: string; label: string; subSchema: JsonSchema | null } {\n const index = findActiveBranch(propertySchema, data, discriminator);\n if (index < 0) return { value: \"\", label: \"\", subSchema: null };\n return {\n value: choices[index]?.value ?? \"\",\n label: choices[index]?.label ?? \"\",\n subSchema: buildBranchSchema(branches[index]),\n };\n}\n\nexport function OneOfWidget({\n propertySchema,\n value,\n onChange,\n registry,\n uiSchema,\n disabled,\n readonly,\n label,\n description,\n id,\n options,\n}: WidgetProps): React.ReactElement | null {\n const { renderer: Renderer, templates } = useNestedFormContext();\n const ContainerTemplate =\n templates.ObjectContainerTemplate ?? DefaultObjectContainerTemplate;\n\n const branches = useMemo(() => propertySchema.oneOf ?? [], [propertySchema]);\n const discriminator = useMemo(\n () => getDiscriminator(propertySchema),\n [propertySchema],\n );\n const choices = useMemo(\n () => buildChoices(branches, discriminator),\n [branches, discriminator],\n );\n\n const data = (value as Record<string, unknown>) || {};\n const active = resolveActive(\n propertySchema,\n branches,\n choices,\n discriminator,\n data,\n );\n\n if (branches.length === 0) return null;\n\n const subUiSchema = (uiSchema?.[\"x-ui-fields\"] ?? {}) as {\n [fieldName: string]: UISchema;\n };\n\n return (\n <div className=\"space-y-4\">\n <BranchSelector\n id={id}\n label={label}\n description={description}\n choices={choices}\n activeValue={active.value}\n disabled={disabled || readonly}\n onSelect={(selected) =>\n onChange(branchChangeData(choices, branches, discriminator, selected))\n }\n />\n {active.subSchema && (\n <ContainerTemplate\n label={active.label}\n description={undefined}\n variant={(options?.variant as string) || \"section\"}\n defaultOpen\n >\n <Renderer\n schema={active.subSchema}\n data={data}\n onChange={onChange}\n disabled={disabled}\n readOnly={readonly}\n widgets={registry}\n uiSchema={subUiSchema}\n // Scope the branch's control ids to this field, so a oneOf inside\n // an array item does not collide with its siblings.\n idPrefix={id}\n />\n </ContainerTemplate>\n )}\n </div>\n );\n}\n","/**\n * Widget Resolution Algorithm\n *\n * Determines which widget to use for a given field based on:\n * 0. Schema x-ui-widget and x-ui-options (merged with uiSchema if present)\n * 1. UISchema x-ui-widget (highest priority - overrides x-ui-widget)\n * 2. Schema x-ui-widget (for widget name)\n * 3. Schema enum (uses SelectWidget)\n * 4. Schema format (email, date, color, etc.)\n * 5. Schema type (string, number, boolean, etc.)\n * 6. Fallback to TextWidget\n *\n * x-ui-widget is a simple string: 'textarea', 'select', etc.\n * x-ui-options is an object with configuration: { rows: 5, etc. }\n */\n\nimport { JsonSchemaProperty } from \"@petrarca/sonnet-core/schema\";\nimport {\n isNullableBoolean,\n isOneOf,\n extractEnumValues,\n getFieldType,\n} from \"@petrarca/sonnet-core/schema\";\nimport { Widget, WidgetRegistry, UISchema, WidgetMap } from \"./types\";\n\n/**\n * Default widget mapping: schema type → format/variant → widget name\n *\n * This defines which widget to use for each combination of schema type and format.\n * Follows the pattern established by react-jsonschema-form.\n *\n * Currently implemented widgets:\n * - TextInputWidget: Basic text input (email, url formats supported)\n * - TextareaWidget: Multi-line text input\n * - NumberWidget: Number and integer input\n * - CheckboxWidget: Boolean checkbox\n * - SelectWidget: Dropdown for enum values\n */\nexport const DEFAULT_WIDGET_MAP: WidgetMap = {\n string: {\n default: \"TextInputWidget\",\n textarea: \"TextareaWidget\",\n email: \"TextInputWidget\", // Uses email input type\n uri: \"TextInputWidget\", // Uses url input type\n url: \"TextInputWidget\", // Uses url input type\n date: \"DateWidget\",\n \"date-time\": \"DateTimeWidget\",\n time: \"TimeWidget\",\n },\n number: {\n default: \"NumberWidget\",\n },\n integer: {\n default: \"NumberWidget\", // NumberWidget handles both number and integer\n },\n boolean: {\n default: \"CheckboxWidget\",\n },\n null: {\n default: \"DisplayWidget\",\n },\n};\n\n/**\n * Resolve a widget name to a widget component using unified resolution logic\n *\n * This function handles both exact widget names and lowercase format names consistently.\n * Used by both schema-embedded x-ui-widget and explicit uiSchema resolution.\n *\n * @param widgetName - The widget name to resolve (e.g., 'TextareaWidget' or 'textarea')\n * @param propertySchema - The JSON schema for context (needed for type-based resolution)\n * @param registry - Widget registry to look up widgets\n * @returns The resolved widget component or null if not found\n */\nfunction resolveWidgetByName(\n widgetName: string,\n propertySchema: JsonSchemaProperty,\n registry: WidgetRegistry,\n): Widget | null {\n // Strategy 1: Direct registry lookup (for exact widget names like 'TextareaWidget')\n if (registry[widgetName]) {\n return registry[widgetName];\n }\n\n // Strategy 2: Map lowercase format names to widget names\n // This allows using 'textarea' instead of 'TextareaWidget' for consistency\n const type = getFieldType(propertySchema);\n const resolvedWidgetName =\n DEFAULT_WIDGET_MAP[type]?.[widgetName.toLowerCase()];\n if (resolvedWidgetName && registry[resolvedWidgetName]) {\n return registry[resolvedWidgetName];\n }\n\n return null;\n}\n\n/**\n * Merge x-ui-* extensions from a property schema with an explicit uiSchema.\n *\n * The explicit uiSchema has higher priority and overrides schema-embedded hints.\n * Returns undefined when neither source provides any values.\n */\nfunction mergeUiSchema(\n propertySchema: JsonSchemaProperty,\n uiSchema: UISchema | undefined,\n): UISchema | undefined {\n const xWidgetName = propertySchema[\"x-ui-widget\"];\n const xWidgetOptions = propertySchema[\"x-ui-options\"];\n\n if (!xWidgetName && !xWidgetOptions) return uiSchema;\n\n if (!uiSchema) {\n return {\n ...(xWidgetName && { \"x-ui-widget\": xWidgetName }),\n ...(xWidgetOptions && { \"x-ui-options\": xWidgetOptions }),\n };\n }\n\n return {\n ...(xWidgetName && { \"x-ui-widget\": xWidgetName }), // lower priority\n ...uiSchema, // higher priority\n \"x-ui-options\": {\n ...(xWidgetOptions || {}), // lower priority\n ...(uiSchema[\"x-ui-options\"] || {}), // higher priority\n },\n };\n}\n\n/**\n * Resolve which widget to use for a field.\n *\n * Resolution order (highest to lowest priority):\n * 1. x-ui-widget (from explicit uiSchema or schema-embedded extension)\n * 2. anyOf boolean+null pattern (tri-state checkbox)\n * 3. enum in schema -- includes nullable anyOf enum pattern (SelectWidget)\n * 4. type + format in schema (string, number, boolean, etc.)\n * 5. Fallback to TextInputWidget\n *\n * @param propertySchema - The JSON schema for this field\n * @param uiSchema - Optional UI schema customization (takes priority over schema hints)\n * @param registry - Widget registry to look up widgets\n * @returns The resolved widget component\n */\n// Step 1: Resolve from explicit x-ui-widget hint.\nfunction resolveFromUiWidget(\n uiWidget: unknown,\n propertySchema: JsonSchemaProperty,\n registry: WidgetRegistry,\n): Widget | null {\n if (typeof uiWidget === \"function\") return uiWidget as Widget;\n if (typeof uiWidget === \"string\")\n return resolveWidgetByName(uiWidget, propertySchema, registry);\n return null;\n}\n\n/** Check if a schema describes an array of objects with properties. */\nfunction isObjectArraySchema(schema: JsonSchemaProperty): boolean {\n return (\n schema.type === \"array\" &&\n schema.items?.type === \"object\" &&\n !!schema.items?.properties\n );\n}\n\n/** Lookup a widget name in the registry, falling back to TextInputWidget. */\nfunction registryLookup(registry: WidgetRegistry, widgetName: string): Widget {\n return registry[widgetName] || registry[\"TextInputWidget\"];\n}\n\n// Step 2-3: Resolve from schema structure (oneOf, nullable bool, enum, object, array).\nfunction resolveFromSchemaStructure(\n schema: JsonSchemaProperty,\n registry: WidgetRegistry,\n): Widget | null {\n if (isOneOf(schema)) return registryLookup(registry, \"OneOfWidget\");\n if (isNullableBoolean(schema))\n return registryLookup(registry, \"CheckboxWidget\");\n if (extractEnumValues(schema).length > 0)\n return registryLookup(registry, \"SelectWidget\");\n if (schema.type === \"object\" && schema.properties)\n return registryLookup(registry, \"ObjectWidget\");\n if (isObjectArraySchema(schema))\n return registryLookup(registry, \"ArrayWidget\");\n return null;\n}\n\n// Step 4: Resolve from type + format via the default widget map.\nfunction resolveFromTypeFormat(\n schema: JsonSchemaProperty,\n registry: WidgetRegistry,\n): Widget {\n const type = getFieldType(schema);\n const format = schema.format;\n const widgetName =\n (format && DEFAULT_WIDGET_MAP[type]?.[format]) ||\n DEFAULT_WIDGET_MAP[type]?.default ||\n \"TextInputWidget\";\n return registry[widgetName] || registry[\"TextInputWidget\"];\n}\n\nexport function resolveWidget(\n propertySchema: JsonSchemaProperty,\n uiSchema: UISchema | undefined,\n registry: WidgetRegistry,\n): Widget {\n const effectiveUiSchema = mergeUiSchema(propertySchema, uiSchema);\n const uiWidget = effectiveUiSchema?.[\"x-ui-widget\"];\n if (uiWidget) {\n const resolved = resolveFromUiWidget(uiWidget, propertySchema, registry);\n if (resolved) return resolved;\n }\n return (\n resolveFromSchemaStructure(propertySchema, registry) ??\n resolveFromTypeFormat(propertySchema, registry)\n );\n}\n\n/**\n * Get the default widget name for a schema type\n *\n * Helper function to determine the default widget for a given type\n * without considering format or other factors.\n *\n * @param type - The JSON schema type\n * @returns The default widget name for that type\n *\n * @example\n * ```typescript\n * getDefaultWidgetForType('string'); // 'TextInputWidget'\n * getDefaultWidgetForType('number'); // 'NumberWidget'\n * getDefaultWidgetForType('boolean'); // 'CheckboxWidget'\n * ```\n */\nexport function getDefaultWidgetForType(type: string): string {\n return DEFAULT_WIDGET_MAP[type]?.default || \"TextInputWidget\";\n}\n","/**\n * Form Widgets - Index and Registry\n *\n * Each widget is imported once and re-exported. The same binding is used in\n * DEFAULT_WIDGETS to avoid the double-import anti-pattern.\n */\n\nimport { TextInputWidget } from \"./TextInputWidget\";\nimport { TextareaWidget } from \"./TextareaWidget\";\nimport { NumberWidget } from \"./NumberWidget\";\nimport { CheckboxWidget } from \"./CheckboxWidget\";\nimport { SelectWidget } from \"./SelectWidget\";\nimport { TagsInputWidget } from \"./TagsInputWidget\";\nimport { JsonEditorWidget } from \"./JsonEditorWidget\";\nimport { EntitySelectWidget } from \"./EntitySelectWidget\";\nimport { ObjectWidget } from \"./ObjectWidget\";\nimport { ArrayWidget } from \"./ArrayWidget\";\nimport { QuantityWidget } from \"./QuantityWidget\";\nimport { DateWidget } from \"./DateWidget\";\nimport { TimeWidget } from \"./TimeWidget\";\nimport { DateTimeWidget } from \"./DateTimeWidget\";\nimport { DisplayWidget } from \"./DisplayWidget\";\nimport { OneOfWidget } from \"./OneOfWidget\";\nimport type { WidgetRegistry } from \"./types\";\n\n// Re-export widget components\nexport {\n TextInputWidget,\n TextareaWidget,\n NumberWidget,\n CheckboxWidget,\n SelectWidget,\n TagsInputWidget,\n JsonEditorWidget,\n EntitySelectWidget,\n ObjectWidget,\n ArrayWidget,\n QuantityWidget,\n DateWidget,\n TimeWidget,\n DateTimeWidget,\n DisplayWidget,\n OneOfWidget,\n};\n\n// Export types and helpers\nexport type {\n Widget,\n WidgetProps,\n WidgetRegistry,\n WidgetDescriptor,\n WidgetMap,\n SelectOption,\n UISchema,\n UISchemaOptions,\n} from \"./types\";\nexport { firstError } from \"./types\";\n\n// Export resolver\nexport {\n resolveWidget,\n getDefaultWidgetForType,\n DEFAULT_WIDGET_MAP,\n} from \"./widgetResolver\";\n\n/**\n * DEFAULT_WIDGETS - The default widget registry.\n *\n * Contains all built-in widgets mapped by their names.\n * Use this as the base registry or extend it with custom widgets.\n *\n * @example\n * ```typescript\n * import { DEFAULT_WIDGETS } from './widgets';\n * import MyCustomWidget from './MyCustomWidget';\n *\n * const registry = { ...DEFAULT_WIDGETS, MyCustomWidget };\n * ```\n */\nexport const DEFAULT_WIDGETS: WidgetRegistry = {\n // Canonical PascalCase names\n TextInputWidget,\n TextareaWidget,\n NumberWidget,\n CheckboxWidget,\n SelectWidget,\n TagsInputWidget,\n JsonEditorWidget,\n EntitySelectWidget,\n ObjectWidget,\n ArrayWidget,\n QuantityWidget,\n DateWidget,\n TimeWidget,\n DateTimeWidget,\n DisplayWidget,\n OneOfWidget,\n\n // Lowercase aliases for x-ui-widget convenience\n text: TextInputWidget,\n textarea: TextareaWidget,\n number: NumberWidget,\n checkbox: CheckboxWidget,\n select: SelectWidget,\n tags: TagsInputWidget,\n \"json-editor\": JsonEditorWidget,\n \"entity-select\": EntitySelectWidget,\n object: ObjectWidget,\n array: ArrayWidget,\n quantity: QuantityWidget,\n date: DateWidget,\n time: TimeWidget,\n \"date-time\": DateTimeWidget,\n display: DisplayWidget,\n \"one-of\": OneOfWidget,\n};\n","/**\n * HorizontalArrayItemTemplate -- CSS grid row layout for array items.\n *\n * Renders each item as a grid row. The sub-form container uses\n * display:contents so its field divs become direct grid cells. The\n * remove button occupies the last column (32px).\n *\n * Activated by x-ui-layout.direction: \"horizontal\" on the array property.\n */\n\nimport { Trash2, ChevronUp, ChevronDown } from \"lucide-react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport type { ArrayItemTemplateProps } from \"../widgets/types\";\nimport { buildGridTemplate } from \"./gridUtils\";\n\nexport function HorizontalArrayItemTemplate({\n children,\n index,\n total,\n canRemove,\n orderable,\n disabled,\n layout,\n fieldCount,\n fid,\n onRemove,\n onMoveUp,\n onMoveDown,\n}: ArrayItemTemplateProps): React.ReactElement {\n const resolvedLayout = layout;\n const template = buildGridTemplate(\n resolvedLayout,\n canRemove,\n fieldCount,\n orderable,\n );\n const gap = resolvedLayout.gap ?? 8;\n // compact rows center-align (controls are short); full-height rows stretch.\n const alignItems = resolvedLayout.compact ? \"center\" : \"start\";\n\n return (\n <div\n data-fid={fid}\n style={{\n display: \"grid\",\n gridTemplateColumns: template,\n gap: `${gap}px`,\n alignItems,\n }}\n >\n {children}\n {orderable && (\n <div className=\"flex flex-col items-center justify-center\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"compact\"\n disabled={disabled || index === 0}\n onClick={onMoveUp}\n title=\"Move up\"\n className=\"h-4 w-8 p-0\"\n >\n <ChevronUp className=\"h-3 w-3\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"compact\"\n disabled={disabled || index >= total - 1}\n onClick={onMoveDown}\n title=\"Move down\"\n className=\"h-4 w-8 p-0\"\n >\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </div>\n )}\n {canRemove && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"compact\"\n disabled={disabled}\n onClick={onRemove}\n title=\"Remove item\"\n className=\"text-muted-foreground hover:text-destructive h-8 w-8 p-0\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n )}\n </div>\n );\n}\n","/**\n * TabsGroupTemplate -- presents field groups as a tab bar (the default for\n * `x-ui-layout.tabs`).\n *\n * Selection is controlled and clamped to a group that still exists, so hiding\n * the group the user is on (via its rule) falls back to the first remaining one\n * instead of leaving an empty body.\n */\n\nimport React, { useState } from \"react\";\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from \"@petrarca/sonnet-ui\";\nimport type { GroupLayoutTemplateProps } from \"../widgets/types\";\nimport { GroupErrorBadge } from \"./GroupErrorBadge\";\n\nexport function TabsGroupTemplate({\n groups,\n}: GroupLayoutTemplateProps): React.ReactElement {\n const [active, setActive] = useState<string>(groups[0].key);\n const value = groups.some((g) => g.key === active) ? active : groups[0].key;\n return (\n <Tabs value={value} onValueChange={setActive}>\n <TabsList className=\"mb-4\">\n {groups.map((g) => (\n <TabsTrigger key={g.key} value={g.key} className=\"gap-1.5\">\n {g.label}\n <GroupErrorBadge count={g.errorCount} />\n </TabsTrigger>\n ))}\n </TabsList>\n {groups.map((g) => (\n <TabsContent key={g.key} value={g.key} className=\"space-y-4\">\n {g.content}\n </TabsContent>\n ))}\n </Tabs>\n );\n}\n","/**\n * GroupErrorBadge -- marks a group's trigger (tab or step) as having\n * validation errors. Shared by the built-in group templates.\n *\n * Deliberately just the icon: a trigger sits in a dense strip alongside its\n * label and, in a stepper, a step number, so a second numeral reads as clutter\n * and competes with the step index. The exact count stays available as the\n * accessible name and the tooltip, and the form-level summary reports totals.\n *\n * The signal is a shape, not a colour, so it survives a colour-vision\n * deficiency or a greyscale print.\n */\n\nimport React from \"react\";\nimport { AlertCircle } from \"lucide-react\";\n\nexport function GroupErrorBadge({\n count,\n}: {\n count: number;\n}): React.ReactElement | null {\n if (count === 0) return null;\n const label =\n count === 1 ? \"1 field needs attention\" : `${count} fields need attention`;\n return (\n <span\n role=\"img\"\n aria-label={label}\n title={label}\n className=\"inline-flex shrink-0 text-destructive\"\n >\n <AlertCircle className=\"h-3.5 w-3.5\" />\n </span>\n );\n}\n","/**\n * StepperGroupTemplate -- presents field groups as a wizard\n * (`x-ui-layout.variant: \"stepper\"`).\n *\n * Same group model as the tab presentation, different chrome: a numbered step\n * rail plus Back/Next. Steps stay directly clickable so the user is never\n * trapped; validation gating is deliberately not applied here, because a\n * group's errors are advisory (the badge) rather than a hard barrier.\n *\n * Selection is controlled and clamped to a group that still exists, so hiding\n * the step the user is on falls back to the first remaining one.\n */\n\nimport React, { useState } from \"react\";\nimport {\n Button,\n Stepper,\n StepperList,\n StepperItem,\n StepperTrigger,\n StepperIndicator,\n StepperSeparator,\n StepperTitle,\n StepperContent,\n StepperPrev,\n StepperNext,\n} from \"@petrarca/sonnet-ui\";\nimport type { GroupLayoutTemplateProps } from \"../widgets/types\";\nimport { GroupErrorBadge } from \"./GroupErrorBadge\";\n\nexport function StepperGroupTemplate({\n groups,\n}: GroupLayoutTemplateProps): React.ReactElement {\n const [active, setActive] = useState<string>(groups[0].key);\n const value = groups.some((g) => g.key === active) ? active : groups[0].key;\n const isLast = value === groups[groups.length - 1].key;\n return (\n <Stepper value={value} onValueChange={setActive}>\n <StepperList className=\"mb-4 gap-2\">\n {groups.map((g) => (\n <StepperItem key={g.key} value={g.key}>\n <StepperTrigger>\n <StepperIndicator />\n {/* StepperTitle is plain text; make it a flex row so the badge\n centres on the label instead of sitting on the baseline. */}\n <StepperTitle className=\"inline-flex items-center gap-1.5\">\n {g.label}\n <GroupErrorBadge count={g.errorCount} />\n </StepperTitle>\n </StepperTrigger>\n <StepperSeparator />\n </StepperItem>\n ))}\n </StepperList>\n {groups.map((g) => (\n <StepperContent key={g.key} value={g.key} className=\"space-y-4\">\n {g.content}\n </StepperContent>\n ))}\n <div className=\"mt-4 flex justify-between\">\n <StepperPrev asChild>\n <Button variant=\"outline\" size=\"sm\">\n Back\n </Button>\n </StepperPrev>\n {/* The last step has nowhere to go; the form's own actions take over. */}\n {!isLast && (\n <StepperNext asChild>\n <Button size=\"sm\">Next</Button>\n </StepperNext>\n )}\n </div>\n </Stepper>\n );\n}\n","/**\n * SectionsGroupTemplate -- presents field groups as stacked titled sections\n * (`x-ui-layout.variant: \"sections\"`).\n *\n * Unlike tabs and stepper, every group is visible at once. This is the\n * multi-row counterpart to a row's `group` fieldset: a section holds as many\n * rows as it likes, whereas `row.group` wraps exactly one.\n *\n * No selection state, so nothing to clamp -- a group hidden by its rule simply\n * does not appear.\n */\n\nimport React from \"react\";\nimport type { GroupLayoutTemplateProps } from \"../widgets/types\";\nimport { GroupErrorBadge } from \"./GroupErrorBadge\";\n\nexport function SectionsGroupTemplate({\n groups,\n}: GroupLayoutTemplateProps): React.ReactElement {\n return (\n <div className=\"space-y-6\">\n {groups.map((g) => (\n <fieldset\n key={g.key}\n className=\"rounded-md border border-border/60 px-3 pb-3 pt-1\"\n >\n <legend className=\"inline-flex items-center gap-1.5 px-1 text-sm font-medium text-muted-foreground\">\n {g.label}\n <GroupErrorBadge count={g.errorCount} />\n </legend>\n <div className=\"space-y-4\">{g.content}</div>\n </fieldset>\n ))}\n </div>\n );\n}\n","/**\n * Default templates for structural layout rendering.\n *\n * These are the pre-built implementations used by ArrayWidget and\n * ObjectWidget when no custom template is injected. Callers override\n * specific templates by passing a partial TemplateRegistry to the\n * `templates` prop on JsonSchemaFormRenderer.\n */\n\nimport type { TemplateRegistry } from \"../widgets/types\";\nimport { DefaultArrayItemTemplate } from \"./DefaultArrayItemTemplate\";\nimport { HorizontalArrayItemTemplate } from \"./HorizontalArrayItemTemplate\";\nimport { DefaultArrayHeaderTemplate } from \"./DefaultArrayHeaderTemplate\";\nimport { DefaultObjectContainerTemplate } from \"./DefaultObjectContainerTemplate\";\nimport { TabsGroupTemplate } from \"./TabsGroupTemplate\";\nimport { StepperGroupTemplate } from \"./StepperGroupTemplate\";\nimport { SectionsGroupTemplate } from \"./SectionsGroupTemplate\";\n\nexport { DefaultArrayItemTemplate } from \"./DefaultArrayItemTemplate\";\nexport { HorizontalArrayItemTemplate } from \"./HorizontalArrayItemTemplate\";\nexport { DefaultArrayHeaderTemplate } from \"./DefaultArrayHeaderTemplate\";\nexport { DefaultObjectContainerTemplate } from \"./DefaultObjectContainerTemplate\";\nexport { TabsGroupTemplate } from \"./TabsGroupTemplate\";\nexport { StepperGroupTemplate } from \"./StepperGroupTemplate\";\nexport { SectionsGroupTemplate } from \"./SectionsGroupTemplate\";\nexport { GroupErrorBadge } from \"./GroupErrorBadge\";\n\n/**\n * DEFAULT_TEMPLATES -- the built-in template implementations.\n *\n * Pass a partial override to JsonSchemaFormRenderer's `templates` prop\n * to replace specific templates globally, or use x-ui-options on a\n * schema property for per-field overrides.\n */\nexport const DEFAULT_TEMPLATES: TemplateRegistry = {\n ArrayItemTemplate: DefaultArrayItemTemplate,\n HorizontalArrayItemTemplate: HorizontalArrayItemTemplate,\n ArrayHeaderTemplate: DefaultArrayHeaderTemplate,\n ObjectContainerTemplate: DefaultObjectContainerTemplate,\n TabsGroupTemplate: TabsGroupTemplate,\n StepperGroupTemplate: StepperGroupTemplate,\n SectionsGroupTemplate: SectionsGroupTemplate,\n};\n\n/**\n * The TemplateRegistry key for a group-layout variant. The variant name maps\n * directly to a template name, so a consumer can register\n * `WizardGroupTemplate` and select it with `variant: \"wizard\"` -- no library\n * change needed. Unknown variants fall back to the tab presentation.\n */\nexport function groupTemplateKey(variant: string | undefined): string {\n if (!variant) return \"TabsGroupTemplate\";\n const name = variant.charAt(0).toUpperCase() + variant.slice(1);\n return `${name}GroupTemplate`;\n}\n","/**\n * FormFieldRenderer - Renders a single form field via the widget system\n *\n * Replaces the `renderField` free function that previously lived in\n * JsonSchemaFormRenderer. Moving it to a proper component ensures the `key`\n * prop is set at the call site (in the parent's `.map()`), not buried inside\n * the function, which is the idiomatic React pattern.\n *\n * @module components/Forms/FormFieldRenderer\n */\n\nimport React from \"react\";\nimport { JsonSchema, JsonSchemaProperty } from \"@petrarca/sonnet-core/schema\";\nimport { warnLog } from \"@petrarca/sonnet-core\";\nimport {\n getFieldTitle,\n getFieldHelpText,\n getFieldPlaceholder,\n} from \"@petrarca/sonnet-core/schema\";\nimport {\n resolveWidget,\n WidgetRegistry,\n UISchema,\n UISchemaOptions,\n} from \"./widgets\";\n\nexport interface FormFieldRendererProps {\n fieldName: string;\n property: JsonSchemaProperty;\n value: unknown;\n onChange: (value: unknown) => void;\n onBlur?: (id: string, value: unknown) => void;\n required: boolean;\n disabled: boolean;\n readOnly: boolean;\n schema: JsonSchema;\n uiSchema?: UISchema;\n registry: WidgetRegistry;\n globalOptions?: UISchemaOptions;\n formData?: Record<string, unknown>;\n /**\n * Prefix for generated control ids: `<idPrefix>-<fieldName>` (default\n * \"field\"). Set a per-form prefix when rendering multiple forms on one page\n * to keep ids unique.\n */\n idPrefix?: string;\n /** Validation messages for this field, rendered inline by the widget. */\n rawErrors?: string[];\n}\n\n/** Merge options: field uiSchema > property x-ui-options > global. */\nfunction mergeFieldOptions(\n globalOptions: UISchemaOptions,\n property: JsonSchemaProperty,\n uiSchema: UISchema | undefined,\n): UISchemaOptions {\n const xWidgetOptions = property[\"x-ui-options\"] || {};\n const fieldOptions = uiSchema?.[\"x-ui-options\"] || {};\n return { ...globalOptions, ...xWidgetOptions, ...fieldOptions };\n}\n\n/** Resolve effective label: global label=false hides it; uiSchema x-ui-title overrides. */\nfunction resolveEffectiveLabel(\n label: string,\n uiTitle: string | boolean | undefined,\n globalLabelOption: string | false | undefined,\n): string {\n if (globalLabelOption === false) return \"\";\n if (typeof uiTitle === \"string\") return uiTitle;\n if (uiTitle === false) return \"\";\n return label;\n}\n\n// Tailwind class equivalents of WIDTH_TOKEN_REMS (sonnet-core): w-32=8rem,\n// w-48=12rem, w-64=16rem. Kept as Tailwind utility strings so the JIT scanner\n// can pick them up (arbitrary rem values in class names are not scanned).\nconst FIELD_WIDTH_CLASS = {\n sm: \"w-32\",\n md: \"w-48\",\n lg: \"w-64\",\n full: \"w-full\",\n} as const satisfies Record<\n import(\"@petrarca/sonnet-core/schema\").WidthToken,\n string\n>;\n\ntype FieldWidth = keyof typeof FIELD_WIDTH_CLASS;\n\n/**\n * Wrap a field in a width-constraining slot when x-ui-width is set. \"full\"\n * (the default) returns the field unwrapped so layout containers control width.\n */\nfunction applyFieldWidth(\n widget: React.ReactElement,\n uiSchema: UISchema | undefined,\n mergedOptions: UISchemaOptions,\n): React.ReactElement {\n const candidate = uiSchema?.[\"x-ui-width\"] ?? mergedOptions.width;\n if (candidate && !(candidate in FIELD_WIDTH_CLASS)) {\n warnLog(\n `[FormFieldRenderer] Unknown x-ui-width value: \"${candidate}\". Falling back to \"full\".`,\n );\n }\n const width: FieldWidth =\n candidate && candidate in FIELD_WIDTH_CLASS\n ? (candidate as FieldWidth)\n : \"full\";\n if (width === \"full\") return widget;\n return <div className={FIELD_WIDTH_CLASS[width]}>{widget}</div>;\n}\n\n/** Resolve description/placeholder: uiSchema override, else schema-derived. */\nfunction resolvePresentationText(\n property: JsonSchemaProperty,\n uiSchema: UISchema | undefined,\n): { description: string | undefined; placeholder: string | undefined } {\n return {\n description: uiSchema?.[\"x-ui-description\"] ?? getFieldHelpText(property),\n placeholder:\n uiSchema?.[\"x-ui-placeholder\"] ?? getFieldPlaceholder(property),\n };\n}\n\n/** Resolve cascading disabled/readonly flags. */\nfunction resolveFieldFlags(\n fieldOptions: UISchemaOptions,\n globalOptions: UISchemaOptions,\n disabled: boolean,\n readOnly: boolean,\n) {\n return {\n disabled: fieldOptions.disabled ?? globalOptions.disabled ?? disabled,\n readOnly: fieldOptions.readonly ?? globalOptions.readonly ?? readOnly,\n };\n}\n\nexport function FormFieldRenderer({\n fieldName,\n property,\n value,\n onChange,\n onBlur,\n required,\n disabled,\n readOnly,\n schema,\n uiSchema,\n registry,\n globalOptions = {},\n formData,\n idPrefix = \"field\",\n rawErrors,\n}: FormFieldRendererProps): React.ReactElement | null {\n const label = getFieldTitle(fieldName, property);\n const { description, placeholder } = resolvePresentationText(\n property,\n uiSchema,\n );\n\n const Widget = resolveWidget(property, uiSchema, registry);\n const mergedOptions = mergeFieldOptions(globalOptions, property, uiSchema);\n\n if (mergedOptions.hidden) return null;\n\n const fieldOptions = uiSchema?.[\"x-ui-options\"] || {};\n const flags = resolveFieldFlags(\n fieldOptions,\n globalOptions,\n disabled,\n readOnly,\n );\n const effectiveLabel = resolveEffectiveLabel(\n label,\n uiSchema?.[\"x-ui-title\"],\n globalOptions.label,\n );\n const widget = (\n <Widget\n id={`${idPrefix}-${fieldName}`}\n name={fieldName}\n value={value}\n onChange={onChange}\n onBlur={onBlur}\n schema={schema}\n propertySchema={property}\n uiSchema={uiSchema}\n registry={registry}\n label={effectiveLabel}\n description={description}\n placeholder={placeholder}\n required={required}\n disabled={flags.disabled}\n readonly={flags.readOnly}\n options={mergedOptions}\n formData={formData}\n rawErrors={rawErrors}\n />\n );\n\n return applyFieldWidth(widget, uiSchema, mergedOptions);\n}\n","/**\n * useFormEngine - Core form state, schema resolution, and update-mode logic\n *\n * Owns:\n * - formData state (internal working copy)\n * - resolvedSchema / orderedProperties (conditional schema + field ordering)\n * - originalData baseline for dirty-tracking\n * - nonSchemaData (fields not in the schema, preserved on save)\n * - pendingChanges (deferred-state-update buffer)\n * - isValid / validation errors\n * - handleFieldChange, handleFieldBlur, handleSave, handleCancel\n *\n * Supports all three update modes:\n * 1. Real-time — onChange on every keystroke\n * 2. Deferred — onChange on blur for text fields (deferChanges)\n * 3. Buffered — Save/Cancel flow (showActions + onUpdate)\n *\n * @module components/Forms/hooks/useFormEngine\n */\n\nimport { useState, useEffect, useMemo, useCallback, useRef } from \"react\";\nimport { isEqual } from \"@petrarca/sonnet-core\";\nimport { JsonSchema, JsonSchemaProperty } from \"@petrarca/sonnet-core/schema\";\nimport {\n getSchemaProperties,\n getFieldDefault,\n applySchemaDefaults,\n resolveSchema,\n resolveRefs,\n validateFormData,\n diffFormData,\n ensureFormItemIds,\n} from \"@petrarca/sonnet-core/schema\";\nimport type {\n FormDiff,\n RefResolver,\n FieldError,\n} from \"@petrarca/sonnet-core/schema\";\nimport { UISchema } from \"../widgets\";\nimport { orderProperties } from \"./orderProperties\";\n\n/**\n * Returns true for field types that should always trigger immediate updates\n * (checkboxes, enum-based selects), regardless of deferral settings.\n */\nfunction isImmediateField(\n fieldName: string,\n properties: Record<string, JsonSchemaProperty>,\n): boolean {\n const property = properties[fieldName];\n return property?.type === \"boolean\" || property?.enum !== undefined;\n}\n\n/**\n * Compute updated originalData baseline when external `data` expands.\n *\n * Returns a result object when an update is needed, null otherwise.\n * `shouldMarkInitialized` is true on first initialization, false on subsequent expansion.\n */\nfunction computeBaselineUpdate(\n newData: Record<string, any>,\n originalData: Record<string, any>,\n initialized: boolean,\n schemaPropertyNames: string[],\n): {\n shouldMarkInitialized: boolean;\n cleanedData: Record<string, any>;\n nonSchema: Record<string, any>;\n} | null {\n const newCount = Object.keys(newData).length;\n const origCount = Object.keys(originalData).length;\n\n if (!initialized && newCount > 0) {\n const cleanedData = Object.fromEntries(\n Object.entries(newData).filter(([k]) => schemaPropertyNames.includes(k)),\n );\n const nonSchema = Object.fromEntries(\n Object.entries(newData).filter(([k]) => !schemaPropertyNames.includes(k)),\n );\n return { shouldMarkInitialized: true, cleanedData, nonSchema };\n }\n\n if (initialized && newCount > origCount) {\n const cleanedData = Object.fromEntries(\n Object.entries(newData).filter(([k]) => schemaPropertyNames.includes(k)),\n );\n const nonSchema = Object.fromEntries(\n Object.entries(newData).filter(([k]) => !schemaPropertyNames.includes(k)),\n );\n return { shouldMarkInitialized: false, cleanedData, nonSchema };\n }\n\n return null;\n}\n\nexport interface UseFormEngineOptions {\n schema: JsonSchema;\n data: Record<string, any>;\n uiSchema: { [fieldName: string]: UISchema };\n onChange?: (data: Record<string, any>) => void;\n onBlur?: (fieldName: string, data: Record<string, any>) => void;\n onValidationChange?: (errors: string[], isValid: boolean) => void;\n onUpdate?: (\n data: Record<string, any>,\n changedFields: Record<string, any>,\n diff: FormDiff,\n ) => void;\n onCancel?: () => void;\n readOnly?: boolean;\n showActions?: boolean;\n deferChanges?: boolean;\n deferStateUpdates?: boolean;\n /**\n * Allow saving when the form is pristine (no changes vs the baseline). Use for\n * CREATE forms, where submitting default / empty values is valid -- the\n * \"must have changed something\" dirty-check is an edit-only concept.\n * Validation (required fields) still applies. Default false (edit semantics).\n */\n allowPristineSave?: boolean;\n /**\n * Optional resolver for non-local `$ref`s (e.g. a schema-registry id or\n * canonical URI). Tried before the in-document `$defs` fallback. Must be\n * synchronous -- pre-load referenced schemas into a map and pass a lookup.\n */\n refResolver?: RefResolver;\n}\n\nexport interface UseFormEngineResult {\n /** The current working form data (for controlled field values) */\n formData: Record<string, any>;\n /**\n * Display data — formData merged with pending deferred changes.\n * Always use this for rendering field values.\n */\n displayData: Record<string, any>;\n /** Schema resolved against the current formData (conditional fields evaluated) */\n resolvedSchema: JsonSchema;\n /** Properties ordered by x-ui-order, ready for rendering */\n orderedProperties: [string, JsonSchemaProperty][];\n hasChanges: boolean;\n isValid: boolean;\n /**\n * Current validation errors, each attributed to its field by JSON Pointer.\n * Lets the renderer surface problems for fields that are not on screen.\n */\n fieldErrors: FieldError[];\n /** Fields the user has touched (focused then blurred). */\n touched: Record<string, boolean>;\n /** Whether a save has been attempted (reveals all errors under any policy). */\n submitAttempted: boolean;\n handleFieldChange: (fieldName: string, value: any) => void;\n handleFieldBlur: (fieldName: string) => void;\n handleSave: () => void;\n handleCancel: () => void;\n}\n\nexport function useFormEngine({\n schema,\n data,\n uiSchema,\n onChange,\n onBlur,\n onValidationChange,\n onUpdate,\n onCancel,\n readOnly = false,\n showActions = false,\n deferChanges = false,\n deferStateUpdates = false,\n allowPristineSave = false,\n refResolver,\n}: UseFormEngineOptions): UseFormEngineResult {\n // Resolve $ref pointers before anything else. This is a pure transformation\n // that only depends on the schema object and the (stable) resolver.\n const refResolvedSchema = useMemo(\n () => resolveRefs(schema, refResolver),\n [schema, refResolver],\n );\n\n // Seed the baseline and the working copy from ONE stamped snapshot, so array\n // items carry the same `_fid` on both sides. Stamping each side separately\n // would mint different ids and defeat the diff -- the very bug this avoids.\n // The stamp runs once at mount; later external `data` changes re-seed through\n // computeBaselineUpdate below.\n const seed = useState<Record<string, any>>(() =>\n ensureFormItemIds(\n applySchemaDefaults(data, refResolvedSchema),\n refResolvedSchema,\n ),\n )[0];\n\n const [originalData, setOriginalData] = useState<Record<string, any>>(\n () => seed,\n );\n const [originalDataInitialized, setOriginalDataInitialized] = useState(false);\n\n const [nonSchemaData, setNonSchemaData] = useState<Record<string, any>>(\n () => {\n const props = getSchemaProperties(refResolvedSchema);\n const names = Object.keys(props);\n return Object.fromEntries(\n Object.entries(data).filter(([k]) => !names.includes(k)),\n );\n },\n );\n\n const [formData, setFormData] = useState<Record<string, any>>(() => seed);\n\n // Mirror the latest formData in a ref so blur handlers read the current value\n // even if they fire before React commits the last keystroke's state update.\n const formDataRef = useRef(formData);\n formDataRef.current = formData;\n\n const [pendingChanges, setPendingChanges] = useState<Record<string, any>>({});\n\n // Schema resolution depends on live formData so conditional fields\n // (if-then-else, allOf) are re-evaluated on every change.\n const resolvedSchema = useMemo(\n () => resolveSchema(refResolvedSchema, formData),\n [refResolvedSchema, formData],\n );\n\n const orderedProperties = useMemo(() => {\n const properties = getSchemaProperties(resolvedSchema);\n const rawOrder = uiSchema[\"x-ui-order\"] ?? resolvedSchema[\"x-ui-order\"];\n const orderArray = Array.isArray(rawOrder)\n ? (rawOrder as string[])\n : undefined;\n return orderProperties(properties, orderArray);\n }, [resolvedSchema, uiSchema]);\n\n const [initialDefaultsSent, setInitialDefaultsSent] = useState(false);\n\n // Validation-display gating: a field's error shows once it has been touched,\n // and every field's error shows after a save attempt. Which of these applies\n // is the renderer's policy; the engine only records the facts. All reset on\n // cancel.\n //\n // \"Touched\" means edited and then blurred -- not merely focused and left.\n // Blurring a field the user never changed (tabbed through, or landed on by\n // autofocus) must not accuse them of leaving it invalid; it also made the\n // error appear mid-interaction, growing the field and shifting whatever sat\n // below it. This matches rjsf, which validates on blur only for \"a field that\n // was updated\".\n const [edited, setEdited] = useState<Record<string, boolean>>({});\n const [touched, setTouched] = useState<Record<string, boolean>>({});\n const [submitAttempted, setSubmitAttempted] = useState(false);\n\n const properties = getSchemaProperties(resolvedSchema);\n\n // On mount: if schema defaults were applied that the caller didn't supply,\n // push the initialized data up via onChange so the parent stays in sync.\n useEffect(() => {\n if (!initialDefaultsSent) {\n const hasDefaults = Object.entries(properties).some(\n ([fieldName, property]) =>\n data[fieldName] === undefined &&\n getFieldDefault(property) !== undefined,\n );\n\n if (hasDefaults && onChange) {\n onChange(formData);\n }\n setInitialDefaultsSent(true);\n }\n }, [initialDefaultsSent, properties, data, formData, onChange]);\n\n // Remove formData keys that are no longer present in the resolved schema.\n // This keeps internal state clean when a conditional branch hides a field.\n useEffect(() => {\n const currentPropertyNames = Object.keys(properties);\n const keysToRemove = Object.keys(formData).filter(\n (k) => !currentPropertyNames.includes(k),\n );\n\n if (keysToRemove.length > 0) {\n const cleanedData = { ...formData };\n keysToRemove.forEach((k) => {\n delete cleanedData[k];\n });\n setFormData(cleanedData);\n if (onChange) onChange(cleanedData);\n }\n }, [properties, formData, onChange]);\n\n // Sync formData when the external data prop changes. Uses a ref to track\n // the previous value so we can avoid triggering on every render while\n // keeping the dependency array honest.\n const prevDataRef = useRef(data);\n useEffect(() => {\n if (isEqual(prevDataRef.current, data)) return;\n prevDataRef.current = data;\n\n // Stamp once, then derive both the working copy and the baseline from the\n // same snapshot so array-item `_fid`s match across the diff (see the mount\n // seed above). computeBaselineUpdate only filters keys, preserving the ids.\n const newData = ensureFormItemIds(\n applySchemaDefaults(data, refResolvedSchema),\n refResolvedSchema,\n );\n setFormData(newData);\n\n const schemaPropertyNames = Object.keys(properties);\n const result = computeBaselineUpdate(\n newData,\n originalData,\n originalDataInitialized,\n schemaPropertyNames,\n );\n\n if (result) {\n setOriginalData(result.cleanedData);\n setNonSchemaData(result.nonSchema);\n if (result.shouldMarkInitialized) {\n setOriginalDataInitialized(true);\n }\n }\n }, [\n data,\n refResolvedSchema,\n resolvedSchema,\n properties,\n originalData,\n originalDataInitialized,\n ]);\n\n const hasChanges = useMemo(\n () => !isEqual(formData, originalData),\n [formData, originalData],\n );\n\n // In deferStateUpdates mode, pending (not-yet-blurred) text field changes\n // are held separately and merged here for display only.\n const displayData = useMemo(() => {\n if (deferStateUpdates && Object.keys(pendingChanges).length > 0) {\n return { ...formData, ...pendingChanges };\n }\n return formData;\n }, [formData, pendingChanges, deferStateUpdates]);\n\n // Validity plus the per-field errors behind it, derived from the live schema\n // and data rather than stored. Deriving keeps it correct when the schema or\n // data props change -- storing it left the value stale until the next edit.\n // Field errors let the renderer attribute a problem to a field that is not on\n // screen: e.g. badging a form tab whose fields sit in an inactive panel.\n const validation = useMemo(\n () => validateFormData(resolvedSchema, displayData),\n [resolvedSchema, displayData],\n );\n const { isValid, fieldErrors } = validation;\n\n // Report validity from the single derived result, so the callback can never\n // disagree with the form's own isValid (it previously re-validated against a\n // partial snapshot, and never fired on mount or on a schema/data prop change).\n const onValidationChangeRef = useRef(onValidationChange);\n onValidationChangeRef.current = onValidationChange;\n useEffect(() => {\n onValidationChangeRef.current?.(validation.errors, validation.isValid);\n }, [validation]);\n\n const handleFieldChange = useCallback(\n (fieldName: string, value: any) => {\n if (readOnly) return;\n\n // Record the edit before any deferral branch: a deferred field is still\n // edited, and blur must be able to reveal its error.\n setEdited((prev) =>\n prev[fieldName] ? prev : { ...prev, [fieldName]: true },\n );\n\n const immediate = isImmediateField(fieldName, properties);\n\n // Deferred state: hold non-immediate (text) edits until blur. Works with\n // or without a Save button; the flush on blur commits (and, when there is\n // no Save button, calls onChange). Immediate fields (checkbox/select)\n // always apply at once.\n if (deferStateUpdates && !immediate) {\n setPendingChanges((prev) => ({ ...prev, [fieldName]: value }));\n return;\n }\n\n const newData = { ...formData, [fieldName]: value };\n setFormData(newData);\n\n if (!showActions) {\n const shouldCallOnChange = !deferChanges || immediate;\n if (shouldCallOnChange && onChange) onChange(newData);\n }\n },\n [\n readOnly,\n formData,\n deferChanges,\n deferStateUpdates,\n showActions,\n onChange,\n properties,\n ],\n );\n\n // Flush deferred pending changes for a field into formData on blur. When\n // there is no Save button (showActions === false) the flushed data is also\n // pushed to onChange so the parent commits the edit.\n const flushPendingField = useCallback(\n (fieldName: string) => {\n if (!deferStateUpdates) return;\n if (pendingChanges[fieldName] === undefined) return;\n\n const newData = { ...formData, ...pendingChanges };\n setFormData(newData);\n setPendingChanges((prev) => {\n const updated = { ...prev };\n delete updated[fieldName];\n return updated;\n });\n\n if (!showActions && onChange) onChange(newData);\n },\n [showActions, deferStateUpdates, pendingChanges, formData, onChange],\n );\n\n const handleFieldBlur = useCallback(\n (fieldName: string) => {\n if (readOnly) return;\n\n // Only an edited field becomes touched -- see the note on `edited`.\n if (edited[fieldName]) {\n setTouched((prev) =>\n prev[fieldName] ? prev : { ...prev, [fieldName]: true },\n );\n }\n\n flushPendingField(fieldName);\n\n // Read the latest data via ref: the last keystroke's setFormData may not\n // have been committed to the closure's `formData` yet when blur fires.\n const latest = formDataRef.current;\n\n if (!showActions && deferChanges && onChange) {\n onChange(latest);\n }\n\n if (onBlur) {\n const hasPending =\n deferStateUpdates && pendingChanges[fieldName] !== undefined;\n const dataToPass = hasPending\n ? { ...latest, [fieldName]: pendingChanges[fieldName] }\n : latest;\n onBlur(fieldName, dataToPass);\n }\n },\n [\n readOnly,\n edited,\n pendingChanges,\n deferChanges,\n deferStateUpdates,\n showActions,\n onChange,\n onBlur,\n flushPendingField,\n ],\n );\n\n const handleSave = useCallback(() => {\n // A save attempt reveals every field's error, whether or not the save then\n // proceeds -- this is what makes an invalid save explain itself.\n setSubmitAttempted(true);\n\n // Pristine saves are blocked for edit forms (dirty-check), allowed for\n // create forms (allowPristineSave). Validity is enforced below regardless.\n if (!hasChanges && !allowPristineSave) return;\n\n const finalData =\n deferStateUpdates && Object.keys(pendingChanges).length > 0\n ? { ...formData, ...pendingChanges }\n : formData;\n\n const completeData = { ...nonSchemaData, ...finalData };\n const validation = validateFormData(resolvedSchema, finalData);\n\n if (validation.isValid && onUpdate) {\n // Compute changed fields at save time (includes any pending changes).\n const changed: Record<string, any> = {};\n for (const key of Object.keys(finalData)) {\n if (!isEqual(finalData[key], originalData[key])) {\n changed[key] = finalData[key];\n }\n }\n const diff = diffFormData(originalData, finalData);\n onUpdate(completeData, changed, diff);\n setPendingChanges({});\n }\n }, [\n hasChanges,\n allowPristineSave,\n resolvedSchema,\n formData,\n originalData,\n pendingChanges,\n deferStateUpdates,\n nonSchemaData,\n onUpdate,\n ]);\n\n const handleCancel = useCallback(() => {\n setFormData({ ...originalData });\n setPendingChanges({});\n setEdited({});\n setTouched({});\n setSubmitAttempted(false);\n onCancel?.();\n }, [originalData, onCancel]);\n\n return {\n formData,\n displayData,\n resolvedSchema,\n orderedProperties,\n hasChanges,\n isValid,\n fieldErrors,\n touched,\n submitAttempted,\n handleFieldChange,\n handleFieldBlur,\n handleSave,\n handleCancel,\n };\n}\n","import { JsonSchemaProperty } from \"@petrarca/sonnet-core/schema\";\n\n/**\n * Order properties based on the x-ui-order array.\n *\n * Fields listed in x-ui-order are rendered first (in that order).\n * Fields not listed are rendered after in their original schema order.\n * Names in x-ui-order that don't exist in properties are silently ignored.\n */\nexport function orderProperties(\n properties: Record<string, JsonSchemaProperty>,\n orderArray: string[] | undefined,\n): [string, JsonSchemaProperty][] {\n const allEntries = Object.entries(properties);\n\n if (!orderArray || orderArray.length === 0) return allEntries;\n\n const orderSet = new Set(orderArray);\n const map = new Map(allEntries);\n\n const ordered: [string, JsonSchemaProperty][] = [];\n for (const name of orderArray) {\n const prop = map.get(name);\n if (prop) ordered.push([name, prop]);\n }\n\n const unordered = allEntries.filter(([name]) => !orderSet.has(name));\n return [...ordered, ...unordered];\n}\n","/**\n * useResolvedSchema - Schema resolution and property ordering\n *\n * Resolves conditional schemas (if-then-else, allOf) based on the current\n * form data, and applies x-ui-order to produce a stable ordered list of\n * [fieldName, property] pairs for rendering.\n *\n * ## Relationship to useFormEngine\n *\n * `useFormEngine` already performs this same resolution internally so that\n * validation and field-cleanup effects have access to the live schema.\n * This hook exists as a **standalone composable** for consumers that need\n * schema resolution without the full form-state machinery — for example:\n *\n * - A read-only schema viewer that renders fields without tracking changes\n * - A field-count or schema-diff preview component\n * - A future form builder that needs to inspect the resolved structure\n * before mounting a full form engine\n *\n * Do **not** import both this hook and `useFormEngine` in the same component\n * for the same schema/data pair — that would resolve the schema twice.\n * Prefer the values returned by `useFormEngine` when the engine is already\n * in use.\n *\n * @module components/Forms/hooks/useResolvedSchema\n */\n\nimport { useMemo } from \"react\";\nimport { JsonSchema, JsonSchemaProperty } from \"@petrarca/sonnet-core/schema\";\nimport {\n getSchemaProperties,\n resolveSchema,\n} from \"@petrarca/sonnet-core/schema\";\nimport { UISchema } from \"../widgets\";\nimport { orderProperties } from \"./orderProperties\";\n\nexport interface UseResolvedSchemaOptions {\n schema: JsonSchema;\n formData: Record<string, any>;\n uiSchema: { [fieldName: string]: UISchema };\n}\n\nexport interface UseResolvedSchemaResult {\n resolvedSchema: JsonSchema;\n orderedProperties: [string, JsonSchemaProperty][];\n}\n\nexport function useResolvedSchema({\n schema,\n formData,\n uiSchema,\n}: UseResolvedSchemaOptions): UseResolvedSchemaResult {\n const resolvedSchema = useMemo(\n () => resolveSchema(schema, formData),\n [schema, formData],\n );\n\n const orderedProperties = useMemo(() => {\n const properties = getSchemaProperties(resolvedSchema);\n const rawOrder = uiSchema[\"x-ui-order\"] ?? resolvedSchema[\"x-ui-order\"];\n const orderArray = Array.isArray(rawOrder)\n ? (rawOrder as string[])\n : undefined;\n return orderProperties(properties, orderArray);\n }, [resolvedSchema, uiSchema]);\n\n return { resolvedSchema, orderedProperties };\n}\n"],"mappings":"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","names":["cn","jsx","jsxs","cn","React","useId","cn","jsx","jsxs","cn","React","useId","React","useId","Input","cn","jsx","React","useId","Input","cn","React","useId","cn","jsx","jsxs","cn","React","useId","React","cn","jsx","jsxs","cn","React","Check","ChevronsUpDown","X","cn","Button","Command","CommandEmpty","CommandGroup","CommandInput","CommandItem","CommandList","Popover","PopoverContent","PopoverTrigger","Fragment","jsx","jsxs","X","Command","CommandInput","CommandList","CommandEmpty","CommandGroup","CommandItem","Check","cn","TriggerIcons","ChevronsUpDown","Popover","PopoverTrigger","Button","PopoverContent","React","X","cn","Input","Badge","jsx","jsxs","Badge","X","cn","Input","React","useCallback","useEffect","useId","useState","ChevronsUpDown","cn","jsx","jsxs","ChevronsUpDown","useState","useEffect","useCallback","React","useId","cn","Button","jsx","jsxs","useMemo","jsx","jsxs","React","useCallback","useContext","useMemo","AlertCircle","FORM_ITEM_ID_FIELD","jsx","jsx","jsx","useCallback","jsx","useCallback","useRef","jsx","useRef","label","jsx","useCallback","useState","jsx","jsxs","useMemo","jsx","jsxs","useMemo","useMemo","useState","ChevronDown","ChevronRight","Card","Collapsible","CollapsibleContent","jsx","jsxs","Fragment","jsx","useMemo","useCallback","useMemo","Plus","Button","ChevronDown","Button","jsx","jsxs","jsx","jsxs","jsx","jsxs","resolveLayout","useCallback","useMemo","Button","Plus","useCallback","useRef","jsx","useRef","useCallback","jsx","jsx","jsx","resolveGranularity","jsx","jsxs","useMemo","jsx","jsxs","useMemo","isNullableBoolean","extractEnumValues","Trash2","ChevronUp","ChevronDown","Button","jsx","jsxs","Button","ChevronUp","ChevronDown","Trash2","useState","jsx","jsx","jsxs","useState","useState","Button","jsx","jsxs","useState","Button","jsx","jsxs","jsx","useState","useEffect","useMemo","useCallback","useRef","applySchemaDefaults","useMemo","useState","applySchemaDefaults","useRef","properties","useEffect","useCallback","validation","jsx","jsxs","FORM_ITEM_ID_FIELD","useCallback","React","useContext","AlertCircle","useMemo","props","useMemo","getSchemaProperties","resolveSchema","useMemo","resolveSchema","getSchemaProperties"]}
1
+ {"version":3,"sources":["../src/FormFieldWrapper.tsx","../src/formFieldUtils.ts","../src/FormInput.tsx","../src/FormTextarea.tsx","../src/FormNumberInput.tsx","../src/FormCheckbox.tsx","../src/FormSelect.tsx","../src/formSelectUtils.ts","../src/FormMultiSelect.tsx","../src/FormTagsInput.tsx","../src/TagBadge.tsx","../src/FormKeyValueInput.tsx","../src/FormQuantityInput.tsx","../src/FormActions.tsx","../src/ExtraPropertiesCard.tsx","../src/JsonSchemaFormRenderer.tsx","../src/widgets/types.ts","../src/widgets/TextInputWidget.tsx","../src/widgets/TextareaWidget.tsx","../src/widgets/NumberWidget.tsx","../src/widgets/CheckboxWidget.tsx","../src/widgets/SelectWidget.tsx","../src/widgets/TagsInputWidget.tsx","../src/widgets/JsonEditorWidget.tsx","../src/widgets/KeyValueWidget.tsx","../src/widgets/EntitySelectWidget.tsx","../src/widgets/ObjectWidget.tsx","../src/hooks/useNestedFormContext.ts","../src/NestedFormContext.tsx","../src/templates/DefaultObjectContainerTemplate.tsx","../src/widgets/ArrayWidget.tsx","../src/templates/DefaultArrayItemTemplate.tsx","../src/templates/gridUtils.ts","../src/templates/DefaultArrayHeaderTemplate.tsx","../src/widgets/QuantityWidget.tsx","../src/widgets/CodedValueWidget.tsx","../src/widgets/codedValue/codedValueModel.ts","../src/widgets/codedValue/useCodedValueOptions.ts","../src/widgets/codedValue/useStoredLabel.ts","../src/widgets/codedValue/useListCheck.ts","../src/widgets/codedValue/HitList.tsx","../src/widgets/codedValue/InlineIconButton.tsx","../src/widgets/codedValue/listOptions.ts","../src/widgets/CodeableConceptWidget.tsx","../src/widgets/codeableConcept/conceptModel.ts","../src/widgets/DateWidget.tsx","../src/widgets/TimeWidget.tsx","../src/widgets/DateTimeWidget.tsx","../src/widgets/DisplayWidget.tsx","../src/widgets/OneOfWidget.tsx","../src/widgets/RadioWidget.tsx","../src/widgets/CheckboxGroupWidget.tsx","../src/widgets/ChoiceWithTextWidget.tsx","../src/widgets/AbsentReasonsWidget.tsx","../src/widgets/widgetResolver.ts","../src/widgets/index.ts","../src/templates/HorizontalArrayItemTemplate.tsx","../src/templates/TabsGroupTemplate.tsx","../src/templates/GroupErrorBadge.tsx","../src/templates/StepperGroupTemplate.tsx","../src/templates/SectionsGroupTemplate.tsx","../src/templates/index.ts","../src/FormFieldRenderer.tsx","../src/hooks/useFormEngine.ts","../src/validators/runValidators.ts","../src/validators/shared.ts","../src/validators/useAsyncValidators.ts","../src/hooks/orderProperties.ts","../src/hooks/useResolvedSchema.ts"],"sourcesContent":["/**\n * FormFieldWrapper - Shared label / description / error chrome for form fields.\n *\n * Eliminates duplication across FormInput, FormNumberInput, FormQuantityInput,\n * etc. Each field component renders its control as `children` and delegates\n * the surrounding chrome here.\n *\n * Supports two modes:\n * - Normal: label, children, description, error displayed vertically\n * - Compact: suppresses label, description, error text (for grid layouts)\n */\n\nimport React from \"react\";\nimport { cn } from \"@petrarca/sonnet-core\";\n\nexport interface FormFieldWrapperProps {\n /** Field id -- wired to the label's htmlFor */\n inputId: string;\n /** Visible label text (false = explicitly hidden) */\n label?: string | false;\n /** Helper text shown below the control */\n description?: string;\n /** Validation error message (takes precedence over description for aria-describedby) */\n error?: string;\n /** Shows a required asterisk next to the label */\n required?: boolean;\n /**\n * Compact mode -- suppresses label, description, and error text so the\n * cell height stays fixed in horizontal grid layouts. Error state is\n * still communicated via the control's own styling (e.g. red border).\n */\n compact?: boolean;\n /**\n * Label placement: \"top\" (default) renders the label above the control;\n * \"start\" renders the label inline on the reading-start side (RTL-safe: left\n * in LTR, right in RTL). Logical values follow the MUI convention.\n */\n labelPlacement?: \"top\" | \"start\";\n /** Additional class name for the outer wrapper div */\n className?: string;\n /** The form control(s) */\n children: React.ReactNode;\n}\n\n/**\n * FormFieldWrapper renders label, children (the control), description, and\n * error in the standard vertical layout used by all form field components.\n */\nexport function FormFieldWrapper({\n inputId,\n label,\n description,\n error,\n required,\n compact,\n labelPlacement = \"top\",\n className,\n children,\n}: FormFieldWrapperProps) {\n if (compact) return <div className={className}>{children}</div>;\n\n const labelEl = !!label && (\n <label\n htmlFor={inputId}\n className=\"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n >\n {label}\n {required && <span className=\"ml-1 text-destructive\">*</span>}\n </label>\n );\n\n const descriptionEl = description && (\n <p id={`${inputId}-description`} className=\"text-sm text-muted-foreground\">\n {description}\n </p>\n );\n\n const errorEl = error && (\n <p id={`${inputId}-error`} className=\"text-sm font-medium text-destructive\">\n {error}\n </p>\n );\n\n // \"start\": label beside the control on the reading-start side, kept tight\n // together. Uses flex so the label flips under dir=rtl. The control box fills\n // its slot (w-full) so an outer x-ui-width wrapper -- or the flow row --\n // governs the width.\n if (labelPlacement === \"start\" && !!label) {\n return (\n <div className={cn(\"flex items-center gap-2\", className)}>\n <div className=\"shrink-0 whitespace-nowrap\">{labelEl}</div>\n <div className=\"w-full min-w-0 space-y-1\">\n {descriptionEl}\n {children}\n {errorEl}\n </div>\n </div>\n );\n }\n\n return (\n <div className={cn(\"space-y-2\", className)}>\n {labelEl}\n {descriptionEl}\n {children}\n {errorEl}\n </div>\n );\n}\n","/**\n * Shared utility functions for form field components.\n * Kept separate from FormFieldWrapper so the wrapper file exports only\n * components (required for React fast-refresh).\n */\n\n/**\n * Returns the correct aria-describedby id for a form control:\n * - error id when there is an error (screen readers announce errors immediately)\n * - description id when there is only a description\n * - undefined when neither is present\n */\nexport function getAriaDescribedBy(\n inputId: string,\n error: string | undefined,\n description: string | undefined,\n): string | undefined {\n if (error) return `${inputId}-error`;\n if (description) return `${inputId}-description`;\n return undefined;\n}\n\n/**\n * Compact-aware version of getAriaDescribedBy.\n * In compact mode, label/description/error text is not rendered, so\n * aria-describedby should be undefined.\n */\nexport function getAriaDescribedByCompact(\n inputId: string,\n error: string | undefined,\n description: string | undefined,\n compact: boolean | undefined,\n): string | undefined {\n if (compact) return undefined;\n return getAriaDescribedBy(inputId, error, description);\n}\n\n/**\n * In compact mode, when label text is hidden, expose it as aria-label\n * so screen readers still announce the field purpose.\n */\nexport function getCompactAriaLabel(\n label: string | false | undefined,\n compact: boolean | undefined,\n): string | undefined {\n if (compact && label) return String(label);\n return undefined;\n}\n\n/**\n * In compact mode, expose the error as a native tooltip so sighted users\n * can hover to see the validation message.\n */\nexport function getCompactTitle(\n error: string | undefined,\n compact: boolean | undefined,\n): string | undefined {\n if (compact && error) return error;\n return undefined;\n}\n\n/**\n * Resolve a `label?: string | false` prop into `string | undefined` for\n * FormFieldWrapper, which does not accept `false` directly.\n * `false` means \"explicitly hidden\"; `undefined` means \"not provided\".\n */\nexport function resolveFieldLabel(\n label: string | false | undefined,\n): string | undefined {\n if (label === false) return undefined;\n return label ?? undefined;\n}\n","/**\n * FormInput - Input wrapper with label, description, and error support\n *\n * Wraps shadcn Input with form field features to match Mantine TextInput API:\n * - Label with required indicator\n * - Description text\n * - Error message display\n * - Proper accessibility attributes\n */\n\nimport React, { useId } from \"react\";\nimport { Input } from \"@petrarca/sonnet-ui\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport {\n getAriaDescribedByCompact,\n getCompactAriaLabel,\n getCompactTitle,\n} from \"./formFieldUtils\";\n\nexport interface FormInputProps\n extends React.ComponentPropsWithoutRef<typeof Input> {\n /** Input label (false = hide label) */\n label?: string | false;\n /** Description text shown below label */\n description?: string;\n /** Error message to display */\n error?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Additional class name for the wrapper */\n wrapperClassName?: string;\n /** Right section content (e.g., icons, buttons) */\n rightSection?: React.ReactNode;\n /** Width of the right section in pixels (for padding adjustment) */\n rightSectionWidth?: number;\n /**\n * Compact mode -- suppresses label, description, and error text so the\n * cell height stays fixed in horizontal grid layouts. Error state is\n * still communicated via a red border on the input.\n */\n compact?: boolean;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n}\n\n/**\n * FormInput component with label, description, and error handling\n */\nexport const FormInput = React.forwardRef<HTMLInputElement, FormInputProps>(\n (\n {\n label,\n description,\n error,\n required,\n wrapperClassName,\n className,\n id,\n rightSection,\n rightSectionWidth,\n compact,\n labelPlacement,\n ...props\n },\n ref,\n ) => {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n\n const paddingStyle = rightSectionWidth\n ? { paddingRight: `${rightSectionWidth}px` }\n : undefined;\n\n return (\n <FormFieldWrapper\n inputId={inputId}\n label={label === false ? undefined : label}\n description={description}\n error={error}\n required={required}\n compact={compact}\n labelPlacement={labelPlacement}\n className={wrapperClassName}\n >\n <div className=\"relative\">\n <Input\n id={inputId}\n ref={ref}\n required={required}\n style={paddingStyle}\n className={cn(\n error && \"border-destructive focus-visible:ring-destructive\",\n className,\n )}\n aria-invalid={error ? \"true\" : \"false\"}\n aria-describedby={getAriaDescribedByCompact(\n inputId,\n error,\n description,\n compact,\n )}\n aria-label={getCompactAriaLabel(label, compact)}\n title={getCompactTitle(error, compact)}\n {...props}\n />\n {rightSection && (\n <div className=\"absolute top-1/2 -translate-y-1/2 right-2 flex items-center gap-1\">\n {rightSection}\n </div>\n )}\n </div>\n </FormFieldWrapper>\n );\n },\n);\n\nFormInput.displayName = \"FormInput\";\n","/**\n * FormTextarea - Textarea wrapper with label, description, error, and autosize support\n *\n * Wraps shadcn Textarea with form field features to match Mantine Textarea API:\n * - Label with required indicator\n * - Description text\n * - Error message display\n * - Auto-resize functionality (via useEffect)\n * - Proper accessibility attributes\n */\n\nimport React, { useEffect, useId, useRef } from \"react\";\nimport { Textarea } from \"@petrarca/sonnet-ui\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport { getAriaDescribedBy } from \"./formFieldUtils\";\n\nexport interface FormTextareaProps\n extends React.ComponentPropsWithoutRef<typeof Textarea> {\n /** Textarea label (false = hide label) */\n label?: string | false;\n /** Description text shown below label */\n description?: string;\n /** Error message to display */\n error?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Additional class name for the wrapper */\n wrapperClassName?: string;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n /** Enable auto-resize behavior (default: false) */\n autosize?: boolean;\n /** Minimum number of rows when autosize is enabled (default: 3) */\n minRows?: number;\n /** Right section content (e.g., action buttons) */\n rightSection?: React.ReactNode;\n /** Width of the right section in pixels (for padding adjustment) */\n rightSectionWidth?: number;\n}\n\n// -- Hooks ----------------------------------------------------------------\n\n/** Merge a forwarded ref with an internal ref. */\nfunction useMergedRef(\n forwardedRef: React.ForwardedRef<HTMLTextAreaElement>,\n internalRef: React.RefObject<HTMLTextAreaElement | null>,\n) {\n return (element: HTMLTextAreaElement | null) => {\n internalRef.current = element;\n if (typeof forwardedRef === \"function\") {\n forwardedRef(element);\n } else if (forwardedRef) {\n forwardedRef.current = element;\n }\n };\n}\n\n/** Auto-resize the textarea to fit its content. */\nfunction useAutoResize(\n ref: React.RefObject<HTMLTextAreaElement | null>,\n value: React.ComponentPropsWithoutRef<typeof Textarea>[\"value\"],\n autosize: boolean,\n minRows: number,\n) {\n useEffect(() => {\n if (!autosize || !ref.current) return;\n const textarea = ref.current;\n textarea.style.height = \"auto\";\n const newHeight = Math.max(textarea.scrollHeight, minRows * 24);\n textarea.style.height = `${newHeight}px`;\n }, [value, autosize, minRows, ref]);\n}\n\n// -- Helpers --------------------------------------------------------------\n\n/** Build the textarea className from state flags. */\nfunction textareaClassName(\n error: string | undefined,\n autosize: boolean,\n className: string | undefined,\n) {\n return cn(\n error && \"border-destructive focus-visible:ring-destructive\",\n autosize && \"resize-none overflow-hidden\",\n \"h-full\",\n className,\n );\n}\n\n// -- FormTextarea ---------------------------------------------------------\n\n/**\n * FormTextarea component with label, description, error, and autosize handling\n */\nexport const FormTextarea = React.forwardRef<\n HTMLTextAreaElement,\n FormTextareaProps\n>((allProps, ref) => {\n const {\n label,\n description,\n error,\n required,\n wrapperClassName,\n labelPlacement,\n className,\n id,\n value,\n onChange,\n rightSection,\n rightSectionWidth,\n // Destructured out so they are not spread onto the DOM textarea below;\n // these are component-level props, not valid HTML attributes.\n autosize: autosizeProp,\n minRows: minRowsProp,\n ...props\n } = allProps;\n const autosize = autosizeProp ?? false;\n const minRows = minRowsProp ?? 3;\n\n const generatedId = useId();\n const textareaId = id ?? generatedId;\n const internalRef = useRef<HTMLTextAreaElement | null>(null);\n const setRefs = useMergedRef(ref, internalRef);\n\n useAutoResize(internalRef, value, autosize, minRows);\n\n const paddingStyle = rightSectionWidth\n ? { paddingRight: `${rightSectionWidth}px` }\n : undefined;\n\n const effectiveRows = autosize ? minRows : props.rows;\n const resolvedLabel = label === false ? undefined : label;\n\n return (\n <FormFieldWrapper\n inputId={textareaId}\n label={resolvedLabel}\n description={description}\n error={error}\n required={required}\n labelPlacement={labelPlacement}\n className={cn(\"flex flex-col\", wrapperClassName)}\n >\n <div className=\"relative flex-1 min-h-0\">\n <Textarea\n id={textareaId}\n ref={setRefs}\n value={value}\n onChange={onChange}\n required={required}\n rows={effectiveRows}\n className={textareaClassName(error, autosize, className)}\n style={paddingStyle}\n aria-invalid={error ? \"true\" : \"false\"}\n aria-describedby={getAriaDescribedBy(textareaId, error, description)}\n {...props}\n />\n {rightSection && (\n <div className=\"absolute top-2 right-2 flex items-start gap-1\">\n {rightSection}\n </div>\n )}\n </div>\n </FormFieldWrapper>\n );\n});\n\nFormTextarea.displayName = \"FormTextarea\";\n","/**\n * FormNumberInput - Number input wrapper with label, description, error, and numeric constraints.\n */\n\nimport React, { useId } from \"react\";\nimport { Input } from \"@petrarca/sonnet-ui\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport { getAriaDescribedBy } from \"./formFieldUtils\";\n\nexport interface FormNumberInputProps {\n /** Input value */\n value?: number | string;\n /** Input label */\n label?: string;\n /** Description text shown below input */\n description?: string;\n /** Error message to display */\n error?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Whether the input is disabled */\n disabled?: boolean;\n /** Whether the input is read-only */\n readOnly?: boolean;\n /** Minimum value */\n min?: number;\n /** Maximum value */\n max?: number;\n /** Step increment/decrement value */\n step?: number;\n /** Allow decimal values (if false, only integers) */\n allowDecimal?: boolean;\n /** Change handler - receives number or undefined */\n onChange?: (value: number | undefined) => void;\n /** Blur handler */\n onBlur?: React.FocusEventHandler<HTMLInputElement>;\n /** Auto-focus on mount */\n autoFocus?: boolean;\n /** Additional class name for the wrapper */\n wrapperClassName?: string;\n /** Additional class name for the input */\n className?: string;\n /** Input ID */\n id?: string;\n /** Input name */\n name?: string;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n}\n\nexport const FormNumberInput = React.forwardRef<\n HTMLInputElement,\n FormNumberInputProps\n>(\n (\n {\n value,\n label,\n description,\n error,\n placeholder,\n required,\n disabled,\n readOnly,\n min,\n max,\n step,\n allowDecimal = true,\n onChange,\n onBlur,\n autoFocus,\n wrapperClassName,\n className,\n id,\n name,\n labelPlacement,\n },\n ref,\n ) => {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!onChange) return;\n const val = e.target.value;\n if (val === \"\" || val === undefined) {\n onChange(undefined);\n } else {\n const numVal = parseFloat(val);\n if (!isNaN(numVal)) onChange(numVal);\n }\n };\n\n const displayValue =\n value !== undefined && value !== null ? String(value) : \"\";\n\n return (\n <FormFieldWrapper\n inputId={inputId}\n label={label}\n description={description}\n error={error}\n required={required}\n labelPlacement={labelPlacement}\n className={wrapperClassName}\n >\n <Input\n id={inputId}\n name={name}\n ref={ref}\n type=\"number\"\n inputMode=\"numeric\"\n value={displayValue}\n onChange={handleChange}\n onBlur={onBlur}\n placeholder={placeholder}\n disabled={disabled}\n readOnly={readOnly}\n autoFocus={autoFocus}\n min={min}\n max={max}\n step={step ?? (allowDecimal ? \"any\" : 1)}\n className={cn(error && \"border-destructive\", className)}\n aria-invalid={error ? \"true\" : \"false\"}\n aria-describedby={getAriaDescribedBy(inputId, error, description)}\n aria-required={required}\n />\n </FormFieldWrapper>\n );\n },\n);\n\nFormNumberInput.displayName = \"FormNumberInput\";\n","/**\n * FormCheckbox - Checkbox wrapper with label, description, error, and indeterminate support\n *\n * Wraps shadcn Checkbox with form field features to match Mantine Checkbox API:\n * - Inline label (checkbox + label on same line)\n * - Description text\n * - Error message display\n * - Indeterminate state support (tri-state)\n * - Proper accessibility attributes\n */\n\nimport React, { useId } from \"react\";\nimport { Checkbox } from \"@petrarca/sonnet-ui\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport {\n getAriaDescribedByCompact,\n getCompactAriaLabel,\n getCompactTitle,\n} from \"./formFieldUtils\";\n\nexport interface FormCheckboxProps {\n /** Checkbox checked state (boolean or 'indeterminate') */\n checked?: boolean | \"indeterminate\";\n /** Checkbox label (displayed inline, false = hide label) */\n label?: string | false;\n /** Description text shown below checkbox */\n description?: string;\n /** Error message to display */\n error?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Whether the checkbox is disabled */\n disabled?: boolean;\n /** Whether the checkbox is read-only */\n readOnly?: boolean;\n /** Change handler */\n onChange?: (checked: boolean | \"indeterminate\") => void;\n /** Blur handler */\n onBlur?: React.FocusEventHandler<HTMLButtonElement>;\n /** Auto-focus on mount */\n autoFocus?: boolean;\n /** Additional class name for the wrapper */\n wrapperClassName?: string;\n /** Additional class name for the checkbox */\n className?: string;\n /** Input ID */\n id?: string;\n /**\n * Compact mode -- suppresses label, description, and error text so the\n * cell height stays fixed in horizontal grid layouts. Error state is\n * still communicated via a red border on the checkbox.\n */\n compact?: boolean;\n}\n\n// -- Sub-components --------------------------------------------------------\n\ninterface CheckboxLabelProps {\n htmlFor: string;\n label: string | false | undefined;\n required: boolean | undefined;\n disabled: boolean | undefined;\n compact: boolean | undefined;\n}\n\nfunction CheckboxLabel({\n htmlFor,\n label,\n required,\n disabled,\n compact,\n}: CheckboxLabelProps) {\n if (compact || !label) return null;\n return (\n <label\n htmlFor={htmlFor}\n className={cn(\n \"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n disabled && \"opacity-70 cursor-not-allowed\",\n )}\n >\n {label}\n {required && <span className=\"text-destructive ml-1\">*</span>}\n </label>\n );\n}\n\ninterface CheckboxChromeProps {\n inputId: string;\n description: string | undefined;\n error: string | undefined;\n compact: boolean | undefined;\n}\n\nfunction CheckboxChrome({\n inputId,\n description,\n error,\n compact,\n}: CheckboxChromeProps) {\n if (compact) return null;\n return (\n <>\n {description && (\n <p\n id={`${inputId}-description`}\n className=\"text-sm text-muted-foreground ml-6\"\n >\n {description}\n </p>\n )}\n {error && (\n <p id={`${inputId}-error`} className=\"text-sm text-destructive ml-6\">\n {error}\n </p>\n )}\n </>\n );\n}\n\n// -- FormCheckbox ----------------------------------------------------------\n\n/**\n * FormCheckbox component with label, description, error, and indeterminate handling\n */\nexport const FormCheckbox = React.forwardRef<\n HTMLButtonElement,\n FormCheckboxProps\n>(\n (\n {\n checked,\n label,\n description,\n error,\n required,\n disabled,\n readOnly,\n onChange,\n onBlur,\n autoFocus,\n wrapperClassName,\n className,\n id,\n compact,\n },\n ref,\n ) => {\n const generatedId = useId();\n const checkboxId = id ?? generatedId;\n\n const handleCheckedChange = (newChecked: boolean | \"indeterminate\") => {\n if (!readOnly && onChange) {\n onChange(newChecked);\n }\n };\n\n return (\n <div className={cn(!compact && \"space-y-2\", wrapperClassName)}>\n <div className=\"flex items-start space-x-2\">\n <Checkbox\n id={checkboxId}\n ref={ref}\n checked={checked}\n onCheckedChange={handleCheckedChange}\n onBlur={onBlur}\n disabled={disabled || readOnly}\n autoFocus={autoFocus}\n className={cn(error && \"border-destructive\", className)}\n aria-invalid={error ? \"true\" : \"false\"}\n aria-describedby={getAriaDescribedByCompact(\n checkboxId,\n error,\n description,\n compact,\n )}\n aria-label={getCompactAriaLabel(label, compact)}\n title={getCompactTitle(error, compact)}\n />\n <CheckboxLabel\n htmlFor={checkboxId}\n label={label}\n required={required}\n disabled={disabled}\n compact={compact}\n />\n </div>\n <CheckboxChrome\n inputId={checkboxId}\n description={description}\n error={error}\n compact={compact}\n />\n </div>\n );\n },\n);\n\nFormCheckbox.displayName = \"FormCheckbox\";\n","/**\n * FormSelect - Searchable single-select dropdown with form field wrapper\n *\n * Composable select component using Popover + Command for searchable,\n * keyboard-navigable dropdown. Follows Form wrapper pattern with\n * label, description, error support.\n */\n\nimport * as React from \"react\";\nimport { Check, ChevronsUpDown, Plus, X } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"@petrarca/sonnet-ui\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@petrarca/sonnet-ui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport {\n getAriaDescribedByCompact,\n getCompactAriaLabel,\n getCompactTitle,\n} from \"./formFieldUtils\";\nimport { canCreateFromSearch } from \"./formSelectUtils\";\nimport type { SelectOption } from \"./widgets/types\";\n\nexport type { SelectOption };\n\nexport interface FormSelectProps {\n // Form wrapper props (consistent with FormInput/FormTextarea)\n label?: string | false;\n description?: string;\n error?: string;\n required?: boolean;\n wrapperClassName?: string;\n /**\n * Compact mode -- suppresses label, description, and error text so the\n * cell height stays fixed in horizontal grid layouts. Error state is\n * still communicated via a red border on the trigger button.\n */\n compact?: boolean;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n\n // Select-specific props\n options: SelectOption[];\n value?: string | null;\n onChange?: (value: string | null) => void;\n onBlur?: () => void;\n placeholder?: string;\n searchPlaceholder?: string;\n emptyMessage?: string;\n clearable?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n loading?: boolean;\n className?: string;\n id?: string;\n name?: string;\n autoFocus?: boolean;\n /**\n * Allow creating a new option from the search text. When set, a\n * `+ Create \"<text>\"` item appears at the bottom of the list whenever the\n * trimmed search matches no existing option label (case-insensitive).\n * Selecting it calls `onCreate(text)`. Requires `onCreate`.\n */\n allowCreate?: boolean;\n /** Called with the trimmed search text when the create item is chosen. */\n onCreate?: (label: string) => void;\n}\n\n// Hook: encapsulate popover state + event handlers.\nfunction useSelectState(\n value: string | null | undefined,\n onChange: ((value: string | null) => void) | undefined,\n onBlur: (() => void) | undefined,\n onCreate: ((label: string) => void) | undefined,\n clearable: boolean,\n) {\n const [open, setOpen] = React.useState(false);\n const [searchQuery, setSearchQuery] = React.useState(\"\");\n\n const handleSelect = (selectedValue: string) => {\n // Re-clicking the selected value deselects it, but only when clearable.\n const next = clearable && selectedValue === value ? null : selectedValue;\n onChange?.(next);\n setOpen(false);\n setSearchQuery(\"\");\n };\n\n const handleCreate = (label: string) => {\n onCreate?.(label);\n setOpen(false);\n setSearchQuery(\"\");\n };\n\n const handleClear = (e: React.MouseEvent) => {\n e.stopPropagation();\n onChange?.(null);\n };\n\n const handleOpenChange = (newOpen: boolean) => {\n setOpen(newOpen);\n if (newOpen) return;\n setSearchQuery(\"\");\n onBlur?.();\n };\n\n return {\n open,\n searchQuery,\n setSearchQuery,\n handleSelect,\n handleCreate,\n handleClear,\n handleOpenChange,\n };\n}\n\n// Trigger trailing icons (clear + chevron).\nfunction TriggerIcons({\n showClear,\n onClear,\n}: {\n showClear: boolean;\n onClear: (e: React.MouseEvent) => void;\n}) {\n return (\n <div className=\"flex items-center gap-1\">\n {showClear && (\n <X className=\"h-4 w-4 opacity-50 hover:opacity-100\" onClick={onClear} />\n )}\n <ChevronsUpDown className=\"h-4 w-4 shrink-0 opacity-50\" />\n </div>\n );\n}\n\n// Dropdown content extracted to keep FormSelect under complexity 10.\n// Not a Radix trigger -- no ref forwarding needed.\nfunction SelectDropdown({\n searchPlaceholder,\n searchQuery,\n onSearchChange,\n loading,\n emptyMessage,\n options,\n value,\n onSelect,\n allowCreate = false,\n onCreate,\n}: {\n searchPlaceholder: string;\n searchQuery: string;\n onSearchChange: (value: string) => void;\n loading: boolean;\n emptyMessage: string;\n options: SelectOption[];\n value: string | null | undefined;\n onSelect: (value: string) => void;\n allowCreate?: boolean;\n onCreate?: (label: string) => void;\n}) {\n const showCreate = canCreateFromSearch(allowCreate, searchQuery, options);\n return (\n <Command shouldFilter={false}>\n <CommandInput\n placeholder={searchPlaceholder}\n value={searchQuery}\n onValueChange={onSearchChange}\n />\n <CommandList>\n {!showCreate && (\n <CommandEmpty>{loading ? \"Loading...\" : emptyMessage}</CommandEmpty>\n )}\n <CommandGroup>\n {options\n .filter((option) =>\n option.label.toLowerCase().includes(searchQuery.toLowerCase()),\n )\n .map((option) => (\n <CommandItem\n key={option.value}\n value={option.value}\n onSelect={onSelect}\n >\n <Check\n className={cn(\n \"mr-2 h-4 w-4\",\n value === option.value ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n {option.label}\n </CommandItem>\n ))}\n {showCreate && (\n <CommandItem\n key=\"__create__\"\n value={`__create__${searchQuery}`}\n onSelect={() => onCreate?.(searchQuery.trim())}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n Create &ldquo;{searchQuery.trim()}&rdquo;\n </CommandItem>\n )}\n </CommandGroup>\n </CommandList>\n </Command>\n );\n}\n\n// Resolve optional props to concrete values.\nfunction resolveDefaults(props: FormSelectProps) {\n return {\n placeholder: props.placeholder ?? \"Select...\",\n searchPlaceholder: props.searchPlaceholder ?? \"Search...\",\n emptyMessage: props.emptyMessage ?? \"No results found\",\n clearable: props.clearable ?? true,\n disabled: props.disabled ?? false,\n readOnly: props.readOnly ?? false,\n loading: props.loading ?? false,\n };\n}\n\nexport function FormSelect(props: FormSelectProps) {\n const {\n label,\n description,\n error,\n required,\n wrapperClassName,\n compact,\n labelPlacement,\n options,\n value,\n onChange,\n onBlur,\n className,\n id,\n autoFocus,\n allowCreate,\n onCreate,\n } = props;\n const {\n placeholder,\n searchPlaceholder,\n emptyMessage,\n clearable,\n disabled,\n readOnly,\n loading,\n } = resolveDefaults(props);\n\n const generatedId = React.useId();\n const selectId = id ?? generatedId;\n\n const {\n open,\n searchQuery,\n setSearchQuery,\n handleSelect,\n handleCreate,\n handleClear,\n handleOpenChange,\n } = useSelectState(value, onChange, onBlur, onCreate, clearable);\n\n const selectedOption = options.find((opt) => opt.value === value);\n const isDisabled = disabled || readOnly || loading;\n\n return (\n <FormFieldWrapper\n inputId={selectId}\n label={label}\n description={description}\n error={error}\n required={required}\n compact={compact}\n labelPlacement={labelPlacement}\n className={wrapperClassName}\n >\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <Button\n id={selectId}\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n aria-invalid={error ? \"true\" : \"false\"}\n aria-describedby={getAriaDescribedByCompact(\n selectId,\n error,\n description,\n compact,\n )}\n aria-label={getCompactAriaLabel(label, compact)}\n title={getCompactTitle(error, compact)}\n className={cn(\n \"w-full justify-between\",\n !selectedOption && \"text-muted-foreground\",\n error && \"border-destructive\",\n className,\n )}\n disabled={isDisabled}\n autoFocus={autoFocus}\n >\n <span className=\"truncate\">\n {selectedOption ? selectedOption.label : placeholder}\n </span>\n <TriggerIcons\n showClear={clearable && !!value && !isDisabled}\n onClear={handleClear}\n />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className=\"w-[--radix-popover-trigger-width] p-0\"\n align=\"start\"\n >\n <SelectDropdown\n searchPlaceholder={searchPlaceholder}\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n loading={loading}\n emptyMessage={emptyMessage}\n options={options}\n value={value}\n onSelect={handleSelect}\n allowCreate={allowCreate}\n onCreate={handleCreate}\n />\n </PopoverContent>\n </Popover>\n </FormFieldWrapper>\n );\n}\n","/**\n * Pure helpers for FormSelect, kept separate from the component module so they\n * can be unit-tested and shared without tripping react-refresh's\n * component-only-export rule.\n */\n\nimport { extractEnumValues } from \"@petrarca/sonnet-core/schema\";\nimport type { JsonSchemaProperty } from \"@petrarca/sonnet-core/schema\";\nimport type { SelectOption } from \"./widgets/types\";\n\n/**\n * The options of a choice: its enum values (a property's, or its items' for an\n * array), each labelled by `enumNames` where it names one. Shared by the select,\n * the radio group and the checkbox group.\n */\nexport function buildSelectOptions(\n propertySchema: JsonSchemaProperty,\n enumNames: Record<string | number, string>,\n): SelectOption[] {\n return extractEnumValues(propertySchema).map((val) => {\n const key = String(val);\n return { value: key, label: enumNames[key] || key };\n });\n}\n\n/**\n * Whether to offer a \"create\" item in a creatable select: creation is enabled,\n * the trimmed search is non-empty, and no existing option's label matches the\n * search (case-insensitive).\n */\nexport function canCreateFromSearch(\n allowCreate: boolean,\n searchQuery: string,\n options: SelectOption[],\n): boolean {\n const trimmed = searchQuery.trim();\n if (!allowCreate || trimmed.length === 0) return false;\n const lower = trimmed.toLowerCase();\n return !options.some((o) => o.label.toLowerCase() === lower);\n}\n","/**\n * FormMultiSelect - Searchable multi-select dropdown with badges\n *\n * Multi-select component using Popover + Command with badge display\n * for selected items. Follows Form wrapper pattern with label,\n * description, error support.\n */\n\nimport * as React from \"react\";\nimport { Check, ChevronsUpDown, X } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport { Badge, badgeVariants } from \"@petrarca/sonnet-ui\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"@petrarca/sonnet-ui\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@petrarca/sonnet-ui\";\nimport type { VariantProps } from \"class-variance-authority\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport { resolveFieldLabel } from \"./formFieldUtils\";\nimport type { SelectOption } from \"./widgets/types\";\n\ntype BadgeColor = NonNullable<VariantProps<typeof badgeVariants>[\"badgeColor\"]>;\n\nexport type { SelectOption };\n\nexport interface FormMultiSelectProps {\n // Form wrapper props (consistent with FormInput/FormTextarea)\n label?: string | false;\n description?: string;\n error?: string;\n required?: boolean;\n wrapperClassName?: string;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n\n // Multi-select specific props\n options: SelectOption[];\n value?: string[];\n onChange?: (value: string[]) => void;\n onBlur?: () => void;\n placeholder?: string;\n searchPlaceholder?: string;\n emptyMessage?: string;\n clearable?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n loading?: boolean;\n className?: string;\n id?: string;\n name?: string;\n autoFocus?: boolean;\n maxDisplay?: number; // Max badges to display before showing \"+X more\"\n badgeColor?: BadgeColor;\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\ninterface RemovableBadgeProps {\n option: SelectOption;\n isDisabled: boolean;\n badgeColor: BadgeColor | undefined;\n onRemove: (value: string, e: React.MouseEvent | React.KeyboardEvent) => void;\n}\n\nfunction RemovableBadge({\n option,\n isDisabled,\n badgeColor,\n onRemove,\n}: RemovableBadgeProps) {\n return (\n <Badge variant=\"secondary\" badgeColor={badgeColor} className=\"mr-1\">\n {option.label}\n {!isDisabled && (\n // Rendered as a role=\"button\" span, not a <button>: this badge lives\n // inside the combobox trigger <button>, and a button cannot be nested\n // in a button (invalid HTML / hydration error). The span keeps click +\n // Enter/Space activation and a focus ring.\n <span\n role=\"button\"\n tabIndex={0}\n aria-label={`Remove ${option.label}`}\n className=\"ml-1 inline-flex cursor-pointer ring-offset-background rounded-full outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\"\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onRemove(option.value, e);\n }\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}\n onClick={(e) => onRemove(option.value, e)}\n >\n <X className=\"h-3 w-3 text-muted-foreground hover:text-foreground\" />\n </span>\n )}\n </Badge>\n );\n}\n\ninterface SelectedBadgesProps {\n selectedOptions: SelectOption[];\n effectiveMaxDisplay: number;\n expanded: boolean;\n maxDisplay: number;\n isDisabled: boolean;\n badgeColor: BadgeColor | undefined;\n placeholder: string;\n onRemove: (value: string, e: React.MouseEvent | React.KeyboardEvent) => void;\n onExpand: (e: React.MouseEvent) => void;\n onCollapse: (e: React.MouseEvent) => void;\n}\n\nfunction SelectedBadges({\n selectedOptions,\n effectiveMaxDisplay,\n expanded,\n maxDisplay,\n isDisabled,\n badgeColor,\n placeholder,\n onRemove,\n onExpand,\n onCollapse,\n}: SelectedBadgesProps) {\n if (selectedOptions.length === 0) {\n return <span className=\"text-muted-foreground\">{placeholder}</span>;\n }\n\n const displayedBadges = selectedOptions.slice(0, effectiveMaxDisplay);\n const remainingCount = selectedOptions.length - effectiveMaxDisplay;\n const showCollapse =\n expanded && remainingCount <= 0 && selectedOptions.length > maxDisplay;\n\n return (\n <>\n {displayedBadges.map((option) => (\n <RemovableBadge\n key={option.value}\n option={option}\n isDisabled={isDisabled}\n badgeColor={badgeColor}\n onRemove={onRemove}\n />\n ))}\n {remainingCount > 0 && (\n <Badge\n variant=\"secondary\"\n badgeColor={badgeColor}\n className=\"mr-1 cursor-pointer hover:bg-secondary/80\"\n onClick={onExpand}\n >\n +{remainingCount} more\n </Badge>\n )}\n {showCollapse && (\n <Badge\n variant=\"secondary\"\n badgeColor={badgeColor}\n className=\"mr-1 cursor-pointer hover:bg-secondary/80\"\n onClick={onCollapse}\n >\n Show less\n </Badge>\n )}\n </>\n );\n}\n\ninterface MultiSelectDropdownProps {\n searchPlaceholder: string;\n searchQuery: string;\n onSearchChange: (value: string) => void;\n loading: boolean;\n emptyMessage: string;\n options: SelectOption[];\n value: string[];\n onSelect: (value: string) => void;\n}\n\nfunction MultiSelectDropdown({\n searchPlaceholder,\n searchQuery,\n onSearchChange,\n loading,\n emptyMessage,\n options,\n value,\n onSelect,\n}: MultiSelectDropdownProps) {\n return (\n <Command shouldFilter={false}>\n <CommandInput\n placeholder={searchPlaceholder}\n value={searchQuery}\n onValueChange={onSearchChange}\n />\n <CommandList>\n <CommandEmpty>{loading ? \"Loading...\" : emptyMessage}</CommandEmpty>\n <CommandGroup>\n {options\n .filter((option) =>\n option.label.toLowerCase().includes(searchQuery.toLowerCase()),\n )\n .map((option) => (\n <CommandItem\n key={option.value}\n value={option.value}\n onSelect={onSelect}\n >\n <Check\n className={cn(\n \"mr-2 h-4 w-4\",\n value.includes(option.value) ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n {option.label}\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Hook: encapsulate popover state + handlers\n// ---------------------------------------------------------------------------\n\nfunction useMultiSelectState(\n value: string[],\n onChange: ((value: string[]) => void) | undefined,\n onBlur: (() => void) | undefined,\n) {\n const [open, setOpen] = React.useState(false);\n const [searchQuery, setSearchQuery] = React.useState(\"\");\n const [expanded, setExpanded] = React.useState(false);\n\n const handleSelect = (selectedValue: string) => {\n const newValue = value.includes(selectedValue)\n ? value.filter((v) => v !== selectedValue)\n : [...value, selectedValue];\n onChange?.(newValue);\n };\n\n const handleRemove = (\n valueToRemove: string,\n e: React.MouseEvent | React.KeyboardEvent,\n ) => {\n e.stopPropagation();\n onChange?.(value.filter((v) => v !== valueToRemove));\n };\n\n const handleClearAll = (e: React.MouseEvent) => {\n e.stopPropagation();\n onChange?.([]);\n };\n\n const handleOpenChange = (newOpen: boolean) => {\n setOpen(newOpen);\n if (newOpen) return;\n setSearchQuery(\"\");\n setExpanded(false);\n onBlur?.();\n };\n\n const handleExpand = (e: React.MouseEvent) => {\n e.stopPropagation();\n setExpanded(true);\n };\n\n const handleCollapse = (e: React.MouseEvent) => {\n e.stopPropagation();\n setExpanded(false);\n };\n\n return {\n open,\n searchQuery,\n setSearchQuery,\n expanded,\n handleSelect,\n handleRemove,\n handleClearAll,\n handleOpenChange,\n handleExpand,\n handleCollapse,\n };\n}\n\n// ---------------------------------------------------------------------------\n// FormMultiSelect\n// ---------------------------------------------------------------------------\n\n/** Resolve optional props to concrete values outside the component to reduce branching. */\nfunction resolveMultiSelectDefaults(props: FormMultiSelectProps) {\n return {\n placeholder: props.placeholder ?? \"Select...\",\n searchPlaceholder: props.searchPlaceholder ?? \"Search...\",\n emptyMessage: props.emptyMessage ?? \"No results found\",\n clearable: props.clearable ?? true,\n disabled: props.disabled ?? false,\n readOnly: props.readOnly ?? false,\n loading: props.loading ?? false,\n maxDisplay: props.maxDisplay ?? Infinity,\n };\n}\n\n// Trigger trailing icons (clear + chevron).\nfunction TriggerIcons({\n showClear,\n onClear,\n}: {\n showClear: boolean;\n onClear: (e: React.MouseEvent) => void;\n}) {\n return (\n <div className=\"flex items-center gap-1 ml-2\">\n {showClear && (\n <X className=\"h-4 w-4 opacity-50 hover:opacity-100\" onClick={onClear} />\n )}\n <ChevronsUpDown className=\"h-4 w-4 shrink-0 opacity-50\" />\n </div>\n );\n}\n\nexport function FormMultiSelect(props: FormMultiSelectProps) {\n const {\n label,\n description,\n error,\n required,\n wrapperClassName,\n labelPlacement,\n options,\n onChange,\n onBlur,\n className,\n id,\n name,\n autoFocus,\n badgeColor,\n } = props;\n const value = props.value ?? [];\n const generatedId = React.useId();\n const fieldId = id ?? generatedId;\n const {\n placeholder,\n searchPlaceholder,\n emptyMessage,\n clearable,\n disabled,\n readOnly,\n loading,\n maxDisplay,\n } = resolveMultiSelectDefaults(props);\n\n const selectedOptions = options.filter((opt) => value.includes(opt.value));\n const isDisabled = disabled || readOnly || loading;\n\n const {\n open,\n searchQuery,\n setSearchQuery,\n expanded,\n handleSelect,\n handleRemove,\n handleClearAll,\n handleOpenChange,\n handleExpand,\n handleCollapse,\n } = useMultiSelectState(value, onChange, onBlur);\n\n const effectiveMaxDisplay = expanded ? Infinity : maxDisplay;\n\n return (\n <FormFieldWrapper\n inputId={fieldId}\n label={resolveFieldLabel(label)}\n description={description}\n error={error}\n required={required}\n labelPlacement={labelPlacement}\n className={wrapperClassName}\n >\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <Button\n id={fieldId}\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n className={cn(\n \"w-full justify-between min-h-10 h-auto\",\n error && \"border-destructive\",\n className,\n )}\n disabled={isDisabled}\n autoFocus={autoFocus}\n >\n <div className=\"flex flex-wrap gap-1 flex-1\">\n <SelectedBadges\n selectedOptions={selectedOptions}\n effectiveMaxDisplay={effectiveMaxDisplay}\n expanded={expanded}\n maxDisplay={maxDisplay}\n isDisabled={isDisabled}\n badgeColor={badgeColor}\n placeholder={placeholder}\n onRemove={handleRemove}\n onExpand={handleExpand}\n onCollapse={handleCollapse}\n />\n </div>\n <TriggerIcons\n showClear={clearable && value.length > 0 && !isDisabled}\n onClear={handleClearAll}\n />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className=\"w-[--radix-popover-trigger-width] p-0\"\n align=\"start\"\n >\n <MultiSelectDropdown\n searchPlaceholder={searchPlaceholder}\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n loading={loading}\n emptyMessage={emptyMessage}\n options={options}\n value={value}\n onSelect={handleSelect}\n />\n </PopoverContent>\n </Popover>\n\n {/* Hidden inputs for form submission */}\n {name &&\n value.map((v) => <input key={v} type=\"hidden\" name={name} value={v} />)}\n </FormFieldWrapper>\n );\n}\n","/**\n * FormTagsInput - Input field for managing tags with badges\n *\n * Allows adding tags by pressing Enter or comma, removing tags via X button\n * or backspace. Displays tags as badges. Follows Form wrapper pattern with\n * label, description, error support.\n */\n\nimport * as React from \"react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { Input } from \"@petrarca/sonnet-ui\";\nimport { TagBadge } from \"./TagBadge\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport { resolveFieldLabel } from \"./formFieldUtils\";\n\nexport interface FormTagsInputProps {\n // Form wrapper props (consistent with FormInput/FormTextarea)\n label?: string | false;\n description?: string;\n error?: string;\n required?: boolean;\n wrapperClassName?: string;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n\n // TagsInput specific props\n id?: string;\n name?: string;\n value: string[];\n onChange?: (tags: string[]) => void;\n placeholder?: string;\n disabled?: boolean;\n readOnly?: boolean;\n maxTags?: number;\n splitKeys?: string[]; // Keys that trigger tag creation (default: ['Enter', ','])\n allowDuplicates?: boolean;\n}\n\n// -- Hook: tag management -------------------------------------------------\n\nfunction useTagManagement(\n value: string[],\n onChange: ((tags: string[]) => void) | undefined,\n allowDuplicates: boolean,\n maxTags: number | undefined,\n splitKeys: string[],\n) {\n const [inputValue, setInputValue] = React.useState(\"\");\n\n const addTag = React.useCallback(\n (tag: string) => {\n const trimmedTag = tag.trim();\n if (!trimmedTag) return;\n if (!allowDuplicates && value.includes(trimmedTag)) return;\n if (maxTags && value.length >= maxTags) return;\n onChange?.([...value, trimmedTag]);\n setInputValue(\"\");\n },\n [value, onChange, allowDuplicates, maxTags],\n );\n\n const removeTag = React.useCallback(\n (indexToRemove: number) => {\n onChange?.(value.filter((_, index) => index !== indexToRemove));\n },\n [value, onChange],\n );\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (splitKeys.includes(e.key)) {\n e.preventDefault();\n addTag(inputValue);\n return;\n }\n if (e.key === \"Backspace\" && !inputValue && value.length > 0) {\n e.preventDefault();\n removeTag(value.length - 1);\n }\n },\n [splitKeys, inputValue, value.length, addTag, removeTag],\n );\n\n const handleInputChange = React.useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n if (!splitKeys.includes(\",\") || !newValue.includes(\",\")) {\n setInputValue(newValue);\n return;\n }\n const parts = newValue.split(\",\");\n parts.slice(0, -1).forEach((tag) => addTag(tag));\n setInputValue(parts[parts.length - 1]);\n },\n [splitKeys, addTag],\n );\n\n return { inputValue, addTag, removeTag, handleKeyDown, handleInputChange };\n}\n\n// -- FormTagsInput --------------------------------------------------------\n\n/** Resolve optional props with defaults outside the component scope. */\nfunction resolveTagsDefaults(props: FormTagsInputProps) {\n return {\n required: props.required ?? false,\n placeholder: props.placeholder ?? \"Enter tag and press Enter\",\n splitKeys: props.splitKeys ?? [\"Enter\", \",\"],\n allowDuplicates: props.allowDuplicates ?? false,\n };\n}\n\nexport const FormTagsInput = React.forwardRef<\n HTMLInputElement,\n FormTagsInputProps\n>((props, ref) => {\n const {\n label,\n description,\n error,\n wrapperClassName,\n labelPlacement,\n id,\n name,\n value = [],\n onChange,\n disabled,\n readOnly,\n maxTags,\n } = props;\n const { required, placeholder, splitKeys, allowDuplicates } =\n resolveTagsDefaults(props);\n\n const generatedId = React.useId();\n const fieldId = id ?? generatedId;\n const inputRef = React.useRef<HTMLInputElement>(null);\n React.useImperativeHandle(ref, () => inputRef.current!);\n\n const isDisabled = disabled || readOnly;\n const { inputValue, removeTag, handleKeyDown, handleInputChange } =\n useTagManagement(value, onChange, allowDuplicates, maxTags, splitKeys);\n\n const handleContainerClick = () => {\n inputRef.current?.focus();\n };\n\n return (\n <FormFieldWrapper\n inputId={fieldId}\n label={resolveFieldLabel(label)}\n description={description}\n error={error}\n required={required}\n labelPlacement={labelPlacement}\n className={wrapperClassName}\n >\n <div\n className={cn(\n \"flex min-h-10 w-full flex-wrap gap-1.5 rounded-md border border-input bg-background px-3 py-2 text-sm\",\n isDisabled && \"cursor-not-allowed opacity-50\",\n error && \"border-destructive\",\n )}\n onClick={handleContainerClick}\n >\n {value.map((tag, index) => (\n <TagBadge\n key={index}\n tag={tag}\n index={index}\n isDisabled={!!isDisabled}\n onRemove={removeTag}\n />\n ))}\n <Input\n ref={inputRef}\n id={fieldId}\n name={name}\n value={inputValue}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n placeholder={value.length === 0 ? placeholder : \"\"}\n disabled={!!isDisabled}\n className=\"flex-1 min-w-[120px] border-0 p-0 h-auto focus-visible:ring-0 focus-visible:ring-offset-0\"\n />\n </div>\n </FormFieldWrapper>\n );\n});\n\nFormTagsInput.displayName = \"FormTagsInput\";\n","/**\n * TagBadge -- one removable tag, shared by the tag and key-value inputs.\n *\n * Optional `onSelect` makes the tag itself clickable (e.g. to edit it).\n */\n\nimport * as React from \"react\";\nimport { X } from \"lucide-react\";\nimport { Badge } from \"@petrarca/sonnet-ui\";\n\nexport interface TagBadgeProps {\n tag: string;\n index: number;\n isDisabled: boolean;\n onRemove: (index: number) => void;\n onSelect?: (index: number) => void;\n}\n\nexport function TagBadge({\n tag,\n index,\n isDisabled,\n onRemove,\n onSelect,\n}: TagBadgeProps) {\n return (\n <Badge variant=\"secondary\" className=\"gap-1\">\n {onSelect && !isDisabled ? (\n <button\n type=\"button\"\n className=\"outline-none hover:underline focus:underline\"\n onClick={(e) => {\n e.stopPropagation();\n onSelect(index);\n }}\n >\n {tag}\n </button>\n ) : (\n tag\n )}\n {!isDisabled && (\n <button\n type=\"button\"\n aria-label={`Remove ${tag}`}\n className=\"ml-1 ring-offset-background rounded-full outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\"\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n onRemove(index);\n }\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}\n onClick={(e) => {\n e.stopPropagation();\n onRemove(index);\n }}\n >\n <X className=\"h-3 w-3 text-muted-foreground hover:text-foreground\" />\n </button>\n )}\n </Badge>\n );\n}\n","/**\n * FormKeyValueInput - Input for a map of string keys to string values\n *\n * Each pair is entered in two fields (key, value) and added with Enter or the\n * add button. A key is unique: adding it again replaces its value. The entered\n * pairs are displayed one of two ways (`display`):\n *\n * tags (default) as \"key:value\" tags -- for short labels. Clicking a tag\n * loads it back into the fields to edit it; its X removes it.\n * rows as a list, a row per pair: its key and value editable in\n * place (taken on leaving the field or Enter), a remove\n * button -- for values too long or too many to read as tags,\n * such as templates or paths.\n\n * keys only the keys, as badges, each value on hover -- a compact\n * summary, not edited (the host edits the pairs elsewhere,\n * e.g. as rows in a dialog).\n *\n * `valueSuggestions` offers values to pick in the value fields (still free to\n * type) -- e.g. the references a value may name.\n *\n * Follows the Form wrapper pattern with label, description, error support.\n */\n\nimport * as React from \"react\";\nimport { Plus, X } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { Badge, Button, IconButton, Input } from \"@petrarca/sonnet-ui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport { FormSelect } from \"./FormSelect\";\nimport { resolveFieldLabel } from \"./formFieldUtils\";\nimport { TagBadge } from \"./TagBadge\";\n\nexport interface FormKeyValueInputProps {\n label?: string | false;\n description?: string;\n error?: string;\n required?: boolean;\n wrapperClassName?: string;\n labelPlacement?: \"top\" | \"start\";\n\n id?: string;\n name?: string;\n value: Record<string, string>;\n onChange?: (value: Record<string, string>) => void;\n disabled?: boolean;\n readOnly?: boolean;\n /** Placeholders of the two fields. Default \"Key\" / \"Value\". */\n keyPlaceholder?: string;\n valuePlaceholder?: string;\n /** How a pair is shown as a tag. Default \":\" (\"key:value\"). */\n separator?: string;\n /** How the pairs are displayed: as tags (default), as rows, or only their\n * keys (a summary, not edited). */\n display?: \"tags\" | \"rows\" | \"keys\";\n /** Values the value fields suggest; one may still type any other. */\n valueSuggestions?: { value: string; label?: string }[];\n}\n\n// The two fields, adding and editing pairs, and why an entry was not added.\nfunction usePairEditor(\n value: Record<string, string>,\n onChange: ((value: Record<string, string>) => void) | undefined,\n) {\n const [key, setKey] = React.useState(\"\");\n const [val, setVal] = React.useState(\"\");\n const [problem, setProblem] = React.useState<string | null>(null);\n\n const add = () => {\n const k = key.trim();\n const v = val.trim();\n if (!k || !v) {\n setProblem(!k ? \"Enter a key.\" : \"Enter a value.\");\n return;\n }\n onChange?.({ ...value, [k]: v });\n setKey(\"\");\n setVal(\"\");\n setProblem(null);\n };\n\n const remove = (k: string) => {\n const { [k]: _removed, ...rest } = value;\n onChange?.(rest);\n };\n\n // Change a pair in place, keeping its position; a key taken by another pair\n // is refused. Returns whether it was taken.\n const replace = (from: string, k: string, v: string): boolean => {\n const nextKey = k.trim();\n if (!nextKey) {\n setProblem(\"Enter a key.\");\n return false;\n }\n if (nextKey !== from && nextKey in value) {\n setProblem(`The key '${nextKey}' is taken.`);\n return false;\n }\n setProblem(null);\n if (nextKey === from && value[from] === v) return true;\n onChange?.(\n Object.fromEntries(\n Object.entries(value).map(([key0, v0]) =>\n key0 === from ? [nextKey, v] : [key0, v0],\n ),\n ),\n );\n return true;\n };\n\n // Load a pair back into the fields; adding it again replaces it.\n const edit = (k: string) => {\n setKey(k);\n setVal(value[k] ?? \"\");\n setProblem(null);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n add();\n };\n\n // Typing in either field clears a previous \"why not added\".\n const typeKey = (k: string) => {\n setKey(k);\n setProblem(null);\n };\n const typeValue = (v: string) => {\n setVal(v);\n setProblem(null);\n };\n\n return {\n key,\n typeKey,\n val,\n typeValue,\n problem,\n add,\n remove,\n replace,\n edit,\n onKeyDown,\n };\n}\n\ntype PairEditor = ReturnType<typeof usePairEditor>;\n\n// The entered pairs as tags: click to edit, X to remove.\nfunction PairTags({\n value,\n separator,\n isDisabled,\n editor,\n}: {\n value: Record<string, string>;\n separator: string;\n isDisabled: boolean;\n editor: PairEditor;\n}): React.ReactElement | null {\n const keys = Object.keys(value);\n if (keys.length === 0) return null;\n return (\n <div className=\"flex flex-wrap gap-1.5\">\n {keys.map((k, index) => (\n <TagBadge\n key={k}\n tag={`${k}${separator}${value[k]}`}\n index={index}\n isDisabled={isDisabled}\n onRemove={(i) => editor.remove(keys[i])}\n onSelect={(i) => editor.edit(keys[i])}\n />\n ))}\n </div>\n );\n}\n\ntype ValueSuggestion = NonNullable<\n FormKeyValueInputProps[\"valueSuggestions\"]\n>[number];\n\n// A value field: typed in an input, or -- with suggestions -- picked in a\n// searchable select that also takes a typed value not on the list.\nfunction ValueInput({\n ariaLabel,\n value,\n onType,\n onPick,\n onBlur,\n onKeyDown,\n placeholder,\n readOnly,\n suggestions,\n className,\n}: {\n ariaLabel: string;\n value: string;\n onType: (value: string) => void;\n onPick: (value: string) => void;\n onBlur?: () => void;\n onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n placeholder?: string;\n readOnly?: boolean;\n suggestions?: ValueSuggestion[];\n className?: string;\n}): React.ReactElement {\n if (!suggestions?.length)\n return (\n <Input\n aria-label={ariaLabel}\n value={value}\n onChange={(e) => onType(e.target.value)}\n onBlur={onBlur}\n onKeyDown={onKeyDown}\n placeholder={placeholder}\n readOnly={readOnly}\n className={className}\n />\n );\n const options = suggestions.map((s) => ({\n value: s.value,\n label: s.label ?? s.value,\n }));\n // A value typed earlier, not on the list, still shows as chosen.\n if (value && !options.some((o) => o.value === value))\n options.unshift({ value, label: value });\n return (\n <FormSelect\n label={ariaLabel}\n compact\n options={options}\n value={value || null}\n onChange={(picked) => onPick(picked ?? \"\")}\n allowCreate\n onCreate={onPick}\n placeholder={placeholder}\n searchPlaceholder=\"Search, or type a value\"\n readOnly={readOnly}\n wrapperClassName={className}\n />\n );\n}\n\n// One pair as a row: key and value edited in place, taken on blur or Enter (a\n// refused key falls back to the current one).\nfunction PairRow({\n pairKey,\n pairValue,\n isDisabled,\n editor,\n suggestions,\n}: {\n pairKey: string;\n pairValue: string;\n isDisabled: boolean;\n editor: PairEditor;\n suggestions?: ValueSuggestion[];\n}): React.ReactElement {\n const [key, setKey] = React.useState(pairKey);\n const [val, setVal] = React.useState(pairValue);\n React.useEffect(() => setKey(pairKey), [pairKey]);\n React.useEffect(() => setVal(pairValue), [pairValue]);\n const commit = () => {\n if (!editor.replace(pairKey, key, val)) setKey(pairKey);\n };\n const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n commit();\n };\n return (\n <li className=\"flex items-center gap-2\">\n <Input\n aria-label={`Key of ${pairKey}`}\n value={key}\n onChange={(e) => setKey(e.target.value)}\n onBlur={commit}\n onKeyDown={onKeyDown}\n readOnly={isDisabled}\n className=\"h-8 w-1/3 shrink-0 font-mono text-xs\"\n />\n <ValueInput\n ariaLabel={`Value of ${pairKey}`}\n value={val}\n onType={setVal}\n onPick={(picked) => {\n setVal(picked);\n if (!editor.replace(pairKey, key, picked)) setVal(pairValue);\n }}\n onBlur={commit}\n onKeyDown={onKeyDown}\n readOnly={isDisabled}\n suggestions={suggestions}\n className=\"h-8 min-w-0 flex-1 font-mono text-xs\"\n />\n {!isDisabled && (\n <IconButton\n label={`Remove ${pairKey}`}\n tone=\"destructive\"\n onClick={() => editor.remove(pairKey)}\n >\n <X />\n </IconButton>\n )}\n </li>\n );\n}\n\n// The entered pairs as rows.\nfunction PairRows({\n value,\n isDisabled,\n editor,\n suggestions,\n}: {\n value: Record<string, string>;\n isDisabled: boolean;\n editor: PairEditor;\n suggestions?: ValueSuggestion[];\n}): React.ReactElement | null {\n const keys = Object.keys(value);\n if (keys.length === 0) return null;\n return (\n <ul className=\"space-y-1.5\">\n {keys.map((k, index) => (\n <PairRow\n key={index}\n pairKey={k}\n pairValue={value[k]}\n isDisabled={isDisabled}\n editor={editor}\n suggestions={suggestions}\n />\n ))}\n </ul>\n );\n}\n\n// Only the keys, as badges, each value on hover: a summary, not edited.\nfunction PairKeys({\n value,\n}: {\n value: Record<string, string>;\n}): React.ReactElement {\n const keys = Object.keys(value);\n return (\n <div className=\"flex flex-wrap gap-1.5\">\n {keys.map((k) => (\n <Badge\n key={k}\n variant=\"outline\"\n className=\"font-mono text-[11px] font-normal\"\n title={value[k]}\n >\n {k}\n </Badge>\n ))}\n </div>\n );\n}\n\n// The entered pairs, as the display asks: tags or rows.\nfunction PairList({\n display,\n suggestions,\n ...props\n}: {\n display: \"tags\" | \"rows\";\n value: Record<string, string>;\n separator: string;\n isDisabled: boolean;\n editor: PairEditor;\n suggestions?: ValueSuggestion[];\n}): React.ReactElement | null {\n return display === \"rows\" ? (\n <PairRows {...props} suggestions={suggestions} />\n ) : (\n <PairTags {...props} />\n );\n}\n\n// The key and value fields and the add button.\nconst PairFields = React.forwardRef<\n HTMLInputElement,\n {\n id: string;\n name?: string;\n keyPlaceholder?: string;\n valuePlaceholder?: string;\n /** Size the fields as the rows above them (a narrower key). */\n asRow?: boolean;\n editor: PairEditor;\n /** Values the value field offers to pick. */\n suggestions?: ValueSuggestion[];\n }\n>(\n (\n {\n id,\n name,\n keyPlaceholder = \"Key\",\n valuePlaceholder = \"Value\",\n asRow = false,\n editor,\n suggestions,\n },\n ref,\n ) => (\n <div className=\"flex items-center gap-2\">\n <Input\n ref={ref}\n id={id}\n name={name}\n value={editor.key}\n onChange={(e) => editor.typeKey(e.target.value)}\n onKeyDown={editor.onKeyDown}\n placeholder={keyPlaceholder}\n className={cn(\"h-8\", asRow && \"w-1/3 shrink-0 font-mono text-xs\")}\n />\n <ValueInput\n ariaLabel={valuePlaceholder}\n value={editor.val}\n onType={editor.typeValue}\n onPick={editor.typeValue}\n onKeyDown={editor.onKeyDown}\n placeholder={valuePlaceholder}\n suggestions={suggestions}\n className={cn(\"h-8\", asRow && \"min-w-0 flex-1 font-mono text-xs\")}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"compact\"\n aria-label=\"Add\"\n onClick={editor.add}\n >\n <Plus className=\"h-4 w-4\" />\n </Button>\n </div>\n ),\n);\n\nPairFields.displayName = \"PairFields\";\n\n// The bordered box around the tags and the fields.\nfunction PairBox({\n isDisabled,\n hasError,\n children,\n}: {\n isDisabled: boolean;\n hasError: boolean;\n children: React.ReactNode;\n}): React.ReactElement {\n return (\n <div\n className={cn(\n \"w-full space-y-2 rounded-md border border-input bg-background px-3 py-2 text-sm\",\n isDisabled && \"cursor-not-allowed opacity-50\",\n hasError && \"border-destructive\",\n )}\n >\n {children}\n </div>\n );\n}\n\n// The pairs and the fields to add one: tags or rows in the bordered box.\nconst PairEditorBox = React.forwardRef<\n HTMLInputElement,\n {\n display: \"tags\" | \"rows\";\n value: Record<string, string>;\n separator: string;\n isDisabled: boolean;\n hasError: boolean;\n id: string;\n name?: string;\n keyPlaceholder?: string;\n valuePlaceholder?: string;\n editor: PairEditor;\n suggestions?: ValueSuggestion[];\n }\n>(\n (\n {\n display,\n value,\n separator,\n isDisabled,\n hasError,\n editor,\n suggestions,\n ...fields\n },\n ref,\n ) => (\n <PairBox isDisabled={isDisabled} hasError={hasError}>\n <PairList\n display={display}\n value={value}\n separator={separator}\n isDisabled={isDisabled}\n editor={editor}\n suggestions={suggestions}\n />\n {!isDisabled && (\n <PairFields\n ref={ref}\n {...fields}\n asRow={display === \"rows\"}\n editor={editor}\n suggestions={suggestions}\n />\n )}\n </PairBox>\n ),\n);\n\nPairEditorBox.displayName = \"PairEditorBox\";\n\nexport const FormKeyValueInput = React.forwardRef<\n HTMLInputElement,\n FormKeyValueInputProps\n>((props, ref) => {\n const {\n label,\n description,\n error,\n wrapperClassName,\n labelPlacement,\n id,\n value = {},\n onChange,\n separator = \":\",\n display = \"tags\",\n } = props;\n const generatedId = React.useId();\n const fieldId = id ?? generatedId;\n const editor = usePairEditor(value, onChange);\n\n return (\n <FormFieldWrapper\n inputId={fieldId}\n label={resolveFieldLabel(label)}\n description={description}\n error={error ?? editor.problem ?? undefined}\n required={props.required ?? false}\n labelPlacement={labelPlacement}\n className={wrapperClassName}\n >\n {display === \"keys\" ? (\n <PairKeys value={value} />\n ) : (\n <PairEditorBox\n ref={ref}\n display={display}\n value={value}\n separator={separator}\n isDisabled={Boolean(props.disabled || props.readOnly)}\n hasError={Boolean(error)}\n id={fieldId}\n name={props.name}\n keyPlaceholder={props.keyPlaceholder}\n valuePlaceholder={props.valuePlaceholder}\n editor={editor}\n suggestions={props.valueSuggestions}\n />\n )}\n </FormFieldWrapper>\n );\n});\n\nFormKeyValueInput.displayName = \"FormKeyValueInput\";\n","/**\n * FormQuantityInput - Compound input for a numeric value paired with a unit selector.\n *\n * Renders as a single visual control using InputGroup: the numeric input fills\n * the left side; the unit selector (or static text) sits inside the right (or\n * left) edge of the same border as an inline addon.\n *\n * Value shape: { value: number | undefined, unit: string }\n *\n * Decimal handling: uses inputMode=\"decimal\" with type=\"text\" to support\n * international decimal separators (comma and period). Input is validated and\n * normalized on blur, not on every keystroke, to allow intermediate states\n * such as \"37.\" or \"-\".\n *\n * NOTE on precision: toFixed() uses IEEE 754 rounding. For values where exact\n * decimal representation matters (e.g. financial amounts), the caller should\n * round the emitted number independently before storing it.\n */\n\nimport React, { useCallback, useEffect, useId, useMemo, useState } from \"react\";\nimport { ChevronsUpDown } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n} from \"@petrarca/sonnet-ui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\nimport { getAriaDescribedBy } from \"./formFieldUtils\";\nimport type { SelectOption } from \"./widgets/types\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/** Compound quantity value: numeric value + unit code */\nexport interface QuantityValue {\n value: number | undefined;\n unit: string;\n}\n\n/** Where the unit label renders relative to the numeric input */\nexport type UnitPosition = \"prefix\" | \"suffix\";\n\n/** A unit option with optional per-unit validation constraints and position */\nexport interface UnitOption extends SelectOption {\n /** Minimum allowed value for this unit */\n min?: number;\n /** Maximum allowed value for this unit */\n max?: number;\n /** Where to render this unit relative to the value (default: \"suffix\") */\n position?: UnitPosition;\n}\n\nexport interface FormQuantityInputProps {\n /** Controlled compound value */\n value?: QuantityValue;\n /** Change handler -- receives the updated quantity */\n onChange?: (value: QuantityValue) => void;\n /** Blur handler */\n onBlur?: () => void;\n\n /** Available unit options. Single = static text, 2+ = dropdown, none = no addon (or a typed unit, with `freeUnit`). */\n units?: UnitOption[];\n /** Without units, the unit is typed -- a code such as `kg`. Default false: no unit at all. */\n freeUnit?: boolean;\n /**\n * Default position for all units. Individual UnitOption.position overrides\n * this. Default: \"suffix\".\n */\n unitPosition?: UnitPosition;\n /**\n * Decimal places to format on blur (undefined = no formatting).\n * Uses toFixed() -- see IEEE 754 note in file header.\n */\n precision?: number;\n /** Arrow-key step increment */\n step?: number;\n /** Global minimum (overridden by per-unit min when present) */\n min?: number;\n /** Global maximum (overridden by per-unit max when present) */\n max?: number;\n\n /** Visible label */\n label?: string;\n /** Helper text shown below the control */\n description?: string;\n /** Validation error message */\n error?: string;\n /** Placeholder for the numeric input */\n placeholder?: string;\n /** Shows a required asterisk */\n required?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n autoFocus?: boolean;\n /** Additional class name for the outer wrapper */\n wrapperClassName?: string;\n /** Label placement: \"vertical\" (default, above) or \"horizontal\" (inline). */\n labelPlacement?: \"top\" | \"start\";\n /** Additional class name for the numeric input */\n className?: string;\n id?: string;\n name?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Pure helpers\n// ---------------------------------------------------------------------------\n\n// Allows in-progress numeric strings: optional leading minus, digits,\n// at most one decimal separator (comma or period).\nconst VALID_NUMERIC_INPUT = /^-?\\d*[.,]?\\d*$/;\n\n/** Sentinel values that represent incomplete but valid in-progress entries. */\nconst INCOMPLETE_SENTINELS = new Set([\"\", \".\", \"-\", \"-.\"]);\n\n/**\n * Round n to p decimal places using integer scaling.\n *\n * Avoids the IEEE 754 trap in toFixed() (e.g. (1.005).toFixed(2) === \"1.00\").\n * The Number.EPSILON nudge shifts values that land exactly halfway between two\n * representable floats (e.g. 1.005, 0.045) to the correct side before rounding.\n * Safe for all values within Number.MAX_SAFE_INTEGER / 10^p, which covers every\n * practical clinical and financial quantity this widget handles (see ADR-0010).\n */\nfunction roundToPrecision(n: number, p: number): number {\n const factor = Math.pow(10, p);\n return Math.round((n + Number.EPSILON) * factor) / factor;\n}\n\n/** Pure validation -- returns an error string or empty string. */\nfunction validateQuantity(\n numValue: number,\n lo: number | undefined,\n hi: number | undefined,\n unitLabel: string,\n): string {\n if (lo !== undefined && numValue < lo) {\n return `Value must be at least ${lo}${unitLabel ? ` ${unitLabel}` : \"\"}`;\n }\n if (hi !== undefined && numValue > hi) {\n return `Value must be at most ${hi}${unitLabel ? ` ${unitLabel}` : \"\"}`;\n }\n return \"\";\n}\n\n/** Round and format a parsed number. Returns { rounded, formatted }. */\nfunction roundAndFormat(\n numValue: number,\n precision: number | undefined,\n): { rounded: number; formatted: string } {\n const rounded =\n precision !== undefined ? roundToPrecision(numValue, precision) : numValue;\n const formatted =\n precision !== undefined ? rounded.toFixed(precision) : String(rounded);\n return { rounded, formatted };\n}\n\n// ---------------------------------------------------------------------------\n// UnitAddon sub-component (named for React DevTools visibility)\n// ---------------------------------------------------------------------------\n\ninterface UnitAddonProps {\n units: UnitOption[];\n freeUnit?: boolean;\n currentUnit: string;\n addonAlign: \"inline-start\" | \"inline-end\";\n disabled?: boolean;\n readOnly?: boolean;\n onChange: (\n e: React.ChangeEvent<HTMLSelectElement | HTMLInputElement>,\n ) => void;\n}\n\n// A unit typed rather than picked: no units offered, any unit taken.\nfunction FreeUnitAddon({\n currentUnit,\n addonAlign,\n disabled,\n readOnly,\n onChange,\n}: Omit<UnitAddonProps, \"units\" | \"freeUnit\">) {\n return (\n <InputGroupAddon align={addonAlign}>\n <input\n value={currentUnit}\n onChange={onChange}\n disabled={disabled}\n readOnly={readOnly}\n placeholder=\"unit\"\n aria-label=\"Unit\"\n className=\"w-16 border-0 bg-transparent px-1 text-right text-sm text-muted-foreground outline-none placeholder:text-muted-foreground/60 focus:text-foreground\"\n />\n </InputGroupAddon>\n );\n}\n\nfunction UnitAddon({ units, freeUnit, ...rest }: UnitAddonProps) {\n if (units.length === 0) return freeUnit ? <FreeUnitAddon {...rest} /> : null;\n return <UnitPicker units={units} {...rest} />;\n}\n\nfunction UnitPicker({\n units,\n currentUnit,\n addonAlign,\n disabled,\n readOnly,\n onChange,\n}: Omit<UnitAddonProps, \"freeUnit\">) {\n if (units.length === 1) {\n return (\n <InputGroupAddon align={addonAlign}>\n <span className=\"text-sm text-muted-foreground\">{units[0].label}</span>\n </InputGroupAddon>\n );\n }\n\n return (\n <InputGroupAddon align={addonAlign}>\n <div className=\"relative flex items-center\">\n <select\n value={currentUnit}\n onChange={onChange}\n disabled={disabled || readOnly}\n className=\"cursor-pointer appearance-none border-0 bg-transparent py-0 pr-5 pl-1 text-sm text-muted-foreground outline-none hover:text-foreground focus:text-foreground\"\n aria-label=\"Unit\"\n >\n {units.map((u) => (\n <option key={u.value} value={u.value}>\n {u.label}\n </option>\n ))}\n </select>\n <ChevronsUpDown className=\"pointer-events-none absolute right-0 h-3.5 w-3.5 text-muted-foreground/60\" />\n </div>\n </InputGroupAddon>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Hooks\n// ---------------------------------------------------------------------------\n\n/** Derive current unit, position, and effective min/max from props. */\nfunction useUnitState(\n value: QuantityValue | undefined,\n units: UnitOption[],\n unitPosition: UnitPosition,\n min: number | undefined,\n max: number | undefined,\n) {\n const currentUnit = useMemo(() => {\n const preferred = value?.unit;\n // No units offered: the value's own unit, typed or given.\n if (units.length === 0) return preferred ?? \"\";\n if (preferred && units.some((u) => u.value === preferred)) return preferred;\n return units[0]?.value ?? \"\";\n }, [value?.unit, units]);\n\n const unitMeta = useMemo(\n () => units.find((u) => u.value === currentUnit),\n [units, currentUnit],\n );\n\n const effectiveMin = unitMeta?.min ?? min;\n const effectiveMax = unitMeta?.max ?? max;\n const effectivePosition = unitMeta?.position ?? unitPosition;\n const addonAlign: \"inline-start\" | \"inline-end\" =\n effectivePosition === \"prefix\" ? \"inline-start\" : \"inline-end\";\n\n return { currentUnit, effectiveMin, effectiveMax, addonAlign };\n}\n\n/** Manage raw text input, validation, and handlers for numeric entry. */\nfunction useQuantityInput(\n value: QuantityValue | undefined,\n onChange: ((value: QuantityValue) => void) | undefined,\n onBlur: (() => void) | undefined,\n currentUnit: string,\n precision: number | undefined,\n effectiveMin: number | undefined,\n effectiveMax: number | undefined,\n externalError: string | undefined,\n) {\n const [rawInput, setRawInput] = useState<string>(\n value?.value !== undefined ? String(value.value) : \"\",\n );\n const [validationError, setValidationError] = useState<string>(\"\");\n\n // Sync rawInput when the controlled value changes from outside.\n useEffect(() => {\n const external = value?.value !== undefined ? String(value.value) : \"\";\n setRawInput((prev) => {\n const parsed = parseFloat(prev.replace(\",\", \".\"));\n if (!isNaN(parsed) && parsed === value?.value) return prev;\n return external;\n });\n }, [value?.value]);\n\n const error = externalError || validationError;\n\n const emit = useCallback(\n (numValue: number | undefined, unitValue: string) => {\n onChange?.({ value: numValue, unit: unitValue });\n },\n [onChange],\n );\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const raw = e.target.value;\n if (raw !== \"\" && !VALID_NUMERIC_INPUT.test(raw)) return;\n setRawInput(raw);\n setValidationError(\"\");\n },\n [],\n );\n\n const handleInputBlur = useCallback(() => {\n const normalized = rawInput.replace(\",\", \".\");\n\n // Handle incomplete entries (empty, just a dot/minus/minus-dot).\n if (INCOMPLETE_SENTINELS.has(normalized)) {\n if (normalized !== \"\") setRawInput(\"\");\n emit(undefined, currentUnit);\n setValidationError(\"\");\n onBlur?.();\n return;\n }\n\n const numValue = parseFloat(normalized);\n if (isNaN(numValue)) {\n setRawInput(\"\");\n emit(undefined, currentUnit);\n onBlur?.();\n return;\n }\n\n const { rounded, formatted } = roundAndFormat(numValue, precision);\n setRawInput(formatted);\n setValidationError(\n validateQuantity(rounded, effectiveMin, effectiveMax, currentUnit),\n );\n emit(rounded, currentUnit);\n onBlur?.();\n }, [\n rawInput,\n currentUnit,\n precision,\n effectiveMin,\n effectiveMax,\n emit,\n onBlur,\n ]);\n\n return {\n rawInput,\n error,\n handleInputChange,\n handleInputBlur,\n emit,\n setValidationError,\n };\n}\n\n// ---------------------------------------------------------------------------\n// FormQuantityInput\n// ---------------------------------------------------------------------------\n\n/**\n * FormQuantityInput -- controlled compound numeric + unit input in a single\n * InputGroup border. See file header for behavioural notes.\n */\nexport const FormQuantityInput = React.forwardRef<\n HTMLInputElement,\n FormQuantityInputProps\n>((allProps, ref) => {\n const {\n value,\n onChange,\n onBlur,\n precision,\n step,\n min,\n max,\n label,\n description,\n placeholder,\n required,\n disabled,\n readOnly,\n autoFocus,\n wrapperClassName,\n labelPlacement,\n className,\n name,\n freeUnit,\n } = allProps;\n const units = useMemo(() => allProps.units ?? [], [allProps.units]);\n const unitPosition = allProps.unitPosition ?? \"suffix\";\n const error = allProps.error;\n\n const generatedId = useId();\n const inputId = allProps.id ?? generatedId;\n\n const { currentUnit, effectiveMin, effectiveMax, addonAlign } = useUnitState(\n value,\n units,\n unitPosition,\n min,\n max,\n );\n\n const {\n rawInput,\n error: resolvedError,\n handleInputChange,\n handleInputBlur,\n emit,\n setValidationError,\n } = useQuantityInput(\n value,\n onChange,\n onBlur,\n currentUnit,\n precision,\n effectiveMin,\n effectiveMax,\n error,\n );\n\n // Unit change handler\n const handleUnitChange = useCallback(\n (e: React.ChangeEvent<HTMLSelectElement | HTMLInputElement>) => {\n const unitValue = e.target.value;\n setValidationError(\"\");\n const normalized = rawInput.replace(\",\", \".\");\n const numValue = parseFloat(normalized);\n // No number yet: the unit is reported alone, so the choice is not lost.\n if (isNaN(numValue)) return emit(undefined, unitValue);\n const um = units.find((u) => u.value === unitValue);\n const lo = um?.min ?? min;\n const hi = um?.max ?? max;\n setValidationError(validateQuantity(numValue, lo, hi, unitValue));\n emit(numValue, unitValue);\n },\n [rawInput, units, min, max, emit, setValidationError],\n );\n\n const unitAddon = useMemo(\n () => (\n <UnitAddon\n units={units}\n freeUnit={freeUnit}\n currentUnit={currentUnit}\n addonAlign={addonAlign}\n disabled={disabled}\n readOnly={readOnly}\n onChange={handleUnitChange}\n />\n ),\n [\n units,\n freeUnit,\n currentUnit,\n addonAlign,\n disabled,\n readOnly,\n handleUnitChange,\n ],\n );\n\n return (\n <FormFieldWrapper\n inputId={inputId}\n label={label}\n description={description}\n error={resolvedError}\n required={required}\n labelPlacement={labelPlacement}\n className={wrapperClassName}\n >\n <InputGroup\n data-disabled={disabled || undefined}\n className={cn(resolvedError && \"border-destructive\")}\n >\n <InputGroupInput\n id={inputId}\n name={name}\n ref={ref}\n type=\"text\"\n inputMode=\"decimal\"\n value={rawInput}\n onChange={handleInputChange}\n onBlur={handleInputBlur}\n placeholder={placeholder}\n disabled={disabled}\n readOnly={readOnly}\n autoFocus={autoFocus}\n step={step}\n className={className}\n aria-invalid={resolvedError ? \"true\" : \"false\"}\n aria-describedby={getAriaDescribedBy(\n inputId,\n resolvedError,\n description,\n )}\n aria-required={required}\n aria-valuemin={effectiveMin}\n aria-valuemax={effectiveMax}\n />\n {unitAddon}\n </InputGroup>\n </FormFieldWrapper>\n );\n});\n\nFormQuantityInput.displayName = \"FormQuantityInput\";\n","/**\n * FormActions - Save / Cancel button row for buffered forms\n *\n * Rendered only when the parent JsonSchemaFormRenderer is in buffered mode\n * (showActions=true). Keeps button logic out of the orchestrator.\n *\n * @module components/Forms/FormActions\n */\n\nimport type { MouseEvent, ReactNode } from \"react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport { SimpleGroup } from \"@petrarca/sonnet-ui\";\nimport type { SaveWhenInvalid } from \"@petrarca/sonnet-core/config\";\n\nexport interface FormActionsProps {\n onSave: () => void;\n onCancel: () => void;\n disabled?: boolean;\n hasChanges: boolean;\n isValid: boolean;\n /**\n * Whether Save is available while invalid. `reveal` (default) keeps it\n * enabled -- an invalid click reveals errors and does not submit; `disable`\n * greys it out while invalid.\n */\n saveWhenInvalid?: SaveWhenInvalid;\n saveLabel?: string;\n cancelLabel?: string;\n showCancel?: boolean;\n /**\n * True while an async validator is in flight. Save is disabled until it\n * settles (validity is not yet known); Cancel stays enabled.\n */\n isValidating?: boolean;\n /**\n * Optional content rendered left-aligned in the action row (e.g. a secondary\n * action like \"Test connection\"). Cancel/Save stay grouped on the right.\n */\n leadingActions?: ReactNode;\n}\n\n// Whether the Save button is disabled. \"reveal\": stays enabled while invalid\n// (the click reveals errors, handleSave declines to submit). \"disable\": greyed\n// out while invalid. Always disabled while an async validator is pending\n// (validity unknown), or while disabled/pristine.\nfunction isSaveDisabled(args: {\n disabled: boolean;\n hasChanges: boolean;\n isValid: boolean;\n isValidating: boolean;\n saveWhenInvalid: SaveWhenInvalid;\n}): boolean {\n if (args.disabled || !args.hasChanges || args.isValidating) return true;\n return args.saveWhenInvalid === \"disable\" && !args.isValid;\n}\n\nexport function FormActions({\n onSave,\n onCancel,\n disabled = false,\n hasChanges,\n isValid,\n saveWhenInvalid = \"reveal\",\n saveLabel = \"Save\",\n cancelLabel = \"Cancel\",\n showCancel = true,\n isValidating = false,\n leadingActions,\n}: FormActionsProps) {\n const saveDisabled = isSaveDisabled({\n disabled,\n hasChanges,\n isValid,\n isValidating,\n saveWhenInvalid,\n });\n // Keep focus in the field on press: a mousedown here would otherwise blur the\n // active input, and under validationDisplay=\"onTouched\" that reveals the\n // field's error, which grows the field in flow and shifts this button down\n // between mousedown and mouseup -- so the first click lands on empty space and\n // is swallowed. Preventing the mousedown default stops the blur (and the\n // shift) without affecting the click, keyboard, or the committed data\n // (handleSave merges pending changes itself).\n const keepFocus = (e: MouseEvent) => e.preventDefault();\n return (\n <div className=\"flex items-center justify-between mt-4\">\n <div className=\"flex items-center gap-2\">{leadingActions}</div>\n <SimpleGroup justify=\"flex-end\">\n {showCancel && (\n <Button\n variant=\"outline\"\n onClick={onCancel}\n onMouseDown={keepFocus}\n disabled={disabled}\n >\n {cancelLabel}\n </Button>\n )}\n <Button\n onClick={onSave}\n onMouseDown={keepFocus}\n disabled={saveDisabled}\n >\n {saveLabel}\n </Button>\n </SimpleGroup>\n </div>\n );\n}\n","import { useMemo } from \"react\";\nimport { ChevronDown, ChevronRight } from \"lucide-react\";\nimport { Card } from \"@petrarca/sonnet-ui\";\nimport { useDisclosure } from \"@petrarca/sonnet-core/hooks\";\nimport { JsonSchema } from \"@petrarca/sonnet-core/schema\";\nimport { Collapsible, CollapsibleContent } from \"@petrarca/sonnet-ui\";\n\ntype Props = {\n properties: Record<string, any>;\n schema: JsonSchema | null;\n};\n\n/**\n * Displays properties that are not defined in the JSON Schema.\n * Shown as a collapsible card, closed by default.\n *\n * This is a generic component that can be used anywhere a schema and properties\n * need to be compared to show additional/extra properties.\n */\nfunction ExtraPropertiesCard({ properties, schema }: Props) {\n const [opened, { toggle }] = useDisclosure(false);\n\n const extraProperties = useMemo(() => {\n if (!schema) return null;\n const schemaProps = schema.properties ?? {};\n const extra = Object.fromEntries(\n Object.entries(properties).filter(([k]) => !(k in schemaProps)),\n );\n return Object.keys(extra).length > 0 ? extra : null;\n }, [properties, schema]);\n\n if (!extraProperties) return null;\n\n return (\n <Card className=\"border p-3\">\n <p\n className={`flex items-center gap-1 text-sm font-medium cursor-pointer select-none ${opened ? \"mb-1\" : \"\"}`}\n onClick={toggle}\n >\n {opened ? (\n <ChevronDown className=\"h-3.5 w-3.5\" />\n ) : (\n <ChevronRight className=\"h-3.5 w-3.5\" />\n )}\n Extra Properties (not in schema)\n </p>\n <Collapsible open={opened}>\n <CollapsibleContent>\n <pre className=\"text-xs bg-muted p-2 rounded overflow-x-auto\">\n <code>{JSON.stringify(extraProperties, null, 2)}</code>\n </pre>\n </CollapsibleContent>\n </Collapsible>\n </Card>\n );\n}\n\nexport default ExtraPropertiesCard;\n","/**\n * JsonSchemaFormRenderer - Generic form renderer based on JSON Schema\n *\n * Thin orchestrator: composes useFormEngine, FormFieldRenderer, and FormActions.\n *\n * Supports three update modes:\n * 1. Real-time (default) — onChange on every field change\n * 2. Deferred (deferChanges=true) — onChange on blur for text fields\n * 3. Buffered (showActions=true) — Save/Cancel managed by form; onUpdate on Save\n *\n * When rendered inside a HorizontalArrayItemTemplate (via ObjectWidget in an\n * array row), the caller sets `displayContents=true` so this renderer's\n * wrapper uses `display: contents`, making each field div a direct grid cell\n * in the parent row grid.\n *\n * @module components/Forms/JsonSchemaFormRenderer\n */\n\nimport React, { useCallback, useContext, useMemo } from \"react\";\nimport { SimpleStack } from \"@petrarca/sonnet-ui\";\nimport { AlertCircle } from \"lucide-react\";\nimport {\n JsonSchema,\n UILayoutConfig,\n UILayoutRowConfig,\n UILayoutGroupConfig,\n WidthToken,\n WIDTH_TOKEN_REMS,\n} from \"@petrarca/sonnet-core/schema\";\nimport type {\n FormDiff,\n RefResolver,\n FieldError,\n} from \"@petrarca/sonnet-core/schema\";\nimport {\n isFieldRequired,\n evaluateUiRule,\n stripFormItemIds,\n} from \"@petrarca/sonnet-core/schema\";\nimport ExtraPropertiesCard from \"./ExtraPropertiesCard\";\nimport { DEFAULT_WIDGETS, WidgetRegistry, UISchema } from \"./widgets\";\nimport { TemplateRegistry, UISchemaOptions } from \"./widgets/types\";\nimport type { FieldGroup, GroupLayoutTemplate } from \"./widgets/types\";\nimport { DEFAULT_TEMPLATES, groupTemplateKey } from \"./templates\";\nimport { FormFieldRenderer } from \"./FormFieldRenderer\";\nimport { FormActions } from \"./FormActions\";\nimport { useFormEngine } from \"./hooks/useFormEngine\";\nimport {\n useValidationDisplay,\n useSaveWhenInvalid,\n type ValidationDisplay,\n type SaveWhenInvalid,\n} from \"@petrarca/sonnet-core/config\";\nimport { NestedFormContext, NestedRenderer } from \"./NestedFormContext\";\nimport type { NestedFormContextValue } from \"./NestedFormContext\";\nimport type { ValidatorRegistry } from \"./validators\";\n\n/** Resolve boolean/flag default values for optional props. */\nfunction resolveFlagDefaults(props: JsonSchemaFormRendererProps) {\n return {\n disabled: props.disabled ?? false,\n readOnly: props.readOnly ?? false,\n showActions: props.showActions ?? false,\n deferChanges: props.deferChanges ?? false,\n deferStateUpdates: props.deferStateUpdates ?? false,\n showCancel: props.showCancel ?? true,\n showExtraProperties: props.showExtraProperties ?? true,\n displayContents: props.displayContents ?? false,\n allowPristineSave: props.allowPristineSave ?? false,\n };\n}\n\n/** Resolve non-boolean default values for optional props. */\nfunction resolveValueDefaults(props: JsonSchemaFormRendererProps) {\n return {\n saveLabel: props.saveLabel ?? \"Save\",\n cancelLabel: props.cancelLabel ?? \"Cancel\",\n widgets: props.widgets ?? DEFAULT_WIDGETS,\n uiSchema: props.uiSchema ?? ({} as { [fieldName: string]: UISchema }),\n };\n}\n\n// A nested sub-form hands its data to the enclosing widget, still inside the\n// renderer -- the item ids must survive, or the enclosing array re-keys (and\n// remounts) its items on every change.\nconst keepFids = (data: Record<string, unknown>): Record<string, unknown> =>\n data;\n\n/**\n * Wrap outbound callbacks to strip _fid before data crosses the renderer\n * boundary -- at the root form only, which is that boundary. Each callback is\n * memoised individually.\n */\nfunction useWrappedCallbacks(\n onChange: JsonSchemaFormRendererProps[\"onChange\"],\n onBlur: JsonSchemaFormRendererProps[\"onBlur\"],\n onUpdate: JsonSchemaFormRendererProps[\"onUpdate\"],\n isRootForm: boolean,\n) {\n const strip = isRootForm ? stripFormItemIds : keepFids;\n\n const wrappedOnChange = useCallback(\n (d: Record<string, any>) => onChange?.(strip(d)),\n [onChange, strip],\n );\n\n const wrappedOnBlur = useCallback(\n (fieldName: string, d: Record<string, any>) =>\n onBlur?.(fieldName, strip(d)),\n [onBlur, strip],\n );\n\n const wrappedOnUpdate = useCallback(\n (d: Record<string, any>, changed: Record<string, any>, diff: FormDiff) =>\n onUpdate?.(strip(d), strip(changed), diff),\n [onUpdate, strip],\n );\n\n return {\n wrappedOnChange: onChange ? wrappedOnChange : undefined,\n wrappedOnBlur: onBlur ? wrappedOnBlur : undefined,\n wrappedOnUpdate: onUpdate ? wrappedOnUpdate : undefined,\n };\n}\n\n/** Index field elements by their React key for O(1) lookup. */\nfunction buildFieldMap(\n fields: React.ReactElement[],\n): Map<string, React.ReactElement> {\n const map = new Map<string, React.ReactElement>();\n for (const field of fields) {\n if (React.isValidElement(field) && field.key != null) {\n map.set(String(field.key), field);\n }\n }\n return map;\n}\n\n/** Build a single CSS grid row element from a row definition. */\n// Column-width tokens re-use the shared WIDTH_TOKEN_REMS from sonnet-core\n// (single source of truth for token -> size; see types.ts).\nconst COLUMN_TRACK: Record<WidthToken, string> = WIDTH_TOKEN_REMS;\n\n/**\n * Resolve a row's grid-template-columns. Precedence: raw `columns` (escape\n * hatch) -> semantic `widths` tokens -> equal 1fr per field.\n */\nfunction resolveGridColumns(\n row: UILayoutRowConfig,\n fieldCount: number,\n): string {\n if (row.columns) return row.columns;\n if (row.widths && row.widths.length > 0) {\n return Array.from(\n { length: fieldCount },\n (_, i) => COLUMN_TRACK[row.widths?.[i] ?? \"full\"],\n ).join(\" \");\n }\n return `repeat(${fieldCount}, 1fr)`;\n}\n\n/**\n * Wrap row content in a titled fieldset when `group` is set. Composable: the\n * fieldset holds arbitrary content, so nesting (groups of rows, tabs)\n * layers on without changing callers.\n */\nfunction wrapInGroup(\n group: string | undefined,\n key: string,\n content: React.ReactElement,\n): React.ReactElement {\n if (!group) return content;\n return (\n <fieldset\n key={`group:${key}`}\n className=\"rounded-md border border-border/60 px-3 pb-3 pt-1\"\n >\n <legend className=\"px-1 text-sm font-medium text-muted-foreground\">\n {group}\n </legend>\n {content}\n </fieldset>\n );\n}\n\nfunction buildRowElement(\n row: UILayoutRowConfig,\n fieldMap: Map<string, React.ReactElement>,\n defaultRowGap: number,\n): { element: React.ReactElement; placed: string[] } | null {\n const rowFields = row.fields\n .map((name) => fieldMap.get(name))\n .filter((el): el is React.ReactElement => el != null);\n if (rowFields.length === 0) return null;\n\n const rowGap = row.gap ?? defaultRowGap;\n const rowKey = row.fields.join(\",\");\n\n // \"flow\": flex row, fields at natural width, left-to-right, wrapping.\n // \"grid\" (default): CSS grid using columns/widths (equal 1fr by default).\n const style: React.CSSProperties =\n row.arrange === \"flow\"\n ? {\n display: \"flex\",\n flexWrap: \"wrap\",\n alignItems: \"center\",\n gap: `${rowGap}px`,\n }\n : {\n display: \"grid\",\n gridTemplateColumns: resolveGridColumns(row, rowFields.length),\n gap: `${rowGap}px`,\n };\n\n const inner = (\n <div key={`row:${rowKey}`} style={style}>\n {rowFields}\n </div>\n );\n\n return {\n element: wrapInGroup(row.group, rowKey, inner),\n placed: row.fields,\n };\n}\n\n/** Collect fields not present in the placed set, preserving source order. */\nfunction collectUnplacedFields(\n fields: React.ReactElement[],\n placed: Set<string>,\n): React.ReactElement[] {\n const result: React.ReactElement[] = [];\n for (const field of fields) {\n if (\n React.isValidElement(field) &&\n field.key != null &&\n !placed.has(String(field.key))\n ) {\n result.push(field);\n }\n }\n return result;\n}\n\n/**\n * Build a list of rows, recording into `placed` every field they declare.\n * Placement is recorded even for a row that renders nothing, so a field named\n * by the layout never also turns up in the unplaced stack.\n */\nfunction buildRows(\n rowDefs: UILayoutRowConfig[],\n fieldMap: Map<string, React.ReactElement>,\n defaultRowGap: number,\n placed: Set<string>,\n): React.ReactElement[] {\n const elements: React.ReactElement[] = [];\n for (const row of rowDefs) {\n const result = buildRowElement(row, fieldMap, defaultRowGap);\n for (const name of row.fields) placed.add(name);\n if (result != null) elements.push(result.element);\n }\n return elements;\n}\n\n/**\n * Arrange field elements into CSS grid rows according to row definitions.\n * Fields not mentioned in any row are appended in source order.\n */\nfunction layoutFieldsInRows(\n fields: React.ReactElement[],\n rowDefs: UILayoutRowConfig[],\n defaultRowGap: number,\n): React.ReactElement[] {\n const placed = new Set<string>();\n const elements = buildRows(\n rowDefs,\n buildFieldMap(fields),\n defaultRowGap,\n placed,\n );\n return elements.concat(collectUnplacedFields(fields, placed));\n}\n\n/**\n * Whether a field must be given a blur handler.\n *\n * Four independent reasons, any one of which is sufficient: the two deferred\n * modes flush on blur, a consumer onBlur must be forwarded, and `onTouched`\n * error display needs blur to record that a field was touched.\n */\n/**\n * The data an `x-ui-rule` scope (or a form validator) resolves against: the\n * whole form, not the renderer's own slice.\n *\n * A nested renderer inherits the root from the enclosing one; the outermost\n * renderer has no enclosing context, so its own data *is* the root. This is\n * what lets a rule or validator on a nested field reference any field by its\n * pointer from the top of the form -- consistent with every other JSON\n * Pointer in the vocabulary (`editablePaths`, validation error pointers).\n *\n * Takes the already-read `NestedFormContext` value (see `isRootForm` at the\n * renderer's call site) rather than reading the context itself, so the\n * component reads it once and this and `isRoot` can never disagree about\n * which renderer they describe.\n */\nfunction rootFormData(\n nestedContext: NestedFormContextValue | null,\n ownData: Record<string, unknown>,\n): Record<string, unknown> {\n return nestedContext?.rootData ?? ownData;\n}\n\n/**\n * Whether the root form's save has been attempted, as seen by this renderer. A\n * nested sub-form has its own submit state that the root's Save never flips, so\n * it inherits the root's; the outermost renderer has no enclosing context and\n * uses its own. Mirrors `rootFormData`, keeping the two root-anchored inherited\n * values computed the same way.\n */\nfunction rootSubmitAttempted(\n nestedContext: NestedFormContextValue | null,\n ownSubmitAttempted: boolean,\n): boolean {\n return ownSubmitAttempted || (nestedContext?.submitAttempted ?? false);\n}\n\nfunction blurHandlerNeeded({\n deferStateUpdates,\n deferChanges,\n hasOnBlur,\n validationDisplay,\n}: {\n deferStateUpdates: boolean;\n deferChanges: boolean;\n hasOnBlur: boolean;\n validationDisplay: ValidationDisplay;\n}): boolean {\n return (\n deferStateUpdates ||\n deferChanges ||\n hasOnBlur ||\n validationDisplay === \"onTouched\"\n );\n}\n\n/** Whether a field's validation errors are shown yet, per the display policy. */\nfunction fieldErrorsVisible(\n validationDisplay: ValidationDisplay,\n submitAttempted: boolean,\n isTouched: boolean | undefined,\n): boolean {\n if (validationDisplay === \"always\") return true;\n if (submitAttempted) return true;\n return validationDisplay === \"onTouched\" && !!isTouched;\n}\n\n// The root field name a JSON Pointer refers to, un-escaped (RFC 6901).\n// \"/contact/email\" -> \"contact\"; \"/a~1b\" -> \"a/b\".\nfunction pointerRoot(pointer: string): string {\n const token = pointer.split(\"/\")[1] ?? \"\";\n return token.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n}\n\n// A field's messages for the widget's `rawErrors`. Validation errors are gated\n// by the validationDisplay policy (`gated`); external `extraErrors` for the same\n// field are ALWAYS shown -- a server rejection is not \"not yet touched\". Returns\n// undefined when there is nothing to show, so the widget stays clean.\nfunction fieldRawErrors(\n fieldName: string,\n fieldErrors: FieldError[],\n extraErrors: FieldError[] | undefined,\n gated: boolean,\n): string[] | undefined {\n // Read from the MERGED fieldErrors, not the raw extraErrors prop: mergeFieldErrors\n // already resolved precedence (structural > content > custom > external), so a\n // field whose extraError lost to a higher-precedence error must not show it here\n // -- reading the raw prop would silently re-surface an error the merge excluded.\n const forField = fieldErrors.filter(\n (e) => pointerRoot(e.pointer) === fieldName,\n );\n if (forField.length === 0) return undefined;\n\n // Of the errors that SURVIVED the merge for this field, the ones that\n // originated as an extraError are always shown (a server rejection is not\n // \"not yet touched\"); everything else follows the usual gating policy.\n const extraMessages = new Set(\n (extraErrors ?? [])\n .filter((e) => pointerRoot(e.pointer) === fieldName)\n .map((e) => e.message),\n );\n const always = forField\n .filter((e) => extraMessages.has(e.message))\n .map((e) => e.message);\n const rest = gated\n ? forField\n .filter((e) => !extraMessages.has(e.message))\n .map((e) => e.message)\n : [];\n const all = [...always, ...rest];\n return all.length > 0 ? all : undefined;\n}\n\n// How many validation errors belong to the fields declared in a tab.\nfunction groupErrorCount(\n tab: UILayoutGroupConfig,\n fieldErrors: FieldError[],\n): number {\n if (fieldErrors.length === 0) return 0;\n const owned = new Set(tab.rows.flatMap((row) => row.fields));\n return fieldErrors.filter((e) => owned.has(pointerRoot(e.pointer))).length;\n}\n\n/**\n * Which groups their rules currently show. The single source of truth for\n * group visibility -- both the layout and the hidden-error summary read it, so\n * they cannot disagree about what is on screen.\n *\n * `allHidden` matters because the renderer then falls back to a flat layout,\n * which means nothing is actually hidden from the user.\n */\nfunction groupVisibility(\n groupDefs: UILayoutGroupConfig[],\n formData: Record<string, unknown>,\n): { visible: boolean[]; allHidden: boolean } {\n const visible = groupDefs.map(\n (tab) => evaluateUiRule(tab.rule, formData).visible,\n );\n return { visible, allHidden: !visible.some(Boolean) };\n}\n\n// Field names declared in groups that are hidden, and so are not on screen.\nfunction hiddenGroupFieldNames(\n groupDefs: UILayoutGroupConfig[],\n formData: Record<string, unknown>,\n): Set<string> {\n const hidden = new Set<string>();\n const { visible, allHidden } = groupVisibility(groupDefs, formData);\n if (allHidden) return hidden; // rendered flat: nothing is hidden\n groupDefs.forEach((tab, i) => {\n if (visible[i]) return;\n for (const row of tab.rows) for (const f of row.fields) hidden.add(f);\n });\n return hidden;\n}\n\n// The presentation for a grouped layout: \"tabs\" (default), \"stepper\",\n// \"sections\", or any template a consumer registered under the matching name.\nfunction resolveGroupTemplate(\n templates: TemplateRegistry,\n variant: string | undefined,\n): GroupLayoutTemplate {\n const registered = templates[groupTemplateKey(variant)];\n if (typeof registered === \"function\") {\n return registered as GroupLayoutTemplate;\n }\n return DEFAULT_TEMPLATES.TabsGroupTemplate as GroupLayoutTemplate;\n}\n\n/**\n * Summary of validation errors that belong to fields the user cannot currently\n * see (they sit in a hidden group). Without this the form is a dead end: Save\n * is disabled, and no on-screen field explains why.\n */\nfunction HiddenErrorNotice({\n count,\n}: {\n count: number;\n}): React.ReactElement | null {\n if (count === 0) return null;\n return (\n <p className=\"flex items-center gap-1.5 text-sm text-destructive\">\n <AlertCircle className=\"h-4 w-4 shrink-0\" />\n {count === 1\n ? \"1 required field is in a section that is not currently shown.\"\n : `${count} required fields are in sections that are not currently shown.`}\n </p>\n );\n}\n\n// Form-level errors (pointer \"\") from cross-field/form validators -- they belong\n// to no single field, so they render here, near the actions, rather than inline.\nfunction FormLevelErrors({\n messages,\n}: {\n messages: string[];\n}): React.ReactElement | null {\n if (messages.length === 0) return null;\n return (\n <div className=\"space-y-1\">\n {messages.map((msg, i) => (\n <p\n key={i}\n role=\"alert\"\n className=\"flex items-center gap-1.5 text-sm text-destructive\"\n >\n <AlertCircle className=\"h-4 w-4 shrink-0\" />\n {msg}\n </p>\n ))}\n </div>\n );\n}\n\n/**\n * Arrange field elements into groups and hand them to the registered group\n * template (tabs by default; stepper, sections or a consumer's own via\n * `x-ui-layout.variant`). This function owns the layout; the template owns the\n * presentation and navigation.\n *\n * Fields declared in a group hidden by its rule are consumed (not rendered);\n * fields in no group at all are appended below so nothing is hidden by accident.\n */\nfunction layoutFieldsInGroups(\n fields: React.ReactElement[],\n groupDefs: UILayoutGroupConfig[],\n defaultRowGap: number,\n fieldErrors: FieldError[],\n formData: Record<string, unknown>,\n GroupTemplate: GroupLayoutTemplate,\n): React.ReactElement[] {\n const fieldMap = buildFieldMap(fields);\n const placed = new Set<string>();\n const { visible, allHidden } = groupVisibility(groupDefs, formData);\n\n // Build every group's rows: a hidden group still consumes its fields so they\n // cannot leak into the unplaced stack below.\n const built = groupDefs.map((tab, index) => ({\n index,\n rows: buildRows(tab.rows, fieldMap, defaultRowGap, placed),\n }));\n const unplaced = collectUnplacedFields(fields, placed);\n\n // Every group hidden: fall back to rendering their rows flat rather than\n // silently dropping the fields they declare.\n if (allHidden) {\n return [...built.flatMap((b) => b.rows), ...unplaced];\n }\n\n const groups: FieldGroup[] = built\n .filter((b) => visible[b.index])\n .map((b) => ({\n key: `group-${b.index}`,\n label: groupDefs[b.index].label,\n content: b.rows,\n errorCount: groupErrorCount(groupDefs[b.index], fieldErrors),\n }));\n\n return [<GroupTemplate key=\"form:groups\" groups={groups} />, ...unplaced];\n}\n\ninterface FormContainerProps {\n displayContents: boolean;\n showExtraProperties: boolean;\n showActions: boolean;\n formData: Record<string, any>;\n resolvedSchema: JsonSchema;\n handleSave: () => void;\n handleCancel: () => void;\n disabled: boolean;\n hasChanges: boolean;\n isValid: boolean;\n isValidating: boolean;\n saveWhenInvalid: SaveWhenInvalid;\n saveLabel: string;\n cancelLabel: string;\n showCancel: boolean;\n leadingActions?: React.ReactNode;\n /** Errors owned by fields inside a currently hidden tab. */\n hiddenErrorCount: number;\n /** Form-level error messages (pointer \"\") from form validators, when visible. */\n formLevelErrors: string[];\n children: React.ReactNode;\n}\n\n/** Container that renders either display:contents or a SimpleStack with actions. */\nfunction FormContainer({\n displayContents,\n showExtraProperties,\n showActions,\n formData,\n resolvedSchema,\n handleSave,\n handleCancel,\n disabled,\n hasChanges,\n isValid,\n isValidating,\n saveWhenInvalid,\n saveLabel,\n cancelLabel,\n showCancel,\n leadingActions,\n hiddenErrorCount,\n formLevelErrors,\n children,\n}: FormContainerProps): React.ReactElement {\n if (displayContents) {\n return <div style={{ display: \"contents\" }}>{children}</div>;\n }\n return (\n <SimpleStack gap=\"md\">\n {children}\n {showExtraProperties && (\n <ExtraPropertiesCard properties={formData} schema={resolvedSchema} />\n )}\n <HiddenErrorNotice count={hiddenErrorCount} />\n <FormLevelErrors messages={formLevelErrors} />\n {showActions && (\n <FormActions\n onSave={handleSave}\n onCancel={handleCancel}\n disabled={disabled}\n hasChanges={hasChanges}\n isValid={isValid}\n isValidating={isValidating}\n saveWhenInvalid={saveWhenInvalid}\n saveLabel={saveLabel}\n cancelLabel={cancelLabel}\n showCancel={showCancel}\n leadingActions={leadingActions}\n />\n )}\n </SimpleStack>\n );\n}\n\nexport type JsonSchemaFormRendererProps = {\n /** JSON Schema defining the form fields */\n schema: JsonSchema;\n\n /** Current form data */\n data: Record<string, any>;\n\n /** Callback when any field changes (real-time updates) */\n onChange?: (data: Record<string, any>) => void;\n\n /** Callback when a field loses focus */\n onBlur?: (fieldName: string, data: Record<string, any>) => void;\n\n /** Optional callback for validation state changes */\n onValidationChange?: (errors: string[], isValid: boolean) => void;\n\n /**\n * Defer onChange to blur for text fields (default: false).\n * Checkboxes and selects always trigger immediately.\n */\n deferChanges?: boolean;\n\n /**\n * Defer internal state updates to blur for text fields (default: false).\n * Only applies when showActions=true. The Save button enables only after\n * leaving a modified text field.\n */\n deferStateUpdates?: boolean;\n\n /**\n * Callback when user saves changes -- only fired if data actually changed.\n *\n * - `data`: complete form data (all fields, _fid stripped)\n * - `changedFields`: only fields that differ from the original baseline,\n * useful for PATCH-style APIs with exclude_unset semantics (_fid stripped)\n * - `diff`: structured diff classifying each change as value/array add/remove/move/modify.\n * Array item changes carry `fid` tokens for correlation; these are form-internal\n * and are never sent to the server.\n */\n onUpdate?: (\n data: Record<string, any>,\n changedFields: Record<string, any>,\n diff: FormDiff,\n ) => void;\n\n /** Callback when user clicks Cancel */\n onCancel?: () => void;\n\n /** Disable all fields */\n disabled?: boolean;\n\n /** Read-only mode — fields are not editable */\n readOnly?: boolean;\n\n /** Show Save/Cancel action buttons */\n showActions?: boolean;\n\n /**\n * Allow Save when the form is pristine (no changes vs the baseline). Set for\n * CREATE forms, where submitting default / empty values is valid -- the\n * \"must have changed something\" dirty-check is an edit-only concept. Required-\n * field validation still applies. Default false (edit semantics).\n */\n allowPristineSave?: boolean;\n\n /**\n * Optional resolver for non-local `$ref`s (schema-registry id / canonical\n * URI). Tried before the in-document `$defs` fallback. Synchronous -- the\n * caller pre-loads referenced schemas into a map and passes a lookup.\n */\n refResolver?: RefResolver;\n\n /**\n * When to reveal field validation errors. Overrides the app-wide default set\n * in SonnetConfigProvider globals. Defaults to `onSubmit`.\n */\n validationDisplay?: ValidationDisplay;\n\n /**\n * Whether Save is available while the form is invalid. Overrides the app-wide\n * default set in SonnetConfigProvider globals. Defaults to `reveal` (Save\n * stays enabled; an invalid click reveals errors and does not submit).\n */\n saveWhenInvalid?: SaveWhenInvalid;\n\n /** Label for Save button (default: \"Save\") */\n saveLabel?: string;\n\n /** Label for Cancel button (default: \"Cancel\") */\n cancelLabel?: string;\n\n /** Show the Cancel button (default: true) */\n showCancel?: boolean;\n\n /**\n * Optional content rendered left-aligned in the Save/Cancel action row\n * (only when showActions=true), e.g. a secondary action like \"Test connection\".\n */\n leadingActions?: React.ReactNode;\n\n /** Show extra properties card (default: true) */\n showExtraProperties?: boolean;\n\n /** Widget registry for custom widgets (default: DEFAULT_WIDGETS) */\n widgets?: WidgetRegistry;\n\n /**\n * Template registry for custom layout templates (default: DEFAULT_TEMPLATES).\n *\n * Templates control structural rendering (array item rows, object containers).\n * Widgets control input rendering. Override specific templates by providing\n * a partial registry -- unspecified keys fall back to DEFAULT_TEMPLATES.\n */\n templates?: TemplateRegistry;\n\n /**\n * Custom validator registry -- named field and form validators referenced\n * from the schema via `x-ui-validate`, run alongside the built-in schema\n * validation. `field`/`form` are synchronous; `asyncField`/`asyncForm`\n * return a promise and gate Save while in flight. See\n * docs/design/custom-validation.md.\n */\n validators?: ValidatorRegistry;\n\n /**\n * Externally-supplied errors (e.g. a server 422) shown as persistent field\n * errors, keyed by JSON Pointer. Always displayed regardless of\n * `validationDisplay`, and block Save. Should be stable/memoized. A\n * higher-precedence error (built-in or a custom validator) on the same field\n * wins over an extraError. See the custom-validation design.\n */\n extraErrors?: FieldError[];\n\n /**\n * When true, renders with `display: contents` instead of a SimpleStack.\n *\n * Used by ObjectWidget when it is a direct child of a HorizontalArrayItemTemplate\n * row grid. `display: contents` makes this renderer's wrapper invisible to the\n * layout algorithm so each field div becomes a direct grid cell in the row.\n */\n displayContents?: boolean;\n\n /**\n * UISchema for customizing widget behavior and appearance.\n *\n * @example\n * ```typescript\n * uiSchema={{\n * 'x-ui-globalOptions': { label: false },\n * 'x-ui-order': ['email', 'name'],\n * name: { 'x-ui-widget': 'textarea' },\n * }}\n * ```\n */\n uiSchema?: { [fieldName: string]: UISchema };\n\n /**\n * Prefix for generated field control ids: `<idPrefix>-<fieldName>` (default\n * \"field\"). Set a distinct prefix per form when rendering multiple forms on\n * one page to avoid duplicate DOM ids.\n */\n idPrefix?: string;\n};\n\nexport function JsonSchemaFormRenderer(\n props: JsonSchemaFormRendererProps,\n): React.ReactElement {\n const {\n schema,\n data,\n onChange,\n onBlur,\n onValidationChange,\n onUpdate,\n onCancel,\n templates,\n validators,\n leadingActions,\n idPrefix = \"field\",\n } = props;\n\n // Read the enclosing NestedFormContext exactly once: a nested sub-form\n // renders inside one, the outermost renderer does not. `isRootForm` gates\n // root-only concerns (running whole-form/cross-field validators); `rootData`\n // (derived from this same value below, once displayData exists) is what\n // those validators and x-ui-rule scopes resolve against.\n const nestedFormContext = useContext(NestedFormContext);\n const isRootForm = nestedFormContext === null;\n\n const {\n disabled,\n readOnly,\n showActions,\n deferChanges,\n deferStateUpdates,\n showCancel,\n showExtraProperties,\n displayContents,\n allowPristineSave,\n } = resolveFlagDefaults(props);\n\n const { saveLabel, cancelLabel, widgets, uiSchema } =\n resolveValueDefaults(props);\n\n const { wrappedOnChange, wrappedOnBlur, wrappedOnUpdate } =\n useWrappedCallbacks(onChange, onBlur, onUpdate, isRootForm);\n\n const {\n formData,\n displayData,\n resolvedSchema,\n orderedProperties,\n hasChanges,\n isValid,\n isValidating,\n fieldErrors,\n touched,\n submitAttempted,\n handleFieldChange,\n handleFieldBlur,\n handleSave,\n handleCancel,\n } = useFormEngine({\n schema,\n data,\n uiSchema,\n onChange: wrappedOnChange,\n onBlur: wrappedOnBlur,\n onValidationChange,\n onUpdate: wrappedOnUpdate,\n onCancel,\n readOnly,\n showActions,\n deferChanges,\n deferStateUpdates,\n allowPristineSave,\n refResolver: props.refResolver,\n extraErrors: props.extraErrors,\n validators,\n isRoot: isRootForm,\n });\n\n // Global options for all fields. A container-level x-ui-layout.labelPlacement\n // is folded in here so it is inherited by the container's fields (a field's\n // own x-ui-options.labelPlacement still wins via mergeFieldOptions).\n const layoutLabelPlacement = (\n uiSchema[\"x-ui-layout\"] as UILayoutConfig | undefined\n )?.labelPlacement;\n const globalOptions: UISchemaOptions = useMemo(\n () => ({\n ...(layoutLabelPlacement ? { labelPlacement: layoutLabelPlacement } : {}),\n ...((uiSchema[\"x-ui-globalOptions\"] as UISchemaOptions) || {}),\n }),\n [layoutLabelPlacement, uiSchema],\n );\n\n // Merge caller-supplied templates over the defaults. Callers only need\n // to provide the templates they want to override.\n const resolvedTemplates = useMemo(\n () => ({ ...DEFAULT_TEMPLATES, ...templates }),\n [templates],\n );\n\n // Provide renderer + templates to nested widgets via context so they can\n // render sub-forms and resolve layout templates without circular imports.\n // The `displayContents` prop is forwarded from the call site (ObjectWidget)\n // when this renderer is inside a horizontal array row grid.\n const nestedRenderer = useCallback<NestedRenderer>(\n (props) => (\n <JsonSchemaFormRenderer\n {...props}\n templates={resolvedTemplates}\n validators={validators}\n showActions={false}\n showExtraProperties={false}\n />\n ),\n [resolvedTemplates, validators],\n );\n\n const rootData = rootFormData(nestedFormContext, displayData);\n\n // A nested sub-form has its own submitAttempted that the root's Save never\n // flips; inherit the root's so a required field inside a nested object\n // reveals its error on submit (see rootSubmitAttempted).\n const effectiveSubmitAttempted = rootSubmitAttempted(\n nestedFormContext,\n submitAttempted,\n );\n\n const contextValue = useMemo(\n () => ({\n renderer: nestedRenderer,\n templates: resolvedTemplates,\n rootData,\n submitAttempted: effectiveSubmitAttempted,\n }),\n [nestedRenderer, resolvedTemplates, rootData, effectiveSubmitAttempted],\n );\n\n const validationDisplay = useValidationDisplay(props.validationDisplay);\n const saveWhenInvalid = useSaveWhenInvalid(props.saveWhenInvalid);\n const needsBlurHandler = blurHandlerNeeded({\n deferStateUpdates,\n deferChanges,\n hasOnBlur: !!onBlur,\n validationDisplay,\n });\n const showFieldErrors = useCallback(\n (fieldName: string): boolean =>\n fieldErrorsVisible(\n validationDisplay,\n effectiveSubmitAttempted,\n touched[fieldName],\n ),\n [validationDisplay, effectiveSubmitAttempted, touched],\n );\n\n // Memoize the rendered field list so the row-layout memo below has a stable\n // dependency. orderedProperties changes only when schema/uiSchema/data change.\n const fields = useMemo(\n () =>\n orderedProperties.flatMap(([fieldName, property]) => {\n // Declarative presentation rule (x-ui-rule): uiSchema entry wins over\n // the schema property. Evaluated against the ROOT form data, so a\n // nested field's rule may reference any field by its pointer from the\n // top of the form -- not merely its own object's slice.\n const rule =\n uiSchema[fieldName]?.[\"x-ui-rule\"] ?? property[\"x-ui-rule\"];\n const { visible, enabled } = evaluateUiRule(rule, rootData);\n if (!visible) return [];\n return [\n <FormFieldRenderer\n key={fieldName}\n fieldName={fieldName}\n property={property}\n value={displayData[fieldName]}\n onChange={(v) => handleFieldChange(fieldName, v)}\n onBlur={\n needsBlurHandler ? () => handleFieldBlur(fieldName) : undefined\n }\n required={isFieldRequired(resolvedSchema, fieldName)}\n disabled={disabled || !enabled}\n readOnly={readOnly}\n schema={schema}\n uiSchema={uiSchema[fieldName]}\n registry={widgets}\n globalOptions={globalOptions}\n formData={displayData}\n idPrefix={idPrefix}\n rawErrors={fieldRawErrors(\n fieldName,\n fieldErrors,\n props.extraErrors,\n showFieldErrors(fieldName),\n )}\n />,\n ];\n }),\n [\n orderedProperties,\n displayData,\n rootData,\n resolvedSchema,\n disabled,\n readOnly,\n schema,\n uiSchema,\n widgets,\n globalOptions,\n idPrefix,\n needsBlurHandler,\n showFieldErrors,\n fieldErrors,\n props.extraErrors,\n handleFieldChange,\n handleFieldBlur,\n ],\n );\n\n // Read row/tab layout config from the uiSchema.\n const layoutConfig = uiSchema[\"x-ui-layout\"] as UILayoutConfig | undefined;\n const rowDefs = layoutConfig?.rows;\n const groupDefs = layoutConfig?.groups;\n // Default gap used within rows when no per-row gap is specified.\n const defaultRowGap = layoutConfig?.gap ?? 24;\n\n const groupTemplate = resolveGroupTemplate(\n resolvedTemplates,\n layoutConfig?.variant,\n );\n\n // Groups take precedence over flat rows (each group carries its own rows).\n // When neither is configured, fields render as a plain vertical stack. Fields\n // not placed by the active layout are appended so nothing is hidden.\n const layoutFields = useMemo(() => {\n if (groupDefs && groupDefs.length > 0) {\n return layoutFieldsInGroups(\n fields,\n groupDefs,\n defaultRowGap,\n fieldErrors,\n // Tab rules are x-ui-rule too: root-anchored like field rules.\n rootData,\n groupTemplate,\n );\n }\n if (rowDefs && rowDefs.length > 0) {\n return layoutFieldsInRows(fields, rowDefs, defaultRowGap);\n }\n return fields;\n }, [\n fields,\n rowDefs,\n groupDefs,\n defaultRowGap,\n fieldErrors,\n rootData,\n groupTemplate,\n ]);\n\n // Errors the user cannot see because their tab is hidden. Surfaced next to\n // the actions so a disabled Save always has a visible explanation.\n const hiddenErrorCount = useMemo(() => {\n if (!groupDefs?.length || fieldErrors.length === 0) return 0;\n const hidden = hiddenGroupFieldNames(groupDefs, rootData);\n if (hidden.size === 0) return 0;\n return fieldErrors.filter((e) => hidden.has(pointerRoot(e.pointer))).length;\n }, [groupDefs, fieldErrors, rootData]);\n\n // Form-level errors (pointer \"\") from form validators belong to no field, so\n // there is no \"touched\" field to gate them: reveal them on a save attempt (or\n // when the policy is \"always\"), matching how required errors surface.\n const formLevelErrors = useMemo(() => {\n if (validationDisplay !== \"always\" && !submitAttempted) return [];\n return fieldErrors.filter((e) => e.pointer === \"\").map((e) => e.message);\n }, [fieldErrors, validationDisplay, submitAttempted]);\n\n return (\n <NestedFormContext.Provider value={contextValue}>\n <FormContainer\n displayContents={displayContents}\n showExtraProperties={showExtraProperties}\n showActions={showActions}\n formData={formData}\n resolvedSchema={resolvedSchema}\n handleSave={handleSave}\n handleCancel={handleCancel}\n disabled={disabled}\n hasChanges={hasChanges || allowPristineSave}\n isValid={isValid}\n isValidating={isValidating}\n saveWhenInvalid={saveWhenInvalid}\n saveLabel={saveLabel}\n cancelLabel={cancelLabel}\n showCancel={showCancel}\n leadingActions={leadingActions}\n hiddenErrorCount={hiddenErrorCount}\n formLevelErrors={formLevelErrors}\n >\n {layoutFields}\n </FormContainer>\n </NestedFormContext.Provider>\n );\n}\n","/**\n * Widget Type System\n *\n * Type definitions for the JSON Schema Form widget architecture.\n * Based on react-jsonschema-form patterns with simplified Mantine-focused implementation.\n */\n\nimport {\n JsonSchema,\n JsonSchemaProperty,\n UISchema,\n UILayoutConfig,\n UISchemaOptions,\n} from \"@petrarca/sonnet-core/schema\";\nimport { ComponentType } from \"react\";\n\n// Re-export for convenience\nexport type {\n UISchema,\n UISchemaOptions,\n UILayoutConfig,\n} from \"@petrarca/sonnet-core/schema\";\n\n/**\n * WidgetRegistry - Map of widget name to component\n *\n * @example\n * ```typescript\n * const registry: WidgetRegistry = {\n * TextWidget: TextWidget,\n * SelectWidget: SelectWidget,\n * CustomWidget: MyCustomWidget\n * }\n * ```\n */\nexport type WidgetRegistry = {\n [widgetName: string]: Widget;\n};\n\n/**\n * WidgetProps - Props passed to every widget\n *\n * Widgets receive comprehensive context to make intelligent decisions.\n * All widgets must accept these props.\n *\n * @example\n * ```typescript\n * export function MyWidget({\n * id,\n * value,\n * onChange,\n * label,\n * propertySchema,\n * options\n * }: WidgetProps) {\n * const customOption = options?.myCustomOption ?? 'default';\n * // ...\n * }\n * ```\n */\nexport interface WidgetProps {\n // Identification\n /** Unique field ID */\n id: string;\n /** Field name */\n name: string;\n\n // Schema Context - Full access to make informed decisions\n /** Full form schema */\n schema: JsonSchema;\n /** This field's schema */\n propertySchema: JsonSchemaProperty;\n /** UI configuration for this field */\n uiSchema?: UISchema;\n /** Access to all widgets */\n registry: WidgetRegistry;\n\n // Data & Events\n /** Current field value */\n value: unknown;\n /** Called when value changes */\n onChange: (value: unknown) => void;\n /** Called when field loses focus */\n onBlur?: (id: string, value: unknown) => void;\n /** Called when field gains focus */\n onFocus?: (id: string, value: unknown) => void;\n\n // Form Context\n /** Current form data - all field values (for dependent/cascading widgets) */\n formData?: Record<string, unknown>;\n\n // Display\n /** Field label (empty string = hidden) */\n label: string;\n /** Field description */\n description?: string;\n /** Placeholder text */\n placeholder?: string;\n\n // State\n /** Is field required */\n required?: boolean;\n /** Is field disabled */\n disabled?: boolean;\n /** Is field readonly */\n readonly?: boolean;\n /** Should field autofocus */\n autofocus?: boolean;\n\n // Validation\n /** Raw validation errors */\n rawErrors?: string[];\n\n // Options - Widget accesses x-ui-options for any configuration it needs\n /** Widget-specific options from x-ui-options */\n options?: UISchemaOptions;\n}\n\n/**\n * Widget - React component type for form widgets\n *\n * @example\n * ```typescript\n * const TextWidget: Widget = ({ id, value, onChange, label }) => (\n * <TextInput id={id} value={value} onChange={e => onChange(e.target.value)} label={label} />\n * );\n * ```\n */\nexport type Widget = ComponentType<WidgetProps>;\n\n/**\n * WidgetDescriptor - Extended information for widget registration\n *\n * Allows providing metadata along with the widget component.\n *\n * @example\n * ```typescript\n * const descriptor: WidgetDescriptor = {\n * component: MyWidget,\n * displayName: 'My Custom Widget',\n * description: 'A widget for custom input',\n * defaultOptions: { rows: 3 }\n * }\n * ```\n */\nexport interface WidgetDescriptor {\n /** The widget component */\n component: Widget;\n /** Display name for debugging */\n displayName?: string;\n /** Description of what the widget does */\n description?: string;\n /** Default options to apply */\n defaultOptions?: UISchemaOptions;\n}\n\n/**\n * WidgetMap - Type/format to widget name mapping\n *\n * Defines the default widget to use for each schema type and format.\n *\n * @example\n * ```typescript\n * const map: WidgetMap = {\n * string: {\n * default: 'TextWidget',\n * email: 'EmailWidget',\n * textarea: 'TextareaWidget'\n * }\n * }\n * ```\n */\nexport type WidgetMap = {\n [schemaType: string]: {\n [variantOrFormat: string]: string;\n };\n};\n\n/**\n * Return the first validation error message, or undefined if there are none.\n * Avoids repeating `rawErrors && rawErrors.length > 0 ? rawErrors[0] : undefined`\n * in every widget.\n */\nexport function firstError(rawErrors?: string[]): string | undefined {\n return rawErrors && rawErrors.length > 0 ? rawErrors[0] : undefined;\n}\n\n/**\n * SelectOption - Single option in a select dropdown\n */\nexport interface SelectOption {\n value: string;\n label: string;\n}\n\n// Templates -- rendering functions for structural layout concerns.\n// Separate from widgets (which render input controls).\n// Injected via JsonSchemaFormRenderer's `templates` prop or per-field\n// via x-ui-options.itemTemplate / x-ui-options.containerTemplate.\n\n/** Props passed to an ArrayItemTemplate */\nexport interface ArrayItemTemplateProps {\n children: React.ReactNode;\n index: number;\n total: number;\n canRemove: boolean;\n orderable: boolean;\n disabled?: boolean;\n layout: UILayoutConfig;\n fieldCount: number;\n /**\n * Stable form-internal item id (_fid). Rendered as `data-fid` on the item\n * container so tests can target a specific item across reorders (the\n * positional `index` is not stable).\n */\n fid?: string;\n onRemove: () => void;\n onMoveUp?: () => void;\n onMoveDown?: () => void;\n}\n\n/** Props passed to an ArrayHeaderTemplate */\nexport interface ArrayHeaderTemplateProps {\n itemSchema: JsonSchemaProperty;\n layout: UILayoutConfig;\n canRemove: boolean;\n orderable: boolean;\n fieldCount: number;\n}\n\n/** Props passed to an ObjectContainerTemplate */\nexport interface ObjectContainerTemplateProps {\n children: React.ReactNode;\n label: string;\n description?: string;\n variant?: string;\n defaultOpen?: boolean;\n}\n\n/**\n * One group of fields in a grouped layout (a tab, a wizard step, a section).\n * `content` is already laid out -- the template only decides how groups are\n * presented and navigated.\n */\nexport interface FieldGroup {\n /** Stable key for React and for the template's own selection state. */\n key: string;\n /** Label shown on the group's trigger, step header or section legend. */\n label: string;\n /** The group's rendered rows. */\n content: React.ReactNode;\n /** Validation errors owned by this group's fields (for a badge). */\n errorCount: number;\n}\n\n/** Props passed to a GroupLayoutTemplate */\nexport interface GroupLayoutTemplateProps {\n /** The visible groups, in declaration order. Never empty. */\n groups: FieldGroup[];\n}\n\n/**\n * Presents a set of field groups: as tabs, as a wizard, as an accordion --\n * whatever the registered template renders. Selected by\n * `x-ui-layout.variant`, which maps to a TemplateRegistry key, so consumers\n * can register their own presentation without changing the renderer.\n */\nexport type GroupLayoutTemplate = (\n props: GroupLayoutTemplateProps,\n) => React.ReactElement;\n\nexport type ArrayItemTemplate = (\n props: ArrayItemTemplateProps,\n) => React.ReactElement;\n\nexport type ArrayHeaderTemplate = (\n props: ArrayHeaderTemplateProps,\n) => React.ReactElement | null;\n\nexport type ObjectContainerTemplate = (\n props: ObjectContainerTemplateProps,\n) => React.ReactElement;\n\n/**\n * TemplateRegistry -- named rendering functions for structural layout.\n *\n * Built-in keys: ArrayItemTemplate, ArrayHeaderTemplate, ObjectContainerTemplate.\n * Custom keys are allowed for per-field template overrides (looked up by name).\n * The index signature uses `unknown` to avoid TypeScript variance conflicts with\n * the specifically-typed named properties.\n */\nexport type TemplateRegistry = {\n ArrayItemTemplate?: ArrayItemTemplate;\n HorizontalArrayItemTemplate?: ArrayItemTemplate;\n ArrayHeaderTemplate?: ArrayHeaderTemplate;\n ObjectContainerTemplate?: ObjectContainerTemplate;\n /** Group presentations, selected by x-ui-layout.variant (default \"tabs\"). */\n TabsGroupTemplate?: GroupLayoutTemplate;\n StepperGroupTemplate?: GroupLayoutTemplate;\n SectionsGroupTemplate?: GroupLayoutTemplate;\n [templateName: string]: unknown;\n};\n","/**\n * TextInputWidget - Standard text input widget\n *\n * Renders a single-line text input field using FormInput.\n * Supports various input types via format (email, url, text).\n */\n\nimport { FormInput } from \"../FormInput\";\nimport { WidgetProps, firstError } from \"./types\";\n\n// Determine HTML input type based on JSON Schema format.\nfunction inputTypeFromFormat(format: string | undefined): string {\n if (format === \"email\") return \"email\";\n if (format === \"uri\" || format === \"url\") return \"url\";\n return \"text\";\n}\n\n/**\n * TextInputWidget renders a standard text input field.\n *\n * Supports:\n * - Basic string input\n * - Email input (format: 'email')\n * - URL input (format: 'uri' or 'url')\n * - Validation constraints (minLength, maxLength, pattern)\n */\nexport function TextInputWidget({\n id,\n name,\n value,\n onChange,\n onBlur,\n propertySchema,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n placeholder,\n autofocus,\n options,\n}: WidgetProps): React.ReactElement {\n const error = firstError(rawErrors);\n const compact = options?.compact;\n\n return (\n <FormInput\n id={id}\n name={name}\n value={value !== undefined && value !== null ? String(value) : \"\"}\n onChange={(event) => onChange(event.currentTarget.value)}\n onBlur={() => onBlur?.(id, value)}\n label={label}\n labelPlacement={options?.labelPlacement}\n description={description}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n type={options?.inputType ?? inputTypeFromFormat(propertySchema.format)}\n minLength={propertySchema.minLength}\n maxLength={propertySchema.maxLength}\n autoFocus={autofocus}\n compact={compact as boolean | undefined}\n className={compact ? \"h-8 text-xs\" : undefined}\n />\n );\n}\n","/**\n * TextareaWidget - Multi-line text input\n *\n * Renders a multi-line textarea field using FormTextarea.\n * Supports autosize and configurable rows.\n */\n\nimport { FormTextarea } from \"../FormTextarea\";\nimport { WidgetProps, firstError } from \"./types\";\n\n/**\n * TextareaWidget renders a multi-line text input field.\n *\n * Supports:\n * - Multi-line text input\n * - Autosize functionality\n * - Configurable minimum rows via x-ui-options\n * - Validation constraints (minLength, maxLength)\n *\n * @param props - WidgetProps\n */\nexport function TextareaWidget({\n id,\n name,\n value,\n onChange,\n onBlur,\n propertySchema,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n placeholder,\n autofocus,\n options = {},\n}: WidgetProps) {\n const minRows = options.rows || options.minRows || 3;\n const autosize = options.autosize !== false; // Default to true\n\n const error = firstError(rawErrors);\n\n return (\n <FormTextarea\n id={id}\n name={name}\n value={value !== undefined && value !== null ? String(value) : \"\"}\n onChange={(event) => onChange(event.currentTarget.value)}\n onBlur={() => onBlur?.(id, value)}\n label={label}\n labelPlacement={options?.labelPlacement}\n description={description}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n minRows={minRows}\n autosize={autosize}\n minLength={propertySchema.minLength}\n maxLength={propertySchema.maxLength}\n autoFocus={autofocus}\n />\n );\n}\n","/**\n * NumberWidget - Number/Integer input widget\n *\n * Renders a number input field using FormNumberInput.\n * Handles both number and integer types with appropriate step values.\n */\n\nimport { FormNumberInput } from \"../FormNumberInput\";\nimport { WidgetProps, firstError } from \"./types\";\n\n/**\n * NumberWidget renders a number input field.\n *\n * Supports:\n * - Number input (decimal allowed)\n * - Integer input (step = 1, no decimals)\n * - Min/max constraints from schema\n * - Step configuration via x-ui-options\n *\n * @param props - WidgetProps\n */\nexport function NumberWidget({\n id,\n name,\n value,\n onChange,\n onBlur,\n propertySchema,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n placeholder,\n autofocus,\n options = {},\n}: WidgetProps) {\n const isInteger = propertySchema.type === \"integer\";\n const step = options.step ?? (isInteger ? 1 : undefined);\n const allowDecimal = options.allowDecimal ?? !isInteger;\n\n const error = firstError(rawErrors);\n\n return (\n <FormNumberInput\n id={id}\n name={name}\n value={value !== undefined && value !== null ? Number(value) : undefined}\n onChange={(val) => onChange(val)}\n onBlur={() => onBlur?.(id, value)}\n label={label}\n labelPlacement={options.labelPlacement}\n description={description}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n min={propertySchema.minimum}\n max={propertySchema.maximum}\n step={step}\n allowDecimal={allowDecimal}\n autoFocus={autofocus}\n />\n );\n}\n","/**\n * CheckboxWidget - Boolean checkbox widget\n *\n * Renders a checkbox input using FormCheckbox.\n * Used for boolean type fields.\n *\n * Supports tri-state behavior for nullable boolean fields (anyOf[boolean, null]):\n * - null or no value (indeterminate) -> true (checked) -> false (unchecked) -> null\n * No value is shown as null is: not answered -- unchecked would read as \"no\".\n */\n\nimport { useCallback } from \"react\";\nimport { FormCheckbox } from \"../FormCheckbox\";\nimport { isNullableBoolean } from \"@petrarca/sonnet-core/schema\";\nimport { WidgetProps, firstError } from \"./types\";\n\n/**\n * CheckboxWidget renders a checkbox for boolean values.\n *\n * Supports:\n * - Boolean true/false values (standard checkbox)\n * - Tri-state true/false/null values (indeterminate checkbox)\n * - Custom labels from schema or UISchema\n * - Description text\n *\n * Tri-state behavior (when anyOf[boolean, null] is detected):\n * - Click on null, or no value -> becomes true\n * - Click on true -> becomes false\n * - Click on false -> becomes null\n */\nexport function CheckboxWidget({\n id,\n value,\n onChange,\n onBlur,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n autofocus,\n propertySchema,\n options,\n}: WidgetProps): React.ReactElement {\n const error = firstError(rawErrors);\n const compact = options?.compact;\n\n // Detect if this is a nullable boolean (tri-state)\n const isTriState = isNullableBoolean(propertySchema);\n\n // Determine checkbox state\n const isChecked = value === true;\n // Not answered -- null, or no value at all -- is neither yes nor no.\n const isIndeterminate = isTriState && value == null;\n const checkedState: boolean | \"indeterminate\" = isIndeterminate\n ? \"indeterminate\"\n : isChecked;\n\n // Handle change with tri-state logic\n const handleChange = useCallback(\n (_newChecked: boolean | \"indeterminate\") => {\n if (isTriState) {\n if (value == null) {\n onChange(true);\n } else if (value === true) {\n onChange(false);\n } else {\n onChange(null);\n }\n } else {\n onChange(_newChecked === true);\n }\n },\n [isTriState, value, onChange],\n );\n\n return (\n <FormCheckbox\n id={id}\n checked={checkedState}\n onChange={handleChange}\n onBlur={() => onBlur?.(id, value)}\n label={label}\n description={description}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n autoFocus={autofocus}\n compact={compact as boolean | undefined}\n />\n );\n}\n","/**\n * SelectWidget - Dropdown selection widget\n *\n * Renders a dropdown select field using FormSelect or FormMultiSelect.\n * Used for enum fields with a list of predefined options.\n * Supports both single-select (returns string) and multi-select (returns array) modes.\n */\n\nimport { useRef } from \"react\";\nimport { FormSelect } from \"../FormSelect\";\nimport { FormMultiSelect } from \"../FormMultiSelect\";\nimport { buildSelectOptions } from \"../formSelectUtils\";\nimport { badgeVariants } from \"@petrarca/sonnet-ui\";\nimport type { VariantProps } from \"class-variance-authority\";\nimport { WidgetProps, firstError } from \"./types\";\n\ntype BadgeColor = NonNullable<VariantProps<typeof badgeVariants>[\"badgeColor\"]>;\n\n/**\n * SelectWidget renders a dropdown select for enum values.\n *\n * Supports:\n * - Enum values from schema\n * - Custom display names via x-ui-options.enumNames\n * - Searchable dropdown\n * - Clearable option (when not required)\n * - Multi-select mode (auto-detected from schema type='array' or explicit multiple option)\n * - Custom badge colors for multi-select mode\n *\n * @param props - WidgetProps\n */\n/** Normalize a value into a string array for multi-select. */\nfunction normalizeMultiValue(value: unknown): string[] {\n if (Array.isArray(value)) return value.map(String);\n if (value) return [String(value)];\n return [];\n}\n\n/** Normalize a value into a string or null for single-select. */\nfunction normalizeSingleValue(value: unknown): string | null {\n if (value !== undefined && value !== null) return String(value);\n return null;\n}\n\nexport function SelectWidget(props: WidgetProps) {\n const {\n id,\n name,\n value,\n onChange,\n onBlur,\n propertySchema,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n placeholder,\n autofocus,\n } = props;\n const widgetOptions = props.options ?? {};\n\n const valueRef = useRef(value);\n valueRef.current = value;\n\n const enumNames = widgetOptions.enumNames || {};\n const clearable = widgetOptions.clearable !== false && !required;\n const isMultiple = widgetOptions.multiple ?? propertySchema.type === \"array\";\n const creatable = !!widgetOptions.creatable;\n const selectOptions = buildSelectOptions(propertySchema, enumNames);\n const error = firstError(rawErrors);\n const compact = widgetOptions?.compact;\n const triggerClassName = compact ? \"h-8 text-xs\" : undefined;\n const handleBlur = () => onBlur?.(id, valueRef.current);\n\n if (isMultiple) {\n return (\n <FormMultiSelect\n id={id}\n name={name}\n options={selectOptions}\n value={normalizeMultiValue(value)}\n onChange={(newValue) => onChange(newValue || [])}\n label={label}\n labelPlacement={widgetOptions.labelPlacement}\n description={description}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n clearable={clearable}\n autoFocus={autofocus}\n badgeColor={widgetOptions.badgeColor as BadgeColor | undefined}\n onBlur={handleBlur}\n className={triggerClassName}\n />\n );\n }\n\n return (\n <FormSelect\n id={id}\n name={name}\n options={selectOptions}\n value={normalizeSingleValue(value)}\n onChange={(val) => onChange(val || \"\")}\n label={label}\n labelPlacement={widgetOptions.labelPlacement}\n description={description}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n clearable={clearable}\n autoFocus={autofocus}\n onBlur={handleBlur}\n className={triggerClassName}\n compact={compact}\n allowCreate={creatable}\n onCreate={(label) => onChange(label)}\n />\n );\n}\n","/**\n * TagsInputWidget - Free-text tag input widget\n *\n * Renders FormTagsInput for array-of-string fields where the user types\n * free-text values (no predefined enum). Tags are entered by pressing\n * Enter or comma and displayed as dismissible badges. Duplicates are\n * rejected by default.\n *\n * Use via x-ui-widget: \"tags\" in a JSON Schema or Zod .meta().\n */\n\nimport React from \"react\";\nimport { FormTagsInput } from \"../FormTagsInput\";\nimport { type WidgetProps, firstError } from \"./types\";\n\n/**\n * TagsInputWidget renders a free-text tag input field.\n *\n * Supports:\n * - Free-text tag creation (Enter or comma)\n * - Duplicate rejection (default)\n * - Max tags limit (via x-ui-options.maxTags)\n * - Custom split keys (via x-ui-options.splitKeys)\n */\nexport function TagsInputWidget({\n id,\n name,\n value,\n onChange,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n placeholder,\n options,\n}: WidgetProps): React.ReactElement {\n const error = firstError(rawErrors);\n const tags = Array.isArray(value) ? value.map(String) : [];\n\n return (\n <FormTagsInput\n id={id}\n name={name}\n value={tags}\n onChange={(newTags) => onChange(newTags)}\n label={label}\n labelPlacement={options?.labelPlacement}\n description={description}\n placeholder={placeholder ?? \"Type and press Enter\"}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n error={error}\n maxTags={options?.maxTags as number | undefined}\n splitKeys={options?.splitKeys as string[] | undefined}\n allowDuplicates={false}\n />\n );\n}\n","/**\n * JsonEditorWidget - JSON document editor widget.\n *\n * Renders JsonEditor for object/any fields where the user authors raw JSON.\n * The full document is editable. Invalid JSON is not propagated -- the last\n * valid value is retained until the user fixes the syntax error.\n *\n * Use via x-ui-widget: \"json-editor\" in a JSON Schema or Zod .meta().\n */\n\nimport React, { Suspense, lazy, useCallback, useState } from \"react\";\nimport { type WidgetProps } from \"./types\";\n\n// The editor (CodeMirror) loads when a form first shows a JSON field, so a\n// form without one -- and an app's startup -- never fetches it.\nconst JsonEditor = lazy(() =>\n import(\"@petrarca/sonnet-ui/json-editor\").then((m) => ({\n default: m.JsonEditor,\n })),\n);\n\n// Single editable path covering the full document.\nconst FULL_DOCUMENT: string[] = [\"/\"];\n\n/**\n * JsonEditorWidget renders a full-document JSON editor.\n *\n * Supports:\n * - Full document editing (no readonly regions)\n * - Invalid JSON is silently retained until fixed\n * - Height configurable via x-ui-options.height (default: \"240px\")\n * - The editor loads on first use (a placeholder of that height meanwhile)\n */\nexport function JsonEditorWidget({\n id,\n value,\n onChange,\n label,\n description,\n required,\n options,\n}: WidgetProps): React.ReactElement {\n const [raw, setRaw] = useState(\n value != null ? JSON.stringify(value, null, 2) : \"\",\n );\n\n const height = (options?.height as string | undefined) ?? \"240px\";\n\n const handleChange = useCallback(\n (val: string) => {\n setRaw(val);\n try {\n const parsed: unknown = JSON.parse(val);\n onChange(parsed);\n } catch {\n // Hold the last valid value -- do not propagate invalid JSON.\n }\n },\n [onChange],\n );\n\n return (\n <div className=\"space-y-2\">\n {label && (\n <label htmlFor={id} className=\"text-sm font-medium leading-none\">\n {label}\n {required && <span className=\"text-destructive ml-1\">*</span>}\n </label>\n )}\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n <Suspense\n fallback={\n <div\n className=\"rounded-md border bg-muted/30\"\n style={{ height }}\n aria-busy\n />\n }\n >\n <JsonEditor\n value={raw}\n editablePaths={FULL_DOCUMENT}\n onChange={handleChange}\n height={height}\n className=\"rounded-md border overflow-hidden\"\n />\n </Suspense>\n </div>\n );\n}\n","/**\n * KeyValueWidget - Key-value pair input widget\n *\n * Renders FormKeyValueInput for an object of string values (a free map such as\n * labels: `additionalProperties: { type: \"string\" }`, no declared properties).\n * Pairs are entered in a key and a value field and shown as \"key:value\" tags,\n * or -- `x-ui-options: { display: \"rows\" }` -- as rows edited in place, for long\n * values such as templates or paths, or -- `display: \"keys\"` -- only the keys,\n * a summary not edited. Chosen automatically for such maps;\n * explicitly via x-ui-widget: \"key-value\".\n */\n\nimport React from \"react\";\nimport { FormKeyValueInput } from \"../FormKeyValueInput\";\nimport { type WidgetProps, firstError } from \"./types\";\n\n// The display x-ui-options asks for; tags unless rows or keys.\nfunction displayOf(display: unknown): \"tags\" | \"rows\" | \"keys\" {\n return display === \"rows\" || display === \"keys\" ? display : \"tags\";\n}\n\n// The stored map as strings (a non-string value is shown as its text).\nfunction asStringMap(value: unknown): Record<string, string> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return {};\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).map(([k, v]) => [\n k,\n String(v),\n ]),\n );\n}\n\nexport function KeyValueWidget({\n id,\n name,\n value,\n onChange,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n options,\n}: WidgetProps): React.ReactElement {\n return (\n <FormKeyValueInput\n id={id}\n name={name}\n value={asStringMap(value)}\n onChange={(next) => onChange(next)}\n label={label}\n labelPlacement={options?.labelPlacement}\n description={description}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n error={firstError(rawErrors)}\n keyPlaceholder={options?.keyPlaceholder as string | undefined}\n valuePlaceholder={options?.valuePlaceholder as string | undefined}\n separator={options?.separator as string | undefined}\n display={displayOf(options?.display)}\n />\n );\n}\n","/**\n * EntitySelectWidget -- form widget for async entity reference selection.\n *\n * Wraps EntitySelect and adapts it to the WidgetProps contract. Reads\n * x-ui-options for fetcher configuration (REST or GraphQL) and uses the\n * FetcherProvider context to create the appropriate fetcher.\n *\n * Schema usage:\n * x-ui-widget: \"entity-select\"\n * x-ui-options: {\n * endpoint: \"/organizations\", // REST: relative to API base\n * valueKey: \"org_id\",\n * labelKey: \"name\",\n * }\n * -- or --\n * x-ui-options: {\n * query: \"query Orgs($search: String, $limit: Int) { ... }\",\n * dataPath: \"organizations\",\n * valueKey: \"org_id\",\n * labelKey: \"name\",\n * }\n */\n\nimport React, { useMemo } from \"react\";\nimport { EntitySelect } from \"@petrarca/sonnet-ui\";\nimport { useFetcherFactory } from \"@petrarca/sonnet-core/entityOptions\";\nimport type { EntitySelectMode } from \"@petrarca/sonnet-core/hooks\";\nimport type { WidgetProps, UISchemaOptions } from \"./types\";\nimport { firstError } from \"./types\";\nimport type {\n RestFetcherConfig,\n GraphqlFetcherConfig,\n} from \"@petrarca/sonnet-core/entityOptions\";\n\n// ---------------------------------------------------------------------------\n// Pure helpers\n// ---------------------------------------------------------------------------\n\nconst VALID_MODES: EntitySelectMode[] = [\"eager\", \"typeahead\", \"explicit\"];\n\n/** Resolve the select mode from widget options. */\nfunction resolveSelectMode(\n options: UISchemaOptions | undefined,\n): EntitySelectMode {\n const rawMode = options?.mode;\n if (\n typeof rawMode === \"string\" &&\n VALID_MODES.includes(rawMode as EntitySelectMode)\n ) {\n return rawMode as EntitySelectMode;\n }\n return \"eager\";\n}\n\n/** Resolve the minimum character threshold. */\nfunction resolveMinChars(options: UISchemaOptions | undefined): number {\n const rawMinChars = options?.minChars;\n if (typeof rawMinChars === \"number\" && rawMinChars >= 1) return rawMinChars;\n return 1;\n}\n\n/** Build a REST fetcher config from options. */\nfunction buildRestConfig(options: UISchemaOptions): RestFetcherConfig | null {\n if (!(\"endpoint\" in options) || !options.endpoint) return null;\n const rawExtra = options.extraParams;\n const extraParams =\n rawExtra && typeof rawExtra === \"object\"\n ? (rawExtra as Record<string, string>)\n : undefined;\n return {\n endpoint: String(options.endpoint),\n valueKey: String(options.valueKey ?? \"id\"),\n labelKey: String(options.labelKey ?? \"name\"),\n searchKey: options.searchKey ? String(options.searchKey) : undefined,\n extraParams,\n };\n}\n\n/** Build a GraphQL fetcher config from options. */\nfunction buildGraphqlConfig(\n options: UISchemaOptions,\n): GraphqlFetcherConfig | null {\n if (!(\"query\" in options) || !options.query) return null;\n return {\n query: String(options.query),\n dataPath: String(options.dataPath ?? \"\"),\n valueKey: String(options.valueKey ?? \"id\"),\n labelKey: String(options.labelKey ?? \"name\"),\n };\n}\n\n/** Build fetcher config from widget options. Returns null if insufficient config. */\nfunction buildFetcherConfig(\n options: UISchemaOptions | undefined,\n): RestFetcherConfig | GraphqlFetcherConfig | null {\n if (!options) return null;\n return buildRestConfig(options) ?? buildGraphqlConfig(options);\n}\n\n/** Derive a stable query key from the fetcher config. */\nfunction deriveQueryKey(\n config: RestFetcherConfig | GraphqlFetcherConfig | null,\n fallbackName: string,\n): string {\n if (!config) return fallbackName;\n if (\"endpoint\" in config) return config.endpoint;\n return `graphql:${config.dataPath}`;\n}\n\n// ---------------------------------------------------------------------------\n// EntitySelectWidget\n// ---------------------------------------------------------------------------\n\nexport function EntitySelectWidget({\n id,\n name,\n value,\n onChange,\n onBlur,\n label,\n description,\n placeholder,\n required,\n disabled,\n readonly,\n rawErrors,\n options,\n}: WidgetProps): React.ReactElement {\n const createFetcher = useFetcherFactory();\n\n const selectMode = resolveSelectMode(options);\n const selectMinChars = resolveMinChars(options);\n\n const fetcherConfig = useMemo(() => buildFetcherConfig(options), [options]);\n const fetcher = useMemo(() => {\n if (!fetcherConfig) return null;\n return createFetcher(fetcherConfig);\n }, [createFetcher, fetcherConfig]);\n const queryKey = useMemo(\n () => deriveQueryKey(fetcherConfig, name ?? \"\"),\n [fetcherConfig, name],\n );\n\n if (!fetcher) {\n return (\n <div className=\"text-sm text-destructive\">\n EntitySelectWidget: missing endpoint or query in x-ui-options for field\n &quot;{name}&quot;\n </div>\n );\n }\n\n return (\n <EntitySelect\n id={id}\n fetcher={fetcher}\n queryKey={queryKey}\n mode={selectMode}\n minChars={selectMinChars}\n value={typeof value === \"string\" ? value : null}\n onChange={(v) => onChange(v ?? null)}\n onBlur={() => onBlur?.(id, value)}\n label={label || false}\n description={description}\n placeholder={placeholder}\n required={required}\n clearable={!required}\n disabled={disabled || readonly}\n error={firstError(rawErrors)}\n />\n );\n}\n","/**\n * ObjectWidget -- renders a nested sub-form for type: \"object\" properties.\n *\n * Composes a JsonSchemaFormRenderer scoped to the sub-schema. The renderer\n * is injected via NestedFormContext so there is no circular import.\n *\n * Presentation is delegated to ObjectContainerTemplate (resolved from context,\n * defaulting to DefaultObjectContainerTemplate). The variant passed via\n * options controls which container is used (section, card, collapsible,\n * inline, borderless).\n *\n * When options.displayContents is true (set by ArrayWidget in horizontal mode)\n * the sub-renderer uses display:contents so its field divs become direct grid\n * cells in the parent row grid.\n *\n * When options.globalOptions is set, it is forwarded to the sub-renderer so\n * compact / label suppression propagates to all nested widgets.\n */\n\nimport { useMemo } from \"react\";\nimport type {\n JsonSchema,\n JsonSchemaProperty,\n UILayoutConfig,\n UISchema,\n} from \"@petrarca/sonnet-core/schema\";\nimport { useNestedFormContext } from \"../hooks/useNestedFormContext\";\nimport { DefaultObjectContainerTemplate } from \"../templates/DefaultObjectContainerTemplate\";\nimport type { WidgetProps } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Pure helpers\n// ---------------------------------------------------------------------------\n\n/** Build a JsonSchema from the property's nested structure. */\nfunction buildSubSchema(prop: JsonSchemaProperty): JsonSchema | null {\n const properties = prop.properties;\n if (!properties) return null;\n return {\n title: prop.title || \"\",\n type: \"object\",\n properties,\n required: prop.required,\n ...(prop.allOf ? { allOf: prop.allOf } : {}),\n ...(prop.if ? { if: prop.if } : {}),\n ...(prop.then ? { then: prop.then } : {}),\n ...(prop.else ? { else: prop.else } : {}),\n ...(prop[\"x-ui-order\"] ? { \"x-ui-order\": prop[\"x-ui-order\"] } : {}),\n };\n}\n\n/** Merge field-level uiSchema with globalOptions and layout for sub-renderer. */\nfunction buildEffectiveUiSchema(\n subUiSchema: { [fieldName: string]: UISchema },\n globalOptions: Record<string, unknown> | undefined,\n layout: UILayoutConfig | undefined,\n): { [fieldName: string]: UISchema } {\n return {\n ...subUiSchema,\n ...(globalOptions\n ? { \"x-ui-globalOptions\": globalOptions as UISchema }\n : {}),\n ...(layout ? { \"x-ui-layout\": layout as unknown as UISchema } : {}),\n };\n}\n\n/** Extract typed options from the generic options bag. */\nfunction resolveObjectOptions(options: WidgetProps[\"options\"]) {\n return {\n variant: (options?.variant as string) || \"section\",\n defaultOpen: options?.defaultOpen !== false,\n displayContents: (options?.displayContents as boolean) ?? false,\n globalOptions: options?.globalOptions as\n | Record<string, unknown>\n | undefined,\n };\n}\n\n/** Resolve layout from uiSchema and property schema. */\nfunction resolveLayout(\n uiSchema: WidgetProps[\"uiSchema\"],\n propertySchema: JsonSchemaProperty,\n): UILayoutConfig | undefined {\n return (\n (uiSchema?.[\"x-ui-layout\"] as UILayoutConfig | undefined) ??\n propertySchema[\"x-ui-layout\"]\n );\n}\n\n// ---------------------------------------------------------------------------\n// ObjectWidget\n// ---------------------------------------------------------------------------\n\nexport function ObjectWidget({\n id,\n propertySchema,\n value,\n onChange,\n onBlur,\n registry,\n uiSchema,\n disabled,\n readonly,\n label,\n description,\n options,\n}: WidgetProps): React.ReactElement | null {\n const { renderer: Renderer, templates } = useNestedFormContext();\n const ContainerTemplate =\n templates.ObjectContainerTemplate ?? DefaultObjectContainerTemplate;\n\n const subSchema = useMemo(\n () => buildSubSchema(propertySchema),\n [propertySchema],\n );\n\n const subUiSchema = useMemo(\n () =>\n (uiSchema?.[\"x-ui-fields\"] ?? {}) as { [fieldName: string]: UISchema },\n [uiSchema],\n );\n\n if (!subSchema) return null;\n\n const { variant, defaultOpen, displayContents, globalOptions } =\n resolveObjectOptions(options);\n const layout = resolveLayout(uiSchema, propertySchema);\n const effectiveUiSchema = buildEffectiveUiSchema(\n subUiSchema,\n globalOptions,\n layout,\n );\n\n const content = (\n <Renderer\n schema={subSchema}\n data={(value as Record<string, unknown>) || {}}\n onChange={onChange}\n disabled={disabled}\n readOnly={readonly}\n widgets={registry}\n uiSchema={effectiveUiSchema}\n displayContents={displayContents}\n // Scope the sub-form's control ids to this object. Without it every\n // array item's fields share the sub-renderer's default prefix, so\n // `htmlFor` and `aria-describedby` bind to the first item's controls.\n idPrefix={id}\n // Bridge a nested field's blur up to this object's own field blur. The\n // parent holds a deferred change until its field blurs; without this the\n // blur never arrives and the change is stranded.\n onBlur={onBlur ? () => onBlur(id, value) : undefined}\n />\n );\n\n if (displayContents) return <>{content}</>;\n\n return (\n <ContainerTemplate\n label={label}\n description={description}\n variant={variant}\n defaultOpen={defaultOpen}\n >\n {content}\n </ContainerTemplate>\n );\n}\n","/**\n * useNestedFormContext -- returns the renderer and templates injected by\n * the nearest JsonSchemaFormRenderer via NestedFormContext.\n *\n * Used by ObjectWidget and ArrayWidget to render nested sub-forms and\n * resolve layout templates without a circular import.\n *\n * Throws if called outside a JsonSchemaFormRenderer tree. This is\n * intentional: ObjectWidget and ArrayWidget cannot function without\n * the renderer context, and a clear error is better than a silent null.\n */\n\nimport { useContext } from \"react\";\nimport { NestedFormContext } from \"../NestedFormContext\";\nimport type { NestedFormContextValue } from \"../NestedFormContext\";\n\nexport function useNestedFormContext(): NestedFormContextValue {\n const ctx = useContext(NestedFormContext);\n if (!ctx) {\n throw new Error(\n \"useNestedFormContext must be used inside a JsonSchemaFormRenderer.\",\n );\n }\n return ctx;\n}\n","/**\n * NestedFormContext -- provides the JsonSchemaFormRenderer and the active\n * TemplateRegistry to nested widgets (ObjectWidget, ArrayWidget) without\n * creating a circular import.\n *\n * JsonSchemaFormRenderer sets this context on mount. Nested widgets read\n * it via useNestedFormContext() to render sub-forms and resolve templates.\n */\n\nimport { createContext } from \"react\";\nimport type { JsonSchemaFormRendererProps } from \"./JsonSchemaFormRenderer\";\nimport type { TemplateRegistry } from \"./widgets/types\";\n\nexport type NestedRenderer = (\n props: Omit<\n JsonSchemaFormRendererProps,\n \"onUpdate\" | \"onCancel\" | \"showActions\" | \"showExtraProperties\"\n >,\n) => React.ReactElement | null;\n\nexport interface NestedFormContextValue {\n renderer: NestedRenderer;\n templates: TemplateRegistry;\n /**\n * The whole form's data, carried down so a nested renderer can evaluate an\n * `x-ui-rule` scope against the form root rather than its own slice.\n *\n * Every other JSON Pointer in the vocabulary (`editablePaths`, validation\n * error pointers) is root-anchored; without this, a rule on a nested field\n * could only ever see its immediate object, so a rule referencing a\n * top-level field silently never fired.\n *\n * The outermost renderer sets this to its own data; nested renderers inherit\n * it unchanged.\n */\n rootData: Record<string, unknown>;\n /**\n * Whether the root form's save has been attempted. A nested sub-form is a\n * separate form-engine instance with its own submit state, which the root's\n * Save never flips -- so without this a required field inside a nested object\n * would never reveal its error on submit (only on touch). Carried down so a\n * nested renderer ORs it into its own error-visibility.\n *\n * The outermost renderer sets this to its own submitAttempted; nested\n * renderers inherit it unchanged.\n */\n submitAttempted: boolean;\n}\n\nexport const NestedFormContext = createContext<NestedFormContextValue | null>(\n null,\n);\n","/**\n * DefaultObjectContainerTemplate -- wraps an ObjectWidget sub-form with\n * the appropriate presentation based on the variant option.\n *\n * Variants: section (default), card, collapsible, inline, borderless.\n * Extracted from ObjectWidget so ObjectWidget can delegate to this template\n * or to a caller-supplied replacement.\n */\n\nimport { useState } from \"react\";\nimport { ChevronDown, ChevronRight } from \"lucide-react\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@petrarca/sonnet-ui\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@petrarca/sonnet-ui\";\nimport type { ObjectContainerTemplateProps } from \"../widgets/types\";\n\n// -- Variant sub-components -----------------------------------------------\n\nfunction CardVariant({\n children,\n label,\n description,\n}: {\n children: React.ReactNode;\n label?: string;\n description?: string;\n}) {\n return (\n <Card>\n {label && (\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"text-base\">{label}</CardTitle>\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </CardHeader>\n )}\n <CardContent>{children}</CardContent>\n </Card>\n );\n}\n\nfunction SectionVariant({\n children,\n label,\n description,\n}: {\n children: React.ReactNode;\n label?: string;\n description?: string;\n}) {\n return (\n <div className=\"space-y-3\">\n {label && (\n <div>\n <h4 className=\"text-sm font-medium\">{label}</h4>\n {description && (\n <p className=\"text-xs text-muted-foreground\">{description}</p>\n )}\n </div>\n )}\n <div className=\"pl-3 border-l-2 border-muted\">{children}</div>\n </div>\n );\n}\n\n// -- DefaultObjectContainerTemplate ----------------------------------------\n\nexport function DefaultObjectContainerTemplate({\n children,\n label,\n description,\n variant = \"section\",\n defaultOpen = true,\n}: ObjectContainerTemplateProps): React.ReactElement {\n switch (variant) {\n case \"card\":\n return (\n <CardVariant label={label} description={description}>\n {children}\n </CardVariant>\n );\n\n case \"collapsible\":\n if (!label) return <SectionVariant>{children}</SectionVariant>;\n return (\n <CollapsibleVariant\n label={label}\n description={description}\n defaultOpen={defaultOpen}\n >\n {children}\n </CollapsibleVariant>\n );\n\n case \"inline\":\n return <div>{children}</div>;\n\n case \"borderless\":\n return <div className=\"space-y-4\">{children}</div>;\n\n case \"section\":\n default:\n return (\n <SectionVariant label={label} description={description}>\n {children}\n </SectionVariant>\n );\n }\n}\n\n// Extracted to its own component so Collapsible state is isolated.\nfunction CollapsibleVariant({\n label,\n description,\n defaultOpen,\n children,\n}: {\n label: string;\n description?: string;\n defaultOpen: boolean;\n children: React.ReactNode;\n}): React.ReactElement {\n const [open, setOpen] = useState(defaultOpen);\n\n return (\n <Collapsible open={open} onOpenChange={setOpen}>\n <CollapsibleTrigger asChild>\n <button\n type=\"button\"\n className=\"flex w-full items-center gap-2 text-sm font-medium hover:text-foreground/80\"\n >\n {open ? (\n <ChevronDown className=\"h-4 w-4\" />\n ) : (\n <ChevronRight className=\"h-4 w-4\" />\n )}\n {label}\n </button>\n </CollapsibleTrigger>\n {description && (\n <p className=\"text-xs text-muted-foreground ml-6\">{description}</p>\n )}\n <CollapsibleContent className=\"mt-2 pl-3 border-l-2 border-muted\">\n {children}\n </CollapsibleContent>\n </Collapsible>\n );\n}\n","/**\n * ArrayWidget -- renders a repeatable list of sub-forms for\n * type: \"array\" properties whose items have type: \"object\".\n *\n * Layout is template-driven. The active templates are resolved from\n * NestedFormContext (injected by JsonSchemaFormRenderer):\n * - ArrayItemTemplate -- how each item is wrapped (default: vertical card)\n * - ArrayHeaderTemplate -- column headers for horizontal mode (default: none)\n *\n * Horizontal layout is activated by x-ui-layout.direction: \"horizontal\" on\n * the array property or UISchema. The HorizontalArrayItemTemplate renders a\n * CSS grid row; ObjectWidget sets displayContents=true on the sub-renderer so\n * field divs become direct grid cells.\n *\n * Each item carries a stable form-internal ID (_fid) assigned via generateId().\n * IDs are used as React keys and for structural diffing at save time. They\n * never leave the renderer boundary.\n */\n\nimport { useCallback, useMemo } from \"react\";\nimport { Plus } from \"lucide-react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport { useNestedFormContext } from \"../hooks/useNestedFormContext\";\nimport type { UILayoutConfig } from \"@petrarca/sonnet-core/schema\";\nimport { applySchemaDefaults } from \"@petrarca/sonnet-core/schema\";\nimport { FORM_ITEM_ID_FIELD, generateId } from \"@petrarca/sonnet-core\";\nimport type { WidgetProps, UISchemaOptions } from \"./types\";\nimport { ObjectWidget } from \"./ObjectWidget\";\nimport { DefaultArrayItemTemplate } from \"../templates/DefaultArrayItemTemplate\";\nimport { DefaultArrayHeaderTemplate } from \"../templates/DefaultArrayHeaderTemplate\";\n\n// ---------------------------------------------------------------------------\n// Pure helpers\n// ---------------------------------------------------------------------------\n\nfunction countFields(itemSchema: WidgetProps[\"propertySchema\"]): number {\n return Object.keys(itemSchema.properties ?? {}).length;\n}\n\nfunction allItemsComplete(\n items: Record<string, unknown>[],\n requiredFields: string[],\n): boolean {\n if (requiredFields.length === 0) return true;\n return items.every((item) =>\n requiredFields.every((field) => {\n const v = item[field];\n return v !== undefined && v !== null && v !== \"\";\n }),\n );\n}\n\n/** Ensure every item has a stable _fid. */\nfunction ensureItemIds(value: unknown): Record<string, unknown>[] {\n return (Array.isArray(value) ? value : []).map((item) =>\n item[FORM_ITEM_ID_FIELD]\n ? item\n : { ...item, [FORM_ITEM_ID_FIELD]: generateId() },\n );\n}\n\n/** Strip the _fid from an item for passing to sub-renderer. */\nfunction stripItemId(item: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(item).filter(([k]) => k !== FORM_ITEM_ID_FIELD),\n );\n}\n\n/** Resolve layout config from UISchema and property schema. */\nfunction resolveLayout(\n uiSchema: WidgetProps[\"uiSchema\"],\n propertySchema: WidgetProps[\"propertySchema\"],\n): UILayoutConfig {\n const schemaLayout = propertySchema[\"x-ui-layout\"];\n const uiLayout = uiSchema?.[\"x-ui-layout\"];\n return { ...schemaLayout, ...uiLayout };\n}\n\n/** Build global options for sub-form (compact / label suppression). */\nfunction buildSubGlobalOptions(\n layout: UILayoutConfig,\n isHorizontal: boolean,\n): Record<string, unknown> | undefined {\n const compactOptions = layout.compact ? { compact: true } : undefined;\n const labelsOption =\n layout.labels !== undefined\n ? layout.labels\n : isHorizontal\n ? false\n : undefined;\n if (!compactOptions && labelsOption !== false) return undefined;\n return {\n ...(compactOptions ?? {}),\n ...(labelsOption === false ? { label: false } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\ninterface ArrayHeaderProps {\n label: string | undefined;\n description: string | undefined;\n}\n\nfunction ArrayHeader({ label, description }: ArrayHeaderProps) {\n if (!label) return null;\n return (\n <div>\n <h4 className=\"text-sm font-medium\">{label}</h4>\n {description && (\n <p className=\"text-xs text-muted-foreground\">{description}</p>\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Hooks\n// ---------------------------------------------------------------------------\n\nfunction useArrayHandlers(\n items: Record<string, unknown>[],\n onChange: (v: unknown) => void,\n propertySchema: WidgetProps[\"propertySchema\"],\n) {\n const handleItemChange = useCallback(\n (index: number, data: Record<string, unknown>) => {\n const next = [...items];\n next[index] = {\n ...data,\n [FORM_ITEM_ID_FIELD]: items[index][FORM_ITEM_ID_FIELD],\n };\n onChange(next);\n },\n [items, onChange],\n );\n\n const handleAdd = useCallback(() => {\n const base = propertySchema.items\n ? applySchemaDefaults({}, propertySchema.items)\n : {};\n onChange([...items, { ...base, [FORM_ITEM_ID_FIELD]: generateId() }]);\n }, [items, onChange, propertySchema.items]);\n\n const handleRemove = useCallback(\n (index: number) => {\n onChange(items.filter((_, i) => i !== index));\n },\n [items, onChange],\n );\n\n const handleMove = useCallback(\n (from: number, to: number) => {\n const next = [...items];\n const [movedItem] = next.splice(from, 1);\n next.splice(to, 0, movedItem);\n onChange(next);\n },\n [items, onChange],\n );\n\n return { handleItemChange, handleAdd, handleRemove, handleMove };\n}\n\n// ---------------------------------------------------------------------------\n// ArrayWidget\n// ---------------------------------------------------------------------------\n\nexport function ArrayWidget({\n propertySchema,\n value,\n onChange,\n registry,\n uiSchema,\n disabled,\n readonly,\n label,\n description,\n options,\n schema,\n name,\n onBlur,\n}: WidgetProps): React.ReactElement {\n const { templates } = useNestedFormContext();\n\n const items = useMemo(() => ensureItemIds(value), [value]);\n const { handleItemChange, handleAdd, handleRemove, handleMove } =\n useArrayHandlers(items, onChange, propertySchema);\n\n const itemSchema = propertySchema.items;\n if (!itemSchema?.properties) {\n return (\n <p className=\"text-sm text-destructive\">\n ArrayWidget requires items with type &quot;object&quot; and properties.\n </p>\n );\n }\n\n const layout = resolveLayout(uiSchema, propertySchema);\n const isHorizontal = layout.direction === \"horizontal\";\n const subGlobalOptions = buildSubGlobalOptions(layout, isHorizontal);\n\n return (\n <ArrayWidgetInner\n items={items}\n propertySchema={propertySchema}\n itemSchema={itemSchema}\n schema={schema}\n name={name ?? \"\"}\n registry={registry}\n uiSchema={uiSchema}\n disabled={disabled}\n readonly={readonly}\n label={label}\n description={description}\n options={options}\n layout={layout}\n isHorizontal={isHorizontal}\n subGlobalOptions={subGlobalOptions}\n templates={templates}\n onItemChange={handleItemChange}\n onAdd={handleAdd}\n onRemove={handleRemove}\n onMove={handleMove}\n onBlur={onBlur}\n />\n );\n}\n\n// ---------------------------------------------------------------------------\n// Inner renderer (split to keep each function below complexity threshold)\n// ---------------------------------------------------------------------------\n\ninterface ArrayWidgetInnerProps {\n items: Record<string, unknown>[];\n propertySchema: WidgetProps[\"propertySchema\"];\n itemSchema: WidgetProps[\"propertySchema\"];\n schema: WidgetProps[\"schema\"];\n name: string;\n registry: WidgetProps[\"registry\"];\n uiSchema: WidgetProps[\"uiSchema\"];\n disabled?: boolean;\n readonly?: boolean;\n label?: string;\n description?: string;\n options?: UISchemaOptions;\n layout: UILayoutConfig;\n isHorizontal: boolean;\n subGlobalOptions: Record<string, unknown> | undefined;\n templates: ReturnType<typeof useNestedFormContext>[\"templates\"];\n onItemChange: (index: number, data: Record<string, unknown>) => void;\n onAdd: () => void;\n onRemove: (index: number) => void;\n onMove: (from: number, to: number) => void;\n /** The array field's blur: a field of an item that loses focus reports it,\n * so a form deferring changes (`deferChanges`) commits the edit. */\n onBlur?: WidgetProps[\"onBlur\"];\n}\n\n/** Resolve array schema constraints. */\nfunction resolveConstraints(\n arraySchema: WidgetProps[\"propertySchema\"],\n itemSchema: WidgetProps[\"propertySchema\"],\n readonly: boolean | undefined,\n disabled: boolean | undefined,\n itemCount: number,\n) {\n const minItems = arraySchema.minItems ?? 0;\n const maxItems = arraySchema.maxItems ?? Infinity;\n const requiredFields = itemSchema.required ?? [];\n const isEditable = !readonly && !disabled;\n return {\n canRemove: isEditable && itemCount > minItems,\n canAddBase: isEditable && itemCount < maxItems,\n requiredFields,\n };\n}\n\n/** Resolve display options from widget options. */\nfunction resolveDisplayOptions(\n options: UISchemaOptions | undefined,\n itemCount: number,\n) {\n return {\n addLabel: (options?.addLabel as string) ?? \"Add item\",\n itemTitle: options?.itemTitle as string | undefined,\n orderable: !!options?.orderable && itemCount > 1,\n emptyMessage: options?.emptyMessage as string | undefined,\n };\n}\n\n/** Resolve the active templates from context with defaults. */\nfunction resolveTemplates(\n templates: ReturnType<typeof useNestedFormContext>[\"templates\"],\n isHorizontal: boolean,\n) {\n const ItemTemplate = templates.ArrayItemTemplate ?? DefaultArrayItemTemplate;\n const HorizontalItemTemplate =\n templates.HorizontalArrayItemTemplate ?? undefined;\n const HeaderTemplate =\n templates.ArrayHeaderTemplate ?? DefaultArrayHeaderTemplate;\n const ActiveItemTemplate =\n isHorizontal && HorizontalItemTemplate\n ? HorizontalItemTemplate\n : ItemTemplate;\n return { ActiveItemTemplate, HeaderTemplate };\n}\n\n/** Build ObjectWidget options for a sub-item. */\nfunction buildItemOptions(\n isHorizontal: boolean,\n subGlobalOptions: Record<string, unknown> | undefined,\n): UISchemaOptions {\n return {\n variant: \"borderless\",\n displayContents: isHorizontal,\n ...(subGlobalOptions ? { globalOptions: subGlobalOptions } : {}),\n };\n}\n\n/** Resolve the label for an array item. */\nfunction resolveItemLabel(\n itemTitle: string | undefined,\n index: number,\n): string {\n return itemTitle ? itemTitle.replace(\"{index}\", String(index + 1)) : \"\";\n}\n\nfunction ArrayWidgetInner({\n items,\n propertySchema,\n itemSchema,\n schema,\n name,\n registry,\n uiSchema,\n disabled,\n readonly,\n label,\n description,\n options,\n layout,\n isHorizontal,\n subGlobalOptions,\n templates,\n onItemChange,\n onAdd,\n onRemove,\n onMove,\n onBlur,\n}: ArrayWidgetInnerProps) {\n const constraints = resolveConstraints(\n propertySchema,\n itemSchema,\n readonly,\n disabled,\n items.length,\n );\n const display = resolveDisplayOptions(options, items.length);\n const canAdd =\n constraints.canAddBase &&\n allItemsComplete(items, constraints.requiredFields);\n const { ActiveItemTemplate, HeaderTemplate } = resolveTemplates(\n templates,\n isHorizontal,\n );\n const fieldCount = countFields(itemSchema);\n const itemOptions = buildItemOptions(isHorizontal, subGlobalOptions);\n\n return (\n <div className={isHorizontal ? \"space-y-1\" : \"space-y-3\"}>\n <ArrayHeader label={label} description={description} />\n\n {items.length === 0 && display.emptyMessage && (\n <p className=\"text-sm text-muted-foreground italic\">\n {display.emptyMessage}\n </p>\n )}\n\n {items.length > 0 && (\n <HeaderTemplate\n itemSchema={itemSchema}\n layout={layout}\n canRemove={constraints.canRemove}\n orderable={display.orderable}\n fieldCount={fieldCount}\n />\n )}\n\n {items.map((item, index) => (\n <ActiveItemTemplate\n key={item[FORM_ITEM_ID_FIELD] as string}\n index={index}\n total={items.length}\n canRemove={constraints.canRemove}\n orderable={display.orderable}\n disabled={disabled}\n layout={layout}\n fieldCount={fieldCount}\n fid={item[FORM_ITEM_ID_FIELD] as string}\n onRemove={() => onRemove(index)}\n onMoveUp={index > 0 ? () => onMove(index, index - 1) : undefined}\n onMoveDown={\n index < items.length - 1\n ? () => onMove(index, index + 1)\n : undefined\n }\n >\n <ObjectWidget\n id={`field-${name}-${index}`}\n name={`${name}[${index}]`}\n schema={schema}\n propertySchema={itemSchema}\n uiSchema={uiSchema}\n registry={registry}\n value={stripItemId(item)}\n onChange={(data: unknown) =>\n onItemChange(index, data as Record<string, unknown>)\n }\n label={resolveItemLabel(display.itemTitle, index)}\n description={undefined}\n disabled={disabled}\n readonly={readonly}\n options={itemOptions}\n onBlur={onBlur}\n />\n </ActiveItemTemplate>\n ))}\n\n {canAdd && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={onAdd}\n disabled={disabled}\n className=\"gap-1.5\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n {display.addLabel}\n </Button>\n )}\n </div>\n );\n}\n","/**\n * DefaultArrayItemTemplate -- vertical card layout for array items.\n *\n * Renders the item content with optional remove, move-up, and move-down\n * controls in a column on the right. This is the default (vertical) layout;\n * HorizontalArrayItemTemplate handles the grid-row case.\n */\n\nimport { Trash2, ChevronUp, ChevronDown } from \"lucide-react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport type { ArrayItemTemplateProps } from \"../widgets/types\";\n\nexport function DefaultArrayItemTemplate({\n children,\n index,\n total,\n canRemove,\n orderable,\n disabled,\n fid,\n onRemove,\n onMoveUp,\n onMoveDown,\n}: ArrayItemTemplateProps): React.ReactElement {\n const showControls = canRemove || orderable;\n\n return (\n <div\n data-fid={fid}\n className=\"relative flex gap-2 rounded-md border border-border/50 bg-muted/20 p-3\"\n >\n <div className=\"flex-1 min-w-0\">{children}</div>\n {showControls && (\n <div className=\"flex flex-col gap-1 pt-0.5\">\n {orderable && index > 0 && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"compact\"\n disabled={disabled}\n onClick={onMoveUp}\n title=\"Move up\"\n >\n <ChevronUp className=\"h-3.5 w-3.5\" />\n </Button>\n )}\n {orderable && index < total - 1 && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"compact\"\n disabled={disabled}\n onClick={onMoveDown}\n title=\"Move down\"\n >\n <ChevronDown className=\"h-3.5 w-3.5\" />\n </Button>\n )}\n {canRemove && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"compact\"\n disabled={disabled}\n onClick={onRemove}\n title=\"Remove item\"\n className=\"text-muted-foreground hover:text-destructive\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n )}\n </div>\n )}\n </div>\n );\n}\n","/**\n * Utility for building CSS grid-template-columns strings for array item rows.\n */\n\nimport type { UILayoutConfig } from \"@petrarca/sonnet-core/schema\";\n\n/** Build the CSS grid-template-columns string for a horizontal item row. */\nexport function buildGridTemplate(\n layout: UILayoutConfig,\n canRemove: boolean,\n fieldCount: number,\n orderable: boolean = false,\n): string {\n const base = layout.columns ?? `repeat(${fieldCount}, 1fr)`;\n const withOrder = orderable ? `${base} 32px` : base;\n return canRemove ? `${withOrder} 32px` : withOrder;\n}\n","/**\n * DefaultArrayHeaderTemplate -- column header row for horizontal array layout.\n *\n * Rendered once above all items by ArrayWidget when direction is \"horizontal\".\n * Returns null in vertical mode (no headers needed).\n */\n\nimport type { ArrayHeaderTemplateProps } from \"../widgets/types\";\nimport { buildGridTemplate } from \"./gridUtils\";\n\nexport function DefaultArrayHeaderTemplate({\n itemSchema,\n layout,\n canRemove,\n orderable,\n fieldCount,\n}: ArrayHeaderTemplateProps): React.ReactElement | null {\n if (layout.direction !== \"horizontal\") return null;\n\n const template = buildGridTemplate(layout, canRemove, fieldCount, orderable);\n const gap = layout.gap ?? 8;\n\n const properties = itemSchema.properties ?? {};\n const order = itemSchema[\"x-ui-order\"];\n const fieldNames = order\n ? order.filter((k) => k in properties)\n : Object.keys(properties);\n\n return (\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: template,\n gap: `${gap}px`,\n }}\n >\n {fieldNames.map((name) => (\n <span key={name} className=\"text-xs font-medium text-muted-foreground\">\n {properties[name]?.title ?? name}\n </span>\n ))}\n {orderable && <span />}\n {canRemove && <span />}\n </div>\n );\n}\n","/**\n * QuantityWidget - JSON-Schema-aware widget for compound value + unit input.\n *\n * Reads unit options from x-ui-options.units (static array) -- or, without\n * them, the unit codes the schema allows (`properties.unit.enum`, as the core\n * quantity type narrowed by a question) -- and delegates rendering to\n * FormQuantityInput. Registered as x-ui-widget: \"quantity\"; the core quantity\n * type carries that hint itself.\n *\n * x-ui-options:\n * units - Array of { value, label, min?, max?, position? } unit options\n * unitPosition - Default position for all units: \"prefix\" | \"suffix\"\n * precision - Number of decimal places to format on blur\n * step - Arrow-key increment\n *\n * Schema-level min/max come from propertySchema.minimum / propertySchema.maximum;\n * a unit's own range from the schema's ranges per unit (`unitRangesOf`), which\n * win over a unit option's min / max.\n *\n * Form value shape: { value: number, unit: string } -- or no value at all: a\n * quantity without its number is not an answer, so it is stored as absent\n * while the unit picked meanwhile stays shown.\n */\n\nimport { useCallback, useRef, useState } from \"react\";\nimport { unitRangesOf } from \"@petrarca/sonnet-core/schema\";\nimport {\n FormQuantityInput,\n type QuantityValue,\n type UnitOption,\n type UnitPosition,\n} from \"../FormQuantityInput\";\nimport { WidgetProps, firstError } from \"./types\";\n\n/** Runtime shape guard for a single unit option from x-ui-options. */\nfunction isUnitOption(u: unknown): u is UnitOption {\n return (\n typeof u === \"object\" &&\n u !== null &&\n typeof (u as UnitOption).value === \"string\" &&\n typeof (u as UnitOption).label === \"string\"\n );\n}\n\ninterface ParsedQuantityOptions {\n units: UnitOption[];\n precision: number | undefined;\n step: number | undefined;\n unitPosition: UnitPosition | undefined;\n}\n\n// The unit codes a schema allows: its `unit` property's enum, each its own label.\nfunction schemaUnits(\n propertySchema: WidgetProps[\"propertySchema\"],\n): UnitOption[] {\n const codes = propertySchema.properties?.unit?.enum;\n return Array.isArray(codes)\n ? codes.map((c) => ({ value: String(c), label: String(c) }))\n : [];\n}\n\n// The units with their ranges from the schema, where it sets one.\nfunction withSchemaRanges(\n units: UnitOption[],\n propertySchema: WidgetProps[\"propertySchema\"],\n): UnitOption[] {\n const ranges = unitRangesOf(propertySchema) ?? {};\n return units.map((u) => {\n const range = ranges[u.value];\n return range ? { ...u, min: range.min, max: range.max } : u;\n });\n}\n\n/** Parse and validate x-ui-options for the quantity widget. */\nfunction parseQuantityOptions(\n options: Record<string, unknown>,\n fallbackUnits: UnitOption[],\n): ParsedQuantityOptions {\n const units = Array.isArray(options.units)\n ? (options.units as unknown[]).filter(isUnitOption)\n : fallbackUnits;\n const precision =\n typeof options.precision === \"number\" ? options.precision : undefined;\n const step = typeof options.step === \"number\" ? options.step : undefined;\n const unitPosition =\n options.unitPosition === \"prefix\" || options.unitPosition === \"suffix\"\n ? options.unitPosition\n : undefined;\n return { units, precision, step, unitPosition };\n}\n\nexport function QuantityWidget({\n id,\n name,\n value,\n onChange,\n onBlur,\n propertySchema,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n placeholder,\n autofocus,\n options = {},\n}: WidgetProps) {\n const error = firstError(rawErrors);\n const {\n units: optionUnits,\n precision,\n step,\n unitPosition: unitPositionOpt,\n } = parseQuantityOptions(options, schemaUnits(propertySchema));\n const units = withSchemaRanges(optionUnits, propertySchema);\n // The unit picked before a number is entered: shown, not stored.\n const [pendingUnit, setPendingUnit] = useState<string | undefined>();\n\n // Coerce incoming value to QuantityValue (unknown -> typed).\n const stored: QuantityValue | undefined =\n value != null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as QuantityValue)\n : undefined;\n const quantityValue =\n stored ??\n (pendingUnit ? { value: undefined, unit: pendingUnit } : undefined);\n\n const handleChange = useCallback(\n (next: QuantityValue) => {\n if (next.value !== undefined) return onChange(next);\n setPendingUnit(next.unit);\n onChange(undefined);\n },\n [onChange],\n );\n\n // L5: We store the current value in a ref so the onBlur handler can pass it\n // to the form engine without capturing a stale snapshot in a useCallback\n // closure. Adding `value` to the useCallback dep array would cause the\n // handler to be recreated on every value change, which in turn makes\n // FormQuantityInput recreate its own blur handler -- unnecessary churn.\n const valueRef = useRef(value);\n valueRef.current = value;\n\n const handleBlur = useCallback(() => {\n onBlur?.(id, valueRef.current);\n }, [id, onBlur]);\n\n return (\n <FormQuantityInput\n id={id}\n name={name}\n value={quantityValue}\n onChange={handleChange}\n onBlur={handleBlur}\n units={units}\n // A quantity's schema with no units narrowed: any unit, typed.\n freeUnit={propertySchema.properties?.unit !== undefined}\n unitPosition={unitPositionOpt}\n precision={precision}\n step={step}\n min={propertySchema.minimum}\n max={propertySchema.maximum}\n label={label}\n labelPlacement={options?.labelPlacement}\n description={description}\n error={error}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n readOnly={readonly}\n autoFocus={autofocus}\n />\n );\n}\n","/**\n * CodedValueWidget -- a code from a list someone else maintains, asked of the\n * application's terminology service (`TerminologyProvider`).\n *\n * The list is the field's binding (`x-binding`: a value set or a code system,\n * its strength). What is stored the field's type decides: the core coding type\n * stores `{ system, code, version?, display? }`; a string bound to a list stores\n * the code alone, its label looked up to show it; a coding or a text (`anyOf`,\n * an open list) stores a coding, or a text of one's own as a plain string --\n * never a coding without its code. An array of any of them takes several\n * answers, shown as chips. The first search decides whether the list is shown\n * whole (it fits one page) or searched; a hit shows its code and, when the\n * service gives it, its path. An open list -- a coding or a text, or an\n * `extensible` binding on a string -- takes a typed text no code fits.\n *\n * Registered as x-ui-widget: \"coded-value\"; the core coding type carries that\n * hint, and a string, a coding or a text, or an array bound to a list resolves\n * to it without one.\n *\n * x-ui-options:\n * mode - \"list\" | \"search\": overrides what the list's size decides\n * minChars - the characters a search waits for (default 1)\n * store - the hit's property a code-only field stores (default \"code\")\n * keep - properties of a hit a coding keeps beside its own -- an\n * application's, which its service returns on its hits\n *\n * See docs/design/coded-values.md (workspace).\n */\n\nimport * as React from \"react\";\nimport { ChevronsUpDown, Loader2, TriangleAlert, X } from \"lucide-react\";\nimport { cn, EMPTY_VALUE } from \"@petrarca/sonnet-core\";\nimport {\n bindingOf,\n codingKey,\n type Binding,\n} from \"@petrarca/sonnet-core/schema\";\nimport {\n useTerminology,\n type CodingHit,\n type TerminologyService,\n} from \"@petrarca/sonnet-core/terminology\";\nimport {\n Badge,\n Button,\n CodedValueDisplay,\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@petrarca/sonnet-ui\";\nimport { FormFieldWrapper } from \"../FormFieldWrapper\";\nimport { firstError, type WidgetProps } from \"./types\";\nimport {\n entriesOf,\n entryKey,\n fieldModelOf,\n takesText,\n toStored,\n withAnswer,\n withoutAnswer,\n type Entry,\n type FieldModel,\n} from \"./codedValue/codedValueModel\";\nimport {\n useCodedValueOptions,\n type CodedValueOptions,\n} from \"./codedValue/useCodedValueOptions\";\nimport { useStoredLabel } from \"./codedValue/useStoredLabel\";\nimport { useListCheck, type ListWarnings } from \"./codedValue/useListCheck\";\nimport { HitList } from \"./codedValue/HitList\";\nimport { InlineIconButton } from \"./codedValue/InlineIconButton\";\nimport {\n minCharsOption,\n modeOption,\n useListRef,\n} from \"./codedValue/listOptions\";\n\n// A typed text taken as an answer: offered when the list is open and no hit is it.\nfunction freeTextOf(o: CodedValueOptions, open: boolean): string | undefined {\n const text = o.search.trim();\n if (!open || !text) return undefined;\n return o.hits.some((h) => h.code === text) ? undefined : text;\n}\n\n/** What an answer is shown with: the field's list, the service, and labels picked meanwhile. */\ninterface Shown {\n binding: Binding | undefined;\n service: TerminologyService | null;\n /** Labels of answers picked here -- shown at once, before any lookup. */\n picked: ReadonlyMap<string, string | undefined>;\n /** Whether a stored code can be looked up: it is a code, not another property. */\n lookup: boolean;\n}\n\n// One answer as text: a coding by its label and code, a text as it is.\nfunction EntryText({\n entry,\n shown,\n}: {\n entry: Entry;\n shown: Shown;\n}): React.ReactElement | null {\n const key = entryKey(entry);\n const known = shown.picked.has(key);\n const looked = useStoredLabel(\n known || !shown.lookup ? null : shown.service,\n entry.coding,\n shown.binding,\n );\n if (!entry.coding)\n return <span className=\"truncate text-sm\">{entry.text}</span>;\n return (\n <CodedValueDisplay\n code={entry.coding.code}\n display={known ? shown.picked.get(key) : looked}\n system={entry.coding.system || undefined}\n />\n );\n}\n\n// An answer of several, as a chip -- removable when the field is editable.\nfunction Chip({\n entry,\n shown,\n onRemove,\n}: {\n entry: Entry;\n shown: Shown;\n onRemove?: (key: string) => void;\n}): React.ReactElement {\n return (\n <Badge variant=\"secondary\" className=\"max-w-full gap-1 font-normal\">\n <EntryText entry={entry} shown={shown} />\n {onRemove && (\n <InlineIconButton\n label=\"Remove\"\n onAct={() => onRemove(entryKey(entry))}\n >\n <X className=\"h-3 w-3\" />\n </InlineIconButton>\n )}\n </Badge>\n );\n}\n\n// The answers as text: one as it is, several as chips; a dash for none.\nfunction Entries({\n entries,\n field,\n shown,\n onRemove,\n}: {\n entries: Entry[];\n field: FieldModel;\n shown: Shown;\n onRemove?: (key: string) => void;\n}): React.ReactElement {\n if (!field.multiple) return <EntryText entry={entries[0]} shown={shown} />;\n return (\n <span className=\"flex min-w-0 flex-wrap gap-1\">\n {entries.map((e) => (\n <Chip key={entryKey(e)} entry={e} shown={shown} onRemove={onRemove} />\n ))}\n </span>\n );\n}\n\n// The trigger's icons: loading, clearing the value, opening.\nfunction TriggerIcons({\n loading,\n onClear,\n}: {\n loading: boolean;\n onClear?: () => void;\n}): React.ReactElement {\n return (\n <span className=\"ml-2 flex shrink-0 items-center gap-1\">\n {loading && <Loader2 className=\"h-4 w-4 animate-spin opacity-50\" />}\n {onClear && (\n <InlineIconButton label=\"Clear selection\" onAct={onClear}>\n <X className=\"h-4 w-4\" />\n </InlineIconButton>\n )}\n <ChevronsUpDown className=\"h-4 w-4 opacity-50\" />\n </span>\n );\n}\n\ninterface FieldState {\n binding: Binding | undefined;\n field: FieldModel;\n entries: Entry[];\n /** Whether it stores codes -- looked up, checked -- not another property of a hit. */\n storesCodes: boolean;\n}\n\n// The field's binding, how it stores its answers, and its answers as read.\nfunction fieldStateOf(props: WidgetProps): FieldState {\n const binding = bindingOf(props.propertySchema);\n const field = fieldModelOf(props.propertySchema, props.options);\n return {\n binding,\n field,\n entries: entriesOf(props.value, field, binding),\n storesCodes: field.store === \"code\",\n };\n}\n\n// Picking and removing answers: the value they make, the labels picked meanwhile.\nfunction useAnswers(props: WidgetProps, state: FieldState) {\n const { value, onChange } = props;\n const { binding, field } = state;\n const [picked, setPicked] = React.useState<Map<string, string | undefined>>(\n () => new Map(),\n );\n const pick = (hit: CodingHit) => {\n setPicked((m) => new Map(m).set(codingKey(hit), hit.display));\n onChange(withAnswer(value, toStored(hit, field, binding), field, binding));\n };\n const takeText = (typed: string) =>\n onChange(withAnswer(value, typed, field, binding));\n const remove = (key: string) =>\n onChange(withoutAnswer(value, key, field, binding));\n return { picked, pick, takeText, remove };\n}\n\nfunction EditableCodedValue({\n props,\n state,\n service,\n}: {\n props: WidgetProps;\n state: FieldState;\n service: TerminologyService;\n}): React.ReactElement {\n const { id, value, onChange, onBlur, required, rawErrors, placeholder } =\n props;\n const { binding, field, entries } = state;\n const [open, setOpen] = React.useState(false);\n const list = useListRef(binding);\n const options = useCodedValueOptions(\n service,\n list,\n modeOption(props.options),\n minCharsOption(props.options),\n );\n const answers = useAnswers(props, state);\n const shown: Shown = {\n binding,\n service,\n picked: answers.picked,\n lookup: state.storesCodes,\n };\n const empty = entries.length === 0;\n\n const close = (next: boolean) => {\n setOpen(next);\n if (!next) {\n options.setSearch(\"\");\n onBlur?.(id, value);\n }\n };\n // One answer closes the list; several keep it open, its search too, for the next.\n const done = () => {\n if (!field.multiple) close(false);\n };\n const clear = () => onChange(undefined);\n\n return (\n <Popover open={open} onOpenChange={close}>\n <PopoverTrigger asChild>\n <Button\n id={id}\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n className={cn(\n \"h-auto min-h-9 w-full justify-between font-normal\",\n empty && \"text-muted-foreground\",\n firstError(rawErrors) && \"border-destructive\",\n )}\n >\n {empty ? (\n <span className=\"truncate\">{placeholder || \"Select...\"}</span>\n ) : (\n <Entries\n entries={entries}\n field={field}\n shown={shown}\n onRemove={answers.remove}\n />\n )}\n <TriggerIcons\n loading={options.loading}\n onClear={!empty && !required ? clear : undefined}\n />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className=\"w-[--radix-popover-trigger-width] p-0\"\n align=\"start\"\n >\n <HitList\n options={options}\n selected={new Set(entries.map(entryKey))}\n freeText={freeTextOf(options, takesText(field, binding))}\n onPick={(hit) => {\n answers.pick(hit);\n done();\n }}\n onFreeText={(typed) => {\n answers.takeText(typed);\n done();\n }}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\n// The stored answers, shown as text: read only, or no service to ask.\nfunction ReadonlyCodedValue({\n state,\n service,\n note,\n}: {\n state: FieldState;\n service: TerminologyService | null;\n note?: string;\n}): React.ReactElement {\n const shown: Shown = {\n binding: state.binding,\n service,\n picked: new Map(),\n lookup: state.storesCodes,\n };\n return (\n <div className=\"space-y-1\">\n {state.entries.length ? (\n <Entries entries={state.entries} field={state.field} shown={shown} />\n ) : (\n <span className=\"text-sm text-muted-foreground\">{EMPTY_VALUE}</span>\n )}\n {note && <p className=\"text-xs text-muted-foreground\">{note}</p>}\n </div>\n );\n}\n\n// Why a field cannot be edited, if it cannot: no list bound, no service to ask.\nfunction readonlyNote(\n state: FieldState,\n service: TerminologyService | null,\n): string | undefined {\n if (!state.binding) return \"No list is bound to this field.\";\n if (!service) return \"No terminology service is available.\";\n return undefined;\n}\n\n// The stored codes the list no longer has -- or never had: a warning each.\nfunction ListWarningsText({\n warnings,\n}: {\n warnings: ListWarnings;\n}): React.ReactElement | null {\n if (warnings.size === 0) return null;\n return (\n <div className=\"space-y-0.5\">\n {[...warnings].map(([key, message]) => (\n <p\n key={key}\n className=\"flex items-center gap-1 text-xs text-amber-600 dark:text-amber-400\"\n >\n <TriangleAlert className=\"h-3 w-3 shrink-0\" />\n {message}\n </p>\n ))}\n </div>\n );\n}\n\n// The field's body: editable when there is a list and a service to ask.\nfunction CodedValueBody({\n props,\n state,\n service,\n}: {\n props: WidgetProps;\n state: FieldState;\n service: TerminologyService | null;\n}): React.ReactElement {\n const note = readonlyNote(state, service);\n if (props.disabled || props.readonly || note || !service)\n return (\n <ReadonlyCodedValue\n state={state}\n service={service}\n note={props.disabled || props.readonly ? undefined : note}\n />\n );\n return <EditableCodedValue props={props} state={state} service={service} />;\n}\n\n// The field: its body, and the warnings of its stored codes not in the list.\nfunction CodedValueField({\n props,\n}: {\n props: WidgetProps;\n}): React.ReactElement {\n const service = useTerminology();\n const state = fieldStateOf(props);\n const warnings = useListCheck(\n service,\n state.binding,\n state.entries.flatMap((e) => (e.coding ? [e.coding] : [])),\n state.storesCodes,\n );\n return (\n <div className=\"space-y-1\">\n <CodedValueBody props={props} state={state} service={service} />\n <ListWarningsText warnings={warnings} />\n </div>\n );\n}\n\nexport function CodedValueWidget(props: WidgetProps): React.ReactElement {\n return (\n <FormFieldWrapper\n inputId={props.id}\n label={props.label}\n description={props.description}\n required={props.required}\n error={firstError(props.rawErrors)}\n >\n <CodedValueField props={props} />\n </FormFieldWrapper>\n );\n}\n","/**\n * The coded-value widget's pure side: what a field stores -- a coding, the\n * code alone when the field is a string, or a coding or a text when its list is\n * open; one, or several when the field is an array -- and how a stored value\n * reads back. See docs/design/coded-values.md (workspace).\n */\n\nimport {\n codingKey,\n type Binding,\n type Coding,\n type JsonSchemaProperty,\n type UISchemaOptions,\n} from \"@petrarca/sonnet-core/schema\";\nimport type { CodingHit } from \"@petrarca/sonnet-core/terminology\";\n\n/** What one answer stores: the full coding, its code alone, or a coding or a text of one's own. */\nexport type StoredShape = \"coding\" | \"code\" | \"codingOrText\";\n\n/** How a field stores its answers. */\nexport interface FieldModel {\n /** Several answers: the field is an array. */\n multiple: boolean;\n shape: StoredShape;\n /** The hit's property a code-only field stores; default `code`. */\n store: string;\n /** Properties of a hit a coding keeps beside its own -- an application's, its service returns them. */\n keep: string[];\n}\n\n/** One stored answer, as read: a coding, or a text of one's own. */\nexport interface Entry {\n coding?: Coding;\n text?: string;\n}\n\nconst CODING_KEYS = [\"system\", \"code\", \"version\", \"display\"];\n\n// What one answer of a property stores: a string its code; a coding or a text\n// (resolved, the $ref member is the coding's definition: the string member says\n// it); else the coding.\nfunction shapeOf(prop: JsonSchemaProperty | undefined): StoredShape {\n if (prop?.type === \"string\") return \"code\";\n return prop?.anyOf?.some((m) => m.type === \"string\")\n ? \"codingOrText\"\n : \"coding\";\n}\n\n/** How a field stores its answers: its schema, and its options `store` and `keep`. */\nexport function fieldModelOf(\n prop: JsonSchemaProperty,\n options: UISchemaOptions | undefined,\n): FieldModel {\n const multiple = prop.type === \"array\";\n const keep = Array.isArray(options?.keep)\n ? (options.keep as unknown[]).filter(\n (k): k is string => typeof k === \"string\",\n )\n : [];\n return {\n multiple,\n shape: shapeOf(multiple ? prop.items : prop),\n store: typeof options?.store === \"string\" ? options.store : \"code\",\n keep: keep.filter((k) => !CODING_KEYS.includes(k)),\n };\n}\n\n/** Whether a field takes a typed text no code fits: an open list's. */\nexport function takesText(\n field: FieldModel,\n binding: Binding | undefined,\n): boolean {\n if (field.shape === \"codingOrText\") return true;\n return field.shape === \"code\" && binding?.strength === \"extensible\";\n}\n\n// A stored coding, if the value is one.\nfunction asCoding(value: unknown): Coding | undefined {\n if (typeof value !== \"object\" || value === null) return undefined;\n const c = value as Partial<Coding>;\n return typeof c.code === \"string\" && c.code\n ? { ...c, system: c.system ?? \"\", code: c.code }\n : undefined;\n}\n\n// One stored answer, read: a coding as it is; a code completed with the\n// binding's system (and version); a string in a coding-or-text field its text.\nfunction entryOf(\n value: unknown,\n field: FieldModel,\n binding: Binding | undefined,\n): Entry | undefined {\n if (typeof value !== \"string\") {\n const coding = asCoding(value);\n return coding && { coding };\n }\n if (!value) return undefined;\n if (field.shape === \"codingOrText\") return { text: value };\n return {\n coding: {\n system: binding?.system ?? \"\",\n code: value,\n ...(binding?.version && { version: binding.version }),\n },\n };\n}\n\n/** A field's stored answers, as read: none, one, or -- an array -- several. */\nexport function entriesOf(\n value: unknown,\n field: FieldModel,\n binding: Binding | undefined,\n): Entry[] {\n const values = field.multiple ? (Array.isArray(value) ? value : []) : [value];\n return values\n .map((v) => entryOf(v, field, binding))\n .filter((e): e is Entry => e !== undefined);\n}\n\n/** An answer's identity: its coding's, or its text. */\nexport function entryKey(e: Entry): string {\n return e.coding ? codingKey(e.coding) : `text:${e.text ?? \"\"}`;\n}\n\n/** What a picked hit stores: the property `store` names, or the coding -- with what it `keep`s -- without its path. */\nexport function toStored(\n hit: CodingHit,\n field: FieldModel,\n binding: Binding | undefined,\n): string | Coding {\n if (field.shape === \"code\") return String(hit[field.store] ?? hit.code);\n const version = hit.version ?? binding?.version;\n const kept = field.keep.filter((k) => hit[k] != null);\n return {\n system: hit.system,\n code: hit.code,\n ...(version && { version }),\n ...(hit.display && { display: hit.display }),\n ...Object.fromEntries(kept.map((k) => [k, hit[k]])),\n };\n}\n\n// An answer's identity as stored: a coding's system and code, a code or text as it is.\nfunction storedKey(\n v: unknown,\n field: FieldModel,\n binding: Binding | undefined,\n): string | undefined {\n const entry = entryOf(v, field, binding);\n return entry ? entryKey(entry) : undefined;\n}\n\n/**\n * The field's value with an answer picked: a single field's is the answer; an\n * array's gains it -- or loses it, when it had it already.\n */\nexport function withAnswer(\n value: unknown,\n answer: string | Coding,\n field: FieldModel,\n binding: Binding | undefined,\n): unknown {\n if (!field.multiple) return answer;\n const current = Array.isArray(value) ? value : [];\n const key = storedKey(answer, field, binding);\n const others = current.filter((v) => storedKey(v, field, binding) !== key);\n if (others.length < current.length) return others.length ? others : undefined;\n return [...current, answer];\n}\n\n/** The field's value without one answer -- a single field's, none. */\nexport function withoutAnswer(\n value: unknown,\n key: string,\n field: FieldModel,\n binding: Binding | undefined,\n): unknown {\n if (!field.multiple) return undefined;\n const current = Array.isArray(value) ? value : [];\n const others = current.filter((v) => storedKey(v, field, binding) !== key);\n return others.length ? others : undefined;\n}\n","/**\n * The hits a coded-value field offers, from the terminology service.\n *\n * The first search, without text, decides how the field is shown: a list that\n * fits one page is a select (its codes shown on open); a larger one a typeahead\n * (nothing until `minChars` are typed). `mode` overrides it. A typed text\n * always searches the service; a result larger than a page loads more on\n * request.\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type {\n CodingHit,\n ListRef,\n SearchResult,\n TerminologyService,\n} from \"@petrarca/sonnet-core/terminology\";\n\n/** How the field is shown: the whole list, or a search. */\nexport type CodedValueMode = \"list\" | \"search\";\n\n/** One page of hits. */\nexport const PAGE_SIZE = 50;\n\nconst DEBOUNCE_MS = 250;\n\nexport interface CodedValueOptions {\n /** The hits shown: the list's first page, or the search's. */\n hits: CodingHit[];\n /** How many hits there are in all, when the service says. */\n total?: number;\n /** Whether more hits can be loaded. */\n hasMore: boolean;\n loading: boolean;\n /** The service failed. */\n error?: string;\n /** Undefined until the first search has answered. */\n mode?: CodedValueMode;\n search: string;\n setSearch: (text: string) => void;\n /** The characters a search waits for. */\n minChars: number;\n loadMore: () => void;\n}\n\n// A text, settled for a moment.\nfunction useDebounced(text: string): string {\n const [settled, setSettled] = useState(text);\n useEffect(() => {\n const t = setTimeout(() => setSettled(text), DEBOUNCE_MS);\n return () => clearTimeout(t);\n }, [text]);\n return settled;\n}\n\n// Whether a page holds the whole list.\nfunction fitsOnePage(result: SearchResult): boolean {\n return result.total !== undefined\n ? result.total <= PAGE_SIZE\n : result.codings.length < PAGE_SIZE;\n}\n\n// Whether there is more after the hits loaded.\nfunction moreAfter(result: SearchResult): boolean {\n return result.total !== undefined\n ? result.codings.length < result.total\n : false;\n}\n\ninterface Page {\n result: SearchResult;\n hasMore: boolean;\n}\n\n// Pages of one search, the latest request winning.\nfunction usePagedSearch(\n service: TerminologyService | null,\n list: ListRef | undefined,\n) {\n const [page, setPage] = useState<Page>();\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string>();\n const request = useRef(0);\n // The text whose first page is shown (\"\" for none), null for none shown.\n const shown = useRef<string | null>(null);\n\n const run = useCallback(\n (text: string | undefined, offset: number, before: CodingHit[]) => {\n if (!service || !list) return Promise.resolve(undefined);\n const id = ++request.current;\n setLoading(true);\n return service\n .search({ ...list, text, limit: PAGE_SIZE, offset })\n .then((r) => {\n if (id !== request.current) return undefined;\n shown.current = text ?? \"\";\n const result = { ...r, codings: [...before, ...r.codings] };\n setPage({ result, hasMore: moreAfter(result) });\n setError(undefined);\n return r;\n })\n .catch((e: unknown) => {\n if (id === request.current) setError(String(e));\n return undefined;\n })\n .finally(() => {\n if (id === request.current) setLoading(false);\n });\n },\n [service, list],\n );\n\n const clear = useCallback(() => {\n request.current++;\n shown.current = null;\n setPage(undefined);\n setLoading(false);\n }, []);\n\n const isShown = useCallback((text: string) => shown.current === text, []);\n\n return { page, loading, error, run, clear, isShown };\n}\n\n/** The hits of a coded-value field: list or search, as the list's size or `mode` decides. */\nexport function useCodedValueOptions(\n service: TerminologyService | null,\n list: ListRef | undefined,\n forced: CodedValueMode | undefined,\n minChars = 1,\n): CodedValueOptions {\n const [search, setSearch] = useState(\"\");\n const [decided, setDecided] = useState<CodedValueMode | undefined>(forced);\n const text = useDebounced(search.trim());\n const { page, loading, error, run, clear, isShown } = usePagedSearch(\n service,\n list,\n );\n const mode = forced ?? decided;\n\n // The first search, without text, decides the mode -- unless it is given.\n useEffect(() => {\n if (forced) return;\n void run(undefined, 0, []).then(\n (r) => r && setDecided(fitsOnePage(r) ? \"list\" : \"search\"),\n );\n }, [forced, run]);\n\n // A text searches; no text shows the list, or nothing in a search.\n useEffect(() => {\n if (!mode) return;\n // A search waits for its characters; a list shows itself without any.\n if (mode === \"search\" && text.length < Math.max(minChars, 1)) clear();\n else if (!isShown(text)) void run(text || undefined, 0, []);\n }, [mode, text, minChars, run, clear, isShown]);\n\n const loadMore = useCallback(() => {\n const loaded = page?.result.codings ?? [];\n void run(text || undefined, loaded.length, loaded);\n }, [page, run, text]);\n\n return {\n hits: page?.result.codings ?? [],\n total: page?.result.total,\n hasMore: page?.hasMore ?? false,\n loading,\n error,\n mode,\n search,\n setSearch,\n minChars,\n loadMore,\n };\n}\n","/**\n * The label of a stored coded value: a coding's own; a code alone looked up --\n * by its system when the binding names one, else found in the bound value set.\n */\n\nimport { useEffect, useState } from \"react\";\nimport {\n codingKey,\n type Binding,\n type Coding,\n} from \"@petrarca/sonnet-core/schema\";\nimport type { TerminologyService } from \"@petrarca/sonnet-core/terminology\";\n\n// A code's label from the service: looked up in its system, or searched in the value set.\nasync function fetchLabel(\n service: TerminologyService,\n coding: Coding,\n valueSet: string | undefined,\n version: string | undefined,\n): Promise<string | undefined> {\n if (coding.system) return (await service.lookup(coding))?.display;\n if (!valueSet) return undefined;\n const { codings } = await service.search({\n valueSet,\n version,\n text: coding.code,\n });\n return codings.find((c) => c.code === coding.code)?.display;\n}\n\n// What a label is asked by: the coding's own label, its identity, the bound value set.\nfunction labelQuery(coding: Coding | undefined, binding: Binding | undefined) {\n const system = coding?.system ?? \"\";\n const code = coding?.code ?? \"\";\n return {\n own: coding?.display,\n system,\n code,\n version: coding?.version ?? binding?.version,\n valueSet: binding?.valueSet,\n key: codingKey({ system, code }),\n };\n}\n\n/** The label of the stored coding, the service asked only when it has none. */\nexport function useStoredLabel(\n service: TerminologyService | null,\n coding: Coding | undefined,\n binding: Binding | undefined,\n): string | undefined {\n const [fetched, setFetched] = useState<{ key: string; label?: string }>();\n const { own, system, code, version, valueSet, key } = labelQuery(\n coding,\n binding,\n );\n\n useEffect(() => {\n if (!service || !code || own) return;\n let live = true;\n fetchLabel(service, { system, code, version }, valueSet, version)\n .then((label) => live && setFetched({ key, label }))\n .catch(() => live && setFetched({ key }));\n return () => {\n live = false;\n };\n }, [service, system, code, version, valueSet, own, key]);\n\n return own ?? (fetched?.key === key ? fetched.label : undefined);\n}\n","/**\n * Stored codes checked against the list -- a code retired since, moved out of\n * the value set, or never in it, as data from elsewhere may hold. Only for a\n * `required` binding, whose codes must be the list's, and only when the\n * service can validate; through the provider, which remembers and batches, so\n * a form of many coded fields asks once per code. A warning, never a block: a\n * failed check shows nothing.\n */\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport {\n codingKey,\n type Binding,\n type Coding,\n} from \"@petrarca/sonnet-core/schema\";\nimport type { TerminologyService } from \"@petrarca/sonnet-core/terminology\";\n\n/** What the check says of a stored code not in the list, by the code's key. */\nexport type ListWarnings = ReadonlyMap<string, string>;\n\nconst NONE: ListWarnings = new Map();\n\ntype Validate = NonNullable<TerminologyService[\"validate\"]>;\n\n// Whether a field's codes are checked: a required list, codes stored as codes.\nfunction checks(binding: Binding | undefined, storesCodes: boolean): boolean {\n return (\n binding?.strength === \"required\" &&\n !!(binding.valueSet || binding.system) &&\n storesCodes\n );\n}\n\n// One code's warning, if it is not in the list; none when it is, or the check fails.\nasync function warningOf(\n validate: Validate,\n binding: Binding,\n coding: Coding,\n): Promise<[string, string] | undefined> {\n try {\n const result = await validate({\n valueSet: binding.valueSet,\n system: binding.system,\n version: binding.version,\n code: coding.code,\n });\n if (result.inList) return undefined;\n return [\n codingKey(coding),\n result.message ?? `${coding.code} is not in the list.`,\n ];\n } catch {\n return undefined;\n }\n}\n\n/** The warnings of a field's stored codes that are not in its list. */\nexport function useListCheck(\n service: TerminologyService | null,\n binding: Binding | undefined,\n codings: Coding[],\n storesCodes: boolean,\n): ListWarnings {\n const [warnings, setWarnings] = useState<ListWarnings>(NONE);\n // The service's own validate, bound to it; none: nothing is checked.\n const validate = useMemo(() => service?.validate?.bind(service), [service]);\n const active = !!validate && checks(binding, storesCodes);\n // The codes and the list, as values: a new array of the same codes asks nothing new.\n const codes = active\n ? JSON.stringify(codings.map((c) => [c.system, c.code]))\n : \"[]\";\n const valueSet = binding?.valueSet;\n const system = binding?.system;\n const version = binding?.version;\n\n useEffect(() => {\n const stored = (JSON.parse(codes) as [string, string][]).map(\n ([s, code]): Coding => ({ system: s, code }),\n );\n if (!validate || !active || stored.length === 0) {\n setWarnings(NONE);\n return;\n }\n const list: Binding = { valueSet, system, version, strength: \"required\" };\n let live = true;\n void Promise.all(stored.map((c) => warningOf(validate, list, c))).then(\n (found) => {\n if (!live) return;\n const entries = found.filter((w) => w !== undefined);\n setWarnings(entries.length ? new Map(entries) : NONE);\n },\n );\n return () => {\n live = false;\n };\n }, [active, validate, codes, valueSet, system, version]);\n\n return warnings;\n}\n","/**\n * A coded-value field's search and hits: the search input, each hit with its\n * code and path, more on request, a typed text when the list takes one --\n * shared by the coded value's picker and the codeable concept's.\n */\n\nimport * as React from \"react\";\nimport { Check } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { codingKey } from \"@petrarca/sonnet-core/schema\";\nimport type { CodingHit } from \"@petrarca/sonnet-core/terminology\";\nimport {\n CodedValueDisplay,\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"@petrarca/sonnet-ui\";\nimport type { CodedValueOptions } from \"./useCodedValueOptions\";\n\n// What the list shows when it has no hit.\nfunction emptyMessage(o: CodedValueOptions): string {\n if (o.loading) return \"Loading...\";\n if (o.error) return \"The list could not be loaded.\";\n const typed = o.search.trim().length;\n if (o.mode === \"search\" && typed < o.minChars)\n return o.minChars > 1 && typed > 0\n ? `Type at least ${o.minChars} characters...`\n : \"Type to search...\";\n return \"No matches.\";\n}\n\nfunction HitItem({\n hit,\n selected,\n onPick,\n}: {\n hit: CodingHit;\n selected: boolean;\n onPick: (hit: CodingHit) => void;\n}): React.ReactElement {\n return (\n <CommandItem value={codingKey(hit)} onSelect={() => onPick(hit)}>\n <Check\n className={cn(\n \"mr-2 h-4 w-4 shrink-0\",\n selected ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n <div className=\"min-w-0\">\n <CodedValueDisplay code={hit.code} display={hit.display} />\n {hit.path && hit.path.length > 0 && (\n <div className=\"truncate text-xs text-muted-foreground\">\n {hit.path.join(\" › \")}\n </div>\n )}\n </div>\n </CommandItem>\n );\n}\n\nexport function HitList({\n options,\n selected,\n freeText,\n onPick,\n onFreeText,\n}: {\n options: CodedValueOptions;\n selected: ReadonlySet<string>;\n freeText?: string;\n onPick: (hit: CodingHit) => void;\n onFreeText: (text: string) => void;\n}): React.ReactElement {\n return (\n <Command shouldFilter={false}>\n <CommandInput\n placeholder=\"Search...\"\n value={options.search}\n onValueChange={options.setSearch}\n />\n <CommandList>\n <CommandEmpty>{emptyMessage(options)}</CommandEmpty>\n <CommandGroup>\n {options.hits.map((hit) => (\n <HitItem\n key={codingKey(hit)}\n hit={hit}\n selected={selected.has(codingKey(hit))}\n onPick={onPick}\n />\n ))}\n {options.hasMore && (\n <CommandItem value=\"__more\" onSelect={options.loadMore}>\n <span className=\"text-sm text-muted-foreground\">\n Show more\n {options.total !== undefined &&\n ` (${options.hits.length} of ${options.total})`}\n </span>\n </CommandItem>\n )}\n {freeText && (\n <CommandItem value=\"__text\" onSelect={() => onFreeText(freeText)}>\n <span className=\"text-sm\">Use &ldquo;{freeText}&rdquo;</span>\n </CommandItem>\n )}\n </CommandGroup>\n </CommandList>\n </Command>\n );\n}\n","/**\n * An icon inside a trigger that acts on its own -- removing a chip, clearing a\n * value -- without opening what the trigger opens, and never a tab stop.\n */\n\nimport * as React from \"react\";\n\n// An icon inside the trigger that acts on its own -- not opening the list, never a tab stop.\nexport function InlineIconButton({\n label,\n onAct,\n children,\n}: {\n label: string;\n onAct: () => void;\n children: React.ReactNode;\n}): React.ReactElement {\n const act = (e: React.PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onAct();\n };\n return (\n <span\n role=\"button\"\n aria-label={label}\n tabIndex={-1}\n className=\"rounded-sm opacity-50 hover:opacity-100\"\n onPointerDown={act}\n >\n {children}\n </span>\n );\n}\n","/**\n * A coded-value field's list and the options that shape its search: the\n * binding's list as a stable ref, the mode and the characters a search waits\n * for -- shared by the coded value and the codeable concept.\n */\n\nimport * as React from \"react\";\nimport type { Binding } from \"@petrarca/sonnet-core/schema\";\nimport type { ListRef } from \"@petrarca/sonnet-core/terminology\";\nimport type { WidgetProps } from \"../types\";\nimport type { CodedValueMode } from \"./useCodedValueOptions\";\n\n// The mode x-ui-options asks for, if any.\nexport function modeOption(\n options: WidgetProps[\"options\"],\n): CodedValueMode | undefined {\n const mode = options?.mode;\n return mode === \"list\" || mode === \"search\" ? mode : undefined;\n}\n\n// The characters a search waits for: x-ui-options.minChars, at least one.\nexport function minCharsOption(options: WidgetProps[\"options\"]): number {\n const n = options?.minChars;\n return typeof n === \"number\" && n >= 1 ? n : 1;\n}\n\n// The binding's list, stable while the binding is the same.\nexport function useListRef(binding: Binding | undefined): ListRef | undefined {\n const { valueSet, system, version } = binding ?? {};\n return React.useMemo(\n () => (valueSet || system ? { valueSet, system, version } : undefined),\n [valueSet, system, version],\n );\n}\n","/**\n * CodeableConceptWidget -- one concept, coded in the field's lists, compact:\n * the coded-value picker on the first list, and one line of chips for the\n * codings of the others -- as clinical systems show a concept: its term, the\n * other codes beside it.\n *\n * [ Glucose [Mass/volume] in Serum or Plasma 2345-7 v ]\n * [Lab GLU-S x] [Registry *] + Coding + Text\n *\n * A chip -- or \"+ Coding\", for a list without one -- opens the same search on\n * its list. What a person picks is stored as theirs (`userSelected`), with the\n * list's purpose; a required list without a coding shows as an empty chip. A\n * coding of a list the field does not name is shown and kept, never dropped.\n *\n * The lists are the field's binding (`x-binding`): the first, then\n * `additional`. Registered as x-ui-widget: \"codeable-concept\"; the core\n * codeable concept type carries that hint.\n *\n * x-ui-options:\n * text - offer the text (default: when the first list is extensible)\n * mode - \"list\" | \"search\", for every list (default: each list's size decides)\n * minChars - the characters a search waits for\n *\n * See docs/design/codeable-concepts.md (workspace).\n */\n\nimport * as React from \"react\";\nimport { Plus, X } from \"lucide-react\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport {\n bindingLists,\n bindingOf,\n CODING_TYPE,\n codingKey,\n codingsByList,\n conceptOf,\n listTitle,\n type AdditionalBinding,\n type ConceptCoding,\n type JsonSchemaProperty,\n} from \"@petrarca/sonnet-core/schema\";\nimport {\n useTerminology,\n type CodingHit,\n} from \"@petrarca/sonnet-core/terminology\";\nimport {\n Badge,\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n Popover,\n PopoverAnchor,\n PopoverContent,\n} from \"@petrarca/sonnet-ui\";\nimport { FormFieldWrapper } from \"../FormFieldWrapper\";\nimport { FormInput } from \"../FormInput\";\nimport { CodedValueWidget } from \"./CodedValueWidget\";\nimport { firstError, type WidgetProps } from \"./types\";\nimport {\n withRow,\n withSuggested,\n withText,\n} from \"./codeableConcept/conceptModel\";\nimport { HitList } from \"./codedValue/HitList\";\nimport { InlineIconButton } from \"./codedValue/InlineIconButton\";\nimport {\n minCharsOption,\n modeOption,\n useListRef,\n} from \"./codedValue/listOptions\";\nimport { toStored, type FieldModel } from \"./codedValue/codedValueModel\";\nimport { useCodedValueOptions } from \"./codedValue/useCodedValueOptions\";\n\n// A list as a coded value's field: a coding, only the list's codes.\nfunction listSchema(list: AdditionalBinding): JsonSchemaProperty {\n const { valueSet, system, version } = list;\n return {\n ...CODING_TYPE.definition,\n \"x-binding\": {\n ...(valueSet ? { valueSet } : {}),\n ...(system ? { system } : {}),\n ...(version ? { version } : {}),\n strength: \"required\",\n },\n };\n}\n\n// A hit as the coding it stores: its system, code, version and label.\nconst AS_CODING: FieldModel = {\n multiple: false,\n shape: \"coding\",\n store: \"code\",\n keep: [],\n};\n\n// Whether the field offers its text: as its options say, else when the first list is open.\nfunction offersText(props: WidgetProps, extensible: boolean): boolean {\n const text = props.options?.text;\n return typeof text === \"boolean\" ? text : extensible;\n}\n\n/** One coding as a chip: its list, its code, its label on hover; mapped ones marked. */\nfunction CodingChip({\n label,\n coding,\n onOpen,\n onRemove,\n}: {\n label: string;\n coding: ConceptCoding;\n onOpen?: () => void;\n onRemove?: () => void;\n}): React.ReactElement {\n const mapped = coding.match !== undefined && !coding.userSelected;\n return (\n <Badge\n variant=\"secondary\"\n className={cn(\"gap-1 font-normal\", onOpen && \"cursor-pointer\")}\n title={coding.display ?? coding.code}\n onClick={onOpen}\n >\n <span className=\"text-muted-foreground\">{label}</span>\n <span className=\"font-mono text-xs\">{coding.code}</span>\n {mapped && <span className=\"text-muted-foreground\">· mapped</span>}\n {onRemove && (\n <InlineIconButton label={`Remove ${label}`} onAct={onRemove}>\n <X className=\"h-3 w-3\" />\n </InlineIconButton>\n )}\n </Badge>\n );\n}\n\n/** A required list without a coding: an empty chip that opens its search. */\nfunction MissingChip({\n label,\n onOpen,\n}: {\n label: string;\n onOpen?: () => void;\n}): React.ReactElement {\n return (\n <Badge\n variant=\"outline\"\n className={cn(\n \"gap-1 border-dashed font-normal text-muted-foreground\",\n onOpen && \"cursor-pointer\",\n )}\n onClick={onOpen}\n >\n {label}\n <span className=\"text-destructive\">*</span>\n </Badge>\n );\n}\n\n/** The search on one list, in the chips' popover: a hit picked is the list's coding. */\nfunction ListSearch({\n list,\n props,\n selected,\n onPick,\n}: {\n list: AdditionalBinding;\n props: WidgetProps;\n selected: ConceptCoding | undefined;\n onPick: (hit: CodingHit) => void;\n}): React.ReactElement {\n const service = useTerminology();\n const ref = useListRef({ ...list, strength: \"required\" });\n const options = useCodedValueOptions(\n service,\n ref,\n modeOption(props.options),\n minCharsOption(props.options),\n );\n return (\n <div className=\"space-y-1\">\n <p className=\"px-2 pt-2 text-xs font-medium text-muted-foreground\">\n {listTitle(list)}\n </p>\n <HitList\n options={options}\n selected={new Set(selected ? [codingKey(selected)] : [])}\n onPick={onPick}\n onFreeText={() => undefined}\n />\n </div>\n );\n}\n\n/** \"+ Coding\": the lists after the first that have no coding yet, to pick from. */\nfunction AddCoding({\n lists,\n onOpen,\n}: {\n lists: [AdditionalBinding, number][];\n onOpen: (row: number) => void;\n}): React.ReactElement | null {\n // The list chosen: its search opens once the menu has closed -- else the\n // menu, handing the focus back, would close the search as it opens.\n const chosen = React.useRef<number | null>(null);\n if (lists.length === 0) return null;\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-6 gap-1 px-2 text-xs\"\n >\n <Plus className=\"h-3 w-3\" />\n Coding\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"start\"\n onCloseAutoFocus={(e) => {\n if (chosen.current === null) return;\n e.preventDefault();\n onOpen(chosen.current);\n chosen.current = null;\n }}\n >\n {lists.map(([list, row]) => (\n <DropdownMenuItem key={row} onSelect={() => (chosen.current = row)}>\n {listTitle(list)}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\n/** What the chips act on: the field's lists, their codings, and what a chip does. */\ninterface ChipsProps {\n lists: AdditionalBinding[];\n rows: (ConceptCoding | undefined)[];\n others: ConceptCoding[];\n /** Open a list's search; none when the field cannot be edited. */\n open?: (row: number) => void;\n /** Set or clear a list's coding; none when the field cannot be edited. */\n set?: (row: number, coding: ConceptCoding | undefined) => void;\n /** Show the text input; none when the text is not offered, or shown already. */\n addText?: () => void;\n}\n\n// One list's chip after the first: its coding, an empty required one, or none.\nfunction ListChip({\n list,\n row,\n coding,\n open,\n set,\n}: {\n list: AdditionalBinding;\n row: number;\n coding: ConceptCoding | undefined;\n open?: (row: number) => void;\n set?: ChipsProps[\"set\"];\n}): React.ReactElement | null {\n const onOpen = open && (() => open(row));\n if (coding)\n return (\n <CodingChip\n label={listTitle(list)}\n coding={coding}\n onOpen={onOpen}\n onRemove={set && (() => set(row, undefined))}\n />\n );\n return list.required ? (\n <MissingChip label={listTitle(list)} onOpen={onOpen} />\n ) : null;\n}\n\n/** The line under the picker: the other lists' codings, those of no list, \"+ Coding\", \"+ Text\". */\nfunction ChipLine({ lists, rows, others, open, set, addText }: ChipsProps) {\n const addable = lists\n .map((l, i) => [l, i] as [AdditionalBinding, number])\n .filter(([l, i]) => i > 0 && !rows[i] && !l.required);\n return (\n <div className=\"flex flex-wrap items-center gap-1\">\n {lists.slice(1).map((list, k) => (\n <ListChip\n key={k + 1}\n list={list}\n row={k + 1}\n coding={rows[k + 1]}\n open={open}\n set={set}\n />\n ))}\n {others.map((c) => (\n <CodingChip key={codingKey(c)} label={listTitle(c)} coding={c} />\n ))}\n {open && <AddCoding lists={addable} onOpen={open} />}\n {addText && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-6 gap-1 px-2 text-xs\"\n onClick={addText}\n >\n <Plus className=\"h-3 w-3\" />\n Text\n </Button>\n )}\n </div>\n );\n}\n\n// The field's state: its lists and codings, the list being searched, whether the text is shown.\nfunction useConcept(props: WidgetProps) {\n const binding = bindingOf(props.propertySchema);\n const lists = binding ? bindingLists(binding) : [];\n const text = conceptOf(props.value).text ?? \"\";\n const [editing, setEditing] = React.useState<number | null>(null);\n const [showText, setShowText] = React.useState(false);\n const offered = offersText(props, binding?.strength === \"extensible\");\n const { byList: rows, others } = codingsByList(props.value, lists);\n return {\n lists,\n rows,\n others,\n text,\n editing,\n setEditing,\n textShown: offered && (showText || text !== \"\"),\n textAsked: showText,\n addText:\n offered && !showText && text === \"\" ? () => setShowText(true) : undefined,\n };\n}\n\n/**\n * The field's value as it changes: the latest, even before the form renders\n * it -- so a suggestion that answers at once lands on the code just picked --\n * and how it changes.\n */\nfunction useLatestValue(props: WidgetProps) {\n const latest = React.useRef(props.value);\n latest.current = props.value;\n return {\n get: () => latest.current,\n change: (next: unknown) => {\n latest.current = next;\n props.onChange(next);\n },\n };\n}\n\n/**\n * The service's suggestions once a code is picked in the first list: the code\n * translated into each further list still empty, each answer filling its list\n * -- if it is still empty then. None when the service cannot translate.\n */\nfunction useSuggestions(\n lists: AdditionalBinding[],\n { get, change }: ReturnType<typeof useLatestValue>,\n) {\n const service = useTerminology();\n return (coding: ConceptCoding | undefined) => {\n if (!coding || !service?.translate) return;\n const { system, code, version } = coding;\n const empty = codingsByList(get(), lists).byList.flatMap((c, row) =>\n row > 0 && !c ? [row] : [],\n );\n for (const row of empty)\n service\n .translate({\n coding: { system, code, ...(version ? { version } : {}) },\n targets: [lists[row]],\n })\n .then(([first]) => {\n if (first) change(withSuggested(get(), lists, row, first));\n })\n // A suggestion that fails is none: the list stays to be picked.\n .catch(() => undefined);\n };\n}\n\nexport function CodeableConceptWidget(props: WidgetProps): React.ReactElement {\n const { id, value, onBlur } = props;\n const c = useConcept(props);\n const editable = !props.disabled && !props.readonly;\n const blur = () => onBlur?.(id, value);\n const latest = useLatestValue(props);\n const suggest = useSuggestions(c.lists, latest);\n const set = (row: number, coding: ConceptCoding | undefined) => {\n latest.change(withRow(latest.get(), c.lists, row, coding));\n // A code picked in the first list: the further lists' codes suggested.\n if (row === 0) suggest(coding);\n };\n const editingList = c.editing !== null ? c.lists[c.editing] : undefined;\n\n return (\n <FormFieldWrapper\n inputId={id}\n label={props.label}\n description={props.description}\n required={props.required}\n error={firstError(props.rawErrors)}\n >\n <div className=\"space-y-1.5\">\n <FirstList\n props={props}\n lists={c.lists}\n coding={c.rows[0]}\n set={set}\n blur={blur}\n />\n <Popover\n open={editingList !== undefined}\n onOpenChange={(o) => {\n if (o) return;\n c.setEditing(null);\n blur();\n }}\n >\n <PopoverAnchor asChild>\n <div>\n <ChipLine\n lists={c.lists}\n rows={c.rows}\n others={c.others}\n open={editable ? c.setEditing : undefined}\n set={editable ? set : undefined}\n addText={editable ? c.addText : undefined}\n />\n </div>\n </PopoverAnchor>\n <PopoverContent\n className=\"w-[--radix-popover-trigger-width] min-w-72 p-0\"\n align=\"start\"\n >\n {editingList && c.editing !== null && (\n <ListSearch\n list={editingList}\n props={props}\n selected={c.rows[c.editing]}\n onPick={(hit) => {\n set(\n c.editing!,\n toStored(hit, AS_CODING, undefined) as ConceptCoding,\n );\n c.setEditing(null);\n }}\n />\n )}\n </PopoverContent>\n </Popover>\n {c.textShown && (\n <FormInput\n id={`${id}-text`}\n label=\"Text\"\n value={c.text}\n placeholder=\"In words, as the person said it\"\n disabled={props.disabled}\n readOnly={props.readonly}\n onChange={(e) =>\n latest.change(withText(latest.get(), e.target.value))\n }\n onBlur={blur}\n // Opened by \"+ Text\": the person asked for it, so it takes the focus.\n autoFocus={c.textAsked}\n />\n )}\n </div>\n </FormFieldWrapper>\n );\n}\n\n/** The first list: the coded value's own picker on it, the field's main control. */\nfunction FirstList({\n props,\n lists,\n coding,\n set,\n blur,\n}: {\n props: WidgetProps;\n lists: AdditionalBinding[];\n coding: ConceptCoding | undefined;\n set: (row: number, coding: ConceptCoding | undefined) => void;\n blur: () => void;\n}): React.ReactElement {\n if (!lists[0])\n return (\n <p className=\"text-sm text-muted-foreground\">\n No list is bound to this field.\n </p>\n );\n return (\n <CodedValueWidget\n {...props}\n label=\"\"\n description={undefined}\n rawErrors={undefined}\n propertySchema={listSchema(lists[0])}\n value={coding}\n onChange={(next) => set(0, next as ConceptCoding | undefined)}\n onBlur={blur}\n />\n );\n}\n","/**\n * The codeable-concept widget's pure side: the value after a list's coding or\n * the text changes. Which coding belongs to which list is sonnet-core's\n * (`codingsByList`). A coding of no list is kept, never dropped; the lists'\n * codings are stored first, in their order, so the first list's coding leads.\n * See docs/design/codeable-concepts.md (workspace).\n */\n\nimport {\n codingsByList,\n conceptOf,\n type AdditionalBinding,\n type CodeableConcept,\n type Coding,\n type CodingMatch,\n type ConceptCoding,\n} from \"@petrarca/sonnet-core/schema\";\n\n// A value from its parts; none when it has neither codings nor a text.\nfunction valueOf(codings: ConceptCoding[], text: string | undefined) {\n const t = text?.trim() ? text : undefined;\n if (codings.length === 0 && !t) return undefined;\n return {\n ...(codings.length ? { codings } : {}),\n ...(t ? { text: t } : {}),\n } satisfies CodeableConcept;\n}\n\n/**\n * The value with a row's coding picked by a person -- or cleared: picked, it is\n * theirs (`userSelected`, no `match`), with its list's purpose.\n */\nexport function withRow(\n value: unknown,\n lists: AdditionalBinding[],\n row: number,\n coding: Coding | undefined,\n): CodeableConcept | undefined {\n return withCoding(\n value,\n lists,\n row,\n coding && { ...coding, userSelected: true },\n );\n}\n\n/**\n * The value with a list's coding suggested by the service -- mapped from the\n * code picked: its `match`, not the person's. Only into a list still empty: a\n * person's code is never replaced by a suggestion.\n */\nexport function withSuggested(\n value: unknown,\n lists: AdditionalBinding[],\n row: number,\n suggestion: { coding: Coding; match?: CodingMatch },\n): CodeableConcept | undefined {\n if (codingsByList(value, lists).byList[row]) return conceptOf(value);\n const { coding, match } = suggestion;\n return withCoding(value, lists, row, {\n ...coding,\n ...(match ? { match } : {}),\n });\n}\n\n// The value with a list's coding set -- or cleared -- with its list's purpose.\nfunction withCoding(\n value: unknown,\n lists: AdditionalBinding[],\n row: number,\n coding: ConceptCoding | undefined,\n): CodeableConcept | undefined {\n const { byList: rows, others } = codingsByList(value, lists);\n const purpose = lists[row]?.purpose;\n const next = rows.map((c, i) =>\n i !== row ? c : coding && { ...coding, ...(purpose ? { purpose } : {}) },\n );\n return valueOf(\n [...next.filter((c): c is ConceptCoding => !!c), ...others],\n conceptOf(value).text,\n );\n}\n\n/** The value with its text -- none when empty. */\nexport function withText(\n value: unknown,\n text: string,\n): CodeableConcept | undefined {\n return valueOf(conceptOf(value).codings ?? [], text);\n}\n","/**\n * DateWidget - date field widget backed by the DateInput primitive.\n *\n * Renders a text input with calendar popover. Value is a partial ISO 8601 date\n * string (`YYYY`, `YYYY-MM`, or `YYYY-MM-DD`). Auto-resolves from schema\n * `format: \"date\"`, or `x-ui-widget: \"date\"`.\n *\n * Its range is the schema's `formatMinimum` / `formatMaximum`: the calendar\n * offers only the dates between; validation names a typed one outside.\n *\n * x-ui-options:\n * precision - \"year\" | \"month\" | \"day\" (default \"day\")\n * locale - BCP-47 locale override (defaults to the app locale)\n *\n * The label/description chrome comes from FormFieldWrapper; the primitive owns\n * the inline error message and invalid border.\n */\n\nimport { DateInput } from \"@petrarca/sonnet-ui\";\nimport type { DatePrecision } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"../FormFieldWrapper\";\nimport { WidgetProps, firstError } from \"./types\";\n\nfunction resolvePrecision(value: unknown): DatePrecision {\n return value === \"year\" || value === \"month\" ? value : \"day\";\n}\n\nexport function DateWidget({\n id,\n value,\n onChange,\n onBlur,\n required,\n disabled,\n rawErrors,\n label,\n description,\n placeholder,\n options,\n propertySchema,\n}: WidgetProps): React.ReactElement {\n const error = firstError(rawErrors);\n const precision = resolvePrecision(options?.precision);\n const locale =\n typeof options?.locale === \"string\" ? options.locale : undefined;\n\n return (\n <FormFieldWrapper\n inputId={id}\n label={label}\n description={description}\n required={required}\n labelPlacement={options?.labelPlacement}\n >\n <DateInput\n id={id}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={onChange}\n onBlur={() => onBlur?.(id, value)}\n precision={precision}\n locale={locale}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n error={error}\n min={propertySchema.formatMinimum}\n max={propertySchema.formatMaximum}\n />\n </FormFieldWrapper>\n );\n}\n","/**\n * TimeWidget - time-of-day field widget backed by the TimeInput primitive.\n *\n * Zone-free time value as a normalized ISO string (`HH:mm` or `HH:mm:ss`).\n * Auto-resolves from schema `format: \"time\"`, or `x-ui-widget: \"time\"`.\n *\n * x-ui-options:\n * granularity - \"minute\" | \"second\" (default \"minute\")\n *\n * The label/description chrome comes from FormFieldWrapper; the primitive owns\n * the inline error message and invalid border.\n */\n\nimport { TimeInput } from \"@petrarca/sonnet-ui\";\nimport type { TimeGranularity } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"../FormFieldWrapper\";\nimport { WidgetProps, firstError } from \"./types\";\n\nfunction resolveGranularity(value: unknown): TimeGranularity {\n return value === \"second\" ? \"second\" : \"minute\";\n}\n\nexport function TimeWidget({\n id,\n value,\n onChange,\n onBlur,\n required,\n disabled,\n rawErrors,\n label,\n description,\n placeholder,\n options,\n}: WidgetProps): React.ReactElement {\n const error = firstError(rawErrors);\n const granularity = resolveGranularity(options?.granularity);\n\n return (\n <FormFieldWrapper\n inputId={id}\n label={label}\n description={description}\n required={required}\n labelPlacement={options?.labelPlacement}\n >\n <TimeInput\n id={id}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={onChange}\n onBlur={() => onBlur?.(id, value)}\n granularity={granularity}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n error={error}\n />\n </FormFieldWrapper>\n );\n}\n","/**\n * DateTimeWidget - date + time field widget backed by the DateTimeInput primitive.\n *\n * Plain wall-clock value as an ISO string (`YYYY-MM-DDTHH:mm[:ss]`), no\n * timezone. Auto-resolves from schema `format: \"date-time\"`, or\n * `x-ui-widget: \"date-time\"`.\n *\n * x-ui-options:\n * granularity - \"minute\" | \"second\" (default \"minute\")\n * timeZone - IANA id shown as a display-only hint (never applied)\n * locale - BCP-47 locale override for the date part\n *\n * The label/description chrome comes from FormFieldWrapper; the primitive owns\n * the inline error message and invalid border.\n */\n\nimport { DateTimeInput } from \"@petrarca/sonnet-ui\";\nimport type { TimeGranularity } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"../FormFieldWrapper\";\nimport { WidgetProps, firstError } from \"./types\";\n\nfunction resolveGranularity(value: unknown): TimeGranularity {\n return value === \"second\" ? \"second\" : \"minute\";\n}\n\nexport function DateTimeWidget({\n id,\n value,\n onChange,\n onBlur,\n required,\n disabled,\n rawErrors,\n label,\n description,\n options,\n propertySchema,\n}: WidgetProps): React.ReactElement {\n const error = firstError(rawErrors);\n const granularity = resolveGranularity(options?.granularity);\n const timeZone =\n typeof options?.timeZone === \"string\" ? options.timeZone : undefined;\n const locale =\n typeof options?.locale === \"string\" ? options.locale : undefined;\n\n return (\n <FormFieldWrapper\n inputId={id}\n label={label}\n description={description}\n required={required}\n labelPlacement={options?.labelPlacement}\n >\n <DateTimeInput\n idPrefix={id}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={onChange}\n onBlur={() => onBlur?.(id, value)}\n granularity={granularity}\n timeZone={timeZone}\n locale={locale}\n required={required}\n disabled={disabled}\n error={error}\n min={propertySchema.formatMinimum}\n max={propertySchema.formatMaximum}\n />\n </FormFieldWrapper>\n );\n}\n","/**\n * DisplayWidget - read-only text block, no data binding.\n *\n * Renders a property's title (and optional description) as static text --\n * instructions, notes, disclaimers placed between fields. Collects no value.\n * Auto-resolves from `type: \"null\"`, or `x-ui-widget: \"display\"`.\n *\n * Modeled as a value-less property so it participates in field ordering and\n * layout (appears exactly where placed). It never contributes to form data.\n */\n\nimport { WidgetProps } from \"./types\";\n\nexport function DisplayWidget({\n label,\n description,\n}: WidgetProps): React.ReactElement | null {\n if (!label && !description) return null;\n return (\n <div className=\"space-y-1\">\n {label && <p className=\"text-sm text-foreground\">{label}</p>}\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n );\n}\n","/**\n * OneOfWidget -- renders a discriminated union (oneOf).\n *\n * A branch selector (reusing the Select primitive) chooses one of the property's\n * `oneOf` branches; the selected branch's object sub-schema is then rendered as\n * a nested sub-form (same pattern as ObjectWidget). The active branch is tracked\n * by the discriminator property (see the oneOf helpers in\n * @petrarca/sonnet-core/schema).\n *\n * Auto-resolves when a property has `oneOf`, or via `x-ui-widget: \"one-of\"`.\n */\n\nimport { useMemo } from \"react\";\nimport type {\n JsonSchema,\n JsonSchemaProperty,\n UISchema,\n} from \"@petrarca/sonnet-core/schema\";\nimport {\n getDiscriminator,\n getBranchValue,\n getBranchLabel,\n findActiveBranch,\n} from \"@petrarca/sonnet-core/schema\";\nimport {\n Label,\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n} from \"@petrarca/sonnet-ui\";\nimport { useNestedFormContext } from \"../hooks/useNestedFormContext\";\nimport { DefaultObjectContainerTemplate } from \"../templates/DefaultObjectContainerTemplate\";\nimport type { WidgetProps } from \"./types\";\n\ninterface BranchChoice {\n index: number;\n value: string;\n label: string;\n}\n\n// Build the selectable branch list from the property's oneOf.\nfunction buildChoices(\n branches: JsonSchemaProperty[],\n discriminator: string | undefined,\n): BranchChoice[] {\n return branches.map((branch, index) => {\n const raw = discriminator\n ? getBranchValue(branch, discriminator)\n : undefined;\n return {\n index,\n value: raw !== undefined ? String(raw) : String(index),\n label: getBranchLabel(branch, discriminator, index),\n };\n });\n}\n\n// Build a renderable object sub-schema from a branch.\nfunction buildBranchSchema(branch: JsonSchemaProperty): JsonSchema | null {\n if (!branch.properties) return null;\n return {\n title: branch.title || \"\",\n type: \"object\",\n properties: branch.properties,\n required: branch.required,\n ...(branch[\"x-ui-order\"] ? { \"x-ui-order\": branch[\"x-ui-order\"] } : {}),\n };\n}\n\n// Reset data to just the new discriminator value so stale branch-specific\n// fields do not leak across branches.\nfunction branchChangeData(\n choices: BranchChoice[],\n branches: JsonSchemaProperty[],\n discriminator: string | undefined,\n selected: string,\n): Record<string, unknown> {\n const choice = choices.find((c) => c.value === selected);\n if (!choice || !discriminator) return {};\n const discValue =\n getBranchValue(branches[choice.index], discriminator) ?? selected;\n return { [discriminator]: discValue };\n}\n\nfunction BranchSelector({\n id,\n label,\n description,\n choices,\n activeValue,\n disabled,\n onSelect,\n}: {\n id?: string;\n label?: string;\n description?: string;\n choices: BranchChoice[];\n activeValue: string;\n disabled?: boolean;\n onSelect: (value: string) => void;\n}): React.ReactElement {\n return (\n <div className=\"space-y-1\">\n {label && <Label htmlFor={id}>{label}</Label>}\n <Select value={activeValue} onValueChange={onSelect} disabled={disabled}>\n <SelectTrigger id={id}>\n <SelectValue placeholder=\"Select an option\" />\n </SelectTrigger>\n <SelectContent>\n {choices.map((c) => (\n <SelectItem key={c.value} value={c.value}>\n {c.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n );\n}\n\n// The branch sub-form's overlay. The branch selector already shows and sets the\n// discriminator, so the sub-form hides it -- hidden, not dropped, so its value\n// still round-trips.\nfunction branchUiSchema(\n uiSchema: UISchema | undefined,\n discriminator: string | undefined,\n): { [fieldName: string]: UISchema } {\n const fields = (uiSchema?.[\"x-ui-fields\"] ?? {}) as {\n [fieldName: string]: UISchema;\n };\n if (!discriminator) return fields;\n return { [discriminator]: { \"x-ui-options\": { hidden: true } }, ...fields };\n}\n\n// Resolve which branch is active for the current data, with its label + schema.\nfunction resolveActive(\n propertySchema: JsonSchemaProperty,\n branches: JsonSchemaProperty[],\n choices: BranchChoice[],\n discriminator: string | undefined,\n data: Record<string, unknown>,\n): { value: string; label: string; subSchema: JsonSchema | null } {\n const index = findActiveBranch(propertySchema, data, discriminator);\n if (index < 0) return { value: \"\", label: \"\", subSchema: null };\n return {\n value: choices[index]?.value ?? \"\",\n label: choices[index]?.label ?? \"\",\n subSchema: buildBranchSchema(branches[index]),\n };\n}\n\nexport function OneOfWidget({\n propertySchema,\n value,\n onChange,\n registry,\n uiSchema,\n disabled,\n readonly,\n label,\n description,\n id,\n options,\n}: WidgetProps): React.ReactElement | null {\n const { renderer: Renderer, templates } = useNestedFormContext();\n const ContainerTemplate =\n templates.ObjectContainerTemplate ?? DefaultObjectContainerTemplate;\n\n const branches = useMemo(() => propertySchema.oneOf ?? [], [propertySchema]);\n const discriminator = useMemo(\n () => getDiscriminator(propertySchema),\n [propertySchema],\n );\n const choices = useMemo(\n () => buildChoices(branches, discriminator),\n [branches, discriminator],\n );\n\n const data = (value as Record<string, unknown>) || {};\n const active = resolveActive(\n propertySchema,\n branches,\n choices,\n discriminator,\n data,\n );\n\n if (branches.length === 0) return null;\n\n const subUiSchema = branchUiSchema(uiSchema, discriminator);\n\n return (\n <div className=\"space-y-4\">\n <BranchSelector\n id={id}\n label={label}\n description={description}\n choices={choices}\n activeValue={active.value}\n disabled={disabled || readonly}\n onSelect={(selected) =>\n onChange(branchChangeData(choices, branches, discriminator, selected))\n }\n />\n {active.subSchema && (\n <ContainerTemplate\n label={active.label}\n description={undefined}\n variant={(options?.variant as string) || \"section\"}\n defaultOpen\n >\n <Renderer\n schema={active.subSchema}\n data={data}\n onChange={onChange}\n disabled={disabled}\n readOnly={readonly}\n widgets={registry}\n uiSchema={subUiSchema}\n // Scope the branch's control ids to this field, so a oneOf inside\n // an array item does not collide with its siblings.\n idPrefix={id}\n />\n </ContainerTemplate>\n )}\n </div>\n );\n}\n","/**\n * RadioWidget -- a single choice as radio buttons, every option in view.\n *\n * For an enum property, selected by `x-ui-widget: \"radio\"`. Labels come from\n * x-ui-options.enumNames, as for the select. `x-ui-options.orientation`\n * \"horizontal\" lays the options out in a row (default: a column).\n */\n\nimport { RadioGroup, RadioGroupItem } from \"@petrarca/sonnet-ui\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"../FormFieldWrapper\";\nimport { buildSelectOptions } from \"../formSelectUtils\";\nimport { WidgetProps, firstError } from \"./types\";\n\nexport function RadioWidget({\n id,\n name,\n value,\n onChange,\n onBlur,\n propertySchema,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n options,\n}: WidgetProps): React.ReactElement {\n const choices = buildSelectOptions(propertySchema, options?.enumNames ?? {});\n const horizontal = options?.orientation === \"horizontal\";\n return (\n <FormFieldWrapper\n inputId={id}\n label={label}\n description={description}\n error={firstError(rawErrors)}\n required={required}\n compact={options?.compact}\n >\n <RadioGroup\n id={id}\n name={name}\n value={value === undefined || value === null ? \"\" : String(value)}\n onValueChange={(v) => onChange(v)}\n onBlur={() => onBlur?.(id, value)}\n disabled={disabled || readonly}\n required={required}\n className={cn(horizontal && \"flex flex-wrap gap-4\")}\n >\n {choices.map((c) => (\n <label key={c.value} className=\"flex items-center gap-2 text-sm\">\n <RadioGroupItem value={c.value} id={`${id}-${c.value}`} />\n {c.label}\n </label>\n ))}\n </RadioGroup>\n </FormFieldWrapper>\n );\n}\n","/**\n * CheckboxGroupWidget -- a multiple choice as checkboxes, every option in view.\n *\n * For an array of enum items, selected by `x-ui-widget: \"checkbox-group\"`.\n * Labels come from x-ui-options.enumNames, as for the select; the value keeps\n * the options' order. `x-ui-options.orientation` \"horizontal\" lays them out in\n * a row (default: a column).\n */\n\nimport { Checkbox } from \"@petrarca/sonnet-ui\";\nimport { cn } from \"@petrarca/sonnet-core\";\nimport { FormFieldWrapper } from \"../FormFieldWrapper\";\nimport { buildSelectOptions } from \"../formSelectUtils\";\nimport { WidgetProps, firstError } from \"./types\";\n\nexport function CheckboxGroupWidget({\n id,\n value,\n onChange,\n onBlur,\n propertySchema,\n required,\n disabled,\n readonly,\n rawErrors,\n label,\n description,\n options,\n}: WidgetProps): React.ReactElement {\n const choices = buildSelectOptions(propertySchema, options?.enumNames ?? {});\n const chosen = new Set(Array.isArray(value) ? value.map(String) : []);\n const toggle = (v: string, on: boolean) => {\n const next = choices\n .map((c) => c.value)\n .filter((c) => (c === v ? on : chosen.has(c)));\n onChange(next);\n };\n return (\n <FormFieldWrapper\n inputId={id}\n label={label}\n description={description}\n error={firstError(rawErrors)}\n required={required}\n compact={options?.compact}\n >\n <div\n id={id}\n role=\"group\"\n className={cn(\n \"grid gap-2\",\n options?.orientation === \"horizontal\" && \"flex flex-wrap gap-4\",\n )}\n onBlur={() => onBlur?.(id, value)}\n >\n {choices.map((c) => (\n <label key={c.value} className=\"flex items-center gap-2 text-sm\">\n <Checkbox\n id={`${id}-${c.value}`}\n checked={chosen.has(c.value)}\n onCheckedChange={(on) => toggle(c.value, on === true)}\n disabled={disabled || readonly}\n />\n {c.label}\n </label>\n ))}\n </div>\n </FormFieldWrapper>\n );\n}\n","/**\n * ChoiceWithTextWidget -- a choice and a text as one answer: \"one of these, and\n * add detail\".\n *\n * A container, selected by `x-ui-widget: \"choice-with-text\"` on an object of\n * `choice` (an enum) and `text` (a string). It only arranges the two -- the\n * choice beside the text, the choice unlabelled -- and renders them as any\n * nested object is (ObjectWidget, inline, under the question's own label):\n * each child by its own widget, resolved as\n * for any field. So the choice is a select, radio buttons or an application's\n * terminology picker, set on the child (`x-ui-fields.choice`), and the text a\n * line or a textarea.\n */\n\nimport type { UILayoutConfig, UISchema } from \"@petrarca/sonnet-core/schema\";\nimport { FormFieldWrapper } from \"../FormFieldWrapper\";\nimport { ObjectWidget } from \"./ObjectWidget\";\nimport type { WidgetProps } from \"./types\";\n\n// The choice beside the text, the text taking the rest of the row.\nconst ROW_LAYOUT: UILayoutConfig = {\n rows: [{ fields: [\"choice\", \"text\"], widths: [\"md\", \"full\"] }],\n};\n\n// The text's title: the text sits among the properties (a note) or in the\n// conditional that asks for it (\"other, please describe\").\nfunction textTitleOf(prop: WidgetProps[\"propertySchema\"]): string | undefined {\n const text = prop.properties?.text ?? prop.allOf?.[0]?.then?.properties?.text;\n return text?.title;\n}\n\n// One answer, one label: the question's. The two children go unlabelled on one\n// line -- the text's title becomes its placeholder.\nfunction containerUiSchema(props: WidgetProps): UISchema {\n const fields = (props.uiSchema?.[\"x-ui-fields\"] ?? {}) as Record<\n string,\n UISchema\n >;\n const textTitle = textTitleOf(props.propertySchema);\n const layout = props.uiSchema?.[\"x-ui-layout\"] as UILayoutConfig | undefined;\n return {\n ...props.uiSchema,\n \"x-ui-layout\": layout ?? ROW_LAYOUT,\n \"x-ui-fields\": {\n ...fields,\n choice: { \"x-ui-title\": false, ...fields.choice },\n text: {\n \"x-ui-title\": false,\n ...(textTitle ? { \"x-ui-placeholder\": textTitle } : {}),\n ...fields.text,\n },\n },\n };\n}\n\nexport function ChoiceWithTextWidget(\n props: WidgetProps,\n): React.ReactElement | null {\n return (\n <FormFieldWrapper\n inputId={props.id}\n label={props.label}\n description={props.description}\n required={props.required}\n compact={props.options?.compact}\n >\n <ObjectWidget\n {...props}\n uiSchema={containerUiSchema(props)}\n options={{ ...props.options, variant: \"inline\" }}\n />\n </FormFieldWrapper>\n );\n}\n","/**\n * AbsentReasonsWidget -- the questions of a section left unanswered, and why:\n * one row each, the question and its reason (*unknown*, *not applicable*).\n *\n * For an object property mapping question keys to reasons, selected by\n * `x-ui-widget: \"absent-reasons\"`. The reasons are its `additionalProperties`\n * enum, labelled by x-ui-options.enumNames; the questions are its siblings in\n * the form schema it renders in -- every field but itself and static texts.\n */\n\nimport {\n Button,\n IconButton,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@petrarca/sonnet-ui\";\nimport { Plus, X } from \"lucide-react\";\nimport type { JsonSchemaProperty } from \"@petrarca/sonnet-core/schema\";\nimport { FormFieldWrapper } from \"../FormFieldWrapper\";\nimport { buildSelectOptions } from \"../formSelectUtils\";\nimport { WidgetProps, firstError } from \"./types\";\n\ntype Reasons = Record<string, string>;\n\nfunction Pick({\n label,\n value,\n items,\n onChange,\n className,\n}: {\n label: string;\n value: string;\n items: { value: string; label: string }[];\n onChange: (v: string) => void;\n className: string;\n}): React.ReactElement {\n return (\n <Select value={value || undefined} onValueChange={onChange}>\n <SelectTrigger aria-label={label} className={className}>\n <SelectValue placeholder={label.toLowerCase()} />\n </SelectTrigger>\n <SelectContent>\n {items.map((i) => (\n <SelectItem key={i.value} value={i.value}>\n {i.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n}\n\n// The questions a reason may be given for: the form's fields but this one and static texts.\nfunction questionsOf(props: WidgetProps): { value: string; label: string }[] {\n return Object.entries(props.schema.properties ?? {})\n .filter(([key, p]) => key !== props.name && p.type !== \"null\")\n .map(([key, p]) => ({ value: key, label: p.title ?? key }));\n}\n\ntype Option = { value: string; label: string };\n\n// One question left unanswered: which, and why.\nfunction ReasonRow({\n questionKey,\n reason,\n given,\n questions,\n reasons,\n locked,\n set,\n}: {\n questionKey: string;\n reason: string;\n given: Reasons;\n questions: Option[];\n reasons: Option[];\n locked: boolean | undefined;\n set: (next: Reasons) => void;\n}): React.ReactElement {\n const { [questionKey]: _, ...rest } = given;\n return (\n <div className=\"group/row flex items-center gap-1.5 px-1.5 py-1\">\n <Pick\n label=\"Question\"\n value={questionKey}\n items={questions.filter(\n (q) => q.value === questionKey || !(q.value in given),\n )}\n onChange={(next) => set({ ...rest, [next]: reason })}\n className=\"h-7 min-w-0 flex-1 text-xs\"\n />\n <Pick\n label=\"Reason\"\n value={reason}\n items={reasons}\n onChange={(r) => set({ ...given, [questionKey]: r })}\n className=\"h-7 w-40 shrink-0 text-xs\"\n />\n {!locked && (\n <IconButton\n label=\"Answer it after all\"\n revealOnHover\n onClick={() => set(rest)}\n >\n <X />\n </IconButton>\n )}\n </div>\n );\n}\n\n// What the widget shows: the reasons, those given, the questions, and whether\n// one more may be left unanswered.\nfunction reasonsState(props: WidgetProps) {\n const { value, readonly, disabled, options } = props;\n const additional = props.propertySchema.additionalProperties as\n | JsonSchemaProperty\n | undefined;\n const reasons = buildSelectOptions(\n additional ?? {},\n options?.enumNames ?? {},\n );\n const given: Reasons =\n value && typeof value === \"object\" ? (value as Reasons) : {};\n const questions = questionsOf(props);\n const free = questions.filter((q) => !(q.value in given));\n const locked = readonly || disabled;\n return {\n reasons,\n given,\n questions,\n free,\n locked,\n canAdd: !locked && free.length > 0 && reasons.length > 0,\n };\n}\n\nexport function AbsentReasonsWidget(props: WidgetProps): React.ReactElement {\n const { id, onChange, label, rawErrors, options } = props;\n const { reasons, given, questions, free, locked, canAdd } =\n reasonsState(props);\n const set = (next: Reasons) =>\n onChange(Object.keys(next).length ? next : undefined);\n\n return (\n <FormFieldWrapper\n inputId={id}\n label={label}\n error={firstError(rawErrors)}\n compact={options?.compact}\n >\n <div className=\"space-y-1.5\">\n {Object.keys(given).length > 0 && (\n <div className=\"rounded-md border divide-y\">\n {Object.entries(given).map(([key, reason]) => (\n <ReasonRow\n key={key}\n questionKey={key}\n reason={reason}\n given={given}\n questions={questions}\n reasons={reasons}\n locked={locked}\n set={set}\n />\n ))}\n </div>\n )}\n {canAdd && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 gap-1 px-2 text-xs\"\n onClick={() => set({ ...given, [free[0].value]: reasons[0].value })}\n >\n <Plus className=\"h-3.5 w-3.5\" />\n Leave a question unanswered\n </Button>\n )}\n </div>\n </FormFieldWrapper>\n );\n}\n","/**\n * Widget Resolution Algorithm\n *\n * Determines which widget to use for a given field based on:\n * 0. Schema x-ui-widget and x-ui-options (merged with uiSchema if present)\n * 1. UISchema x-ui-widget (highest priority - overrides x-ui-widget)\n * 2. Schema x-ui-widget (for widget name)\n * 3. Schema enum (uses SelectWidget)\n * 4. Schema format (email, date, color, etc.)\n * 5. Schema type (string, number, boolean, etc.)\n * 6. Fallback to TextWidget\n *\n * x-ui-widget is a simple string: 'textarea', 'select', etc.\n * x-ui-options is an object with configuration: { rows: 5, etc. }\n */\n\nimport { JsonSchemaProperty } from \"@petrarca/sonnet-core/schema\";\nimport {\n bindingOf,\n isNullableBoolean,\n isOneOf,\n extractEnumValues,\n getFieldType,\n} from \"@petrarca/sonnet-core/schema\";\nimport { Widget, WidgetRegistry, UISchema, WidgetMap } from \"./types\";\n\n/**\n * Default widget mapping: schema type → format/variant → widget name\n *\n * This defines which widget to use for each combination of schema type and format.\n * Follows the pattern established by react-jsonschema-form.\n *\n * Currently implemented widgets:\n * - TextInputWidget: Basic text input (email, url formats supported)\n * - TextareaWidget: Multi-line text input\n * - NumberWidget: Number and integer input\n * - CheckboxWidget: Boolean checkbox\n * - SelectWidget: Dropdown for enum values\n */\nexport const DEFAULT_WIDGET_MAP: WidgetMap = {\n string: {\n default: \"TextInputWidget\",\n textarea: \"TextareaWidget\",\n email: \"TextInputWidget\", // Uses email input type\n uri: \"TextInputWidget\", // Uses url input type\n url: \"TextInputWidget\", // Uses url input type\n date: \"DateWidget\",\n \"date-time\": \"DateTimeWidget\",\n time: \"TimeWidget\",\n },\n number: {\n default: \"NumberWidget\",\n },\n integer: {\n default: \"NumberWidget\", // NumberWidget handles both number and integer\n },\n boolean: {\n default: \"CheckboxWidget\",\n },\n null: {\n default: \"DisplayWidget\",\n },\n};\n\n/**\n * Resolve a widget name to a widget component using unified resolution logic\n *\n * This function handles both exact widget names and lowercase format names consistently.\n * Used by both schema-embedded x-ui-widget and explicit uiSchema resolution.\n *\n * @param widgetName - The widget name to resolve (e.g., 'TextareaWidget' or 'textarea')\n * @param propertySchema - The JSON schema for context (needed for type-based resolution)\n * @param registry - Widget registry to look up widgets\n * @returns The resolved widget component or null if not found\n */\nfunction resolveWidgetByName(\n widgetName: string,\n propertySchema: JsonSchemaProperty,\n registry: WidgetRegistry,\n): Widget | null {\n // Strategy 1: Direct registry lookup (for exact widget names like 'TextareaWidget')\n if (registry[widgetName]) {\n return registry[widgetName];\n }\n\n // Strategy 2: Map lowercase format names to widget names\n // This allows using 'textarea' instead of 'TextareaWidget' for consistency\n const type = getFieldType(propertySchema);\n const resolvedWidgetName =\n DEFAULT_WIDGET_MAP[type]?.[widgetName.toLowerCase()];\n if (resolvedWidgetName && registry[resolvedWidgetName]) {\n return registry[resolvedWidgetName];\n }\n\n return null;\n}\n\n/**\n * Merge x-ui-* extensions from a property schema with an explicit uiSchema.\n *\n * The explicit uiSchema has higher priority and overrides schema-embedded hints.\n * Returns undefined when neither source provides any values.\n */\nfunction mergeUiSchema(\n propertySchema: JsonSchemaProperty,\n uiSchema: UISchema | undefined,\n): UISchema | undefined {\n const xWidgetName = propertySchema[\"x-ui-widget\"];\n const xWidgetOptions = propertySchema[\"x-ui-options\"];\n\n if (!xWidgetName && !xWidgetOptions) return uiSchema;\n\n if (!uiSchema) {\n return {\n ...(xWidgetName && { \"x-ui-widget\": xWidgetName }),\n ...(xWidgetOptions && { \"x-ui-options\": xWidgetOptions }),\n };\n }\n\n return {\n ...(xWidgetName && { \"x-ui-widget\": xWidgetName }), // lower priority\n ...uiSchema, // higher priority\n \"x-ui-options\": {\n ...(xWidgetOptions || {}), // lower priority\n ...(uiSchema[\"x-ui-options\"] || {}), // higher priority\n },\n };\n}\n\n/**\n * Resolve which widget to use for a field.\n *\n * Resolution order (highest to lowest priority):\n * 1. x-ui-widget (from explicit uiSchema or schema-embedded extension)\n * 2. Schema structure: oneOf (OneOfWidget); anyOf boolean+null (tri-state\n * checkbox); enum, including the nullable anyOf enum (SelectWidget); an\n * object with properties (ObjectWidget); an array of such objects\n * (ArrayWidget); a string, a coding-or-text or an array bound to a list (CodedValueWidget); an array of enum items (multi-select SelectWidget); an\n * array of free strings (TagsInputWidget)\n * 3. type + format in schema (string, number, boolean, etc.)\n * 4. Fallback to TextInputWidget\n *\n * @param propertySchema - The JSON schema for this field\n * @param uiSchema - Optional UI schema customization (takes priority over schema hints)\n * @param registry - Widget registry to look up widgets\n * @returns The resolved widget component\n */\n// Step 1: Resolve from explicit x-ui-widget hint.\nfunction resolveFromUiWidget(\n uiWidget: unknown,\n propertySchema: JsonSchemaProperty,\n registry: WidgetRegistry,\n): Widget | null {\n if (typeof uiWidget === \"function\") return uiWidget as Widget;\n if (typeof uiWidget === \"string\")\n return resolveWidgetByName(uiWidget, propertySchema, registry);\n return null;\n}\n\n/** Check if a schema describes an array of objects with properties. */\nfunction isObjectArraySchema(schema: JsonSchemaProperty): boolean {\n return (\n schema.type === \"array\" &&\n schema.items?.type === \"object\" &&\n !!schema.items?.properties\n );\n}\n\n// An array of free strings (not an enum) -- edited as tags.\nfunction isStringArraySchema(schema: JsonSchemaProperty): boolean {\n return (\n schema.type === \"array\" &&\n schema.items?.type === \"string\" &&\n !Array.isArray(schema.items?.enum)\n );\n}\n\n// An object of string values and no declared fields (additionalProperties: string).\nfunction isStringMapSchema(schema: JsonSchemaProperty): boolean {\n const extra = (schema as { additionalProperties?: unknown })\n .additionalProperties;\n return (\n schema.type === \"object\" &&\n !schema.properties &&\n typeof extra === \"object\" &&\n extra !== null &&\n (extra as { type?: unknown }).type === \"string\"\n );\n}\n\n// An array whose items are an enum -- a multi-select.\nfunction isEnumArraySchema(schema: JsonSchemaProperty): boolean {\n return schema.type === \"array\" && Array.isArray(schema.items?.enum);\n}\n\n// What a list's codes are stored as: a string, a coding or a text, an array.\nfunction isCodedShape(schema: JsonSchemaProperty): boolean {\n return schema.type === \"string\" || schema.type === \"array\" || !!schema.anyOf;\n}\n\n/** Lookup a widget name in the registry, falling back to TextInputWidget. */\nfunction registryLookup(registry: WidgetRegistry, widgetName: string): Widget {\n return registry[widgetName] || registry[\"TextInputWidget\"];\n}\n\n// The widget of an object: its fields; a free map of strings (labels) as\n// key-value pairs shown as tags; any other free map edited as JSON.\nfunction objectWidgetName(schema: JsonSchemaProperty): string {\n if (schema.properties) return \"ObjectWidget\";\n if (isStringMapSchema(schema)) return \"KeyValueWidget\";\n return \"JsonEditorWidget\";\n}\n\n// The widget of an array, if its items decide one.\nfunction arrayWidgetName(schema: JsonSchemaProperty): string | null {\n if (isObjectArraySchema(schema)) return \"ArrayWidget\";\n if (isEnumArraySchema(schema)) return \"SelectWidget\";\n if (isStringArraySchema(schema)) return \"TagsInputWidget\";\n return null;\n}\n\n// Step 2-3: Resolve from schema structure (oneOf, nullable bool, enum, object, array).\nfunction resolveFromSchemaStructure(\n schema: JsonSchemaProperty,\n registry: WidgetRegistry,\n): Widget | null {\n if (isOneOf(schema)) return registryLookup(registry, \"OneOfWidget\");\n if (isNullableBoolean(schema))\n return registryLookup(registry, \"CheckboxWidget\");\n if (extractEnumValues(schema).length > 0)\n return registryLookup(registry, \"SelectWidget\");\n // Bound to a list: a string, a coding or a text (anyOf), or an array of them.\n if (bindingOf(schema) && isCodedShape(schema))\n return registryLookup(registry, \"CodedValueWidget\");\n if (schema.type === \"object\")\n return registryLookup(registry, objectWidgetName(schema));\n const arrayWidget = arrayWidgetName(schema);\n return arrayWidget ? registryLookup(registry, arrayWidget) : null;\n}\n\n// Step 4: Resolve from type + format via the default widget map.\nfunction resolveFromTypeFormat(\n schema: JsonSchemaProperty,\n registry: WidgetRegistry,\n): Widget {\n const type = getFieldType(schema);\n const format = schema.format;\n const widgetName =\n (format && DEFAULT_WIDGET_MAP[type]?.[format]) ||\n DEFAULT_WIDGET_MAP[type]?.default ||\n \"TextInputWidget\";\n return registry[widgetName] || registry[\"TextInputWidget\"];\n}\n\nexport function resolveWidget(\n propertySchema: JsonSchemaProperty,\n uiSchema: UISchema | undefined,\n registry: WidgetRegistry,\n): Widget {\n const effectiveUiSchema = mergeUiSchema(propertySchema, uiSchema);\n const uiWidget = effectiveUiSchema?.[\"x-ui-widget\"];\n if (uiWidget) {\n const resolved = resolveFromUiWidget(uiWidget, propertySchema, registry);\n if (resolved) return resolved;\n }\n return (\n resolveFromSchemaStructure(propertySchema, registry) ??\n resolveFromTypeFormat(propertySchema, registry)\n );\n}\n\n/**\n * Get the default widget name for a schema type\n *\n * Helper function to determine the default widget for a given type\n * without considering format or other factors.\n *\n * @param type - The JSON schema type\n * @returns The default widget name for that type\n *\n * @example\n * ```typescript\n * getDefaultWidgetForType('string'); // 'TextInputWidget'\n * getDefaultWidgetForType('number'); // 'NumberWidget'\n * getDefaultWidgetForType('boolean'); // 'CheckboxWidget'\n * ```\n */\nexport function getDefaultWidgetForType(type: string): string {\n return DEFAULT_WIDGET_MAP[type]?.default || \"TextInputWidget\";\n}\n","/**\n * Form Widgets - Index and Registry\n *\n * Each widget is imported once and re-exported. The same binding is used in\n * DEFAULT_WIDGETS to avoid the double-import anti-pattern.\n */\n\nimport { TextInputWidget } from \"./TextInputWidget\";\nimport { TextareaWidget } from \"./TextareaWidget\";\nimport { NumberWidget } from \"./NumberWidget\";\nimport { CheckboxWidget } from \"./CheckboxWidget\";\nimport { SelectWidget } from \"./SelectWidget\";\nimport { TagsInputWidget } from \"./TagsInputWidget\";\nimport { JsonEditorWidget } from \"./JsonEditorWidget\";\nimport { KeyValueWidget } from \"./KeyValueWidget\";\nimport { EntitySelectWidget } from \"./EntitySelectWidget\";\nimport { ObjectWidget } from \"./ObjectWidget\";\nimport { ArrayWidget } from \"./ArrayWidget\";\nimport { QuantityWidget } from \"./QuantityWidget\";\nimport { CodedValueWidget } from \"./CodedValueWidget\";\nimport { CodeableConceptWidget } from \"./CodeableConceptWidget\";\nimport { DateWidget } from \"./DateWidget\";\nimport { TimeWidget } from \"./TimeWidget\";\nimport { DateTimeWidget } from \"./DateTimeWidget\";\nimport { DisplayWidget } from \"./DisplayWidget\";\nimport { OneOfWidget } from \"./OneOfWidget\";\nimport { RadioWidget } from \"./RadioWidget\";\nimport { CheckboxGroupWidget } from \"./CheckboxGroupWidget\";\nimport { ChoiceWithTextWidget } from \"./ChoiceWithTextWidget\";\nimport { AbsentReasonsWidget } from \"./AbsentReasonsWidget\";\nimport type { WidgetRegistry } from \"./types\";\n\n// Re-export widget components\nexport {\n TextInputWidget,\n TextareaWidget,\n NumberWidget,\n CheckboxWidget,\n SelectWidget,\n TagsInputWidget,\n JsonEditorWidget,\n KeyValueWidget,\n EntitySelectWidget,\n ObjectWidget,\n ArrayWidget,\n QuantityWidget,\n CodedValueWidget,\n CodeableConceptWidget,\n DateWidget,\n TimeWidget,\n DateTimeWidget,\n DisplayWidget,\n OneOfWidget,\n RadioWidget,\n CheckboxGroupWidget,\n ChoiceWithTextWidget,\n AbsentReasonsWidget,\n};\n\n// Export types and helpers\nexport type {\n Widget,\n WidgetProps,\n WidgetRegistry,\n WidgetDescriptor,\n WidgetMap,\n SelectOption,\n UISchema,\n UISchemaOptions,\n} from \"./types\";\nexport { firstError } from \"./types\";\n\n// Export resolver\nexport {\n resolveWidget,\n getDefaultWidgetForType,\n DEFAULT_WIDGET_MAP,\n} from \"./widgetResolver\";\n\n/**\n * DEFAULT_WIDGETS - The default widget registry.\n *\n * Contains all built-in widgets mapped by their names.\n * Use this as the base registry or extend it with custom widgets.\n *\n * @example\n * ```typescript\n * import { DEFAULT_WIDGETS } from './widgets';\n * import MyCustomWidget from './MyCustomWidget';\n *\n * const registry = { ...DEFAULT_WIDGETS, MyCustomWidget };\n * ```\n */\nexport const DEFAULT_WIDGETS: WidgetRegistry = {\n // Canonical PascalCase names\n TextInputWidget,\n TextareaWidget,\n NumberWidget,\n CheckboxWidget,\n SelectWidget,\n TagsInputWidget,\n JsonEditorWidget,\n KeyValueWidget,\n EntitySelectWidget,\n ObjectWidget,\n ArrayWidget,\n QuantityWidget,\n CodedValueWidget,\n CodeableConceptWidget,\n DateWidget,\n TimeWidget,\n DateTimeWidget,\n DisplayWidget,\n OneOfWidget,\n RadioWidget,\n CheckboxGroupWidget,\n ChoiceWithTextWidget,\n AbsentReasonsWidget,\n\n // Lowercase aliases for x-ui-widget convenience\n text: TextInputWidget,\n textarea: TextareaWidget,\n number: NumberWidget,\n checkbox: CheckboxWidget,\n select: SelectWidget,\n tags: TagsInputWidget,\n \"json-editor\": JsonEditorWidget,\n \"key-value\": KeyValueWidget,\n \"entity-select\": EntitySelectWidget,\n object: ObjectWidget,\n array: ArrayWidget,\n quantity: QuantityWidget,\n \"coded-value\": CodedValueWidget,\n \"codeable-concept\": CodeableConceptWidget,\n date: DateWidget,\n time: TimeWidget,\n \"date-time\": DateTimeWidget,\n display: DisplayWidget,\n \"one-of\": OneOfWidget,\n radio: RadioWidget,\n \"checkbox-group\": CheckboxGroupWidget,\n \"choice-with-text\": ChoiceWithTextWidget,\n \"absent-reasons\": AbsentReasonsWidget,\n};\n","/**\n * HorizontalArrayItemTemplate -- CSS grid row layout for array items.\n *\n * Renders each item as a grid row. The sub-form container uses\n * display:contents so its field divs become direct grid cells. The\n * remove button occupies the last column (32px).\n *\n * Activated by x-ui-layout.direction: \"horizontal\" on the array property.\n */\n\nimport { Trash2, ChevronUp, ChevronDown } from \"lucide-react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport type { ArrayItemTemplateProps } from \"../widgets/types\";\nimport { buildGridTemplate } from \"./gridUtils\";\n\nexport function HorizontalArrayItemTemplate({\n children,\n index,\n total,\n canRemove,\n orderable,\n disabled,\n layout,\n fieldCount,\n fid,\n onRemove,\n onMoveUp,\n onMoveDown,\n}: ArrayItemTemplateProps): React.ReactElement {\n const resolvedLayout = layout;\n const template = buildGridTemplate(\n resolvedLayout,\n canRemove,\n fieldCount,\n orderable,\n );\n const gap = resolvedLayout.gap ?? 8;\n // compact rows center-align (controls are short); full-height rows stretch.\n const alignItems = resolvedLayout.compact ? \"center\" : \"start\";\n\n return (\n <div\n data-fid={fid}\n style={{\n display: \"grid\",\n gridTemplateColumns: template,\n gap: `${gap}px`,\n alignItems,\n }}\n >\n {children}\n {orderable && (\n <div className=\"flex flex-col items-center justify-center\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"compact\"\n disabled={disabled || index === 0}\n onClick={onMoveUp}\n title=\"Move up\"\n className=\"h-4 w-8 p-0\"\n >\n <ChevronUp className=\"h-3 w-3\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"compact\"\n disabled={disabled || index >= total - 1}\n onClick={onMoveDown}\n title=\"Move down\"\n className=\"h-4 w-8 p-0\"\n >\n <ChevronDown className=\"h-3 w-3\" />\n </Button>\n </div>\n )}\n {canRemove && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"compact\"\n disabled={disabled}\n onClick={onRemove}\n title=\"Remove item\"\n className=\"text-muted-foreground hover:text-destructive h-8 w-8 p-0\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n )}\n </div>\n );\n}\n","/**\n * TabsGroupTemplate -- presents field groups as a tab bar (the default for\n * `x-ui-layout.tabs`).\n *\n * Selection is controlled and clamped to a group that still exists, so hiding\n * the group the user is on (via its rule) falls back to the first remaining one\n * instead of leaving an empty body.\n */\n\nimport React, { useState } from \"react\";\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from \"@petrarca/sonnet-ui\";\nimport type { GroupLayoutTemplateProps } from \"../widgets/types\";\nimport { GroupErrorBadge } from \"./GroupErrorBadge\";\n\nexport function TabsGroupTemplate({\n groups,\n}: GroupLayoutTemplateProps): React.ReactElement {\n const [active, setActive] = useState<string>(groups[0].key);\n const value = groups.some((g) => g.key === active) ? active : groups[0].key;\n return (\n <Tabs value={value} onValueChange={setActive}>\n <TabsList className=\"mb-4\">\n {groups.map((g) => (\n <TabsTrigger key={g.key} value={g.key} className=\"gap-1.5\">\n {g.label}\n <GroupErrorBadge count={g.errorCount} />\n </TabsTrigger>\n ))}\n </TabsList>\n {groups.map((g) => (\n <TabsContent key={g.key} value={g.key} className=\"space-y-4\">\n {g.content}\n </TabsContent>\n ))}\n </Tabs>\n );\n}\n","/**\n * GroupErrorBadge -- marks a group's trigger (tab or step) as having\n * validation errors. Shared by the built-in group templates.\n *\n * Deliberately just the icon: a trigger sits in a dense strip alongside its\n * label and, in a stepper, a step number, so a second numeral reads as clutter\n * and competes with the step index. The exact count stays available as the\n * accessible name and the tooltip, and the form-level summary reports totals.\n *\n * The signal is a shape, not a colour, so it survives a colour-vision\n * deficiency or a greyscale print.\n */\n\nimport React from \"react\";\nimport { AlertCircle } from \"lucide-react\";\n\nexport function GroupErrorBadge({\n count,\n}: {\n count: number;\n}): React.ReactElement | null {\n if (count === 0) return null;\n const label =\n count === 1 ? \"1 field needs attention\" : `${count} fields need attention`;\n return (\n <span\n role=\"img\"\n aria-label={label}\n title={label}\n className=\"inline-flex shrink-0 text-destructive\"\n >\n <AlertCircle className=\"h-3.5 w-3.5\" />\n </span>\n );\n}\n","/**\n * StepperGroupTemplate -- presents field groups as a wizard\n * (`x-ui-layout.variant: \"stepper\"`).\n *\n * Same group model as the tab presentation, different chrome: a numbered step\n * rail plus Back/Next. Steps stay directly clickable so the user is never\n * trapped; validation gating is deliberately not applied here, because a\n * group's errors are advisory (the badge) rather than a hard barrier.\n *\n * Selection is controlled and clamped to a group that still exists, so hiding\n * the step the user is on falls back to the first remaining one.\n */\n\nimport React, { useState } from \"react\";\nimport {\n Button,\n Stepper,\n StepperList,\n StepperItem,\n StepperTrigger,\n StepperIndicator,\n StepperSeparator,\n StepperTitle,\n StepperContent,\n StepperPrev,\n StepperNext,\n} from \"@petrarca/sonnet-ui\";\nimport type { GroupLayoutTemplateProps } from \"../widgets/types\";\nimport { GroupErrorBadge } from \"./GroupErrorBadge\";\n\nexport function StepperGroupTemplate({\n groups,\n}: GroupLayoutTemplateProps): React.ReactElement {\n const [active, setActive] = useState<string>(groups[0].key);\n const value = groups.some((g) => g.key === active) ? active : groups[0].key;\n const isLast = value === groups[groups.length - 1].key;\n return (\n <Stepper value={value} onValueChange={setActive}>\n <StepperList className=\"mb-4 gap-2\">\n {groups.map((g) => (\n <StepperItem key={g.key} value={g.key}>\n <StepperTrigger>\n <StepperIndicator />\n {/* StepperTitle is plain text; make it a flex row so the badge\n centres on the label instead of sitting on the baseline. */}\n <StepperTitle className=\"inline-flex items-center gap-1.5\">\n {g.label}\n <GroupErrorBadge count={g.errorCount} />\n </StepperTitle>\n </StepperTrigger>\n <StepperSeparator />\n </StepperItem>\n ))}\n </StepperList>\n {groups.map((g) => (\n <StepperContent key={g.key} value={g.key} className=\"space-y-4\">\n {g.content}\n </StepperContent>\n ))}\n <div className=\"mt-4 flex justify-between\">\n <StepperPrev asChild>\n <Button variant=\"outline\" size=\"sm\">\n Back\n </Button>\n </StepperPrev>\n {/* The last step has nowhere to go; the form's own actions take over. */}\n {!isLast && (\n <StepperNext asChild>\n <Button size=\"sm\">Next</Button>\n </StepperNext>\n )}\n </div>\n </Stepper>\n );\n}\n","/**\n * SectionsGroupTemplate -- presents field groups as stacked titled sections\n * (`x-ui-layout.variant: \"sections\"`).\n *\n * Unlike tabs and stepper, every group is visible at once. This is the\n * multi-row counterpart to a row's `group` fieldset: a section holds as many\n * rows as it likes, whereas `row.group` wraps exactly one.\n *\n * No selection state, so nothing to clamp -- a group hidden by its rule simply\n * does not appear.\n */\n\nimport React from \"react\";\nimport type { GroupLayoutTemplateProps } from \"../widgets/types\";\nimport { GroupErrorBadge } from \"./GroupErrorBadge\";\n\nexport function SectionsGroupTemplate({\n groups,\n}: GroupLayoutTemplateProps): React.ReactElement {\n return (\n <div className=\"space-y-6\">\n {groups.map((g) => (\n <fieldset\n key={g.key}\n className=\"rounded-md border border-border/60 px-3 pb-3 pt-1\"\n >\n <legend className=\"inline-flex items-center gap-1.5 px-1 text-sm font-medium text-muted-foreground\">\n {g.label}\n <GroupErrorBadge count={g.errorCount} />\n </legend>\n <div className=\"space-y-4\">{g.content}</div>\n </fieldset>\n ))}\n </div>\n );\n}\n","/**\n * Default templates for structural layout rendering.\n *\n * These are the pre-built implementations used by ArrayWidget and\n * ObjectWidget when no custom template is injected. Callers override\n * specific templates by passing a partial TemplateRegistry to the\n * `templates` prop on JsonSchemaFormRenderer.\n */\n\nimport type { TemplateRegistry } from \"../widgets/types\";\nimport { DefaultArrayItemTemplate } from \"./DefaultArrayItemTemplate\";\nimport { HorizontalArrayItemTemplate } from \"./HorizontalArrayItemTemplate\";\nimport { DefaultArrayHeaderTemplate } from \"./DefaultArrayHeaderTemplate\";\nimport { DefaultObjectContainerTemplate } from \"./DefaultObjectContainerTemplate\";\nimport { TabsGroupTemplate } from \"./TabsGroupTemplate\";\nimport { StepperGroupTemplate } from \"./StepperGroupTemplate\";\nimport { SectionsGroupTemplate } from \"./SectionsGroupTemplate\";\n\nexport { DefaultArrayItemTemplate } from \"./DefaultArrayItemTemplate\";\nexport { HorizontalArrayItemTemplate } from \"./HorizontalArrayItemTemplate\";\nexport { DefaultArrayHeaderTemplate } from \"./DefaultArrayHeaderTemplate\";\nexport { DefaultObjectContainerTemplate } from \"./DefaultObjectContainerTemplate\";\nexport { TabsGroupTemplate } from \"./TabsGroupTemplate\";\nexport { StepperGroupTemplate } from \"./StepperGroupTemplate\";\nexport { SectionsGroupTemplate } from \"./SectionsGroupTemplate\";\nexport { GroupErrorBadge } from \"./GroupErrorBadge\";\n\n/**\n * DEFAULT_TEMPLATES -- the built-in template implementations.\n *\n * Pass a partial override to JsonSchemaFormRenderer's `templates` prop\n * to replace specific templates globally, or use x-ui-options on a\n * schema property for per-field overrides.\n */\nexport const DEFAULT_TEMPLATES: TemplateRegistry = {\n ArrayItemTemplate: DefaultArrayItemTemplate,\n HorizontalArrayItemTemplate: HorizontalArrayItemTemplate,\n ArrayHeaderTemplate: DefaultArrayHeaderTemplate,\n ObjectContainerTemplate: DefaultObjectContainerTemplate,\n TabsGroupTemplate: TabsGroupTemplate,\n StepperGroupTemplate: StepperGroupTemplate,\n SectionsGroupTemplate: SectionsGroupTemplate,\n};\n\n/**\n * The TemplateRegistry key for a group-layout variant. The variant name maps\n * directly to a template name, so a consumer can register\n * `WizardGroupTemplate` and select it with `variant: \"wizard\"` -- no library\n * change needed. Unknown variants fall back to the tab presentation.\n */\nexport function groupTemplateKey(variant: string | undefined): string {\n if (!variant) return \"TabsGroupTemplate\";\n const name = variant.charAt(0).toUpperCase() + variant.slice(1);\n return `${name}GroupTemplate`;\n}\n","/**\n * FormFieldRenderer - Renders a single form field via the widget system\n *\n * Replaces the `renderField` free function that previously lived in\n * JsonSchemaFormRenderer. Moving it to a proper component ensures the `key`\n * prop is set at the call site (in the parent's `.map()`), not buried inside\n * the function, which is the idiomatic React pattern.\n *\n * @module components/Forms/FormFieldRenderer\n */\n\nimport React, { useMemo } from \"react\";\nimport { JsonSchema, JsonSchemaProperty } from \"@petrarca/sonnet-core/schema\";\nimport { warnLog } from \"@petrarca/sonnet-core\";\nimport {\n getFieldTitle,\n getFieldHelpText,\n getFieldPlaceholder,\n liftNullableMember,\n} from \"@petrarca/sonnet-core/schema\";\nimport {\n resolveWidget,\n WidgetRegistry,\n UISchema,\n UISchemaOptions,\n} from \"./widgets\";\n\nexport interface FormFieldRendererProps {\n fieldName: string;\n property: JsonSchemaProperty;\n value: unknown;\n onChange: (value: unknown) => void;\n onBlur?: (id: string, value: unknown) => void;\n required: boolean;\n disabled: boolean;\n readOnly: boolean;\n schema: JsonSchema;\n uiSchema?: UISchema;\n registry: WidgetRegistry;\n globalOptions?: UISchemaOptions;\n formData?: Record<string, unknown>;\n /**\n * Prefix for generated control ids: `<idPrefix>-<fieldName>` (default\n * \"field\"). Set a per-form prefix when rendering multiple forms on one page\n * to keep ids unique.\n */\n idPrefix?: string;\n /** Validation messages for this field, rendered inline by the widget. */\n rawErrors?: string[];\n}\n\n/** Merge options: field uiSchema > property x-ui-options > global. */\nfunction mergeFieldOptions(\n globalOptions: UISchemaOptions,\n property: JsonSchemaProperty,\n uiSchema: UISchema | undefined,\n): UISchemaOptions {\n const xWidgetOptions = property[\"x-ui-options\"] || {};\n const fieldOptions = uiSchema?.[\"x-ui-options\"] || {};\n return { ...globalOptions, ...xWidgetOptions, ...fieldOptions };\n}\n\n/** Resolve effective label: global label=false hides it; uiSchema x-ui-title overrides. */\nfunction resolveEffectiveLabel(\n label: string,\n uiTitle: string | boolean | undefined,\n globalLabelOption: string | false | undefined,\n): string {\n if (globalLabelOption === false) return \"\";\n if (typeof uiTitle === \"string\") return uiTitle;\n if (uiTitle === false) return \"\";\n return label;\n}\n\n// Tailwind class equivalents of WIDTH_TOKEN_REMS (sonnet-core): w-32=8rem,\n// w-48=12rem, w-64=16rem. Kept as Tailwind utility strings so the JIT scanner\n// can pick them up (arbitrary rem values in class names are not scanned).\nconst FIELD_WIDTH_CLASS = {\n sm: \"w-32\",\n md: \"w-48\",\n lg: \"w-64\",\n full: \"w-full\",\n} as const satisfies Record<\n import(\"@petrarca/sonnet-core/schema\").WidthToken,\n string\n>;\n\ntype FieldWidth = keyof typeof FIELD_WIDTH_CLASS;\n\n/**\n * Wrap a field in a width-constraining slot when x-ui-width is set. \"full\"\n * (the default) returns the field unwrapped so layout containers control width.\n */\nfunction applyFieldWidth(\n widget: React.ReactElement,\n uiSchema: UISchema | undefined,\n mergedOptions: UISchemaOptions,\n): React.ReactElement {\n const candidate = uiSchema?.[\"x-ui-width\"] ?? mergedOptions.width;\n if (candidate && !(candidate in FIELD_WIDTH_CLASS)) {\n warnLog(\n `[FormFieldRenderer] Unknown x-ui-width value: \"${candidate}\". Falling back to \"full\".`,\n );\n }\n const width: FieldWidth =\n candidate && candidate in FIELD_WIDTH_CLASS\n ? (candidate as FieldWidth)\n : \"full\";\n if (width === \"full\") return widget;\n return <div className={FIELD_WIDTH_CLASS[width]}>{widget}</div>;\n}\n\n/** Resolve description/placeholder: uiSchema override, else schema-derived. */\nfunction resolvePresentationText(\n property: JsonSchemaProperty,\n uiSchema: UISchema | undefined,\n): { description: string | undefined; placeholder: string | undefined } {\n return {\n description: uiSchema?.[\"x-ui-description\"] ?? getFieldHelpText(property),\n placeholder:\n uiSchema?.[\"x-ui-placeholder\"] ?? getFieldPlaceholder(property),\n };\n}\n\n/** Resolve cascading disabled/readonly flags. */\nfunction resolveFieldFlags(\n fieldOptions: UISchemaOptions,\n globalOptions: UISchemaOptions,\n disabled: boolean,\n readOnly: boolean,\n) {\n return {\n disabled: fieldOptions.disabled ?? globalOptions.disabled ?? disabled,\n readOnly: fieldOptions.readonly ?? globalOptions.readonly ?? readOnly,\n };\n}\n\nexport function FormFieldRenderer({\n fieldName,\n property: declared,\n value,\n onChange,\n onBlur,\n required,\n disabled,\n readOnly,\n schema,\n uiSchema,\n registry,\n globalOptions = {},\n formData,\n idPrefix = \"field\",\n rawErrors,\n}: FormFieldRendererProps): React.ReactElement | null {\n // Optional[T] carries its keywords (bounds, items, format) on the non-null\n // member; widgets read them off the property.\n const property = useMemo(() => liftNullableMember(declared), [declared]);\n const label = getFieldTitle(fieldName, property);\n const { description, placeholder } = resolvePresentationText(\n property,\n uiSchema,\n );\n\n const Widget = resolveWidget(property, uiSchema, registry);\n const mergedOptions = mergeFieldOptions(globalOptions, property, uiSchema);\n\n if (mergedOptions.hidden) return null;\n\n const fieldOptions = uiSchema?.[\"x-ui-options\"] || {};\n const flags = resolveFieldFlags(\n fieldOptions,\n globalOptions,\n disabled,\n readOnly,\n );\n const effectiveLabel = resolveEffectiveLabel(\n label,\n uiSchema?.[\"x-ui-title\"],\n globalOptions.label,\n );\n const widget = (\n <Widget\n id={`${idPrefix}-${fieldName}`}\n name={fieldName}\n value={value}\n onChange={onChange}\n onBlur={onBlur}\n schema={schema}\n propertySchema={property}\n uiSchema={uiSchema}\n registry={registry}\n label={effectiveLabel}\n description={description}\n placeholder={placeholder}\n required={required}\n disabled={flags.disabled}\n readonly={flags.readOnly}\n options={mergedOptions}\n formData={formData}\n rawErrors={rawErrors}\n />\n );\n\n return applyFieldWidth(widget, uiSchema, mergedOptions);\n}\n","/**\n * useFormEngine - Core form state, schema resolution, and update-mode logic\n *\n * Owns:\n * - formData state (internal working copy)\n * - resolvedSchema / orderedProperties (conditional schema + field ordering)\n * - originalData baseline for dirty-tracking\n * - nonSchemaData (fields not in the schema, preserved on save)\n * - pendingChanges (deferred-state-update buffer)\n * - isValid / validation errors\n * - handleFieldChange, handleFieldBlur, handleSave, handleCancel\n *\n * Supports all three update modes:\n * 1. Real-time — onChange on every keystroke\n * 2. Deferred — onChange on blur for text fields (deferChanges)\n * 3. Buffered — Save/Cancel flow (showActions + onUpdate)\n *\n * @module components/Forms/hooks/useFormEngine\n */\n\nimport { useState, useEffect, useMemo, useCallback, useRef } from \"react\";\nimport { isEqual } from \"@petrarca/sonnet-core\";\nimport { JsonSchema, JsonSchemaProperty } from \"@petrarca/sonnet-core/schema\";\nimport {\n isNullableBoolean,\n getSchemaProperties,\n getFieldDefault,\n applySchemaDefaults,\n resolveSchema,\n resolveRefs,\n validateFormData,\n stripFormItemIds,\n mergeFieldErrors,\n diffFormData,\n ensureFormItemIds,\n} from \"@petrarca/sonnet-core/schema\";\nimport type {\n FormDiff,\n RefResolver,\n FieldError,\n} from \"@petrarca/sonnet-core/schema\";\nimport { UISchema } from \"../widgets\";\nimport { runValidators, useAsyncValidators } from \"../validators\";\nimport type { ValidatorRegistry } from \"../validators\";\nimport { orderProperties } from \"./orderProperties\";\n\n// The formats whose widgets emit only a committed value.\nconst COMMITTED_FORMATS = new Set([\"date\", \"time\", \"date-time\"]);\n\n// A date or a time emits only what is committed -- a day picked, a typed text\n// parsed when the field is left -- so it applies at once: held, its change\n// would arrive with its blur, and the flush would find nothing yet.\nfunction isCommittedFormat(property: JsonSchemaProperty): boolean {\n return (\n property.format !== undefined && COMMITTED_FORMATS.has(property.format)\n );\n}\n\n/**\n * Returns true for field types that should always trigger immediate updates\n * (checkboxes, enum-based selects, dates and times), regardless of deferral\n * settings.\n */\nfunction isImmediateField(\n fieldName: string,\n properties: Record<string, JsonSchemaProperty>,\n): boolean {\n const property = properties[fieldName];\n if (!property) return false;\n // A pick is final: a checkbox (a three-state one too), a single choice and a multiple choice (its\n // items' enum) apply at once -- as does a field whose widget says so\n // (`x-ui-options.immediate`), a control built of picks rather than typing.\n return (\n property.type === \"boolean\" ||\n isNullableBoolean(property) ||\n isCommittedFormat(property) ||\n property.enum !== undefined ||\n property.items?.enum !== undefined ||\n (property[\"x-ui-options\"] as { immediate?: boolean } | undefined)\n ?.immediate === true\n );\n}\n\n/**\n * Compute updated originalData baseline when external `data` expands.\n *\n * Returns a result object when an update is needed, null otherwise.\n * `shouldMarkInitialized` is true on first initialization, false on subsequent expansion.\n */\nfunction computeBaselineUpdate(\n newData: Record<string, any>,\n originalData: Record<string, any>,\n initialized: boolean,\n schemaPropertyNames: string[],\n): {\n shouldMarkInitialized: boolean;\n cleanedData: Record<string, any>;\n nonSchema: Record<string, any>;\n} | null {\n const newCount = Object.keys(newData).length;\n const origCount = Object.keys(originalData).length;\n\n if (!initialized && newCount > 0) {\n const cleanedData = Object.fromEntries(\n Object.entries(newData).filter(([k]) => schemaPropertyNames.includes(k)),\n );\n const nonSchema = Object.fromEntries(\n Object.entries(newData).filter(([k]) => !schemaPropertyNames.includes(k)),\n );\n return { shouldMarkInitialized: true, cleanedData, nonSchema };\n }\n\n if (initialized && newCount > origCount) {\n const cleanedData = Object.fromEntries(\n Object.entries(newData).filter(([k]) => schemaPropertyNames.includes(k)),\n );\n const nonSchema = Object.fromEntries(\n Object.entries(newData).filter(([k]) => !schemaPropertyNames.includes(k)),\n );\n return { shouldMarkInitialized: false, cleanedData, nonSchema };\n }\n\n return null;\n}\n\n// The complete field-error set for a data snapshot, in precedence order:\n// built-in (schema/content/structural) > custom sync (field + form validators,\n// already isRoot-gated by the caller's runValidators call -- see the `isRoot`\n// option below) > async (settled asyncField/asyncForm results) > external\n// extraErrors. Shared by the live-validity memo and the save-gate so the two\n// never disagree, and so handleSave stays under the complexity limit.\nfunction computeAllErrors(args: {\n schema: JsonSchema;\n data: Record<string, any>;\n customSync: FieldError[];\n asyncErrors: FieldError[];\n extraErrors: FieldError[] | undefined;\n}): FieldError[] {\n const { schema, data, customSync, asyncErrors, extraErrors } = args;\n // Item ids are the renderer's bookkeeping, not data: validate without them.\n const base = validateFormData(schema, stripFormItemIds(data)).fieldErrors;\n return mergeFieldErrors(base, customSync, asyncErrors, extraErrors ?? []);\n}\n\nexport interface UseFormEngineOptions {\n schema: JsonSchema;\n data: Record<string, any>;\n uiSchema: { [fieldName: string]: UISchema };\n onChange?: (data: Record<string, any>) => void;\n onBlur?: (fieldName: string, data: Record<string, any>) => void;\n onValidationChange?: (errors: string[], isValid: boolean) => void;\n onUpdate?: (\n data: Record<string, any>,\n changedFields: Record<string, any>,\n diff: FormDiff,\n ) => void;\n onCancel?: () => void;\n readOnly?: boolean;\n showActions?: boolean;\n deferChanges?: boolean;\n deferStateUpdates?: boolean;\n /**\n * Allow saving when the form is pristine (no changes vs the baseline). Use for\n * CREATE forms, where submitting default / empty values is valid -- the\n * \"must have changed something\" dirty-check is an edit-only concept.\n * Validation (required fields) still applies. Default false (edit semantics).\n */\n allowPristineSave?: boolean;\n /**\n * Optional resolver for non-local `$ref`s (e.g. a schema-registry id or\n * canonical URI). Tried before the in-document `$defs` fallback. Must be\n * synchronous -- pre-load referenced schemas into a map and pass a lookup.\n */\n refResolver?: RefResolver;\n /**\n * Externally-supplied errors (e.g. a server 422), keyed by JSON Pointer.\n * Merged into `fieldErrors` (so they affect `isValid` and block Save) with\n * the lowest precedence -- a built-in error on the same field wins. The\n * renderer shows them regardless of `validationDisplay`; see the\n * custom-validation design.\n */\n extraErrors?: FieldError[];\n /**\n * Custom validator registry. Field validators (named by `x-ui-validate` on a\n * property) and, at the root, form/cross-field validators (named on the root\n * object) run here and merge into `fieldErrors` between built-in errors and\n * extraErrors. The sync `field`/`form` namespaces run every pass via\n * `runValidators`; the async `asyncField`/`asyncForm` namespaces are invoked\n * by `useAsyncValidators` and gate Save (`isValidating`) while in flight.\n */\n validators?: ValidatorRegistry;\n /**\n * Whether this engine is the ROOT form (not a nested sub-form). Root-only\n * concerns -- currently the whole-form/cross-field validators -- run only when\n * true, so a nested sub-form does not re-run them against its slice.\n */\n isRoot?: boolean;\n}\n\nexport interface UseFormEngineResult {\n /** The current working form data (for controlled field values) */\n formData: Record<string, any>;\n /**\n * Display data — formData merged with pending deferred changes.\n * Always use this for rendering field values.\n */\n displayData: Record<string, any>;\n /** Schema resolved against the current formData (conditional fields evaluated) */\n resolvedSchema: JsonSchema;\n /** Properties ordered by x-ui-order, ready for rendering */\n orderedProperties: [string, JsonSchemaProperty][];\n hasChanges: boolean;\n isValid: boolean;\n /** True while any async validator's promise is in flight. */\n isValidating: boolean;\n /**\n * Current validation errors, each attributed to its field by JSON Pointer.\n * Lets the renderer surface problems for fields that are not on screen.\n */\n fieldErrors: FieldError[];\n /** Fields the user has touched (focused then blurred). */\n touched: Record<string, boolean>;\n /** Whether a save has been attempted (reveals all errors under any policy). */\n submitAttempted: boolean;\n handleFieldChange: (fieldName: string, value: any) => void;\n handleFieldBlur: (fieldName: string) => void;\n handleSave: () => void;\n handleCancel: () => void;\n}\n\nexport function useFormEngine({\n schema,\n data,\n uiSchema,\n onChange,\n onBlur,\n onValidationChange,\n onUpdate,\n onCancel,\n readOnly = false,\n showActions = false,\n deferChanges = false,\n deferStateUpdates = false,\n allowPristineSave = false,\n refResolver,\n extraErrors,\n validators,\n isRoot = true,\n}: UseFormEngineOptions): UseFormEngineResult {\n // Resolve $ref pointers before anything else. This is a pure transformation\n // that only depends on the schema object and the (stable) resolver.\n const refResolvedSchema = useMemo(\n () => resolveRefs(schema, refResolver),\n [schema, refResolver],\n );\n\n // Seed the baseline and the working copy from ONE stamped snapshot, so array\n // items carry the same `_fid` on both sides. Stamping each side separately\n // would mint different ids and defeat the diff -- the very bug this avoids.\n // The stamp runs once at mount; later external `data` changes re-seed through\n // computeBaselineUpdate below.\n const seed = useState<Record<string, any>>(() =>\n ensureFormItemIds(\n applySchemaDefaults(data, refResolvedSchema),\n refResolvedSchema,\n ),\n )[0];\n\n const [originalData, setOriginalData] = useState<Record<string, any>>(\n () => seed,\n );\n const [originalDataInitialized, setOriginalDataInitialized] = useState(false);\n\n const [nonSchemaData, setNonSchemaData] = useState<Record<string, any>>(\n () => {\n const props = getSchemaProperties(refResolvedSchema);\n const names = Object.keys(props);\n return Object.fromEntries(\n Object.entries(data).filter(([k]) => !names.includes(k)),\n );\n },\n );\n\n const [formData, setFormData] = useState<Record<string, any>>(() => seed);\n\n // Mirror the latest formData in a ref so blur handlers read the current value\n // even if they fire before React commits the last keystroke's state update.\n const formDataRef = useRef(formData);\n formDataRef.current = formData;\n\n const [pendingChanges, setPendingChanges] = useState<Record<string, any>>({});\n\n // Schema resolution depends on live formData so conditional fields\n // (if-then-else, allOf) are re-evaluated on every change.\n const resolvedSchema = useMemo(\n () => resolveSchema(refResolvedSchema, formData),\n [refResolvedSchema, formData],\n );\n\n const orderedProperties = useMemo(() => {\n const properties = getSchemaProperties(resolvedSchema);\n const rawOrder = uiSchema[\"x-ui-order\"] ?? resolvedSchema[\"x-ui-order\"];\n const orderArray = Array.isArray(rawOrder)\n ? (rawOrder as string[])\n : undefined;\n return orderProperties(properties, orderArray);\n }, [resolvedSchema, uiSchema]);\n\n const [initialDefaultsSent, setInitialDefaultsSent] = useState(false);\n\n // Validation-display gating: a field's error shows once it has been touched,\n // and every field's error shows after a save attempt. Which of these applies\n // is the renderer's policy; the engine only records the facts. All reset on\n // cancel.\n //\n // \"Touched\" means edited and then blurred -- not merely focused and left.\n // Blurring a field the user never changed (tabbed through, or landed on by\n // autofocus) must not accuse them of leaving it invalid; it also made the\n // error appear mid-interaction, growing the field and shifting whatever sat\n // below it. This matches rjsf, which validates on blur only for \"a field that\n // was updated\".\n // Bookkeeping, never rendered -- a ref, so a blur that follows its change at\n // once (a picker that closes as it picks) already sees the field edited.\n const edited = useRef<Set<string>>(new Set());\n const [touched, setTouched] = useState<Record<string, boolean>>({});\n const [submitAttempted, setSubmitAttempted] = useState(false);\n\n const properties = getSchemaProperties(resolvedSchema);\n\n // On mount: if schema defaults were applied that the caller didn't supply,\n // push the initialized data up via onChange so the parent stays in sync.\n useEffect(() => {\n if (!initialDefaultsSent) {\n const hasDefaults = Object.entries(properties).some(\n ([fieldName, property]) =>\n data[fieldName] === undefined &&\n getFieldDefault(property) !== undefined,\n );\n\n if (hasDefaults && onChange) {\n onChange(formData);\n }\n setInitialDefaultsSent(true);\n }\n }, [initialDefaultsSent, properties, data, formData, onChange]);\n\n // Remove formData keys that are no longer present in the resolved schema.\n // This keeps internal state clean when a conditional branch hides a field.\n useEffect(() => {\n const currentPropertyNames = Object.keys(properties);\n const keysToRemove = Object.keys(formData).filter(\n (k) => !currentPropertyNames.includes(k),\n );\n\n if (keysToRemove.length > 0) {\n const cleanedData = { ...formData };\n keysToRemove.forEach((k) => {\n delete cleanedData[k];\n });\n setFormData(cleanedData);\n if (onChange) onChange(cleanedData);\n }\n }, [properties, formData, onChange]);\n\n // A field a condition brings in takes its default as it appears -- at the\n // start, when its condition already holds, or when an answer makes it hold.\n // Only then: a field already shown is the person's, cleared or not. The\n // fields seeded at mount are the schema's own; a conditional one is not.\n const shownFields = useRef<ReadonlySet<string>>(\n new Set(Object.keys(getSchemaProperties(refResolvedSchema))),\n );\n useEffect(() => {\n const names = Object.keys(properties);\n const appeared = names.filter((n) => !shownFields.current.has(n));\n shownFields.current = new Set(names);\n if (appeared.length === 0) return;\n const filled = applySchemaDefaults(formData, {\n properties: Object.fromEntries(appeared.map((n) => [n, properties[n]])),\n });\n if (isEqual(filled, formData)) return;\n setFormData(filled);\n if (onChange) onChange(filled);\n }, [properties, formData, onChange]);\n\n // Sync formData when the external data prop changes. Uses a ref to track\n // the previous value so we can avoid triggering on every render while\n // keeping the dependency array honest.\n const prevDataRef = useRef(data);\n useEffect(() => {\n if (isEqual(prevDataRef.current, data)) return;\n prevDataRef.current = data;\n\n // Stamp once, then derive both the working copy and the baseline from the\n // same snapshot so array-item `_fid`s match across the diff (see the mount\n // seed above). computeBaselineUpdate only filters keys, preserving the ids.\n const newData = ensureFormItemIds(\n applySchemaDefaults(data, refResolvedSchema),\n refResolvedSchema,\n );\n setFormData(newData);\n\n const schemaPropertyNames = Object.keys(properties);\n const result = computeBaselineUpdate(\n newData,\n originalData,\n originalDataInitialized,\n schemaPropertyNames,\n );\n\n if (result) {\n setOriginalData(result.cleanedData);\n setNonSchemaData(result.nonSchema);\n if (result.shouldMarkInitialized) {\n setOriginalDataInitialized(true);\n }\n }\n }, [\n data,\n refResolvedSchema,\n resolvedSchema,\n properties,\n originalData,\n originalDataInitialized,\n ]);\n\n const hasChanges = useMemo(\n () => !isEqual(formData, originalData),\n [formData, originalData],\n );\n\n // In deferStateUpdates mode, pending (not-yet-blurred) text field changes\n // are held separately and merged here for display only.\n const displayData = useMemo(() => {\n if (deferStateUpdates && Object.keys(pendingChanges).length > 0) {\n return { ...formData, ...pendingChanges };\n }\n return formData;\n }, [formData, pendingChanges, deferStateUpdates]);\n\n // Sync custom validators run every pass (cheap, idempotent). Async validators\n // live in their own namespaces and are invoked only by useAsyncValidators,\n // keyed on their inputs -- so a remote check fires on change, not per render.\n const customSync = useMemo(\n () =>\n runValidators(resolvedSchema, displayData, validators, uiSchema, isRoot),\n [resolvedSchema, displayData, validators, uiSchema, isRoot],\n );\n const { asyncErrors, isValidating } = useAsyncValidators(\n resolvedSchema,\n displayData,\n validators,\n uiSchema,\n isRoot,\n );\n\n // Validity plus the per-field errors behind it, derived from the live schema\n // and data rather than stored. Deriving keeps it correct when the schema or\n // data props change -- storing it left the value stale until the next edit.\n // Field errors let the renderer attribute a problem to a field that is not on\n // screen: e.g. badging a form tab whose fields sit in an inactive panel.\n const validation = useMemo(() => {\n const merged = computeAllErrors({\n schema: resolvedSchema,\n data: displayData,\n customSync,\n asyncErrors,\n extraErrors,\n });\n return {\n fieldErrors: merged,\n errors: merged.map((e) => e.message),\n isValid: merged.length === 0,\n };\n }, [resolvedSchema, displayData, customSync, asyncErrors, extraErrors]);\n const { isValid, fieldErrors } = validation;\n\n // Report validity from the single derived result, so the callback can never\n // disagree with the form's own isValid (it previously re-validated against a\n // partial snapshot, and never fired on mount or on a schema/data prop change).\n const onValidationChangeRef = useRef(onValidationChange);\n onValidationChangeRef.current = onValidationChange;\n useEffect(() => {\n onValidationChangeRef.current?.(validation.errors, validation.isValid);\n }, [validation]);\n\n const handleFieldChange = useCallback(\n (fieldName: string, value: any) => {\n if (readOnly) return;\n\n // Record the edit before any deferral branch: a deferred field is still\n // edited, and blur must be able to reveal its error.\n edited.current.add(fieldName);\n\n const immediate = isImmediateField(fieldName, properties);\n\n // Deferred state: hold non-immediate (text) edits until blur. Works with\n // or without a Save button; the flush on blur commits (and, when there is\n // no Save button, calls onChange). Immediate fields (checkbox/select)\n // always apply at once.\n if (deferStateUpdates && !immediate) {\n setPendingChanges((prev) => ({ ...prev, [fieldName]: value }));\n return;\n }\n\n const newData = { ...formData, [fieldName]: value };\n setFormData(newData);\n\n if (!showActions) {\n const shouldCallOnChange = !deferChanges || immediate;\n if (shouldCallOnChange && onChange) onChange(newData);\n }\n },\n [\n readOnly,\n formData,\n deferChanges,\n deferStateUpdates,\n showActions,\n onChange,\n properties,\n ],\n );\n\n // Flush deferred pending changes for a field into formData on blur. When\n // there is no Save button (showActions === false) the flushed data is also\n // pushed to onChange so the parent commits the edit.\n const flushPendingField = useCallback(\n (fieldName: string) => {\n if (!deferStateUpdates) return;\n if (pendingChanges[fieldName] === undefined) return;\n\n const newData = { ...formData, ...pendingChanges };\n setFormData(newData);\n setPendingChanges((prev) => {\n const updated = { ...prev };\n delete updated[fieldName];\n return updated;\n });\n\n if (!showActions && onChange) onChange(newData);\n },\n [showActions, deferStateUpdates, pendingChanges, formData, onChange],\n );\n\n const handleFieldBlur = useCallback(\n (fieldName: string) => {\n if (readOnly) return;\n\n // Only an edited field becomes touched -- see the note on `edited`.\n if (edited.current.has(fieldName)) {\n setTouched((prev) =>\n prev[fieldName] ? prev : { ...prev, [fieldName]: true },\n );\n }\n\n flushPendingField(fieldName);\n\n // Read the latest data via ref: the last keystroke's setFormData may not\n // have been committed to the closure's `formData` yet when blur fires.\n const latest = formDataRef.current;\n\n if (!showActions && deferChanges && onChange) {\n onChange(latest);\n }\n\n if (onBlur) {\n const hasPending =\n deferStateUpdates && pendingChanges[fieldName] !== undefined;\n const dataToPass = hasPending\n ? { ...latest, [fieldName]: pendingChanges[fieldName] }\n : latest;\n onBlur(fieldName, dataToPass);\n }\n },\n [\n readOnly,\n pendingChanges,\n deferChanges,\n deferStateUpdates,\n showActions,\n onChange,\n onBlur,\n flushPendingField,\n ],\n );\n\n const handleSave = useCallback(() => {\n // A save attempt reveals every field's error, whether or not the save then\n // proceeds -- this is what makes an invalid save explain itself.\n setSubmitAttempted(true);\n\n // Pristine saves are blocked for edit forms (dirty-check), allowed for\n // create forms (allowPristineSave). Validity is enforced below regardless.\n if (!hasChanges && !allowPristineSave) return;\n\n // An async validator in flight means validity is not yet known: block the\n // save until it settles, rather than submitting an unvalidated value.\n if (isValidating) return;\n\n const finalData =\n deferStateUpdates && Object.keys(pendingChanges).length > 0\n ? { ...formData, ...pendingChanges }\n : formData;\n\n const completeData = { ...nonSchemaData, ...finalData };\n // Re-run sync custom validators against the save-time snapshot (async is\n // already gated by isValidating above); merge like the live-validity path so\n // the gate and the on-screen state agree.\n const saveErrors = computeAllErrors({\n schema: resolvedSchema,\n data: finalData,\n customSync: runValidators(\n resolvedSchema,\n finalData,\n validators,\n uiSchema,\n isRoot,\n ),\n asyncErrors,\n extraErrors,\n });\n\n if (saveErrors.length === 0 && onUpdate) {\n // Compute changed fields at save time (includes any pending changes).\n const changed: Record<string, any> = {};\n for (const key of Object.keys(finalData)) {\n if (!isEqual(finalData[key], originalData[key])) {\n changed[key] = finalData[key];\n }\n }\n const diff = diffFormData(originalData, finalData);\n onUpdate(completeData, changed, diff);\n setPendingChanges({});\n }\n }, [\n hasChanges,\n allowPristineSave,\n resolvedSchema,\n formData,\n originalData,\n pendingChanges,\n deferStateUpdates,\n nonSchemaData,\n onUpdate,\n extraErrors,\n asyncErrors,\n isValidating,\n uiSchema,\n validators,\n isRoot,\n ]);\n\n const handleCancel = useCallback(() => {\n setFormData({ ...originalData });\n setPendingChanges({});\n edited.current = new Set();\n setTouched({});\n setSubmitAttempted(false);\n onCancel?.();\n }, [originalData, onCancel]);\n\n return {\n formData,\n displayData,\n resolvedSchema,\n orderedProperties,\n hasChanges,\n isValid,\n isValidating,\n fieldErrors,\n touched,\n submitAttempted,\n handleFieldChange,\n handleFieldBlur,\n handleSave,\n handleCancel,\n };\n}\n","/**\n * Synchronous custom-validator runner: walks a form's sync field validators and\n * (at the root) its sync form validators, invoking each and collecting errors.\n *\n * Sync only, by construction: async validators live in the separate `asyncField`\n * / `asyncForm` namespaces and are invoked by useAsyncValidators (never here),\n * so a remote check is never fired from this render-phase pass. A name is\n * still checked against ALL FOUR namespaces in the same walk (an async\n * validator's name is \"known\", just invoked elsewhere) -- a genuine typo throws\n * immediately rather than a second pass re-walking the schema to find it.\n *\n * Pure: no React, no side effects beyond calling the (synchronous) validators.\n */\n\nimport { getSchemaProperties } from \"@petrarca/sonnet-core/schema\";\nimport type {\n JsonSchema,\n UISchema,\n FieldError,\n} from \"@petrarca/sonnet-core/schema\";\nimport type { ValidatorRegistry, ValidatorContext } from \"./types\";\nimport {\n toRefs,\n resolveFieldRefs,\n fieldPointer,\n toFieldErrors,\n} from \"./shared\";\n\n// Whether `name` resolves to a validator in ANY namespace (sync or async). A\n// typo must fail loudly even though this function only INVOKES the sync ones.\nfunction isKnownName(registry: ValidatorRegistry, name: string): boolean {\n return !!(\n registry.field?.[name] ||\n registry.asyncField?.[name] ||\n registry.form?.[name] ||\n registry.asyncForm?.[name]\n );\n}\n\nfunction unknownValidator(\n kind: string,\n name: string,\n registry: ValidatorRegistry,\n): never {\n const registered = [\n ...Object.keys(registry.field ?? {}),\n ...Object.keys(registry.asyncField ?? {}),\n ...Object.keys(registry.form ?? {}),\n ...Object.keys(registry.asyncForm ?? {}),\n ];\n throw new Error(\n `unknown ${kind} validator '${name}' (registered: [${registered.join(\", \")}])`,\n );\n}\n\nfunction runFieldRefs(\n fieldName: string,\n data: Record<string, unknown>,\n registry: ValidatorRegistry,\n uiSchema: { [fieldName: string]: UISchema },\n schema: JsonSchema,\n out: FieldError[],\n): void {\n const refs = resolveFieldRefs(fieldName, schema, uiSchema);\n if (refs.length === 0) return;\n const pointer = fieldPointer(fieldName);\n const value = data[fieldName];\n for (const ref of refs) {\n if (!isKnownName(registry, ref.name)) {\n unknownValidator(\"field\", ref.name, registry);\n }\n const fn = registry.field?.[ref.name];\n if (!fn) continue; // a known name, but async -- invoked by useAsyncValidators\n const ctx: ValidatorContext = {\n formData: data,\n path: pointer,\n args: ref.args,\n };\n out.push(...toFieldErrors(fn(value, ctx), pointer));\n }\n}\n\nfunction runFormRefs(\n data: Record<string, unknown>,\n registry: ValidatorRegistry,\n schema: JsonSchema,\n out: FieldError[],\n): void {\n for (const ref of toRefs(schema[\"x-ui-validate\"])) {\n if (!isKnownName(registry, ref.name)) {\n unknownValidator(\"form\", ref.name, registry);\n }\n const fn = registry.form?.[ref.name];\n if (!fn) continue; // a known name, but async\n const ctx: ValidatorContext = { formData: data, path: \"\", args: ref.args };\n out.push(...fn(data, ctx));\n }\n}\n\n/**\n * Run sync custom validators (field + optionally root form) and return errors.\n *\n * @param includeFormValidators run root form validators (root engine only).\n */\nexport function runValidators(\n schema: JsonSchema,\n data: Record<string, unknown>,\n registry: ValidatorRegistry | undefined,\n uiSchema: { [fieldName: string]: UISchema },\n includeFormValidators: boolean,\n): FieldError[] {\n const out: FieldError[] = [];\n if (!registry) return out;\n\n // Always walk every field, even one with no `.field` entries, so a name that\n // only exists in an async namespace still resolves (and a genuine typo still\n // throws) in this single pass.\n for (const fieldName of Object.keys(getSchemaProperties(schema))) {\n runFieldRefs(fieldName, data, registry, uiSchema, schema, out);\n }\n if (includeFormValidators) {\n runFormRefs(data, registry, schema, out);\n }\n return out;\n}\n","/**\n * Shared helpers for the validator runners (sync runValidators, async\n * useAsyncValidators). Both walk the same schema/uiSchema shape to resolve\n * `x-ui-validate` refs -- kept here once so the walk is not duplicated between\n * the sync and async invokers.\n */\n\nimport { getSchemaProperties } from \"@petrarca/sonnet-core/schema\";\nimport type {\n JsonSchema,\n UISchema,\n UIValidate,\n UIValidateRef,\n FieldError,\n} from \"@petrarca/sonnet-core/schema\";\n\n// Normalize the x-ui-validate value (string | ref | array) to a ref list.\nexport function toRefs(v: UIValidate | undefined): UIValidateRef[] {\n if (v === undefined) return [];\n const arr = Array.isArray(v) ? v : [v];\n return arr.map((item) => (typeof item === \"string\" ? { name: item } : item));\n}\n\n// RFC 6901 escaping for a single path token.\nexport function escapeToken(token: string): string {\n return token.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\n\n// RFC 6901 pointer for a top-level field.\nexport function fieldPointer(fieldName: string): string {\n return `/${escapeToken(fieldName)}`;\n}\n\n// The x-ui-validate refs for one field. A uiSchema override wins over the\n// schema property's own value, matching every other x-ui-* key.\nexport function resolveFieldRefs(\n fieldName: string,\n schema: JsonSchema,\n uiSchema: { [fieldName: string]: UISchema },\n): UIValidateRef[] {\n const property = getSchemaProperties(schema)[fieldName] ?? {};\n return toRefs(\n uiSchema[fieldName]?.[\"x-ui-validate\"] ?? property[\"x-ui-validate\"],\n );\n}\n\n// Turn a validator's (sync or resolved-async) result into FieldError[].\n// A bare string / null is attached to the given field pointer.\nexport function toFieldErrors(result: unknown, pointer: string): FieldError[] {\n if (result == null || result === \"\") return [];\n if (typeof result === \"string\") return [{ pointer, message: result }];\n if (Array.isArray(result)) return result as FieldError[];\n return [];\n}\n","/**\n * useAsyncValidators -- the sole invoker of async validators (`asyncField` /\n * `asyncForm`), controlling firing so a remote check runs when its inputs change\n * -- not on every render -- and exposing settled errors plus a pending flag.\n *\n * Because async validators live in their own registry namespaces, the engine\n * knows which are async WITHOUT calling them; the sync runner never touches\n * them, so a request is never fired speculatively. Invocation is keyed: a field\n * validator by its field+value, a form validator by its `dependsOn` values (or\n * the whole data). A key already handled does not re-fire (a ref guard set\n * synchronously at call time, immune to render/memo churn). The last settled\n * result for an id wins; a superseded key's result is discarded. A rejected\n * promise settles to \"no error\" -- a failed check is not an invalid value.\n */\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { getSchemaProperties } from \"@petrarca/sonnet-core/schema\";\nimport type {\n JsonSchema,\n UISchema,\n FieldError,\n} from \"@petrarca/sonnet-core/schema\";\nimport type { ValidatorRegistry, ValidatorContext } from \"./types\";\nimport {\n toRefs,\n resolveFieldRefs,\n fieldPointer,\n toFieldErrors,\n} from \"./shared\";\n\ninterface Candidate {\n id: string;\n key: string;\n pointer: string;\n run: () => Promise<unknown>;\n}\n\ninterface Entry {\n key: string;\n pending: boolean;\n errors: FieldError[];\n}\n\nfunction keyOf(value: unknown): string {\n try {\n return JSON.stringify(value) ?? \"undefined\";\n } catch {\n return String(value);\n }\n}\n\nfunction collectFieldCandidates(\n schema: JsonSchema,\n data: Record<string, unknown>,\n registry: NonNullable<ValidatorRegistry[\"asyncField\"]>,\n uiSchema: { [fieldName: string]: UISchema },\n out: Candidate[],\n): void {\n for (const fieldName of Object.keys(getSchemaProperties(schema))) {\n const refs = resolveFieldRefs(fieldName, schema, uiSchema);\n const pointer = fieldPointer(fieldName);\n const value = data[fieldName];\n for (const ref of refs) {\n const fn = registry[ref.name];\n if (!fn) continue; // a sync name; not ours (runValidators owns it, or\n // reports it as unknown -- see runValidators.ts)\n const ctx: ValidatorContext = {\n formData: data,\n path: pointer,\n args: ref.args,\n };\n out.push({\n id: `asyncField:${pointer}:${ref.name}`,\n key: keyOf(value),\n pointer,\n run: () => fn(value, ctx),\n });\n }\n }\n}\n\nfunction collectFormCandidates(\n schema: JsonSchema,\n data: Record<string, unknown>,\n registry: NonNullable<ValidatorRegistry[\"asyncForm\"]>,\n out: Candidate[],\n): void {\n for (const ref of toRefs(schema[\"x-ui-validate\"])) {\n const fn = registry[ref.name];\n if (!fn) continue;\n const ctx: ValidatorContext = { formData: data, path: \"\", args: ref.args };\n const basis = ref.dependsOn\n ? ref.dependsOn.map((f) => keyOf(data[f])).join(\"|\")\n : keyOf(data);\n out.push({\n id: `asyncForm:${ref.name}`,\n key: basis,\n pointer: \"\",\n run: () => fn(data, ctx),\n });\n }\n}\n\nfunction collectCandidates(\n schema: JsonSchema,\n data: Record<string, unknown>,\n registry: ValidatorRegistry,\n uiSchema: { [fieldName: string]: UISchema },\n isRoot: boolean,\n): Candidate[] {\n const out: Candidate[] = [];\n if (registry.asyncField) {\n collectFieldCandidates(schema, data, registry.asyncField, uiSchema, out);\n }\n if (registry.asyncForm && isRoot) {\n collectFormCandidates(schema, data, registry.asyncForm, out);\n }\n return out;\n}\n\nexport interface UseAsyncValidatorsResult {\n /** Settled async errors, ready to merge (lowest precedence, like extraErrors). */\n asyncErrors: FieldError[];\n /** True while any async validator is in flight (or not yet settled for its key). */\n isValidating: boolean;\n}\n\nexport function useAsyncValidators(\n schema: JsonSchema,\n data: Record<string, unknown>,\n registry: ValidatorRegistry | undefined,\n uiSchema: { [fieldName: string]: UISchema },\n isRoot: boolean,\n): UseAsyncValidatorsResult {\n const [entries, setEntries] = useState<Record<string, Entry>>({});\n // Key handled per id, set synchronously at call time so a render/memo re-run\n // never re-fires the same key and a superseded settle is discarded.\n const handledKey = useRef<Record<string, string>>({});\n\n const candidates =\n registry && (registry.asyncField || registry.asyncForm)\n ? collectCandidates(schema, data, registry, uiSchema, isRoot)\n : [];\n const liveIds = new Set(candidates.map((c) => c.id));\n const signature = candidates.map((c) => `${c.id}=${c.key}`).join(\";\");\n\n useEffect(() => {\n for (const c of candidates) {\n if (handledKey.current[c.id] === c.key) continue;\n handledKey.current[c.id] = c.key; // mark BEFORE firing (sync guard)\n\n setEntries((e) => ({\n ...e,\n [c.id]: { key: c.key, pending: true, errors: [] },\n }));\n const settle = (errors: FieldError[]) => {\n if (handledKey.current[c.id] !== c.key) return; // superseded\n setEntries((e) => ({\n ...e,\n [c.id]: { key: c.key, pending: false, errors },\n }));\n };\n c.run()\n .then((r) => settle(toFieldErrors(r, c.pointer)))\n .catch(() => settle([])); // a failed check is not an invalid value\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [signature]);\n\n // Prune state for validators no longer present.\n const liveKey = [...liveIds].sort().join(\",\");\n useEffect(() => {\n setEntries((e) => {\n const kept = Object.entries(e).filter(([id]) => liveIds.has(id));\n return kept.length === Object.keys(e).length\n ? e\n : Object.fromEntries(kept);\n });\n for (const id of Object.keys(handledKey.current)) {\n if (!liveIds.has(id)) delete handledKey.current[id];\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [liveKey]);\n\n let isValidating = false;\n const errorList: FieldError[] = [];\n for (const c of candidates) {\n const entry = entries[c.id];\n if (!entry || entry.key !== c.key || entry.pending) {\n isValidating = true;\n continue;\n }\n errorList.push(...entry.errors);\n }\n\n // Stabilize by content so the caller's validation memo (and onValidationChange)\n // do not see a new array every render.\n const errorSig = errorList\n .map((e) => `${e.pointer}\\u0000${e.message}`)\n .join(\"|\");\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const asyncErrors = useMemo(() => errorList, [errorSig]);\n\n return { asyncErrors, isValidating };\n}\n","import { JsonSchemaProperty } from \"@petrarca/sonnet-core/schema\";\n\n/**\n * Order properties based on the x-ui-order array.\n *\n * Fields listed in x-ui-order are rendered first (in that order).\n * Fields not listed are rendered after in their original schema order.\n * Names in x-ui-order that don't exist in properties are silently ignored.\n */\nexport function orderProperties(\n properties: Record<string, JsonSchemaProperty>,\n orderArray: string[] | undefined,\n): [string, JsonSchemaProperty][] {\n const allEntries = Object.entries(properties);\n\n if (!orderArray || orderArray.length === 0) return allEntries;\n\n const orderSet = new Set(orderArray);\n const map = new Map(allEntries);\n\n const ordered: [string, JsonSchemaProperty][] = [];\n for (const name of orderArray) {\n const prop = map.get(name);\n if (prop) ordered.push([name, prop]);\n }\n\n const unordered = allEntries.filter(([name]) => !orderSet.has(name));\n return [...ordered, ...unordered];\n}\n","/**\n * useResolvedSchema - Schema resolution and property ordering\n *\n * Resolves conditional schemas (if-then-else, allOf) based on the current\n * form data, and applies x-ui-order to produce a stable ordered list of\n * [fieldName, property] pairs for rendering.\n *\n * ## Relationship to useFormEngine\n *\n * `useFormEngine` already performs this same resolution internally so that\n * validation and field-cleanup effects have access to the live schema.\n * This hook exists as a **standalone composable** for consumers that need\n * schema resolution without the full form-state machinery — for example:\n *\n * - A read-only schema viewer that renders fields without tracking changes\n * - A field-count or schema-diff preview component\n * - A future form builder that needs to inspect the resolved structure\n * before mounting a full form engine\n *\n * Do **not** import both this hook and `useFormEngine` in the same component\n * for the same schema/data pair — that would resolve the schema twice.\n * Prefer the values returned by `useFormEngine` when the engine is already\n * in use.\n *\n * @module components/Forms/hooks/useResolvedSchema\n */\n\nimport { useMemo } from \"react\";\nimport { JsonSchema, JsonSchemaProperty } from \"@petrarca/sonnet-core/schema\";\nimport {\n getSchemaProperties,\n resolveSchema,\n} from \"@petrarca/sonnet-core/schema\";\nimport { UISchema } from \"../widgets\";\nimport { orderProperties } from \"./orderProperties\";\n\nexport interface UseResolvedSchemaOptions {\n schema: JsonSchema;\n formData: Record<string, any>;\n uiSchema: { [fieldName: string]: UISchema };\n}\n\nexport interface UseResolvedSchemaResult {\n resolvedSchema: JsonSchema;\n orderedProperties: [string, JsonSchemaProperty][];\n}\n\nexport function useResolvedSchema({\n schema,\n formData,\n uiSchema,\n}: UseResolvedSchemaOptions): UseResolvedSchemaResult {\n const resolvedSchema = useMemo(\n () => resolveSchema(schema, formData),\n [schema, formData],\n );\n\n const orderedProperties = useMemo(() => {\n const properties = getSchemaProperties(resolvedSchema);\n const rawOrder = uiSchema[\"x-ui-order\"] ?? resolvedSchema[\"x-ui-order\"];\n const orderArray = Array.isArray(rawOrder)\n ? (rawOrder as string[])\n : undefined;\n return orderProperties(properties, orderArray);\n }, [resolvedSchema, uiSchema]);\n\n return { resolvedSchema, orderedProperties };\n}\n"],"mappings":";AAaA,SAAS,UAAU;AA8CG,cAGlB,YAHkB;AAXf,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA;AACF,GAA0B;AACxB,MAAI,QAAS,QAAO,oBAAC,SAAI,WAAuB,UAAS;AAEzD,QAAM,UAAU,CAAC,CAAC,SAChB;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT,WAAU;AAAA,MAET;AAAA;AAAA,QACA,YAAY,oBAAC,UAAK,WAAU,yBAAwB,eAAC;AAAA;AAAA;AAAA,EACxD;AAGF,QAAM,gBAAgB,eACpB,oBAAC,OAAE,IAAI,GAAG,OAAO,gBAAgB,WAAU,iCACxC,uBACH;AAGF,QAAM,UAAU,SACd,oBAAC,OAAE,IAAI,GAAG,OAAO,UAAU,WAAU,wCAClC,iBACH;AAOF,MAAI,mBAAmB,WAAW,CAAC,CAAC,OAAO;AACzC,WACE,qBAAC,SAAI,WAAW,GAAG,2BAA2B,SAAS,GACrD;AAAA,0BAAC,SAAI,WAAU,8BAA8B,mBAAQ;AAAA,MACrD,qBAAC,SAAI,WAAU,4BACZ;AAAA;AAAA,QACA;AAAA,QACA;AAAA,SACH;AAAA,OACF;AAAA,EAEJ;AAEA,SACE,qBAAC,SAAI,WAAW,GAAG,aAAa,SAAS,GACtC;AAAA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,KACH;AAEJ;;;AChGO,SAAS,mBACd,SACA,OACA,aACoB;AACpB,MAAI,MAAO,QAAO,GAAG,OAAO;AAC5B,MAAI,YAAa,QAAO,GAAG,OAAO;AAClC,SAAO;AACT;AAOO,SAAS,0BACd,SACA,OACA,aACA,SACoB;AACpB,MAAI,QAAS,QAAO;AACpB,SAAO,mBAAmB,SAAS,OAAO,WAAW;AACvD;AAMO,SAAS,oBACd,OACA,SACoB;AACpB,MAAI,WAAW,MAAO,QAAO,OAAO,KAAK;AACzC,SAAO;AACT;AAMO,SAAS,gBACd,OACA,SACoB;AACpB,MAAI,WAAW,MAAO,QAAO;AAC7B,SAAO;AACT;AAOO,SAAS,kBACd,OACoB;AACpB,MAAI,UAAU,MAAO,QAAO;AAC5B,SAAO,SAAS;AAClB;;;AC7DA,OAAO,SAAS,aAAa;AAC7B,SAAS,aAAa;AACtB,SAAS,MAAAA,WAAU;AAyEX,SACE,OAAAC,MADF,QAAAC,aAAA;AApCD,IAAM,YAAY,MAAM;AAAA,EAC7B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,cAAc,MAAM;AAC1B,UAAM,UAAU,MAAM;AAEtB,UAAM,eAAe,oBACjB,EAAE,cAAc,GAAG,iBAAiB,KAAK,IACzC;AAEJ,WACE,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAO,UAAU,QAAQ,SAAY;AAAA,QACrC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QAEX,0BAAAC,MAAC,SAAI,WAAU,YACb;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,IAAI;AAAA,cACJ;AAAA,cACA;AAAA,cACA,OAAO;AAAA,cACP,WAAWE;AAAA,gBACT,SAAS;AAAA,gBACT;AAAA,cACF;AAAA,cACA,gBAAc,QAAQ,SAAS;AAAA,cAC/B,oBAAkB;AAAA,gBAChB;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,cACA,cAAY,oBAAoB,OAAO,OAAO;AAAA,cAC9C,OAAO,gBAAgB,OAAO,OAAO;AAAA,cACpC,GAAG;AAAA;AAAA,UACN;AAAA,UACC,gBACC,gBAAAF,KAAC,SAAI,WAAU,qEACZ,wBACH;AAAA,WAEJ;AAAA;AAAA,IACF;AAAA,EAEJ;AACF;AAEA,UAAU,cAAc;;;AC1GxB,OAAOG,UAAS,WAAW,SAAAC,QAAO,cAAc;AAChD,SAAS,gBAAgB;AACzB,SAAS,MAAAC,WAAU;AAoIb,SACE,OAAAC,MADF,QAAAC,aAAA;AArGN,SAAS,aACP,cACA,aACA;AACA,SAAO,CAAC,YAAwC;AAC9C,gBAAY,UAAU;AACtB,QAAI,OAAO,iBAAiB,YAAY;AACtC,mBAAa,OAAO;AAAA,IACtB,WAAW,cAAc;AACvB,mBAAa,UAAU;AAAA,IACzB;AAAA,EACF;AACF;AAGA,SAAS,cACP,KACA,OACA,UACA,SACA;AACA,YAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,IAAI,QAAS;AAC/B,UAAM,WAAW,IAAI;AACrB,aAAS,MAAM,SAAS;AACxB,UAAM,YAAY,KAAK,IAAI,SAAS,cAAc,UAAU,EAAE;AAC9D,aAAS,MAAM,SAAS,GAAG,SAAS;AAAA,EACtC,GAAG,CAAC,OAAO,UAAU,SAAS,GAAG,CAAC;AACpC;AAKA,SAAS,kBACP,OACA,UACA,WACA;AACA,SAAOC;AAAA,IACL,SAAS;AAAA,IACT,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACF;AAOO,IAAM,eAAeC,OAAM,WAGhC,CAAC,UAAU,QAAQ;AACnB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA;AAAA,IAGA,UAAU;AAAA,IACV,SAAS;AAAA,IACT,GAAG;AAAA,EACL,IAAI;AACJ,QAAM,WAAW,gBAAgB;AACjC,QAAM,UAAU,eAAe;AAE/B,QAAM,cAAcC,OAAM;AAC1B,QAAM,aAAa,MAAM;AACzB,QAAM,cAAc,OAAmC,IAAI;AAC3D,QAAM,UAAU,aAAa,KAAK,WAAW;AAE7C,gBAAc,aAAa,OAAO,UAAU,OAAO;AAEnD,QAAM,eAAe,oBACjB,EAAE,cAAc,GAAG,iBAAiB,KAAK,IACzC;AAEJ,QAAM,gBAAgB,WAAW,UAAU,MAAM;AACjD,QAAM,gBAAgB,UAAU,QAAQ,SAAY;AAEpD,SACE,gBAAAJ;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAWE,IAAG,iBAAiB,gBAAgB;AAAA,MAE/C,0BAAAD,MAAC,SAAI,WAAU,2BACb;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,IAAI;AAAA,YACJ,KAAK;AAAA,YACL;AAAA,YACA;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN,WAAW,kBAAkB,OAAO,UAAU,SAAS;AAAA,YACvD,OAAO;AAAA,YACP,gBAAc,QAAQ,SAAS;AAAA,YAC/B,oBAAkB,mBAAmB,YAAY,OAAO,WAAW;AAAA,YAClE,GAAG;AAAA;AAAA,QACN;AAAA,QACC,gBACC,gBAAAA,KAAC,SAAI,WAAU,iDACZ,wBACH;AAAA,SAEJ;AAAA;AAAA,EACF;AAEJ,CAAC;AAED,aAAa,cAAc;;;ACrK3B,OAAOK,UAAS,SAAAC,cAAa;AAC7B,SAAS,SAAAC,cAAa;AACtB,SAAS,MAAAC,WAAU;AAuGX,gBAAAC,YAAA;AAxDD,IAAM,kBAAkBC,OAAM;AAAA,EAInC,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GACA,QACG;AACH,UAAM,cAAcC,OAAM;AAC1B,UAAM,UAAU,MAAM;AAEtB,UAAM,eAAe,CAAC,MAA2C;AAC/D,UAAI,CAAC,SAAU;AACf,YAAM,MAAM,EAAE,OAAO;AACrB,UAAI,QAAQ,MAAM,QAAQ,QAAW;AACnC,iBAAS,MAAS;AAAA,MACpB,OAAO;AACL,cAAM,SAAS,WAAW,GAAG;AAC7B,YAAI,CAAC,MAAM,MAAM,EAAG,UAAS,MAAM;AAAA,MACrC;AAAA,IACF;AAEA,UAAM,eACJ,UAAU,UAAa,UAAU,OAAO,OAAO,KAAK,IAAI;AAE1D,WACE,gBAAAF;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QAEX,0BAAAA;AAAA,UAACG;AAAA,UAAA;AAAA,YACC,IAAI;AAAA,YACJ;AAAA,YACA;AAAA,YACA,MAAK;AAAA,YACL,WAAU;AAAA,YACV,OAAO;AAAA,YACP,UAAU;AAAA,YACV;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,MAAM,SAAS,eAAe,QAAQ;AAAA,YACtC,WAAWC,IAAG,SAAS,sBAAsB,SAAS;AAAA,YACtD,gBAAc,QAAQ,SAAS;AAAA,YAC/B,oBAAkB,mBAAmB,SAAS,OAAO,WAAW;AAAA,YAChE,iBAAe;AAAA;AAAA,QACjB;AAAA;AAAA,IACF;AAAA,EAEJ;AACF;AAEA,gBAAgB,cAAc;;;AC5H9B,OAAOC,UAAS,SAAAC,cAAa;AAC7B,SAAS,gBAAgB;AACzB,SAAS,MAAAC,WAAU;AA6Df,SA4BA,UApBe,OAAAC,MARf,QAAAC,aAAA;AATJ,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuB;AACrB,MAAI,WAAW,CAAC,MAAO,QAAO;AAC9B,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAWC;AAAA,QACT;AAAA,QACA,YAAY;AAAA,MACd;AAAA,MAEC;AAAA;AAAA,QACA,YAAY,gBAAAF,KAAC,UAAK,WAAU,yBAAwB,eAAC;AAAA;AAAA;AAAA,EACxD;AAEJ;AASA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,MAAI,QAAS,QAAO;AACpB,SACE,gBAAAC,MAAA,YACG;AAAA,mBACC,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,IAAI,GAAG,OAAO;AAAA,QACd,WAAU;AAAA,QAET;AAAA;AAAA,IACH;AAAA,IAED,SACC,gBAAAA,KAAC,OAAE,IAAI,GAAG,OAAO,UAAU,WAAU,iCAClC,iBACH;AAAA,KAEJ;AAEJ;AAOO,IAAM,eAAeG,OAAM;AAAA,EAIhC,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GACA,QACG;AACH,UAAM,cAAcC,OAAM;AAC1B,UAAM,aAAa,MAAM;AAEzB,UAAM,sBAAsB,CAAC,eAA0C;AACrE,UAAI,CAAC,YAAY,UAAU;AACzB,iBAAS,UAAU;AAAA,MACrB;AAAA,IACF;AAEA,WACE,gBAAAH,MAAC,SAAI,WAAWC,IAAG,CAAC,WAAW,aAAa,gBAAgB,GAC1D;AAAA,sBAAAD,MAAC,SAAI,WAAU,8BACb;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,IAAI;AAAA,YACJ;AAAA,YACA;AAAA,YACA,iBAAiB;AAAA,YACjB;AAAA,YACA,UAAU,YAAY;AAAA,YACtB;AAAA,YACA,WAAWE,IAAG,SAAS,sBAAsB,SAAS;AAAA,YACtD,gBAAc,QAAQ,SAAS;AAAA,YAC/B,oBAAkB;AAAA,cAChB;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,YACA,cAAY,oBAAoB,OAAO,OAAO;AAAA,YAC9C,OAAO,gBAAgB,OAAO,OAAO;AAAA;AAAA,QACvC;AAAA,QACA,gBAAAF;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,QACF;AAAA,SACF;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA;AAAA,MACF;AAAA,OACF;AAAA,EAEJ;AACF;AAEA,aAAa,cAAc;;;AC9L3B,YAAYK,YAAW;AACvB,SAAS,OAAO,gBAAgB,MAAM,SAAS;AAC/C,SAAS,MAAAC,WAAU;AACnB,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,SAAS,gBAAgB,sBAAsB;;;ACdxD,SAAS,yBAAyB;AAS3B,SAAS,mBACd,gBACA,WACgB;AAChB,SAAO,kBAAkB,cAAc,EAAE,IAAI,CAAC,QAAQ;AACpD,UAAM,MAAM,OAAO,GAAG;AACtB,WAAO,EAAE,OAAO,KAAK,OAAO,UAAU,GAAG,KAAK,IAAI;AAAA,EACpD,CAAC;AACH;AAOO,SAAS,oBACd,aACA,aACA,SACS;AACT,QAAM,UAAU,YAAY,KAAK;AACjC,MAAI,CAAC,eAAe,QAAQ,WAAW,EAAG,QAAO;AACjD,QAAM,QAAQ,QAAQ,YAAY;AAClC,SAAO,CAAC,QAAQ,KAAK,CAAC,MAAM,EAAE,MAAM,YAAY,MAAM,KAAK;AAC7D;;;AD6FI,SAEI,OAAAC,MAFJ,QAAAC,aAAA;AAxDJ,SAAS,eACP,OACA,UACA,QACA,UACA,WACA;AACA,QAAM,CAAC,MAAM,OAAO,IAAU,gBAAS,KAAK;AAC5C,QAAM,CAAC,aAAa,cAAc,IAAU,gBAAS,EAAE;AAEvD,QAAM,eAAe,CAAC,kBAA0B;AAE9C,UAAM,OAAO,aAAa,kBAAkB,QAAQ,OAAO;AAC3D,eAAW,IAAI;AACf,YAAQ,KAAK;AACb,mBAAe,EAAE;AAAA,EACnB;AAEA,QAAM,eAAe,CAAC,UAAkB;AACtC,eAAW,KAAK;AAChB,YAAQ,KAAK;AACb,mBAAe,EAAE;AAAA,EACnB;AAEA,QAAM,cAAc,CAAC,MAAwB;AAC3C,MAAE,gBAAgB;AAClB,eAAW,IAAI;AAAA,EACjB;AAEA,QAAM,mBAAmB,CAAC,YAAqB;AAC7C,YAAQ,OAAO;AACf,QAAI,QAAS;AACb,mBAAe,EAAE;AACjB,aAAS;AAAA,EACX;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AACF,GAGG;AACD,SACE,gBAAAA,MAAC,SAAI,WAAU,2BACZ;AAAA,iBACC,gBAAAD,KAAC,KAAE,WAAU,wCAAuC,SAAS,SAAS;AAAA,IAExE,gBAAAA,KAAC,kBAAe,WAAU,+BAA8B;AAAA,KAC1D;AAEJ;AAIA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAAE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AACF,GAWG;AACD,QAAM,aAAa,oBAAoB,aAAa,aAAa,OAAO;AACxE,SACE,gBAAAD,MAAC,WAAQ,cAAc,OACrB;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,aAAa;AAAA,QACb,OAAO;AAAA,QACP,eAAe;AAAA;AAAA,IACjB;AAAA,IACA,gBAAAC,MAAC,eACE;AAAA,OAAC,cACA,gBAAAD,KAAC,gBAAc,oBAAU,eAAeE,eAAa;AAAA,MAEvD,gBAAAD,MAAC,gBACE;AAAA,gBACE;AAAA,UAAO,CAAC,WACP,OAAO,MAAM,YAAY,EAAE,SAAS,YAAY,YAAY,CAAC;AAAA,QAC/D,EACC,IAAI,CAAC,WACJ,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,OAAO,OAAO;AAAA,YACd;AAAA,YAEA;AAAA,8BAAAD;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAWG;AAAA,oBACT;AAAA,oBACA,UAAU,OAAO,QAAQ,gBAAgB;AAAA,kBAC3C;AAAA;AAAA,cACF;AAAA,cACC,OAAO;AAAA;AAAA;AAAA,UAVH,OAAO;AAAA,QAWd,CACD;AAAA,QACF,cACC,gBAAAF;AAAA,UAAC;AAAA;AAAA,YAEC,OAAO,aAAa,WAAW;AAAA,YAC/B,UAAU,MAAM,WAAW,YAAY,KAAK,CAAC;AAAA,YAE7C;AAAA,8BAAAD,KAAC,QAAK,WAAU,gBAAe;AAAA,cAAE;AAAA,cAClB,YAAY,KAAK;AAAA,cAAE;AAAA;AAAA;AAAA,UAL9B;AAAA,QAMN;AAAA,SAEJ;AAAA,OACF;AAAA,KACF;AAEJ;AAGA,SAAS,gBAAgB,OAAwB;AAC/C,SAAO;AAAA,IACL,aAAa,MAAM,eAAe;AAAA,IAClC,mBAAmB,MAAM,qBAAqB;AAAA,IAC9C,cAAc,MAAM,gBAAgB;AAAA,IACpC,WAAW,MAAM,aAAa;AAAA,IAC9B,UAAU,MAAM,YAAY;AAAA,IAC5B,UAAU,MAAM,YAAY;AAAA,IAC5B,SAAS,MAAM,WAAW;AAAA,EAC5B;AACF;AAEO,SAAS,WAAW,OAAwB;AACjD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,cAAAE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,gBAAgB,KAAK;AAEzB,QAAM,cAAoB,aAAM;AAChC,QAAM,WAAW,MAAM;AAEvB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,eAAe,OAAO,UAAU,QAAQ,UAAU,SAAS;AAE/D,QAAM,iBAAiB,QAAQ,KAAK,CAAC,QAAQ,IAAI,UAAU,KAAK;AAChE,QAAM,aAAa,YAAY,YAAY;AAE3C,SACE,gBAAAF;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MAEX,0BAAAC,MAAC,WAAQ,MAAY,cAAc,kBACjC;AAAA,wBAAAD,KAAC,kBAAe,SAAO,MACrB,0BAAAC;AAAA,UAAC;AAAA;AAAA,YACC,IAAI;AAAA,YACJ,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,gBAAc,QAAQ,SAAS;AAAA,YAC/B,oBAAkB;AAAA,cAChB;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,YACA,cAAY,oBAAoB,OAAO,OAAO;AAAA,YAC9C,OAAO,gBAAgB,OAAO,OAAO;AAAA,YACrC,WAAWE;AAAA,cACT;AAAA,cACA,CAAC,kBAAkB;AAAA,cACnB,SAAS;AAAA,cACT;AAAA,YACF;AAAA,YACA,UAAU;AAAA,YACV;AAAA,YAEA;AAAA,8BAAAH,KAAC,UAAK,WAAU,YACb,2BAAiB,eAAe,QAAQ,aAC3C;AAAA,cACA,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAW,aAAa,CAAC,CAAC,SAAS,CAAC;AAAA,kBACpC,SAAS;AAAA;AAAA,cACX;AAAA;AAAA;AAAA,QACF,GACF;AAAA,QACA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAM;AAAA,YAEN,0BAAAA;AAAA,cAAC;AAAA;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA,gBAAgB;AAAA,gBAChB;AAAA,gBACA,cAAcE;AAAA,gBACd;AAAA,gBACA;AAAA,gBACA,UAAU;AAAA,gBACV;AAAA,gBACA,UAAU;AAAA;AAAA,YACZ;AAAA;AAAA,QACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;;;AEzUA,YAAYE,YAAW;AACvB,SAAS,SAAAC,QAAO,kBAAAC,iBAAgB,KAAAC,UAAS;AACzC,SAAS,MAAAC,WAAU;AACnB,SAAS,UAAAC,eAAc;AACvB,SAAS,aAA4B;AACrC;AAAA,EACE,WAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,eAAAC;AAAA,OACK;AACP,SAAS,WAAAC,UAAS,kBAAAC,iBAAgB,kBAAAC,uBAAsB;AA0DpD,SAkEA,YAAAC,WA1CM,OAAAC,MAxBN,QAAAC,aAAA;AAPJ,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,SACE,gBAAAA,MAAC,SAAM,SAAQ,aAAY,YAAwB,WAAU,QAC1D;AAAA,WAAO;AAAA,IACP,CAAC;AAAA;AAAA;AAAA;AAAA,IAKA,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,UAAU;AAAA,QACV,cAAY,UAAU,OAAO,KAAK;AAAA,QAClC,WAAU;AAAA,QACV,WAAW,CAAC,MAAM;AAChB,cAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,cAAE,eAAe;AACjB,qBAAS,OAAO,OAAO,CAAC;AAAA,UAC1B;AAAA,QACF;AAAA,QACA,aAAa,CAAC,MAAM;AAClB,YAAE,eAAe;AACjB,YAAE,gBAAgB;AAAA,QACpB;AAAA,QACA,SAAS,CAAC,MAAM,SAAS,OAAO,OAAO,CAAC;AAAA,QAExC,0BAAAA,KAACE,IAAA,EAAE,WAAU,uDAAsD;AAAA;AAAA,IACrE;AAAA,KAEJ;AAEJ;AAeA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,MAAI,gBAAgB,WAAW,GAAG;AAChC,WAAO,gBAAAF,KAAC,UAAK,WAAU,yBAAyB,uBAAY;AAAA,EAC9D;AAEA,QAAM,kBAAkB,gBAAgB,MAAM,GAAG,mBAAmB;AACpE,QAAM,iBAAiB,gBAAgB,SAAS;AAChD,QAAM,eACJ,YAAY,kBAAkB,KAAK,gBAAgB,SAAS;AAE9D,SACE,gBAAAC,MAAAF,WAAA,EACG;AAAA,oBAAgB,IAAI,CAAC,WACpB,gBAAAC;AAAA,MAAC;AAAA;AAAA,QAEC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,MAJK,OAAO;AAAA,IAKd,CACD;AAAA,IACA,iBAAiB,KAChB,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,SAAQ;AAAA,QACR;AAAA,QACA,WAAU;AAAA,QACV,SAAS;AAAA,QACV;AAAA;AAAA,UACG;AAAA,UAAe;AAAA;AAAA;AAAA,IACnB;AAAA,IAED,gBACC,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,SAAQ;AAAA,QACR;AAAA,QACA,WAAU;AAAA,QACV,SAAS;AAAA,QACV;AAAA;AAAA,IAED;AAAA,KAEJ;AAEJ;AAaA,SAAS,oBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAAG;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA6B;AAC3B,SACE,gBAAAF,MAACG,UAAA,EAAQ,cAAc,OACrB;AAAA,oBAAAJ;AAAA,MAACK;AAAA,MAAA;AAAA,QACC,aAAa;AAAA,QACb,OAAO;AAAA,QACP,eAAe;AAAA;AAAA,IACjB;AAAA,IACA,gBAAAJ,MAACK,cAAA,EACC;AAAA,sBAAAN,KAACO,eAAA,EAAc,oBAAU,eAAeJ,eAAa;AAAA,MACrD,gBAAAH,KAACQ,eAAA,EACE,kBACE;AAAA,QAAO,CAAC,WACP,OAAO,MAAM,YAAY,EAAE,SAAS,YAAY,YAAY,CAAC;AAAA,MAC/D,EACC,IAAI,CAAC,WACJ,gBAAAP;AAAA,QAACQ;AAAA,QAAA;AAAA,UAEC,OAAO,OAAO;AAAA,UACd;AAAA,UAEA;AAAA,4BAAAT;AAAA,cAACU;AAAA,cAAA;AAAA,gBACC,WAAWC;AAAA,kBACT;AAAA,kBACA,MAAM,SAAS,OAAO,KAAK,IAAI,gBAAgB;AAAA,gBACjD;AAAA;AAAA,YACF;AAAA,YACC,OAAO;AAAA;AAAA;AAAA,QAVH,OAAO;AAAA,MAWd,CACD,GACL;AAAA,OACF;AAAA,KACF;AAEJ;AAMA,SAAS,oBACP,OACA,UACA,QACA;AACA,QAAM,CAAC,MAAM,OAAO,IAAU,gBAAS,KAAK;AAC5C,QAAM,CAAC,aAAa,cAAc,IAAU,gBAAS,EAAE;AACvD,QAAM,CAAC,UAAU,WAAW,IAAU,gBAAS,KAAK;AAEpD,QAAM,eAAe,CAAC,kBAA0B;AAC9C,UAAM,WAAW,MAAM,SAAS,aAAa,IACzC,MAAM,OAAO,CAAC,MAAM,MAAM,aAAa,IACvC,CAAC,GAAG,OAAO,aAAa;AAC5B,eAAW,QAAQ;AAAA,EACrB;AAEA,QAAM,eAAe,CACnB,eACA,MACG;AACH,MAAE,gBAAgB;AAClB,eAAW,MAAM,OAAO,CAAC,MAAM,MAAM,aAAa,CAAC;AAAA,EACrD;AAEA,QAAM,iBAAiB,CAAC,MAAwB;AAC9C,MAAE,gBAAgB;AAClB,eAAW,CAAC,CAAC;AAAA,EACf;AAEA,QAAM,mBAAmB,CAAC,YAAqB;AAC7C,YAAQ,OAAO;AACf,QAAI,QAAS;AACb,mBAAe,EAAE;AACjB,gBAAY,KAAK;AACjB,aAAS;AAAA,EACX;AAEA,QAAM,eAAe,CAAC,MAAwB;AAC5C,MAAE,gBAAgB;AAClB,gBAAY,IAAI;AAAA,EAClB;AAEA,QAAM,iBAAiB,CAAC,MAAwB;AAC9C,MAAE,gBAAgB;AAClB,gBAAY,KAAK;AAAA,EACnB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAOA,SAAS,2BAA2B,OAA6B;AAC/D,SAAO;AAAA,IACL,aAAa,MAAM,eAAe;AAAA,IAClC,mBAAmB,MAAM,qBAAqB;AAAA,IAC9C,cAAc,MAAM,gBAAgB;AAAA,IACpC,WAAW,MAAM,aAAa;AAAA,IAC9B,UAAU,MAAM,YAAY;AAAA,IAC5B,UAAU,MAAM,YAAY;AAAA,IAC5B,SAAS,MAAM,WAAW;AAAA,IAC1B,YAAY,MAAM,cAAc;AAAA,EAClC;AACF;AAGA,SAASC,cAAa;AAAA,EACpB;AAAA,EACA;AACF,GAGG;AACD,SACE,gBAAAX,MAAC,SAAI,WAAU,gCACZ;AAAA,iBACC,gBAAAD,KAACE,IAAA,EAAE,WAAU,wCAAuC,SAAS,SAAS;AAAA,IAExE,gBAAAF,KAACa,iBAAA,EAAe,WAAU,+BAA8B;AAAA,KAC1D;AAEJ;AAEO,SAAS,gBAAgB,OAA6B;AAC3D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,QAAQ,MAAM,SAAS,CAAC;AAC9B,QAAM,cAAoB,aAAM;AAChC,QAAM,UAAU,MAAM;AACtB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,cAAAV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,2BAA2B,KAAK;AAEpC,QAAM,kBAAkB,QAAQ,OAAO,CAAC,QAAQ,MAAM,SAAS,IAAI,KAAK,CAAC;AACzE,QAAM,aAAa,YAAY,YAAY;AAE3C,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,oBAAoB,OAAO,UAAU,MAAM;AAE/C,QAAM,sBAAsB,WAAW,WAAW;AAElD,SACE,gBAAAF;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT,OAAO,kBAAkB,KAAK;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MAEX;AAAA,wBAAAA,MAACa,UAAA,EAAQ,MAAY,cAAc,kBACjC;AAAA,0BAAAd,KAACe,iBAAA,EAAe,SAAO,MACrB,0BAAAd;AAAA,YAACe;AAAA,YAAA;AAAA,cACC,IAAI;AAAA,cACJ,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,iBAAe;AAAA,cACf,WAAWL;AAAA,gBACT;AAAA,gBACA,SAAS;AAAA,gBACT;AAAA,cACF;AAAA,cACA,UAAU;AAAA,cACV;AAAA,cAEA;AAAA,gCAAAX,KAAC,SAAI,WAAU,+BACb,0BAAAA;AAAA,kBAAC;AAAA;AAAA,oBACC;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA,UAAU;AAAA,oBACV,UAAU;AAAA,oBACV,YAAY;AAAA;AAAA,gBACd,GACF;AAAA,gBACA,gBAAAA;AAAA,kBAACY;AAAA,kBAAA;AAAA,oBACC,WAAW,aAAa,MAAM,SAAS,KAAK,CAAC;AAAA,oBAC7C,SAAS;AAAA;AAAA,gBACX;AAAA;AAAA;AAAA,UACF,GACF;AAAA,UACA,gBAAAZ;AAAA,YAACiB;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAM;AAAA,cAEN,0BAAAjB;AAAA,gBAAC;AAAA;AAAA,kBACC;AAAA,kBACA;AAAA,kBACA,gBAAgB;AAAA,kBAChB;AAAA,kBACA,cAAcG;AAAA,kBACd;AAAA,kBACA;AAAA,kBACA,UAAU;AAAA;AAAA,cACZ;AAAA;AAAA,UACF;AAAA,WACF;AAAA,QAGC,QACC,MAAM,IAAI,CAAC,MAAM,gBAAAH,KAAC,WAAc,MAAK,UAAS,MAAY,OAAO,KAApC,CAAuC,CAAE;AAAA;AAAA;AAAA,EAC1E;AAEJ;;;AC5bA,YAAYkB,YAAW;AACvB,SAAS,MAAAC,WAAU;AACnB,SAAS,SAAAC,cAAa;;;ACHtB,SAAS,KAAAC,UAAS;AAClB,SAAS,SAAAC,cAAa;AAkBlB,SAEI,OAAAC,MAFJ,QAAAC,aAAA;AARG,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkB;AAChB,SACE,gBAAAA,MAACF,QAAA,EAAM,SAAQ,aAAY,WAAU,SAClC;AAAA,gBAAY,CAAC,aACZ,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,SAAS,CAAC,MAAM;AACd,YAAE,gBAAgB;AAClB,mBAAS,KAAK;AAAA,QAChB;AAAA,QAEC;AAAA;AAAA,IACH,IAEA;AAAA,IAED,CAAC,cACA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY,UAAU,GAAG;AAAA,QACzB,WAAU;AAAA,QACV,WAAW,CAAC,MAAM;AAChB,cAAI,EAAE,QAAQ,SAAS;AACrB,cAAE,eAAe;AACjB,qBAAS,KAAK;AAAA,UAChB;AAAA,QACF;AAAA,QACA,aAAa,CAAC,MAAM;AAClB,YAAE,eAAe;AACjB,YAAE,gBAAgB;AAAA,QACpB;AAAA,QACA,SAAS,CAAC,MAAM;AACd,YAAE,gBAAgB;AAClB,mBAAS,KAAK;AAAA,QAChB;AAAA,QAEA,0BAAAA,KAACF,IAAA,EAAE,WAAU,uDAAsD;AAAA;AAAA,IACrE;AAAA,KAEJ;AAEJ;;;AD0FM,SASI,OAAAI,MATJ,QAAAC,aAAA;AApHN,SAAS,iBACP,OACA,UACA,iBACA,SACA,WACA;AACA,QAAM,CAAC,YAAY,aAAa,IAAU,gBAAS,EAAE;AAErD,QAAM,SAAe;AAAA,IACnB,CAAC,QAAgB;AACf,YAAM,aAAa,IAAI,KAAK;AAC5B,UAAI,CAAC,WAAY;AACjB,UAAI,CAAC,mBAAmB,MAAM,SAAS,UAAU,EAAG;AACpD,UAAI,WAAW,MAAM,UAAU,QAAS;AACxC,iBAAW,CAAC,GAAG,OAAO,UAAU,CAAC;AACjC,oBAAc,EAAE;AAAA,IAClB;AAAA,IACA,CAAC,OAAO,UAAU,iBAAiB,OAAO;AAAA,EAC5C;AAEA,QAAM,YAAkB;AAAA,IACtB,CAAC,kBAA0B;AACzB,iBAAW,MAAM,OAAO,CAAC,GAAG,UAAU,UAAU,aAAa,CAAC;AAAA,IAChE;AAAA,IACA,CAAC,OAAO,QAAQ;AAAA,EAClB;AAEA,QAAM,gBAAsB;AAAA,IAC1B,CAAC,MAA6C;AAC5C,UAAI,UAAU,SAAS,EAAE,GAAG,GAAG;AAC7B,UAAE,eAAe;AACjB,eAAO,UAAU;AACjB;AAAA,MACF;AACA,UAAI,EAAE,QAAQ,eAAe,CAAC,cAAc,MAAM,SAAS,GAAG;AAC5D,UAAE,eAAe;AACjB,kBAAU,MAAM,SAAS,CAAC;AAAA,MAC5B;AAAA,IACF;AAAA,IACA,CAAC,WAAW,YAAY,MAAM,QAAQ,QAAQ,SAAS;AAAA,EACzD;AAEA,QAAM,oBAA0B;AAAA,IAC9B,CAAC,MAA2C;AAC1C,YAAM,WAAW,EAAE,OAAO;AAC1B,UAAI,CAAC,UAAU,SAAS,GAAG,KAAK,CAAC,SAAS,SAAS,GAAG,GAAG;AACvD,sBAAc,QAAQ;AACtB;AAAA,MACF;AACA,YAAM,QAAQ,SAAS,MAAM,GAAG;AAChC,YAAM,MAAM,GAAG,EAAE,EAAE,QAAQ,CAAC,QAAQ,OAAO,GAAG,CAAC;AAC/C,oBAAc,MAAM,MAAM,SAAS,CAAC,CAAC;AAAA,IACvC;AAAA,IACA,CAAC,WAAW,MAAM;AAAA,EACpB;AAEA,SAAO,EAAE,YAAY,QAAQ,WAAW,eAAe,kBAAkB;AAC3E;AAKA,SAAS,oBAAoB,OAA2B;AACtD,SAAO;AAAA,IACL,UAAU,MAAM,YAAY;AAAA,IAC5B,aAAa,MAAM,eAAe;AAAA,IAClC,WAAW,MAAM,aAAa,CAAC,SAAS,GAAG;AAAA,IAC3C,iBAAiB,MAAM,mBAAmB;AAAA,EAC5C;AACF;AAEO,IAAM,gBAAsB,kBAGjC,CAAC,OAAO,QAAQ;AAChB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,CAAC;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,EAAE,UAAU,aAAa,WAAW,gBAAgB,IACxD,oBAAoB,KAAK;AAE3B,QAAM,cAAoB,aAAM;AAChC,QAAM,UAAU,MAAM;AACtB,QAAM,WAAiB,cAAyB,IAAI;AACpD,EAAM,2BAAoB,KAAK,MAAM,SAAS,OAAQ;AAEtD,QAAM,aAAa,YAAY;AAC/B,QAAM,EAAE,YAAY,WAAW,eAAe,kBAAkB,IAC9D,iBAAiB,OAAO,UAAU,iBAAiB,SAAS,SAAS;AAEvE,QAAM,uBAAuB,MAAM;AACjC,aAAS,SAAS,MAAM;AAAA,EAC1B;AAEA,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT,OAAO,kBAAkB,KAAK;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MAEX,0BAAAC;AAAA,QAAC;AAAA;AAAA,UACC,WAAWC;AAAA,YACT;AAAA,YACA,cAAc;AAAA,YACd,SAAS;AAAA,UACX;AAAA,UACA,SAAS;AAAA,UAER;AAAA,kBAAM,IAAI,CAAC,KAAK,UACf,gBAAAF;AAAA,cAAC;AAAA;AAAA,gBAEC;AAAA,gBACA;AAAA,gBACA,YAAY,CAAC,CAAC;AAAA,gBACd,UAAU;AAAA;AAAA,cAJL;AAAA,YAKP,CACD;AAAA,YACD,gBAAAA;AAAA,cAACG;AAAA,cAAA;AAAA,gBACC,KAAK;AAAA,gBACL,IAAI;AAAA,gBACJ;AAAA,gBACA,OAAO;AAAA,gBACP,UAAU;AAAA,gBACV,WAAW;AAAA,gBACX,aAAa,MAAM,WAAW,IAAI,cAAc;AAAA,gBAChD,UAAU,CAAC,CAAC;AAAA,gBACZ,WAAU;AAAA;AAAA,YACZ;AAAA;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ,CAAC;AAED,cAAc,cAAc;;;AErK5B,YAAYC,YAAW;AACvB,SAAS,QAAAC,OAAM,KAAAC,UAAS;AACxB,SAAS,MAAAC,WAAU;AACnB,SAAS,SAAAC,QAAO,UAAAC,SAAQ,YAAY,SAAAC,cAAa;AA2IzC,gBAAAC,OA2GJ,QAAAC,aA3GI;AA1GR,SAAS,cACP,OACA,UACA;AACA,QAAM,CAAC,KAAK,MAAM,IAAU,gBAAS,EAAE;AACvC,QAAM,CAAC,KAAK,MAAM,IAAU,gBAAS,EAAE;AACvC,QAAM,CAAC,SAAS,UAAU,IAAU,gBAAwB,IAAI;AAEhE,QAAM,MAAM,MAAM;AAChB,UAAM,IAAI,IAAI,KAAK;AACnB,UAAM,IAAI,IAAI,KAAK;AACnB,QAAI,CAAC,KAAK,CAAC,GAAG;AACZ,iBAAW,CAAC,IAAI,iBAAiB,gBAAgB;AACjD;AAAA,IACF;AACA,eAAW,EAAE,GAAG,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC;AAC/B,WAAO,EAAE;AACT,WAAO,EAAE;AACT,eAAW,IAAI;AAAA,EACjB;AAEA,QAAM,SAAS,CAAC,MAAc;AAC5B,UAAM,EAAE,CAAC,CAAC,GAAG,UAAU,GAAG,KAAK,IAAI;AACnC,eAAW,IAAI;AAAA,EACjB;AAIA,QAAM,UAAU,CAAC,MAAc,GAAW,MAAuB;AAC/D,UAAM,UAAU,EAAE,KAAK;AACvB,QAAI,CAAC,SAAS;AACZ,iBAAW,cAAc;AACzB,aAAO;AAAA,IACT;AACA,QAAI,YAAY,QAAQ,WAAW,OAAO;AACxC,iBAAW,YAAY,OAAO,aAAa;AAC3C,aAAO;AAAA,IACT;AACA,eAAW,IAAI;AACf,QAAI,YAAY,QAAQ,MAAM,IAAI,MAAM,EAAG,QAAO;AAClD;AAAA,MACE,OAAO;AAAA,QACL,OAAO,QAAQ,KAAK,EAAE;AAAA,UAAI,CAAC,CAAC,MAAM,EAAE,MAClC,SAAS,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE;AAAA,QAC1C;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAGA,QAAM,OAAO,CAAC,MAAc;AAC1B,WAAO,CAAC;AACR,WAAO,MAAM,CAAC,KAAK,EAAE;AACrB,eAAW,IAAI;AAAA,EACjB;AAEA,QAAM,YAAY,CAAC,MAA6C;AAC9D,QAAI,EAAE,QAAQ,QAAS;AACvB,MAAE,eAAe;AACjB,QAAI;AAAA,EACN;AAGA,QAAM,UAAU,CAAC,MAAc;AAC7B,WAAO,CAAC;AACR,eAAW,IAAI;AAAA,EACjB;AACA,QAAM,YAAY,CAAC,MAAc;AAC/B,WAAO,CAAC;AACR,eAAW,IAAI;AAAA,EACjB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKA,SAAS,SAAS;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAK8B;AAC5B,QAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,MAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,SACE,gBAAAD,MAAC,SAAI,WAAU,0BACZ,eAAK,IAAI,CAAC,GAAG,UACZ,gBAAAA;AAAA,IAAC;AAAA;AAAA,MAEC,KAAK,GAAG,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,CAAC;AAAA,MAChC;AAAA,MACA;AAAA,MACA,UAAU,CAAC,MAAM,OAAO,OAAO,KAAK,CAAC,CAAC;AAAA,MACtC,UAAU,CAAC,MAAM,OAAO,KAAK,KAAK,CAAC,CAAC;AAAA;AAAA,IAL/B;AAAA,EAMP,CACD,GACH;AAEJ;AAQA,SAAS,WAAW;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAWuB;AACrB,MAAI,CAAC,aAAa;AAChB,WACE,gBAAAA;AAAA,MAACE;AAAA,MAAA;AAAA,QACC,cAAY;AAAA,QACZ;AAAA,QACA,UAAU,CAAC,MAAM,OAAO,EAAE,OAAO,KAAK;AAAA,QACtC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAEJ,QAAM,UAAU,YAAY,IAAI,CAAC,OAAO;AAAA,IACtC,OAAO,EAAE;AAAA,IACT,OAAO,EAAE,SAAS,EAAE;AAAA,EACtB,EAAE;AAEF,MAAI,SAAS,CAAC,QAAQ,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK;AACjD,YAAQ,QAAQ,EAAE,OAAO,OAAO,MAAM,CAAC;AACzC,SACE,gBAAAF;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,MACP,SAAO;AAAA,MACP;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,UAAU,CAAC,WAAW,OAAO,UAAU,EAAE;AAAA,MACzC,aAAW;AAAA,MACX,UAAU;AAAA,MACV;AAAA,MACA,mBAAkB;AAAA,MAClB;AAAA,MACA,kBAAkB;AAAA;AAAA,EACpB;AAEJ;AAIA,SAAS,QAAQ;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMuB;AACrB,QAAM,CAAC,KAAK,MAAM,IAAU,gBAAS,OAAO;AAC5C,QAAM,CAAC,KAAK,MAAM,IAAU,gBAAS,SAAS;AAC9C,EAAM,iBAAU,MAAM,OAAO,OAAO,GAAG,CAAC,OAAO,CAAC;AAChD,EAAM,iBAAU,MAAM,OAAO,SAAS,GAAG,CAAC,SAAS,CAAC;AACpD,QAAM,SAAS,MAAM;AACnB,QAAI,CAAC,OAAO,QAAQ,SAAS,KAAK,GAAG,EAAG,QAAO,OAAO;AAAA,EACxD;AACA,QAAM,YAAY,CAAC,MAA6C;AAC9D,QAAI,EAAE,QAAQ,QAAS;AACvB,MAAE,eAAe;AACjB,WAAO;AAAA,EACT;AACA,SACE,gBAAAC,MAAC,QAAG,WAAU,2BACZ;AAAA,oBAAAD;AAAA,MAACE;AAAA,MAAA;AAAA,QACC,cAAY,UAAU,OAAO;AAAA,QAC7B,OAAO;AAAA,QACP,UAAU,CAAC,MAAM,OAAO,EAAE,OAAO,KAAK;AAAA,QACtC,QAAQ;AAAA,QACR;AAAA,QACA,UAAU;AAAA,QACV,WAAU;AAAA;AAAA,IACZ;AAAA,IACA,gBAAAF;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,YAAY,OAAO;AAAA,QAC9B,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ,CAAC,WAAW;AAClB,iBAAO,MAAM;AACb,cAAI,CAAC,OAAO,QAAQ,SAAS,KAAK,MAAM,EAAG,QAAO,SAAS;AAAA,QAC7D;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA,WAAU;AAAA;AAAA,IACZ;AAAA,IACC,CAAC,cACA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,UAAU,OAAO;AAAA,QACxB,MAAK;AAAA,QACL,SAAS,MAAM,OAAO,OAAO,OAAO;AAAA,QAEpC,0BAAAA,MAACG,IAAA,EAAE;AAAA;AAAA,IACL;AAAA,KAEJ;AAEJ;AAGA,SAAS,SAAS;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAK8B;AAC5B,QAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,MAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,SACE,gBAAAH,MAAC,QAAG,WAAU,eACX,eAAK,IAAI,CAAC,GAAG,UACZ,gBAAAA;AAAA,IAAC;AAAA;AAAA,MAEC,SAAS;AAAA,MACT,WAAW,MAAM,CAAC;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA;AAAA,IALK;AAAA,EAMP,CACD,GACH;AAEJ;AAGA,SAAS,SAAS;AAAA,EAChB;AACF,GAEuB;AACrB,QAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,SACE,gBAAAA,MAAC,SAAI,WAAU,0BACZ,eAAK,IAAI,CAAC,MACT,gBAAAA;AAAA,IAACI;AAAA,IAAA;AAAA,MAEC,SAAQ;AAAA,MACR,WAAU;AAAA,MACV,OAAO,MAAM,CAAC;AAAA,MAEb;AAAA;AAAA,IALI;AAAA,EAMP,CACD,GACH;AAEJ;AAGA,SAAS,SAAS;AAAA,EAChB;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAO8B;AAC5B,SAAO,YAAY,SACjB,gBAAAJ,MAAC,YAAU,GAAG,OAAO,aAA0B,IAE/C,gBAAAA,MAAC,YAAU,GAAG,OAAO;AAEzB;AAGA,IAAM,aAAmB;AAAA,EAcvB,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,IACnB,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,EACF,GACA,QAEA,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,oBAAAD;AAAA,MAACE;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,OAAO;AAAA,QACd,UAAU,CAAC,MAAM,OAAO,QAAQ,EAAE,OAAO,KAAK;AAAA,QAC9C,WAAW,OAAO;AAAA,QAClB,aAAa;AAAA,QACb,WAAWG,IAAG,OAAO,SAAS,kCAAkC;AAAA;AAAA,IAClE;AAAA,IACA,gBAAAL;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,QACX,OAAO,OAAO;AAAA,QACd,QAAQ,OAAO;AAAA,QACf,QAAQ,OAAO;AAAA,QACf,WAAW,OAAO;AAAA,QAClB,aAAa;AAAA,QACb;AAAA,QACA,WAAWK,IAAG,OAAO,SAAS,kCAAkC;AAAA;AAAA,IAClE;AAAA,IACA,gBAAAL;AAAA,MAACM;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,cAAW;AAAA,QACX,SAAS,OAAO;AAAA,QAEhB,0BAAAN,MAACO,OAAA,EAAK,WAAU,WAAU;AAAA;AAAA,IAC5B;AAAA,KACF;AAEJ;AAEA,WAAW,cAAc;AAGzB,SAAS,QAAQ;AAAA,EACf;AAAA,EACA;AAAA,EACA;AACF,GAIuB;AACrB,SACE,gBAAAP;AAAA,IAAC;AAAA;AAAA,MACC,WAAWK;AAAA,QACT;AAAA,QACA,cAAc;AAAA,QACd,YAAY;AAAA,MACd;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAGA,IAAM,gBAAsB;AAAA,EAgB1B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GACA,QAEA,gBAAAJ,MAAC,WAAQ,YAAwB,UAC/B;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,IACC,CAAC,cACA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACC,GAAG;AAAA,QACJ,OAAO,YAAY;AAAA,QACnB;AAAA,QACA;AAAA;AAAA,IACF;AAAA,KAEJ;AAEJ;AAEA,cAAc,cAAc;AAErB,IAAM,oBAA0B,kBAGrC,CAAC,OAAO,QAAQ;AAChB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,CAAC;AAAA,IACT;AAAA,IACA,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ,IAAI;AACJ,QAAM,cAAoB,aAAM;AAChC,QAAM,UAAU,MAAM;AACtB,QAAM,SAAS,cAAc,OAAO,QAAQ;AAE5C,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT,OAAO,kBAAkB,KAAK;AAAA,MAC9B;AAAA,MACA,OAAO,SAAS,OAAO,WAAW;AAAA,MAClC,UAAU,MAAM,YAAY;AAAA,MAC5B;AAAA,MACA,WAAW;AAAA,MAEV,sBAAY,SACX,gBAAAA,MAAC,YAAS,OAAc,IAExB,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,YAAY,QAAQ,MAAM,YAAY,MAAM,QAAQ;AAAA,UACpD,UAAU,QAAQ,KAAK;AAAA,UACvB,IAAI;AAAA,UACJ,MAAM,MAAM;AAAA,UACZ,gBAAgB,MAAM;AAAA,UACtB,kBAAkB,MAAM;AAAA,UACxB;AAAA,UACA,aAAa,MAAM;AAAA;AAAA,MACrB;AAAA;AAAA,EAEJ;AAEJ,CAAC;AAED,kBAAkB,cAAc;;;AC5iBhC,OAAOQ,UAAS,eAAAC,cAAa,aAAAC,YAAW,SAAAC,QAAO,SAAS,YAAAC,iBAAgB;AACxE,SAAS,kBAAAC,uBAAsB;AAC/B,SAAS,MAAAC,YAAU;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA+JD,gBAAAC,OAoCA,QAAAC,cApCA;AAzEN,IAAM,sBAAsB;AAG5B,IAAM,uBAAuB,oBAAI,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC;AAWzD,SAAS,iBAAiB,GAAW,GAAmB;AACtD,QAAM,SAAS,KAAK,IAAI,IAAI,CAAC;AAC7B,SAAO,KAAK,OAAO,IAAI,OAAO,WAAW,MAAM,IAAI;AACrD;AAGA,SAAS,iBACP,UACA,IACA,IACA,WACQ;AACR,MAAI,OAAO,UAAa,WAAW,IAAI;AACrC,WAAO,0BAA0B,EAAE,GAAG,YAAY,IAAI,SAAS,KAAK,EAAE;AAAA,EACxE;AACA,MAAI,OAAO,UAAa,WAAW,IAAI;AACrC,WAAO,yBAAyB,EAAE,GAAG,YAAY,IAAI,SAAS,KAAK,EAAE;AAAA,EACvE;AACA,SAAO;AACT;AAGA,SAAS,eACP,UACA,WACwC;AACxC,QAAM,UACJ,cAAc,SAAY,iBAAiB,UAAU,SAAS,IAAI;AACpE,QAAM,YACJ,cAAc,SAAY,QAAQ,QAAQ,SAAS,IAAI,OAAO,OAAO;AACvE,SAAO,EAAE,SAAS,UAAU;AAC9B;AAmBA,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA+C;AAC7C,SACE,gBAAAD,MAAC,mBAAgB,OAAO,YACtB,0BAAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAY;AAAA,MACZ,cAAW;AAAA,MACX,WAAU;AAAA;AAAA,EACZ,GACF;AAEJ;AAEA,SAAS,UAAU,EAAE,OAAO,UAAU,GAAG,KAAK,GAAmB;AAC/D,MAAI,MAAM,WAAW,EAAG,QAAO,WAAW,gBAAAA,MAAC,iBAAe,GAAG,MAAM,IAAK;AACxE,SAAO,gBAAAA,MAAC,cAAW,OAAe,GAAG,MAAM;AAC7C;AAEA,SAAS,WAAW;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqC;AACnC,MAAI,MAAM,WAAW,GAAG;AACtB,WACE,gBAAAA,MAAC,mBAAgB,OAAO,YACtB,0BAAAA,MAAC,UAAK,WAAU,iCAAiC,gBAAM,CAAC,EAAE,OAAM,GAClE;AAAA,EAEJ;AAEA,SACE,gBAAAA,MAAC,mBAAgB,OAAO,YACtB,0BAAAC,OAAC,SAAI,WAAU,8BACb;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,QACP;AAAA,QACA,UAAU,YAAY;AAAA,QACtB,WAAU;AAAA,QACV,cAAW;AAAA,QAEV,gBAAM,IAAI,CAAC,MACV,gBAAAA,MAAC,YAAqB,OAAO,EAAE,OAC5B,YAAE,SADQ,EAAE,KAEf,CACD;AAAA;AAAA,IACH;AAAA,IACA,gBAAAA,MAACE,iBAAA,EAAe,WAAU,6EAA4E;AAAA,KACxG,GACF;AAEJ;AAOA,SAAS,aACP,OACA,OACA,cACA,KACA,KACA;AACA,QAAM,cAAc,QAAQ,MAAM;AAChC,UAAM,YAAY,OAAO;AAEzB,QAAI,MAAM,WAAW,EAAG,QAAO,aAAa;AAC5C,QAAI,aAAa,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,SAAS,EAAG,QAAO;AAClE,WAAO,MAAM,CAAC,GAAG,SAAS;AAAA,EAC5B,GAAG,CAAC,OAAO,MAAM,KAAK,CAAC;AAEvB,QAAM,WAAW;AAAA,IACf,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,WAAW;AAAA,IAC/C,CAAC,OAAO,WAAW;AAAA,EACrB;AAEA,QAAM,eAAe,UAAU,OAAO;AACtC,QAAM,eAAe,UAAU,OAAO;AACtC,QAAM,oBAAoB,UAAU,YAAY;AAChD,QAAM,aACJ,sBAAsB,WAAW,iBAAiB;AAEpD,SAAO,EAAE,aAAa,cAAc,cAAc,WAAW;AAC/D;AAGA,SAAS,iBACP,OACA,UACA,QACA,aACA,WACA,cACA,cACA,eACA;AACA,QAAM,CAAC,UAAU,WAAW,IAAIC;AAAA,IAC9B,OAAO,UAAU,SAAY,OAAO,MAAM,KAAK,IAAI;AAAA,EACrD;AACA,QAAM,CAAC,iBAAiB,kBAAkB,IAAIA,UAAiB,EAAE;AAGjE,EAAAC,WAAU,MAAM;AACd,UAAM,WAAW,OAAO,UAAU,SAAY,OAAO,MAAM,KAAK,IAAI;AACpE,gBAAY,CAAC,SAAS;AACpB,YAAM,SAAS,WAAW,KAAK,QAAQ,KAAK,GAAG,CAAC;AAChD,UAAI,CAAC,MAAM,MAAM,KAAK,WAAW,OAAO,MAAO,QAAO;AACtD,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,OAAO,KAAK,CAAC;AAEjB,QAAM,QAAQ,iBAAiB;AAE/B,QAAM,OAAOC;AAAA,IACX,CAAC,UAA8B,cAAsB;AACnD,iBAAW,EAAE,OAAO,UAAU,MAAM,UAAU,CAAC;AAAA,IACjD;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,oBAAoBA;AAAA,IACxB,CAAC,MAA2C;AAC1C,YAAM,MAAM,EAAE,OAAO;AACrB,UAAI,QAAQ,MAAM,CAAC,oBAAoB,KAAK,GAAG,EAAG;AAClD,kBAAY,GAAG;AACf,yBAAmB,EAAE;AAAA,IACvB;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,kBAAkBA,aAAY,MAAM;AACxC,UAAM,aAAa,SAAS,QAAQ,KAAK,GAAG;AAG5C,QAAI,qBAAqB,IAAI,UAAU,GAAG;AACxC,UAAI,eAAe,GAAI,aAAY,EAAE;AACrC,WAAK,QAAW,WAAW;AAC3B,yBAAmB,EAAE;AACrB,eAAS;AACT;AAAA,IACF;AAEA,UAAM,WAAW,WAAW,UAAU;AACtC,QAAI,MAAM,QAAQ,GAAG;AACnB,kBAAY,EAAE;AACd,WAAK,QAAW,WAAW;AAC3B,eAAS;AACT;AAAA,IACF;AAEA,UAAM,EAAE,SAAS,UAAU,IAAI,eAAe,UAAU,SAAS;AACjE,gBAAY,SAAS;AACrB;AAAA,MACE,iBAAiB,SAAS,cAAc,cAAc,WAAW;AAAA,IACnE;AACA,SAAK,SAAS,WAAW;AACzB,aAAS;AAAA,EACX,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAUO,IAAM,oBAAoBC,OAAM,WAGrC,CAAC,UAAU,QAAQ;AACnB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,QAAQ,QAAQ,MAAM,SAAS,SAAS,CAAC,GAAG,CAAC,SAAS,KAAK,CAAC;AAClE,QAAM,eAAe,SAAS,gBAAgB;AAC9C,QAAM,QAAQ,SAAS;AAEvB,QAAM,cAAcC,OAAM;AAC1B,QAAM,UAAU,SAAS,MAAM;AAE/B,QAAM,EAAE,aAAa,cAAc,cAAc,WAAW,IAAI;AAAA,IAC9D;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM;AAAA,IACJ;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,QAAM,mBAAmBF;AAAA,IACvB,CAAC,MAA+D;AAC9D,YAAM,YAAY,EAAE,OAAO;AAC3B,yBAAmB,EAAE;AACrB,YAAM,aAAa,SAAS,QAAQ,KAAK,GAAG;AAC5C,YAAM,WAAW,WAAW,UAAU;AAEtC,UAAI,MAAM,QAAQ,EAAG,QAAO,KAAK,QAAW,SAAS;AACrD,YAAM,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,SAAS;AAClD,YAAM,KAAK,IAAI,OAAO;AACtB,YAAM,KAAK,IAAI,OAAO;AACtB,yBAAmB,iBAAiB,UAAU,IAAI,IAAI,SAAS,CAAC;AAChE,WAAK,UAAU,SAAS;AAAA,IAC1B;AAAA,IACA,CAAC,UAAU,OAAO,KAAK,KAAK,MAAM,kBAAkB;AAAA,EACtD;AAEA,QAAM,YAAY;AAAA,IAChB,MACE,gBAAAL;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,UAAU;AAAA;AAAA,IACZ;AAAA,IAEF;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MAEX,0BAAAC;AAAA,QAAC;AAAA;AAAA,UACC,iBAAe,YAAY;AAAA,UAC3B,WAAWO,KAAG,iBAAiB,oBAAoB;AAAA,UAEnD;AAAA,4BAAAR;AAAA,cAAC;AAAA;AAAA,gBACC,IAAI;AAAA,gBACJ;AAAA,gBACA;AAAA,gBACA,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,OAAO;AAAA,gBACP,UAAU;AAAA,gBACV,QAAQ;AAAA,gBACR;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA,gBAAc,gBAAgB,SAAS;AAAA,gBACvC,oBAAkB;AAAA,kBAChB;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF;AAAA,gBACA,iBAAe;AAAA,gBACf,iBAAe;AAAA,gBACf,iBAAe;AAAA;AAAA,YACjB;AAAA,YACC;AAAA;AAAA;AAAA,MACH;AAAA;AAAA,EACF;AAEJ,CAAC;AAED,kBAAkB,cAAc;;;AC7fhC,SAAS,UAAAS,eAAc;AACvB,SAAS,mBAAmB;AA2EtB,gBAAAC,OACA,QAAAC,cADA;AAzCN,SAAS,eAAe,MAMZ;AACV,MAAI,KAAK,YAAY,CAAC,KAAK,cAAc,KAAK,aAAc,QAAO;AACnE,SAAO,KAAK,oBAAoB,aAAa,CAAC,KAAK;AACrD;AAEO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,aAAa;AAAA,EACb,eAAe;AAAA,EACf;AACF,GAAqB;AACnB,QAAM,eAAe,eAAe;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAQD,QAAM,YAAY,CAAC,MAAkB,EAAE,eAAe;AACtD,SACE,gBAAAA,OAAC,SAAI,WAAU,0CACb;AAAA,oBAAAD,MAAC,SAAI,WAAU,2BAA2B,0BAAe;AAAA,IACzD,gBAAAC,OAAC,eAAY,SAAQ,YAClB;AAAA,oBACC,gBAAAD;AAAA,QAACD;AAAA,QAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS;AAAA,UACT,aAAa;AAAA,UACb;AAAA,UAEC;AAAA;AAAA,MACH;AAAA,MAEF,gBAAAC;AAAA,QAACD;AAAA,QAAA;AAAA,UACC,SAAS;AAAA,UACT,aAAa;AAAA,UACb,UAAU;AAAA,UAET;AAAA;AAAA,MACH;AAAA,OACF;AAAA,KACF;AAEJ;;;AC5GA,SAAS,WAAAG,gBAAe;AACxB,SAAS,aAAa,oBAAoB;AAC1C,SAAS,YAAY;AACrB,SAAS,qBAAqB;AAE9B,SAAS,aAAa,0BAA0B;AA8B1C,SAKI,OAAAC,OALJ,QAAAC,cAAA;AAhBN,SAAS,oBAAoB,EAAE,YAAY,OAAO,GAAU;AAC1D,QAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,cAAc,KAAK;AAEhD,QAAM,kBAAkBF,SAAQ,MAAM;AACpC,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,cAAc,OAAO,cAAc,CAAC;AAC1C,UAAM,QAAQ,OAAO;AAAA,MACnB,OAAO,QAAQ,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,YAAY;AAAA,IAChE;AACA,WAAO,OAAO,KAAK,KAAK,EAAE,SAAS,IAAI,QAAQ;AAAA,EACjD,GAAG,CAAC,YAAY,MAAM,CAAC;AAEvB,MAAI,CAAC,gBAAiB,QAAO;AAE7B,SACE,gBAAAE,OAAC,QAAK,WAAU,cACd;AAAA,oBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,0EAA0E,SAAS,SAAS,EAAE;AAAA,QACzG,SAAS;AAAA,QAER;AAAA,mBACC,gBAAAD,MAAC,eAAY,WAAU,eAAc,IAErC,gBAAAA,MAAC,gBAAa,WAAU,eAAc;AAAA,UACtC;AAAA;AAAA;AAAA,IAEJ;AAAA,IACA,gBAAAA,MAAC,eAAY,MAAM,QACjB,0BAAAA,MAAC,sBACC,0BAAAA,MAAC,SAAI,WAAU,gDACb,0BAAAA,MAAC,UAAM,eAAK,UAAU,iBAAiB,MAAM,CAAC,GAAE,GAClD,GACF,GACF;AAAA,KACF;AAEJ;AAEA,IAAO,8BAAQ;;;ACvCf,OAAOE,WAAS,eAAAC,cAAa,cAAAC,aAAY,WAAAC,iBAAe;AACxD,SAAS,mBAAmB;AAC5B,SAAS,eAAAC,oBAAmB;AAC5B;AAAA,EAME;AAAA,OACK;AAMP;AAAA,EACE;AAAA,EACA;AAAA,EACA,oBAAAC;AAAA,OACK;;;ACiJA,SAAS,WAAW,WAA0C;AACnE,SAAO,aAAa,UAAU,SAAS,IAAI,UAAU,CAAC,IAAI;AAC5D;;;AC1II,gBAAAC,aAAA;AApCJ,SAAS,oBAAoB,QAAoC;AAC/D,MAAI,WAAW,QAAS,QAAO;AAC/B,MAAI,WAAW,SAAS,WAAW,MAAO,QAAO;AACjD,SAAO;AACT;AAWO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoC;AAClC,QAAM,QAAQ,WAAW,SAAS;AAClC,QAAM,UAAU,SAAS;AAEzB,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,OAAO,UAAU,UAAa,UAAU,OAAO,OAAO,KAAK,IAAI;AAAA,MAC/D,UAAU,CAAC,UAAU,SAAS,MAAM,cAAc,KAAK;AAAA,MACvD,QAAQ,MAAM,SAAS,IAAI,KAAK;AAAA,MAChC;AAAA,MACA,gBAAgB,SAAS;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA,MAAM,SAAS,aAAa,oBAAoB,eAAe,MAAM;AAAA,MACrE,WAAW,eAAe;AAAA,MAC1B,WAAW,eAAe;AAAA,MAC1B,WAAW;AAAA,MACX;AAAA,MACA,WAAW,UAAU,gBAAgB;AAAA;AAAA,EACvC;AAEJ;;;ACzBI,gBAAAC,aAAA;AAvBG,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU,CAAC;AACb,GAAgB;AACd,QAAM,UAAU,QAAQ,QAAQ,QAAQ,WAAW;AACnD,QAAM,WAAW,QAAQ,aAAa;AAEtC,QAAM,QAAQ,WAAW,SAAS;AAElC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,OAAO,UAAU,UAAa,UAAU,OAAO,OAAO,KAAK,IAAI;AAAA,MAC/D,UAAU,CAAC,UAAU,SAAS,MAAM,cAAc,KAAK;AAAA,MACvD,QAAQ,MAAM,SAAS,IAAI,KAAK;AAAA,MAChC;AAAA,MACA,gBAAgB,SAAS;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,eAAe;AAAA,MAC1B,WAAW,eAAe;AAAA,MAC1B,WAAW;AAAA;AAAA,EACb;AAEJ;;;ACpBI,gBAAAC,aAAA;AAxBG,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU,CAAC;AACb,GAAgB;AACd,QAAM,YAAY,eAAe,SAAS;AAC1C,QAAM,OAAO,QAAQ,SAAS,YAAY,IAAI;AAC9C,QAAM,eAAe,QAAQ,gBAAgB,CAAC;AAE9C,QAAM,QAAQ,WAAW,SAAS;AAElC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,OAAO,UAAU,UAAa,UAAU,OAAO,OAAO,KAAK,IAAI;AAAA,MAC/D,UAAU,CAAC,QAAQ,SAAS,GAAG;AAAA,MAC/B,QAAQ,MAAM,SAAS,IAAI,KAAK;AAAA,MAChC;AAAA,MACA,gBAAgB,QAAQ;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA,KAAK,eAAe;AAAA,MACpB,KAAK,eAAe;AAAA,MACpB;AAAA,MACA;AAAA,MACA,WAAW;AAAA;AAAA,EACb;AAEJ;;;ACvDA,SAAS,eAAAC,oBAAmB;AAE5B,SAAS,yBAAyB;AAgE9B,gBAAAC,aAAA;AA/CG,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoC;AAClC,QAAM,QAAQ,WAAW,SAAS;AAClC,QAAM,UAAU,SAAS;AAGzB,QAAM,aAAa,kBAAkB,cAAc;AAGnD,QAAM,YAAY,UAAU;AAE5B,QAAM,kBAAkB,cAAc,SAAS;AAC/C,QAAM,eAA0C,kBAC5C,kBACA;AAGJ,QAAM,eAAeC;AAAA,IACnB,CAAC,gBAA2C;AAC1C,UAAI,YAAY;AACd,YAAI,SAAS,MAAM;AACjB,mBAAS,IAAI;AAAA,QACf,WAAW,UAAU,MAAM;AACzB,mBAAS,KAAK;AAAA,QAChB,OAAO;AACL,mBAAS,IAAI;AAAA,QACf;AAAA,MACF,OAAO;AACL,iBAAS,gBAAgB,IAAI;AAAA,MAC/B;AAAA,IACF;AAAA,IACA,CAAC,YAAY,OAAO,QAAQ;AAAA,EAC9B;AAEA,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,SAAS;AAAA,MACT,UAAU;AAAA,MACV,QAAQ,MAAM,SAAS,IAAI,KAAK;AAAA,MAChC;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA,WAAW;AAAA,MACX;AAAA;AAAA,EACF;AAEJ;;;ACnFA,SAAS,UAAAE,eAAc;AAsEjB,gBAAAC,aAAA;AA9CN,SAAS,oBAAoB,OAA0B;AACrD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,MAAM;AACjD,MAAI,MAAO,QAAO,CAAC,OAAO,KAAK,CAAC;AAChC,SAAO,CAAC;AACV;AAGA,SAAS,qBAAqB,OAA+B;AAC3D,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO,OAAO,KAAK;AAC9D,SAAO;AACT;AAEO,SAAS,aAAa,OAAoB;AAC/C,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,gBAAgB,MAAM,WAAW,CAAC;AAExC,QAAM,WAAWC,QAAO,KAAK;AAC7B,WAAS,UAAU;AAEnB,QAAM,YAAY,cAAc,aAAa,CAAC;AAC9C,QAAM,YAAY,cAAc,cAAc,SAAS,CAAC;AACxD,QAAM,aAAa,cAAc,YAAY,eAAe,SAAS;AACrE,QAAM,YAAY,CAAC,CAAC,cAAc;AAClC,QAAM,gBAAgB,mBAAmB,gBAAgB,SAAS;AAClE,QAAM,QAAQ,WAAW,SAAS;AAClC,QAAM,UAAU,eAAe;AAC/B,QAAM,mBAAmB,UAAU,gBAAgB;AACnD,QAAM,aAAa,MAAM,SAAS,IAAI,SAAS,OAAO;AAEtD,MAAI,YAAY;AACd,WACE,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT,OAAO,oBAAoB,KAAK;AAAA,QAChC,UAAU,CAAC,aAAa,SAAS,YAAY,CAAC,CAAC;AAAA,QAC/C;AAAA,QACA,gBAAgB,cAAc;AAAA,QAC9B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QACX,YAAY,cAAc;AAAA,QAC1B,QAAQ;AAAA,QACR,WAAW;AAAA;AAAA,IACb;AAAA,EAEJ;AAEA,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,OAAO,qBAAqB,KAAK;AAAA,MACjC,UAAU,CAAC,QAAQ,SAAS,OAAO,EAAE;AAAA,MACrC;AAAA,MACA,gBAAgB,cAAc;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,WAAW;AAAA,MACX;AAAA,MACA,aAAa;AAAA,MACb,UAAU,CAACE,WAAU,SAASA,MAAK;AAAA;AAAA,EACrC;AAEJ;;;ACnFI,gBAAAC,aAAA;AAlBG,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoC;AAClC,QAAM,QAAQ,WAAW,SAAS;AAClC,QAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,MAAM,IAAI,MAAM,IAAI,CAAC;AAEzD,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP,UAAU,CAAC,YAAY,SAAS,OAAO;AAAA,MACvC;AAAA,MACA,gBAAgB,SAAS;AAAA,MACzB;AAAA,MACA,aAAa,eAAe;AAAA,MAC5B;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA,SAAS,SAAS;AAAA,MAClB,WAAW,SAAS;AAAA,MACpB,iBAAiB;AAAA;AAAA,EACnB;AAEJ;;;AClDA,SAAgB,UAAU,MAAM,eAAAC,cAAa,YAAAC,iBAAgB;AAsDrD,SAEe,OAAAC,OAFf,QAAAC,cAAA;AAjDR,IAAM,aAAa;AAAA,EAAK,MACtB,OAAO,iCAAiC,EAAE,KAAK,CAAC,OAAO;AAAA,IACrD,SAAS,EAAE;AAAA,EACb,EAAE;AACJ;AAGA,IAAM,gBAA0B,CAAC,GAAG;AAW7B,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoC;AAClC,QAAM,CAAC,KAAK,MAAM,IAAIF;AAAA,IACpB,SAAS,OAAO,KAAK,UAAU,OAAO,MAAM,CAAC,IAAI;AAAA,EACnD;AAEA,QAAM,SAAU,SAAS,UAAiC;AAE1D,QAAM,eAAeD;AAAA,IACnB,CAAC,QAAgB;AACf,aAAO,GAAG;AACV,UAAI;AACF,cAAM,SAAkB,KAAK,MAAM,GAAG;AACtC,iBAAS,MAAM;AAAA,MACjB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,SACE,gBAAAG,OAAC,SAAI,WAAU,aACZ;AAAA,aACC,gBAAAA,OAAC,WAAM,SAAS,IAAI,WAAU,oCAC3B;AAAA;AAAA,MACA,YAAY,gBAAAD,MAAC,UAAK,WAAU,yBAAwB,eAAC;AAAA,OACxD;AAAA,IAED,eACC,gBAAAA,MAAC,OAAE,WAAU,iCAAiC,uBAAY;AAAA,IAE5D,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,UACE,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,OAAO;AAAA,YAChB,aAAS;AAAA;AAAA,QACX;AAAA,QAGF,0BAAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,YACP,eAAe;AAAA,YACf,UAAU;AAAA,YACV;AAAA,YACA,WAAU;AAAA;AAAA,QACZ;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;;;AC7CI,gBAAAE,aAAA;AA7BJ,SAAS,UAAU,SAA4C;AAC7D,SAAO,YAAY,UAAU,YAAY,SAAS,UAAU;AAC9D;AAGA,SAAS,YAAY,OAAwC;AAC3D,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACzE,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQ,KAAgC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM;AAAA,MAC/D;AAAA,MACA,OAAO,CAAC;AAAA,IACV,CAAC;AAAA,EACH;AACF;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoC;AAClC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,OAAO,YAAY,KAAK;AAAA,MACxB,UAAU,CAAC,SAAS,SAAS,IAAI;AAAA,MACjC;AAAA,MACA,gBAAgB,SAAS;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,OAAO,WAAW,SAAS;AAAA,MAC3B,gBAAgB,SAAS;AAAA,MACzB,kBAAkB,SAAS;AAAA,MAC3B,WAAW,SAAS;AAAA,MACpB,SAAS,UAAU,SAAS,OAAO;AAAA;AAAA,EACrC;AAEJ;;;ACzCA,SAAgB,WAAAC,gBAAe;AAC/B,SAAS,oBAAoB;AAC7B,SAAS,yBAAyB;AAwH5B,SAQF,OAAAC,OARE,QAAAC,cAAA;AA3GN,IAAM,cAAkC,CAAC,SAAS,aAAa,UAAU;AAGzE,SAAS,kBACP,SACkB;AAClB,QAAM,UAAU,SAAS;AACzB,MACE,OAAO,YAAY,YACnB,YAAY,SAAS,OAA2B,GAChD;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAGA,SAAS,gBAAgB,SAA8C;AACrE,QAAM,cAAc,SAAS;AAC7B,MAAI,OAAO,gBAAgB,YAAY,eAAe,EAAG,QAAO;AAChE,SAAO;AACT;AAGA,SAAS,gBAAgB,SAAoD;AAC3E,MAAI,EAAE,cAAc,YAAY,CAAC,QAAQ,SAAU,QAAO;AAC1D,QAAM,WAAW,QAAQ;AACzB,QAAM,cACJ,YAAY,OAAO,aAAa,WAC3B,WACD;AACN,SAAO;AAAA,IACL,UAAU,OAAO,QAAQ,QAAQ;AAAA,IACjC,UAAU,OAAO,QAAQ,YAAY,IAAI;AAAA,IACzC,UAAU,OAAO,QAAQ,YAAY,MAAM;AAAA,IAC3C,WAAW,QAAQ,YAAY,OAAO,QAAQ,SAAS,IAAI;AAAA,IAC3D;AAAA,EACF;AACF;AAGA,SAAS,mBACP,SAC6B;AAC7B,MAAI,EAAE,WAAW,YAAY,CAAC,QAAQ,MAAO,QAAO;AACpD,SAAO;AAAA,IACL,OAAO,OAAO,QAAQ,KAAK;AAAA,IAC3B,UAAU,OAAO,QAAQ,YAAY,EAAE;AAAA,IACvC,UAAU,OAAO,QAAQ,YAAY,IAAI;AAAA,IACzC,UAAU,OAAO,QAAQ,YAAY,MAAM;AAAA,EAC7C;AACF;AAGA,SAAS,mBACP,SACiD;AACjD,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,gBAAgB,OAAO,KAAK,mBAAmB,OAAO;AAC/D;AAGA,SAAS,eACP,QACA,cACQ;AACR,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,cAAc,OAAQ,QAAO,OAAO;AACxC,SAAO,WAAW,OAAO,QAAQ;AACnC;AAMO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoC;AAClC,QAAM,gBAAgB,kBAAkB;AAExC,QAAM,aAAa,kBAAkB,OAAO;AAC5C,QAAM,iBAAiB,gBAAgB,OAAO;AAE9C,QAAM,gBAAgBC,SAAQ,MAAM,mBAAmB,OAAO,GAAG,CAAC,OAAO,CAAC;AAC1E,QAAM,UAAUA,SAAQ,MAAM;AAC5B,QAAI,CAAC,cAAe,QAAO;AAC3B,WAAO,cAAc,aAAa;AAAA,EACpC,GAAG,CAAC,eAAe,aAAa,CAAC;AACjC,QAAM,WAAWA;AAAA,IACf,MAAM,eAAe,eAAe,QAAQ,EAAE;AAAA,IAC9C,CAAC,eAAe,IAAI;AAAA,EACtB;AAEA,MAAI,CAAC,SAAS;AACZ,WACE,gBAAAD,OAAC,SAAI,WAAU,4BAA2B;AAAA;AAAA,MAEjC;AAAA,MAAK;AAAA,OACd;AAAA,EAEJ;AAEA,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,MAC3C,UAAU,CAAC,MAAM,SAAS,KAAK,IAAI;AAAA,MACnC,QAAQ,MAAM,SAAS,IAAI,KAAK;AAAA,MAChC,OAAO,SAAS;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,CAAC;AAAA,MACZ,UAAU,YAAY;AAAA,MACtB,OAAO,WAAW,SAAS;AAAA;AAAA,EAC7B;AAEJ;;;ACxJA,SAAS,WAAAG,gBAAe;;;ACPxB,SAAS,kBAAkB;;;ACH3B,SAAS,qBAAqB;AAwCvB,IAAM,oBAAoB;AAAA,EAC/B;AACF;;;ADnCO,SAAS,uBAA+C;AAC7D,QAAM,MAAM,WAAW,iBAAiB;AACxC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;AEfA,SAAS,YAAAC,iBAAgB;AACzB,SAAS,eAAAC,cAAa,gBAAAC,qBAAoB;AAC1C,SAAS,QAAAC,OAAM,aAAa,YAAY,iBAAiB;AACzD;AAAA,EACE,eAAAC;AAAA,EACA,sBAAAC;AAAA,EACA;AAAA,OACK;AAiBC,SACE,OAAAC,OADF,QAAAC,cAAA;AAZR,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,gBAAAA,OAACJ,OAAA,EACE;AAAA,aACC,gBAAAI,OAAC,cAAW,WAAU,QACpB;AAAA,sBAAAD,MAAC,aAAU,WAAU,aAAa,iBAAM;AAAA,MACvC,eACC,gBAAAA,MAAC,OAAE,WAAU,iCAAiC,uBAAY;AAAA,OAE9D;AAAA,IAEF,gBAAAA,MAAC,eAAa,UAAS;AAAA,KACzB;AAEJ;AAEA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,gBAAAC,OAAC,SAAI,WAAU,aACZ;AAAA,aACC,gBAAAA,OAAC,SACC;AAAA,sBAAAD,MAAC,QAAG,WAAU,uBAAuB,iBAAM;AAAA,MAC1C,eACC,gBAAAA,MAAC,OAAE,WAAU,iCAAiC,uBAAY;AAAA,OAE9D;AAAA,IAEF,gBAAAA,MAAC,SAAI,WAAU,gCAAgC,UAAS;AAAA,KAC1D;AAEJ;AAIO,SAAS,+BAA+B;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,cAAc;AAChB,GAAqD;AACnD,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aACE,gBAAAA,MAAC,eAAY,OAAc,aACxB,UACH;AAAA,IAGJ,KAAK;AACH,UAAI,CAAC,MAAO,QAAO,gBAAAA,MAAC,kBAAgB,UAAS;AAC7C,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UAEC;AAAA;AAAA,MACH;AAAA,IAGJ,KAAK;AACH,aAAO,gBAAAA,MAAC,SAAK,UAAS;AAAA,IAExB,KAAK;AACH,aAAO,gBAAAA,MAAC,SAAI,WAAU,aAAa,UAAS;AAAA,IAE9C,KAAK;AAAA,IACL;AACE,aACE,gBAAAA,MAAC,kBAAe,OAAc,aAC3B,UACH;AAAA,EAEN;AACF;AAGA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKuB;AACrB,QAAM,CAAC,MAAM,OAAO,IAAIN,UAAS,WAAW;AAE5C,SACE,gBAAAO,OAACH,cAAA,EAAY,MAAY,cAAc,SACrC;AAAA,oBAAAE,MAAC,sBAAmB,SAAO,MACzB,0BAAAC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QAET;AAAA,iBACC,gBAAAD,MAACL,cAAA,EAAY,WAAU,WAAU,IAEjC,gBAAAK,MAACJ,eAAA,EAAa,WAAU,WAAU;AAAA,UAEnC;AAAA;AAAA;AAAA,IACH,GACF;AAAA,IACC,eACC,gBAAAI,MAAC,OAAE,WAAU,sCAAsC,uBAAY;AAAA,IAEjE,gBAAAA,MAACD,qBAAA,EAAmB,WAAU,qCAC3B,UACH;AAAA,KACF;AAEJ;;;AHjBI,SAoB0B,YAAAG,WApB1B,OAAAC,aAAA;AAnGJ,SAAS,eAAe,MAA6C;AACnE,QAAM,aAAa,KAAK;AACxB,MAAI,CAAC,WAAY,QAAO;AACxB,SAAO;AAAA,IACL,OAAO,KAAK,SAAS;AAAA,IACrB,MAAM;AAAA,IACN;AAAA,IACA,UAAU,KAAK;AAAA,IACf,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,IAC1C,GAAI,KAAK,KAAK,EAAE,IAAI,KAAK,GAAG,IAAI,CAAC;AAAA,IACjC,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,IACvC,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,IACvC,GAAI,KAAK,YAAY,IAAI,EAAE,cAAc,KAAK,YAAY,EAAE,IAAI,CAAC;AAAA,EACnE;AACF;AAGA,SAAS,uBACP,aACA,eACA,QACmC;AACnC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,gBACA,EAAE,sBAAsB,cAA0B,IAClD,CAAC;AAAA,IACL,GAAI,SAAS,EAAE,eAAe,OAA8B,IAAI,CAAC;AAAA,EACnE;AACF;AAGA,SAAS,qBAAqB,SAAiC;AAC7D,SAAO;AAAA,IACL,SAAU,SAAS,WAAsB;AAAA,IACzC,aAAa,SAAS,gBAAgB;AAAA,IACtC,iBAAkB,SAAS,mBAA+B;AAAA,IAC1D,eAAe,SAAS;AAAA,EAG1B;AACF;AAGA,SAAS,cACP,UACA,gBAC4B;AAC5B,SACG,WAAW,aAAa,KACzB,eAAe,aAAa;AAEhC;AAMO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2C;AACzC,QAAM,EAAE,UAAU,UAAU,UAAU,IAAI,qBAAqB;AAC/D,QAAM,oBACJ,UAAU,2BAA2B;AAEvC,QAAM,YAAYC;AAAA,IAChB,MAAM,eAAe,cAAc;AAAA,IACnC,CAAC,cAAc;AAAA,EACjB;AAEA,QAAM,cAAcA;AAAA,IAClB,MACG,WAAW,aAAa,KAAK,CAAC;AAAA,IACjC,CAAC,QAAQ;AAAA,EACX;AAEA,MAAI,CAAC,UAAW,QAAO;AAEvB,QAAM,EAAE,SAAS,aAAa,iBAAiB,cAAc,IAC3D,qBAAqB,OAAO;AAC9B,QAAM,SAAS,cAAc,UAAU,cAAc;AACrD,QAAM,oBAAoB;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,UACJ,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ;AAAA,MACR,MAAO,SAAqC,CAAC;AAAA,MAC7C;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV;AAAA,MAIA,UAAU;AAAA,MAIV,QAAQ,SAAS,MAAM,OAAO,IAAI,KAAK,IAAI;AAAA;AAAA,EAC7C;AAGF,MAAI,gBAAiB,QAAO,gBAAAA,MAAAD,WAAA,EAAG,mBAAQ;AAEvC,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;;;AInJA,SAAS,eAAAE,cAAa,WAAAC,gBAAe;AACrC,SAAS,QAAAC,aAAY;AACrB,SAAS,UAAAC,eAAc;AAGvB,SAAS,2BAA2B;AACpC,SAAS,oBAAoB,kBAAkB;;;ACjB/C,SAAS,QAAQ,WAAW,eAAAC,oBAAmB;AAC/C,SAAS,UAAAC,eAAc;AAsBjB,gBAAAC,OAEE,QAAAC,cAFF;AAnBC,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA+C;AAC7C,QAAM,eAAe,aAAa;AAElC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,YAAU;AAAA,MACV,WAAU;AAAA,MAEV;AAAA,wBAAAD,MAAC,SAAI,WAAU,kBAAkB,UAAS;AAAA,QACzC,gBACC,gBAAAC,OAAC,SAAI,WAAU,8BACZ;AAAA,uBAAa,QAAQ,KACpB,gBAAAD;AAAA,YAACD;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAK;AAAA,cACL;AAAA,cACA,SAAS;AAAA,cACT,OAAM;AAAA,cAEN,0BAAAC,MAAC,aAAU,WAAU,eAAc;AAAA;AAAA,UACrC;AAAA,UAED,aAAa,QAAQ,QAAQ,KAC5B,gBAAAA;AAAA,YAACD;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAK;AAAA,cACL;AAAA,cACA,SAAS;AAAA,cACT,OAAM;AAAA,cAEN,0BAAAC,MAACF,cAAA,EAAY,WAAU,eAAc;AAAA;AAAA,UACvC;AAAA,UAED,aACC,gBAAAE;AAAA,YAACD;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAK;AAAA,cACL;AAAA,cACA,SAAS;AAAA,cACT,OAAM;AAAA,cACN,WAAU;AAAA,cAEV,0BAAAC,MAAC,UAAO,WAAU,eAAc;AAAA;AAAA,UAClC;AAAA,WAEJ;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;ACpEO,SAAS,kBACd,QACA,WACA,YACA,YAAqB,OACb;AACR,QAAM,OAAO,OAAO,WAAW,UAAU,UAAU;AACnD,QAAM,YAAY,YAAY,GAAG,IAAI,UAAU;AAC/C,SAAO,YAAY,GAAG,SAAS,UAAU;AAC3C;;;ACaI,SAQI,OAAAE,OARJ,QAAAC,cAAA;AAnBG,SAAS,2BAA2B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwD;AACtD,MAAI,OAAO,cAAc,aAAc,QAAO;AAE9C,QAAM,WAAW,kBAAkB,QAAQ,WAAW,YAAY,SAAS;AAC3E,QAAM,MAAM,OAAO,OAAO;AAE1B,QAAM,aAAa,WAAW,cAAc,CAAC;AAC7C,QAAM,QAAQ,WAAW,YAAY;AACrC,QAAM,aAAa,QACf,MAAM,OAAO,CAAC,MAAM,KAAK,UAAU,IACnC,OAAO,KAAK,UAAU;AAE1B,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,SAAS;AAAA,QACT,qBAAqB;AAAA,QACrB,KAAK,GAAG,GAAG;AAAA,MACb;AAAA,MAEC;AAAA,mBAAW,IAAI,CAAC,SACf,gBAAAD,MAAC,UAAgB,WAAU,6CACxB,qBAAW,IAAI,GAAG,SAAS,QADnB,IAEX,CACD;AAAA,QACA,aAAa,gBAAAA,MAAC,UAAK;AAAA,QACnB,aAAa,gBAAAA,MAAC,UAAK;AAAA;AAAA;AAAA,EACtB;AAEJ;;;AHgEI,SACE,OAAAE,OADF,QAAAC,cAAA;AA1EJ,SAAS,YAAY,YAAmD;AACtE,SAAO,OAAO,KAAK,WAAW,cAAc,CAAC,CAAC,EAAE;AAClD;AAEA,SAAS,iBACP,OACA,gBACS;AACT,MAAI,eAAe,WAAW,EAAG,QAAO;AACxC,SAAO,MAAM;AAAA,IAAM,CAAC,SAClB,eAAe,MAAM,CAAC,UAAU;AAC9B,YAAM,IAAI,KAAK,KAAK;AACpB,aAAO,MAAM,UAAa,MAAM,QAAQ,MAAM;AAAA,IAChD,CAAC;AAAA,EACH;AACF;AAGA,SAAS,cAAc,OAA2C;AAChE,UAAQ,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,GAAG;AAAA,IAAI,CAAC,SAC9C,KAAK,kBAAkB,IACnB,OACA,EAAE,GAAG,MAAM,CAAC,kBAAkB,GAAG,WAAW,EAAE;AAAA,EACpD;AACF;AAGA,SAAS,YAAY,MAAwD;AAC3E,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQ,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,kBAAkB;AAAA,EAC/D;AACF;AAGA,SAASC,eACP,UACA,gBACgB;AAChB,QAAM,eAAe,eAAe,aAAa;AACjD,QAAM,WAAW,WAAW,aAAa;AACzC,SAAO,EAAE,GAAG,cAAc,GAAG,SAAS;AACxC;AAGA,SAAS,sBACP,QACA,cACqC;AACrC,QAAM,iBAAiB,OAAO,UAAU,EAAE,SAAS,KAAK,IAAI;AAC5D,QAAM,eACJ,OAAO,WAAW,SACd,OAAO,SACP,eACE,QACA;AACR,MAAI,CAAC,kBAAkB,iBAAiB,MAAO,QAAO;AACtD,SAAO;AAAA,IACL,GAAI,kBAAkB,CAAC;AAAA,IACvB,GAAI,iBAAiB,QAAQ,EAAE,OAAO,MAAM,IAAI,CAAC;AAAA,EACnD;AACF;AAWA,SAAS,YAAY,EAAE,OAAO,YAAY,GAAqB;AAC7D,MAAI,CAAC,MAAO,QAAO;AACnB,SACE,gBAAAD,OAAC,SACC;AAAA,oBAAAD,MAAC,QAAG,WAAU,uBAAuB,iBAAM;AAAA,IAC1C,eACC,gBAAAA,MAAC,OAAE,WAAU,iCAAiC,uBAAY;AAAA,KAE9D;AAEJ;AAMA,SAAS,iBACP,OACA,UACA,gBACA;AACA,QAAM,mBAAmBG;AAAA,IACvB,CAAC,OAAe,SAAkC;AAChD,YAAM,OAAO,CAAC,GAAG,KAAK;AACtB,WAAK,KAAK,IAAI;AAAA,QACZ,GAAG;AAAA,QACH,CAAC,kBAAkB,GAAG,MAAM,KAAK,EAAE,kBAAkB;AAAA,MACvD;AACA,eAAS,IAAI;AAAA,IACf;AAAA,IACA,CAAC,OAAO,QAAQ;AAAA,EAClB;AAEA,QAAM,YAAYA,aAAY,MAAM;AAClC,UAAM,OAAO,eAAe,QACxB,oBAAoB,CAAC,GAAG,eAAe,KAAK,IAC5C,CAAC;AACL,aAAS,CAAC,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC,kBAAkB,GAAG,WAAW,EAAE,CAAC,CAAC;AAAA,EACtE,GAAG,CAAC,OAAO,UAAU,eAAe,KAAK,CAAC;AAE1C,QAAM,eAAeA;AAAA,IACnB,CAAC,UAAkB;AACjB,eAAS,MAAM,OAAO,CAAC,GAAG,MAAM,MAAM,KAAK,CAAC;AAAA,IAC9C;AAAA,IACA,CAAC,OAAO,QAAQ;AAAA,EAClB;AAEA,QAAM,aAAaA;AAAA,IACjB,CAAC,MAAc,OAAe;AAC5B,YAAM,OAAO,CAAC,GAAG,KAAK;AACtB,YAAM,CAAC,SAAS,IAAI,KAAK,OAAO,MAAM,CAAC;AACvC,WAAK,OAAO,IAAI,GAAG,SAAS;AAC5B,eAAS,IAAI;AAAA,IACf;AAAA,IACA,CAAC,OAAO,QAAQ;AAAA,EAClB;AAEA,SAAO,EAAE,kBAAkB,WAAW,cAAc,WAAW;AACjE;AAMO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoC;AAClC,QAAM,EAAE,UAAU,IAAI,qBAAqB;AAE3C,QAAM,QAAQC,SAAQ,MAAM,cAAc,KAAK,GAAG,CAAC,KAAK,CAAC;AACzD,QAAM,EAAE,kBAAkB,WAAW,cAAc,WAAW,IAC5D,iBAAiB,OAAO,UAAU,cAAc;AAElD,QAAM,aAAa,eAAe;AAClC,MAAI,CAAC,YAAY,YAAY;AAC3B,WACE,gBAAAJ,MAAC,OAAE,WAAU,4BAA2B,2EAExC;AAAA,EAEJ;AAEA,QAAM,SAASE,eAAc,UAAU,cAAc;AACrD,QAAM,eAAe,OAAO,cAAc;AAC1C,QAAM,mBAAmB,sBAAsB,QAAQ,YAAY;AAEnE,SACE,gBAAAF;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,QAAQ;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,MACR;AAAA;AAAA,EACF;AAEJ;AAiCA,SAAS,mBACP,aACA,YACA,UACA,UACA,WACA;AACA,QAAM,WAAW,YAAY,YAAY;AACzC,QAAM,WAAW,YAAY,YAAY;AACzC,QAAM,iBAAiB,WAAW,YAAY,CAAC;AAC/C,QAAM,aAAa,CAAC,YAAY,CAAC;AACjC,SAAO;AAAA,IACL,WAAW,cAAc,YAAY;AAAA,IACrC,YAAY,cAAc,YAAY;AAAA,IACtC;AAAA,EACF;AACF;AAGA,SAAS,sBACP,SACA,WACA;AACA,SAAO;AAAA,IACL,UAAW,SAAS,YAAuB;AAAA,IAC3C,WAAW,SAAS;AAAA,IACpB,WAAW,CAAC,CAAC,SAAS,aAAa,YAAY;AAAA,IAC/C,cAAc,SAAS;AAAA,EACzB;AACF;AAGA,SAAS,iBACP,WACA,cACA;AACA,QAAM,eAAe,UAAU,qBAAqB;AACpD,QAAM,yBACJ,UAAU,+BAA+B;AAC3C,QAAM,iBACJ,UAAU,uBAAuB;AACnC,QAAM,qBACJ,gBAAgB,yBACZ,yBACA;AACN,SAAO,EAAE,oBAAoB,eAAe;AAC9C;AAGA,SAAS,iBACP,cACA,kBACiB;AACjB,SAAO;AAAA,IACL,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,GAAI,mBAAmB,EAAE,eAAe,iBAAiB,IAAI,CAAC;AAAA,EAChE;AACF;AAGA,SAAS,iBACP,WACA,OACQ;AACR,SAAO,YAAY,UAAU,QAAQ,WAAW,OAAO,QAAQ,CAAC,CAAC,IAAI;AACvE;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,EACR;AACA,QAAM,UAAU,sBAAsB,SAAS,MAAM,MAAM;AAC3D,QAAM,SACJ,YAAY,cACZ,iBAAiB,OAAO,YAAY,cAAc;AACpD,QAAM,EAAE,oBAAoB,eAAe,IAAI;AAAA,IAC7C;AAAA,IACA;AAAA,EACF;AACA,QAAM,aAAa,YAAY,UAAU;AACzC,QAAM,cAAc,iBAAiB,cAAc,gBAAgB;AAEnE,SACE,gBAAAC,OAAC,SAAI,WAAW,eAAe,cAAc,aAC3C;AAAA,oBAAAD,MAAC,eAAY,OAAc,aAA0B;AAAA,IAEpD,MAAM,WAAW,KAAK,QAAQ,gBAC7B,gBAAAA,MAAC,OAAE,WAAU,wCACV,kBAAQ,cACX;AAAA,IAGD,MAAM,SAAS,KACd,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,WAAW,YAAY;AAAA,QACvB,WAAW,QAAQ;AAAA,QACnB;AAAA;AAAA,IACF;AAAA,IAGD,MAAM,IAAI,CAAC,MAAM,UAChB,gBAAAA;AAAA,MAAC;AAAA;AAAA,QAEC;AAAA,QACA,OAAO,MAAM;AAAA,QACb,WAAW,YAAY;AAAA,QACvB,WAAW,QAAQ;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK,KAAK,kBAAkB;AAAA,QAC5B,UAAU,MAAM,SAAS,KAAK;AAAA,QAC9B,UAAU,QAAQ,IAAI,MAAM,OAAO,OAAO,QAAQ,CAAC,IAAI;AAAA,QACvD,YACE,QAAQ,MAAM,SAAS,IACnB,MAAM,OAAO,OAAO,QAAQ,CAAC,IAC7B;AAAA,QAGN,0BAAAA;AAAA,UAAC;AAAA;AAAA,YACC,IAAI,SAAS,IAAI,IAAI,KAAK;AAAA,YAC1B,MAAM,GAAG,IAAI,IAAI,KAAK;AAAA,YACtB;AAAA,YACA,gBAAgB;AAAA,YAChB;AAAA,YACA;AAAA,YACA,OAAO,YAAY,IAAI;AAAA,YACvB,UAAU,CAAC,SACT,aAAa,OAAO,IAA+B;AAAA,YAErD,OAAO,iBAAiB,QAAQ,WAAW,KAAK;AAAA,YAChD,aAAa;AAAA,YACb;AAAA,YACA;AAAA,YACA,SAAS;AAAA,YACT;AAAA;AAAA,QACF;AAAA;AAAA,MAlCK,KAAK,kBAAkB;AAAA,IAmC9B,CACD;AAAA,IAEA,UACC,gBAAAC;AAAA,MAACI;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,SAAS;AAAA,QACT;AAAA,QACA,WAAU;AAAA,QAEV;AAAA,0BAAAL,MAACM,OAAA,EAAK,WAAU,eAAc;AAAA,UAC7B,QAAQ;AAAA;AAAA;AAAA,IACX;AAAA,KAEJ;AAEJ;;;AItaA,SAAS,eAAAC,cAAa,UAAAC,SAAQ,YAAAC,iBAAgB;AAC9C,SAAS,oBAAoB;AA6HzB,gBAAAC,aAAA;AAnHJ,SAAS,aAAa,GAA6B;AACjD,SACE,OAAO,MAAM,YACb,MAAM,QACN,OAAQ,EAAiB,UAAU,YACnC,OAAQ,EAAiB,UAAU;AAEvC;AAUA,SAAS,YACP,gBACc;AACd,QAAM,QAAQ,eAAe,YAAY,MAAM;AAC/C,SAAO,MAAM,QAAQ,KAAK,IACtB,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE,EAAE,IACzD,CAAC;AACP;AAGA,SAAS,iBACP,OACA,gBACc;AACd,QAAM,SAAS,aAAa,cAAc,KAAK,CAAC;AAChD,SAAO,MAAM,IAAI,CAAC,MAAM;AACtB,UAAM,QAAQ,OAAO,EAAE,KAAK;AAC5B,WAAO,QAAQ,EAAE,GAAG,GAAG,KAAK,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI;AAAA,EAC5D,CAAC;AACH;AAGA,SAAS,qBACP,SACA,eACuB;AACvB,QAAM,QAAQ,MAAM,QAAQ,QAAQ,KAAK,IACpC,QAAQ,MAAoB,OAAO,YAAY,IAChD;AACJ,QAAM,YACJ,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY;AAC9D,QAAM,OAAO,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AAC/D,QAAM,eACJ,QAAQ,iBAAiB,YAAY,QAAQ,iBAAiB,WAC1D,QAAQ,eACR;AACN,SAAO,EAAE,OAAO,WAAW,MAAM,aAAa;AAChD;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU,CAAC;AACb,GAAgB;AACd,QAAM,QAAQ,WAAW,SAAS;AAClC,QAAM;AAAA,IACJ,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,cAAc;AAAA,EAChB,IAAI,qBAAqB,SAAS,YAAY,cAAc,CAAC;AAC7D,QAAM,QAAQ,iBAAiB,aAAa,cAAc;AAE1D,QAAM,CAAC,aAAa,cAAc,IAAIC,UAA6B;AAGnE,QAAM,SACJ,SAAS,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAC7D,QACD;AACN,QAAM,gBACJ,WACC,cAAc,EAAE,OAAO,QAAW,MAAM,YAAY,IAAI;AAE3D,QAAM,eAAeC;AAAA,IACnB,CAAC,SAAwB;AACvB,UAAI,KAAK,UAAU,OAAW,QAAO,SAAS,IAAI;AAClD,qBAAe,KAAK,IAAI;AACxB,eAAS,MAAS;AAAA,IACpB;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAOA,QAAM,WAAWC,QAAO,KAAK;AAC7B,WAAS,UAAU;AAEnB,QAAM,aAAaD,aAAY,MAAM;AACnC,aAAS,IAAI,SAAS,OAAO;AAAA,EAC/B,GAAG,CAAC,IAAI,MAAM,CAAC;AAEf,SACE,gBAAAF;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,MACR;AAAA,MAEA,UAAU,eAAe,YAAY,SAAS;AAAA,MAC9C,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA,KAAK,eAAe;AAAA,MACpB,KAAK,eAAe;AAAA,MACpB;AAAA,MACA,gBAAgB,SAAS;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,WAAW;AAAA;AAAA,EACb;AAEJ;;;AClJA,YAAYI,aAAW;AACvB,SAAS,kBAAAC,iBAAgB,SAAS,eAAe,KAAAC,UAAS;AAC1D,SAAS,MAAAC,MAAI,mBAAmB;AAChC;AAAA,EACE;AAAA,EACA,aAAAC;AAAA,OAEK;AACP;AAAA,EACE;AAAA,OAGK;AACP;AAAA,EACE,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,qBAAAC;AAAA,EACA,WAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,kBAAAC;AAAA,OACK;;;AC1CP;AAAA,EACE;AAAA,OAKK;AAuBP,IAAM,cAAc,CAAC,UAAU,QAAQ,WAAW,SAAS;AAK3D,SAAS,QAAQ,MAAmD;AAClE,MAAI,MAAM,SAAS,SAAU,QAAO;AACpC,SAAO,MAAM,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,IAC/C,iBACA;AACN;AAGO,SAAS,aACd,MACA,SACY;AACZ,QAAM,WAAW,KAAK,SAAS;AAC/B,QAAM,OAAO,MAAM,QAAQ,SAAS,IAAI,IACnC,QAAQ,KAAmB;AAAA,IAC1B,CAAC,MAAmB,OAAO,MAAM;AAAA,EACnC,IACA,CAAC;AACL,SAAO;AAAA,IACL;AAAA,IACA,OAAO,QAAQ,WAAW,KAAK,QAAQ,IAAI;AAAA,IAC3C,OAAO,OAAO,SAAS,UAAU,WAAW,QAAQ,QAAQ;AAAA,IAC5D,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,YAAY,SAAS,CAAC,CAAC;AAAA,EACnD;AACF;AAGO,SAAS,UACd,OACA,SACS;AACT,MAAI,MAAM,UAAU,eAAgB,QAAO;AAC3C,SAAO,MAAM,UAAU,UAAU,SAAS,aAAa;AACzD;AAGA,SAAS,SAAS,OAAoC;AACpD,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,IAAI;AACV,SAAO,OAAO,EAAE,SAAS,YAAY,EAAE,OACnC,EAAE,GAAG,GAAG,QAAQ,EAAE,UAAU,IAAI,MAAM,EAAE,KAAK,IAC7C;AACN;AAIA,SAAS,QACP,OACA,OACA,SACmB;AACnB,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,SAAS,SAAS,KAAK;AAC7B,WAAO,UAAU,EAAE,OAAO;AAAA,EAC5B;AACA,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,MAAM,UAAU,eAAgB,QAAO,EAAE,MAAM,MAAM;AACzD,SAAO;AAAA,IACL,QAAQ;AAAA,MACN,QAAQ,SAAS,UAAU;AAAA,MAC3B,MAAM;AAAA,MACN,GAAI,SAAS,WAAW,EAAE,SAAS,QAAQ,QAAQ;AAAA,IACrD;AAAA,EACF;AACF;AAGO,SAAS,UACd,OACA,OACA,SACS;AACT,QAAM,SAAS,MAAM,WAAY,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,IAAK,CAAC,KAAK;AAC5E,SAAO,OACJ,IAAI,CAAC,MAAM,QAAQ,GAAG,OAAO,OAAO,CAAC,EACrC,OAAO,CAAC,MAAkB,MAAM,MAAS;AAC9C;AAGO,SAAS,SAAS,GAAkB;AACzC,SAAO,EAAE,SAAS,UAAU,EAAE,MAAM,IAAI,QAAQ,EAAE,QAAQ,EAAE;AAC9D;AAGO,SAAS,SACd,KACA,OACA,SACiB;AACjB,MAAI,MAAM,UAAU,OAAQ,QAAO,OAAO,IAAI,MAAM,KAAK,KAAK,IAAI,IAAI;AACtE,QAAM,UAAU,IAAI,WAAW,SAAS;AACxC,QAAM,OAAO,MAAM,KAAK,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,IAAI;AACpD,SAAO;AAAA,IACL,QAAQ,IAAI;AAAA,IACZ,MAAM,IAAI;AAAA,IACV,GAAI,WAAW,EAAE,QAAQ;AAAA,IACzB,GAAI,IAAI,WAAW,EAAE,SAAS,IAAI,QAAQ;AAAA,IAC1C,GAAG,OAAO,YAAY,KAAK,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAAA,EACpD;AACF;AAGA,SAAS,UACP,GACA,OACA,SACoB;AACpB,QAAM,QAAQ,QAAQ,GAAG,OAAO,OAAO;AACvC,SAAO,QAAQ,SAAS,KAAK,IAAI;AACnC;AAMO,SAAS,WACd,OACA,QACA,OACA,SACS;AACT,MAAI,CAAC,MAAM,SAAU,QAAO;AAC5B,QAAM,UAAU,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC;AAChD,QAAM,MAAM,UAAU,QAAQ,OAAO,OAAO;AAC5C,QAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,UAAU,GAAG,OAAO,OAAO,MAAM,GAAG;AACzE,MAAI,OAAO,SAAS,QAAQ,OAAQ,QAAO,OAAO,SAAS,SAAS;AACpE,SAAO,CAAC,GAAG,SAAS,MAAM;AAC5B;AAGO,SAAS,cACd,OACA,KACA,OACA,SACS;AACT,MAAI,CAAC,MAAM,SAAU,QAAO;AAC5B,QAAM,UAAU,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC;AAChD,QAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,UAAU,GAAG,OAAO,OAAO,MAAM,GAAG;AACzE,SAAO,OAAO,SAAS,SAAS;AAClC;;;AC3KA,SAAS,eAAAC,cAAa,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AAYlD,IAAM,YAAY;AAEzB,IAAM,cAAc;AAsBpB,SAAS,aAAa,MAAsB;AAC1C,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,IAAI;AAC3C,EAAAF,WAAU,MAAM;AACd,UAAM,IAAI,WAAW,MAAM,WAAW,IAAI,GAAG,WAAW;AACxD,WAAO,MAAM,aAAa,CAAC;AAAA,EAC7B,GAAG,CAAC,IAAI,CAAC;AACT,SAAO;AACT;AAGA,SAAS,YAAY,QAA+B;AAClD,SAAO,OAAO,UAAU,SACpB,OAAO,SAAS,YAChB,OAAO,QAAQ,SAAS;AAC9B;AAGA,SAAS,UAAU,QAA+B;AAChD,SAAO,OAAO,UAAU,SACpB,OAAO,QAAQ,SAAS,OAAO,QAC/B;AACN;AAQA,SAAS,eACP,SACA,MACA;AACA,QAAM,CAAC,MAAM,OAAO,IAAIE,UAAe;AACvC,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAiB;AAC3C,QAAM,UAAUD,QAAO,CAAC;AAExB,QAAM,QAAQA,QAAsB,IAAI;AAExC,QAAM,MAAMF;AAAA,IACV,CAAC,MAA0B,QAAgB,WAAwB;AACjE,UAAI,CAAC,WAAW,CAAC,KAAM,QAAO,QAAQ,QAAQ,MAAS;AACvD,YAAM,KAAK,EAAE,QAAQ;AACrB,iBAAW,IAAI;AACf,aAAO,QACJ,OAAO,EAAE,GAAG,MAAM,MAAM,OAAO,WAAW,OAAO,CAAC,EAClD,KAAK,CAAC,MAAM;AACX,YAAI,OAAO,QAAQ,QAAS,QAAO;AACnC,cAAM,UAAU,QAAQ;AACxB,cAAM,SAAS,EAAE,GAAG,GAAG,SAAS,CAAC,GAAG,QAAQ,GAAG,EAAE,OAAO,EAAE;AAC1D,gBAAQ,EAAE,QAAQ,SAAS,UAAU,MAAM,EAAE,CAAC;AAC9C,iBAAS,MAAS;AAClB,eAAO;AAAA,MACT,CAAC,EACA,MAAM,CAAC,MAAe;AACrB,YAAI,OAAO,QAAQ,QAAS,UAAS,OAAO,CAAC,CAAC;AAC9C,eAAO;AAAA,MACT,CAAC,EACA,QAAQ,MAAM;AACb,YAAI,OAAO,QAAQ,QAAS,YAAW,KAAK;AAAA,MAC9C,CAAC;AAAA,IACL;AAAA,IACA,CAAC,SAAS,IAAI;AAAA,EAChB;AAEA,QAAM,QAAQA,aAAY,MAAM;AAC9B,YAAQ;AACR,UAAM,UAAU;AAChB,YAAQ,MAAS;AACjB,eAAW,KAAK;AAAA,EAClB,GAAG,CAAC,CAAC;AAEL,QAAM,UAAUA,aAAY,CAAC,SAAiB,MAAM,YAAY,MAAM,CAAC,CAAC;AAExE,SAAO,EAAE,MAAM,SAAS,OAAO,KAAK,OAAO,QAAQ;AACrD;AAGO,SAAS,qBACd,SACA,MACA,QACA,WAAW,GACQ;AACnB,QAAM,CAAC,QAAQ,SAAS,IAAIG,UAAS,EAAE;AACvC,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAqC,MAAM;AACzE,QAAM,OAAO,aAAa,OAAO,KAAK,CAAC;AACvC,QAAM,EAAE,MAAM,SAAS,OAAO,KAAK,OAAO,QAAQ,IAAI;AAAA,IACpD;AAAA,IACA;AAAA,EACF;AACA,QAAM,OAAO,UAAU;AAGvB,EAAAF,WAAU,MAAM;AACd,QAAI,OAAQ;AACZ,SAAK,IAAI,QAAW,GAAG,CAAC,CAAC,EAAE;AAAA,MACzB,CAAC,MAAM,KAAK,WAAW,YAAY,CAAC,IAAI,SAAS,QAAQ;AAAA,IAC3D;AAAA,EACF,GAAG,CAAC,QAAQ,GAAG,CAAC;AAGhB,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,KAAM;AAEX,QAAI,SAAS,YAAY,KAAK,SAAS,KAAK,IAAI,UAAU,CAAC,EAAG,OAAM;AAAA,aAC3D,CAAC,QAAQ,IAAI,EAAG,MAAK,IAAI,QAAQ,QAAW,GAAG,CAAC,CAAC;AAAA,EAC5D,GAAG,CAAC,MAAM,MAAM,UAAU,KAAK,OAAO,OAAO,CAAC;AAE9C,QAAM,WAAWD,aAAY,MAAM;AACjC,UAAM,SAAS,MAAM,OAAO,WAAW,CAAC;AACxC,SAAK,IAAI,QAAQ,QAAW,OAAO,QAAQ,MAAM;AAAA,EACnD,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC;AAEpB,SAAO;AAAA,IACL,MAAM,MAAM,OAAO,WAAW,CAAC;AAAA,IAC/B,OAAO,MAAM,OAAO;AAAA,IACpB,SAAS,MAAM,WAAW;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACxKA,SAAS,aAAAI,YAAW,YAAAC,kBAAgB;AACpC;AAAA,EACE,aAAAC;AAAA,OAGK;AAIP,eAAe,WACb,SACA,QACA,UACA,SAC6B;AAC7B,MAAI,OAAO,OAAQ,SAAQ,MAAM,QAAQ,OAAO,MAAM,IAAI;AAC1D,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,EAAE,QAAQ,IAAI,MAAM,QAAQ,OAAO;AAAA,IACvC;AAAA,IACA;AAAA,IACA,MAAM,OAAO;AAAA,EACf,CAAC;AACD,SAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,IAAI,GAAG;AACtD;AAGA,SAAS,WAAW,QAA4B,SAA8B;AAC5E,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,OAAO,QAAQ,QAAQ;AAC7B,SAAO;AAAA,IACL,KAAK,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,IACA,SAAS,QAAQ,WAAW,SAAS;AAAA,IACrC,UAAU,SAAS;AAAA,IACnB,KAAKA,WAAU,EAAE,QAAQ,KAAK,CAAC;AAAA,EACjC;AACF;AAGO,SAAS,eACd,SACA,QACA,SACoB;AACpB,QAAM,CAAC,SAAS,UAAU,IAAID,WAA0C;AACxE,QAAM,EAAE,KAAK,QAAQ,MAAM,SAAS,UAAU,IAAI,IAAI;AAAA,IACpD;AAAA,IACA;AAAA,EACF;AAEA,EAAAD,WAAU,MAAM;AACd,QAAI,CAAC,WAAW,CAAC,QAAQ,IAAK;AAC9B,QAAI,OAAO;AACX,eAAW,SAAS,EAAE,QAAQ,MAAM,QAAQ,GAAG,UAAU,OAAO,EAC7D,KAAK,CAAC,UAAU,QAAQ,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC,EAClD,MAAM,MAAM,QAAQ,WAAW,EAAE,IAAI,CAAC,CAAC;AAC1C,WAAO,MAAM;AACX,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,SAAS,QAAQ,MAAM,SAAS,UAAU,KAAK,GAAG,CAAC;AAEvD,SAAO,QAAQ,SAAS,QAAQ,MAAM,QAAQ,QAAQ;AACxD;;;AC3DA,SAAS,aAAAG,YAAW,WAAAC,UAAS,YAAAC,kBAAgB;AAC7C;AAAA,EACE,aAAAC;AAAA,OAGK;AAMP,IAAM,OAAqB,oBAAI,IAAI;AAKnC,SAAS,OAAO,SAA8B,aAA+B;AAC3E,SACE,SAAS,aAAa,cACtB,CAAC,EAAE,QAAQ,YAAY,QAAQ,WAC/B;AAEJ;AAGA,eAAe,UACb,UACA,SACA,QACuC;AACvC,MAAI;AACF,UAAM,SAAS,MAAM,SAAS;AAAA,MAC5B,UAAU,QAAQ;AAAA,MAClB,QAAQ,QAAQ;AAAA,MAChB,SAAS,QAAQ;AAAA,MACjB,MAAM,OAAO;AAAA,IACf,CAAC;AACD,QAAI,OAAO,OAAQ,QAAO;AAC1B,WAAO;AAAA,MACLA,WAAU,MAAM;AAAA,MAChB,OAAO,WAAW,GAAG,OAAO,IAAI;AAAA,IAClC;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,aACd,SACA,SACA,SACA,aACc;AACd,QAAM,CAAC,UAAU,WAAW,IAAID,WAAuB,IAAI;AAE3D,QAAM,WAAWD,SAAQ,MAAM,SAAS,UAAU,KAAK,OAAO,GAAG,CAAC,OAAO,CAAC;AAC1E,QAAM,SAAS,CAAC,CAAC,YAAY,OAAO,SAAS,WAAW;AAExD,QAAM,QAAQ,SACV,KAAK,UAAU,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,IACrD;AACJ,QAAM,WAAW,SAAS;AAC1B,QAAM,SAAS,SAAS;AACxB,QAAM,UAAU,SAAS;AAEzB,EAAAD,WAAU,MAAM;AACd,UAAM,SAAU,KAAK,MAAM,KAAK,EAAyB;AAAA,MACvD,CAAC,CAAC,GAAG,IAAI,OAAe,EAAE,QAAQ,GAAG,KAAK;AAAA,IAC5C;AACA,QAAI,CAAC,YAAY,CAAC,UAAU,OAAO,WAAW,GAAG;AAC/C,kBAAY,IAAI;AAChB;AAAA,IACF;AACA,UAAM,OAAgB,EAAE,UAAU,QAAQ,SAAS,UAAU,WAAW;AACxE,QAAI,OAAO;AACX,SAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,MAAM,UAAU,UAAU,MAAM,CAAC,CAAC,CAAC,EAAE;AAAA,MAChE,CAAC,UAAU;AACT,YAAI,CAAC,KAAM;AACX,cAAM,UAAU,MAAM,OAAO,CAAC,MAAM,MAAM,MAAS;AACnD,oBAAY,QAAQ,SAAS,IAAI,IAAI,OAAO,IAAI,IAAI;AAAA,MACtD;AAAA,IACF;AACA,WAAO,MAAM;AACX,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,QAAQ,UAAU,OAAO,UAAU,QAAQ,OAAO,CAAC;AAEvD,SAAO;AACT;;;AC3FA,SAAS,SAAAI,cAAa;AACtB,SAAS,MAAAC,YAAU;AACnB,SAAS,aAAAC,kBAAiB;AAE1B;AAAA,EACE;AAAA,EACA,WAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,eAAAC;AAAA,OACK;AA0BD,gBAAAC,OAMA,QAAAC,cANA;AAtBN,SAAS,aAAa,GAA8B;AAClD,MAAI,EAAE,QAAS,QAAO;AACtB,MAAI,EAAE,MAAO,QAAO;AACpB,QAAM,QAAQ,EAAE,OAAO,KAAK,EAAE;AAC9B,MAAI,EAAE,SAAS,YAAY,QAAQ,EAAE;AACnC,WAAO,EAAE,WAAW,KAAK,QAAQ,IAC7B,iBAAiB,EAAE,QAAQ,mBAC3B;AACN,SAAO;AACT;AAEA,SAAS,QAAQ;AAAA,EACf;AAAA,EACA;AAAA,EACA;AACF,GAIuB;AACrB,SACE,gBAAAA,OAACH,cAAA,EAAY,OAAOL,WAAU,GAAG,GAAG,UAAU,MAAM,OAAO,GAAG,GAC5D;AAAA,oBAAAO;AAAA,MAACT;AAAA,MAAA;AAAA,QACC,WAAWC;AAAA,UACT;AAAA,UACA,WAAW,gBAAgB;AAAA,QAC7B;AAAA;AAAA,IACF;AAAA,IACA,gBAAAS,OAAC,SAAI,WAAU,WACb;AAAA,sBAAAD,MAAC,qBAAkB,MAAM,IAAI,MAAM,SAAS,IAAI,SAAS;AAAA,MACxD,IAAI,QAAQ,IAAI,KAAK,SAAS,KAC7B,gBAAAA,MAAC,SAAI,WAAU,0CACZ,cAAI,KAAK,KAAK,UAAK,GACtB;AAAA,OAEJ;AAAA,KACF;AAEJ;AAEO,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMuB;AACrB,SACE,gBAAAC,OAACP,UAAA,EAAQ,cAAc,OACrB;AAAA,oBAAAM;AAAA,MAACH;AAAA,MAAA;AAAA,QACC,aAAY;AAAA,QACZ,OAAO,QAAQ;AAAA,QACf,eAAe,QAAQ;AAAA;AAAA,IACzB;AAAA,IACA,gBAAAI,OAACF,cAAA,EACC;AAAA,sBAAAC,MAACL,eAAA,EAAc,uBAAa,OAAO,GAAE;AAAA,MACrC,gBAAAM,OAACL,eAAA,EACE;AAAA,gBAAQ,KAAK,IAAI,CAAC,QACjB,gBAAAI;AAAA,UAAC;AAAA;AAAA,YAEC;AAAA,YACA,UAAU,SAAS,IAAIP,WAAU,GAAG,CAAC;AAAA,YACrC;AAAA;AAAA,UAHKA,WAAU,GAAG;AAAA,QAIpB,CACD;AAAA,QACA,QAAQ,WACP,gBAAAO,MAACF,cAAA,EAAY,OAAM,UAAS,UAAU,QAAQ,UAC5C,0BAAAG,OAAC,UAAK,WAAU,iCAAgC;AAAA;AAAA,UAE7C,QAAQ,UAAU,UACjB,KAAK,QAAQ,KAAK,MAAM,OAAO,QAAQ,KAAK;AAAA,WAChD,GACF;AAAA,QAED,YACC,gBAAAD,MAACF,cAAA,EAAY,OAAM,UAAS,UAAU,MAAM,WAAW,QAAQ,GAC7D,0BAAAG,OAAC,UAAK,WAAU,WAAU;AAAA;AAAA,UAAY;AAAA,UAAS;AAAA,WAAO,GACxD;AAAA,SAEJ;AAAA,OACF;AAAA,KACF;AAEJ;;;ACzFI,gBAAAC,aAAA;AAfG,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AACF,GAIuB;AACrB,QAAM,MAAM,CAAC,MAA0B;AACrC,MAAE,eAAe;AACjB,MAAE,gBAAgB;AAClB,UAAM;AAAA,EACR;AACA,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,UAAU;AAAA,MACV,WAAU;AAAA,MACV,eAAe;AAAA,MAEd;AAAA;AAAA,EACH;AAEJ;;;AC3BA,YAAYC,aAAW;AAOhB,SAAS,WACd,SAC4B;AAC5B,QAAM,OAAO,SAAS;AACtB,SAAO,SAAS,UAAU,SAAS,WAAW,OAAO;AACvD;AAGO,SAAS,eAAe,SAAyC;AACtE,QAAM,IAAI,SAAS;AACnB,SAAO,OAAO,MAAM,YAAY,KAAK,IAAI,IAAI;AAC/C;AAGO,SAAS,WAAW,SAAmD;AAC5E,QAAM,EAAE,UAAU,QAAQ,QAAQ,IAAI,WAAW,CAAC;AAClD,SAAa;AAAA,IACX,MAAO,YAAY,SAAS,EAAE,UAAU,QAAQ,QAAQ,IAAI;AAAA,IAC5D,CAAC,UAAU,QAAQ,OAAO;AAAA,EAC5B;AACF;;;AP6EW,gBAAAC,OAqBP,QAAAC,cArBO;AAhCX,SAAS,WAAW,GAAsB,MAAmC;AAC3E,QAAM,OAAO,EAAE,OAAO,KAAK;AAC3B,MAAI,CAAC,QAAQ,CAAC,KAAM,QAAO;AAC3B,SAAO,EAAE,KAAK,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI,IAAI,SAAY;AAC3D;AAaA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AACF,GAG8B;AAC5B,QAAM,MAAM,SAAS,KAAK;AAC1B,QAAM,QAAQ,MAAM,OAAO,IAAI,GAAG;AAClC,QAAM,SAAS;AAAA,IACb,SAAS,CAAC,MAAM,SAAS,OAAO,MAAM;AAAA,IACtC,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACA,MAAI,CAAC,MAAM;AACT,WAAO,gBAAAD,MAAC,UAAK,WAAU,oBAAoB,gBAAM,MAAK;AACxD,SACE,gBAAAA;AAAA,IAACE;AAAA,IAAA;AAAA,MACC,MAAM,MAAM,OAAO;AAAA,MACnB,SAAS,QAAQ,MAAM,OAAO,IAAI,GAAG,IAAI;AAAA,MACzC,QAAQ,MAAM,OAAO,UAAU;AAAA;AAAA,EACjC;AAEJ;AAGA,SAAS,KAAK;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AACF,GAIuB;AACrB,SACE,gBAAAD,OAACE,QAAA,EAAM,SAAQ,aAAY,WAAU,gCACnC;AAAA,oBAAAH,MAAC,aAAU,OAAc,OAAc;AAAA,IACtC,YACC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,OAAO,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,QAErC,0BAAAA,MAACI,IAAA,EAAE,WAAU,WAAU;AAAA;AAAA,IACzB;AAAA,KAEJ;AAEJ;AAGA,SAAS,QAAQ;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKuB;AACrB,MAAI,CAAC,MAAM,SAAU,QAAO,gBAAAJ,MAAC,aAAU,OAAO,QAAQ,CAAC,GAAG,OAAc;AACxE,SACE,gBAAAA,MAAC,UAAK,WAAU,gCACb,kBAAQ,IAAI,CAAC,MACZ,gBAAAA,MAAC,QAAuB,OAAO,GAAG,OAAc,YAArC,SAAS,CAAC,CAA+C,CACrE,GACH;AAEJ;AAGA,SAASK,cAAa;AAAA,EACpB;AAAA,EACA;AACF,GAGuB;AACrB,SACE,gBAAAJ,OAAC,UAAK,WAAU,yCACb;AAAA,eAAW,gBAAAD,MAAC,WAAQ,WAAU,mCAAkC;AAAA,IAChE,WACC,gBAAAA,MAAC,oBAAiB,OAAM,mBAAkB,OAAO,SAC/C,0BAAAA,MAACI,IAAA,EAAE,WAAU,WAAU,GACzB;AAAA,IAEF,gBAAAJ,MAACM,iBAAA,EAAe,WAAU,sBAAqB;AAAA,KACjD;AAEJ;AAWA,SAAS,aAAa,OAAgC;AACpD,QAAM,UAAU,UAAU,MAAM,cAAc;AAC9C,QAAM,QAAQ,aAAa,MAAM,gBAAgB,MAAM,OAAO;AAC9D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS,UAAU,MAAM,OAAO,OAAO,OAAO;AAAA,IAC9C,aAAa,MAAM,UAAU;AAAA,EAC/B;AACF;AAGA,SAAS,WAAW,OAAoB,OAAmB;AACzD,QAAM,EAAE,OAAO,SAAS,IAAI;AAC5B,QAAM,EAAE,SAAS,MAAM,IAAI;AAC3B,QAAM,CAAC,QAAQ,SAAS,IAAU;AAAA,IAChC,MAAM,oBAAI,IAAI;AAAA,EAChB;AACA,QAAM,OAAO,CAAC,QAAmB;AAC/B,cAAU,CAAC,MAAM,IAAI,IAAI,CAAC,EAAE,IAAIC,WAAU,GAAG,GAAG,IAAI,OAAO,CAAC;AAC5D,aAAS,WAAW,OAAO,SAAS,KAAK,OAAO,OAAO,GAAG,OAAO,OAAO,CAAC;AAAA,EAC3E;AACA,QAAM,WAAW,CAAC,UAChB,SAAS,WAAW,OAAO,OAAO,OAAO,OAAO,CAAC;AACnD,QAAM,SAAS,CAAC,QACd,SAAS,cAAc,OAAO,KAAK,OAAO,OAAO,CAAC;AACpD,SAAO,EAAE,QAAQ,MAAM,UAAU,OAAO;AAC1C;AAEA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AACF,GAIuB;AACrB,QAAM,EAAE,IAAI,OAAO,UAAU,QAAQ,UAAU,WAAW,YAAY,IACpE;AACF,QAAM,EAAE,SAAS,OAAO,QAAQ,IAAI;AACpC,QAAM,CAAC,MAAM,OAAO,IAAU,iBAAS,KAAK;AAC5C,QAAM,OAAO,WAAW,OAAO;AAC/B,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA,WAAW,MAAM,OAAO;AAAA,IACxB,eAAe,MAAM,OAAO;AAAA,EAC9B;AACA,QAAM,UAAU,WAAW,OAAO,KAAK;AACvC,QAAM,QAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA,QAAQ,QAAQ;AAAA,IAChB,QAAQ,MAAM;AAAA,EAChB;AACA,QAAM,QAAQ,QAAQ,WAAW;AAEjC,QAAM,QAAQ,CAAC,SAAkB;AAC/B,YAAQ,IAAI;AACZ,QAAI,CAAC,MAAM;AACT,cAAQ,UAAU,EAAE;AACpB,eAAS,IAAI,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,OAAO,MAAM;AACjB,QAAI,CAAC,MAAM,SAAU,OAAM,KAAK;AAAA,EAClC;AACA,QAAM,QAAQ,MAAM,SAAS,MAAS;AAEtC,SACE,gBAAAN,OAACO,UAAA,EAAQ,MAAY,cAAc,OACjC;AAAA,oBAAAR,MAACS,iBAAA,EAAe,SAAO,MACrB,0BAAAR;AAAA,MAACS;AAAA,MAAA;AAAA,QACC;AAAA,QACA,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,iBAAe;AAAA,QACf,WAAWC;AAAA,UACT;AAAA,UACA,SAAS;AAAA,UACT,WAAW,SAAS,KAAK;AAAA,QAC3B;AAAA,QAEC;AAAA,kBACC,gBAAAX,MAAC,UAAK,WAAU,YAAY,yBAAe,aAAY,IAEvD,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA;AAAA,cACA,UAAU,QAAQ;AAAA;AAAA,UACpB;AAAA,UAEF,gBAAAA;AAAA,YAACK;AAAA,YAAA;AAAA,cACC,SAAS,QAAQ;AAAA,cACjB,SAAS,CAAC,SAAS,CAAC,WAAW,QAAQ;AAAA;AAAA,UACzC;AAAA;AAAA;AAAA,IACF,GACF;AAAA,IACA,gBAAAL;AAAA,MAACY;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAM;AAAA,QAEN,0BAAAZ;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,UAAU,IAAI,IAAI,QAAQ,IAAI,QAAQ,CAAC;AAAA,YACvC,UAAU,WAAW,SAAS,UAAU,OAAO,OAAO,CAAC;AAAA,YACvD,QAAQ,CAAC,QAAQ;AACf,sBAAQ,KAAK,GAAG;AAChB,mBAAK;AAAA,YACP;AAAA,YACA,YAAY,CAAC,UAAU;AACrB,sBAAQ,SAAS,KAAK;AACtB,mBAAK;AAAA,YACP;AAAA;AAAA,QACF;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;AAGA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AACF,GAIuB;AACrB,QAAM,QAAe;AAAA,IACnB,SAAS,MAAM;AAAA,IACf;AAAA,IACA,QAAQ,oBAAI,IAAI;AAAA,IAChB,QAAQ,MAAM;AAAA,EAChB;AACA,SACE,gBAAAC,OAAC,SAAI,WAAU,aACZ;AAAA,UAAM,QAAQ,SACb,gBAAAD,MAAC,WAAQ,SAAS,MAAM,SAAS,OAAO,MAAM,OAAO,OAAc,IAEnE,gBAAAA,MAAC,UAAK,WAAU,iCAAiC,uBAAY;AAAA,IAE9D,QAAQ,gBAAAA,MAAC,OAAE,WAAU,iCAAiC,gBAAK;AAAA,KAC9D;AAEJ;AAGA,SAAS,aACP,OACA,SACoB;AACpB,MAAI,CAAC,MAAM,QAAS,QAAO;AAC3B,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO;AACT;AAGA,SAAS,iBAAiB;AAAA,EACxB;AACF,GAE8B;AAC5B,MAAI,SAAS,SAAS,EAAG,QAAO;AAChC,SACE,gBAAAA,MAAC,SAAI,WAAU,eACZ,WAAC,GAAG,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,OAAO,MAC/B,gBAAAC;AAAA,IAAC;AAAA;AAAA,MAEC,WAAU;AAAA,MAEV;AAAA,wBAAAD,MAAC,iBAAc,WAAU,oBAAmB;AAAA,QAC3C;AAAA;AAAA;AAAA,IAJI;AAAA,EAKP,CACD,GACH;AAEJ;AAGA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AACF,GAIuB;AACrB,QAAM,OAAO,aAAa,OAAO,OAAO;AACxC,MAAI,MAAM,YAAY,MAAM,YAAY,QAAQ,CAAC;AAC/C,WACE,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,MAAM,MAAM,YAAY,MAAM,WAAW,SAAY;AAAA;AAAA,IACvD;AAEJ,SAAO,gBAAAA,MAAC,sBAAmB,OAAc,OAAc,SAAkB;AAC3E;AAGA,SAAS,gBAAgB;AAAA,EACvB;AACF,GAEuB;AACrB,QAAM,UAAU,eAAe;AAC/B,QAAM,QAAQ,aAAa,KAAK;AAChC,QAAM,WAAW;AAAA,IACf;AAAA,IACA,MAAM;AAAA,IACN,MAAM,QAAQ,QAAQ,CAAC,MAAO,EAAE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC,CAAE;AAAA,IACzD,MAAM;AAAA,EACR;AACA,SACE,gBAAAC,OAAC,SAAI,WAAU,aACb;AAAA,oBAAAD,MAAC,kBAAe,OAAc,OAAc,SAAkB;AAAA,IAC9D,gBAAAA,MAAC,oBAAiB,UAAoB;AAAA,KACxC;AAEJ;AAEO,SAAS,iBAAiB,OAAwC;AACvE,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,MAAM;AAAA,MACf,OAAO,MAAM;AAAA,MACb,aAAa,MAAM;AAAA,MACnB,UAAU,MAAM;AAAA,MAChB,OAAO,WAAW,MAAM,SAAS;AAAA,MAEjC,0BAAAA,MAAC,mBAAgB,OAAc;AAAA;AAAA,EACjC;AAEJ;;;AQ1ZA,YAAYa,aAAW;AACvB,SAAS,QAAAC,OAAM,KAAAC,UAAS;AACxB,SAAS,MAAAC,YAAU;AACnB;AAAA,EACE;AAAA,EACA,aAAAC;AAAA,EACA;AAAA,EACA,aAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,aAAAC;AAAA,EACA;AAAA,OAIK;AACP;AAAA,EACE,kBAAAC;AAAA,OAEK;AACP;AAAA,EACE,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAAC;AAAA,EACA;AAAA,EACA,kBAAAC;AAAA,OACK;;;AC/CP;AAAA,EACE;AAAA,EACA;AAAA,OAMK;AAGP,SAAS,QAAQ,SAA0B,MAA0B;AACnE,QAAM,IAAI,MAAM,KAAK,IAAI,OAAO;AAChC,MAAI,QAAQ,WAAW,KAAK,CAAC,EAAG,QAAO;AACvC,SAAO;AAAA,IACL,GAAI,QAAQ,SAAS,EAAE,QAAQ,IAAI,CAAC;AAAA,IACpC,GAAI,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC;AAAA,EACzB;AACF;AAMO,SAAS,QACd,OACA,OACA,KACA,QAC6B;AAC7B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,EAAE,GAAG,QAAQ,cAAc,KAAK;AAAA,EAC5C;AACF;AAOO,SAAS,cACd,OACA,OACA,KACA,YAC6B;AAC7B,MAAI,cAAc,OAAO,KAAK,EAAE,OAAO,GAAG,EAAG,QAAO,UAAU,KAAK;AACnE,QAAM,EAAE,QAAQ,MAAM,IAAI;AAC1B,SAAO,WAAW,OAAO,OAAO,KAAK;AAAA,IACnC,GAAG;AAAA,IACH,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,EAC3B,CAAC;AACH;AAGA,SAAS,WACP,OACA,OACA,KACA,QAC6B;AAC7B,QAAM,EAAE,QAAQ,MAAM,OAAO,IAAI,cAAc,OAAO,KAAK;AAC3D,QAAM,UAAU,MAAM,GAAG,GAAG;AAC5B,QAAM,OAAO,KAAK;AAAA,IAAI,CAAC,GAAG,MACxB,MAAM,MAAM,IAAI,UAAU,EAAE,GAAG,QAAQ,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC,EAAG;AAAA,EACzE;AACA,SAAO;AAAA,IACL,CAAC,GAAG,KAAK,OAAO,CAAC,MAA0B,CAAC,CAAC,CAAC,GAAG,GAAG,MAAM;AAAA,IAC1D,UAAU,KAAK,EAAE;AAAA,EACnB;AACF;AAGO,SAAS,SACd,OACA,MAC6B;AAC7B,SAAO,QAAQ,UAAU,KAAK,EAAE,WAAW,CAAC,GAAG,IAAI;AACrD;;;AD4BI,SAME,OAAAC,OANF,QAAAC,cAAA;AAzCJ,SAAS,WAAW,MAA6C;AAC/D,QAAM,EAAE,UAAU,QAAQ,QAAQ,IAAI;AACtC,SAAO;AAAA,IACL,GAAG,YAAY;AAAA,IACf,aAAa;AAAA,MACX,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,MAC/B,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7B,UAAU;AAAA,IACZ;AAAA,EACF;AACF;AAGA,IAAM,YAAwB;AAAA,EAC5B,UAAU;AAAA,EACV,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM,CAAC;AACT;AAGA,SAAS,WAAW,OAAoB,YAA8B;AACpE,QAAM,OAAO,MAAM,SAAS;AAC5B,SAAO,OAAO,SAAS,YAAY,OAAO;AAC5C;AAGA,SAAS,WAAW;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKuB;AACrB,QAAM,SAAS,OAAO,UAAU,UAAa,CAAC,OAAO;AACrD,SACE,gBAAAA;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,WAAWC,KAAG,qBAAqB,UAAU,gBAAgB;AAAA,MAC7D,OAAO,OAAO,WAAW,OAAO;AAAA,MAChC,SAAS;AAAA,MAET;AAAA,wBAAAH,MAAC,UAAK,WAAU,yBAAyB,iBAAM;AAAA,QAC/C,gBAAAA,MAAC,UAAK,WAAU,qBAAqB,iBAAO,MAAK;AAAA,QAChD,UAAU,gBAAAA,MAAC,UAAK,WAAU,yBAAwB,yBAAQ;AAAA,QAC1D,YACC,gBAAAA,MAAC,oBAAiB,OAAO,UAAU,KAAK,IAAI,OAAO,UACjD,0BAAAA,MAACI,IAAA,EAAE,WAAU,WAAU,GACzB;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAGA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AACF,GAGuB;AACrB,SACE,gBAAAH;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,WAAWC;AAAA,QACT;AAAA,QACA,UAAU;AAAA,MACZ;AAAA,MACA,SAAS;AAAA,MAER;AAAA;AAAA,QACD,gBAAAH,MAAC,UAAK,WAAU,oBAAmB,eAAC;AAAA;AAAA;AAAA,EACtC;AAEJ;AAGA,SAAS,WAAW;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKuB;AACrB,QAAM,UAAUK,gBAAe;AAC/B,QAAM,MAAM,WAAW,EAAE,GAAG,MAAM,UAAU,WAAW,CAAC;AACxD,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA,WAAW,MAAM,OAAO;AAAA,IACxB,eAAe,MAAM,OAAO;AAAA,EAC9B;AACA,SACE,gBAAAJ,OAAC,SAAI,WAAU,aACb;AAAA,oBAAAD,MAAC,OAAE,WAAU,uDACV,oBAAU,IAAI,GACjB;AAAA,IACA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,UAAU,IAAI,IAAI,WAAW,CAACM,WAAU,QAAQ,CAAC,IAAI,CAAC,CAAC;AAAA,QACvD;AAAA,QACA,YAAY,MAAM;AAAA;AAAA,IACpB;AAAA,KACF;AAEJ;AAGA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AACF,GAG8B;AAG5B,QAAM,SAAe,eAAsB,IAAI;AAC/C,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SACE,gBAAAL,OAAC,gBACC;AAAA,oBAAAD,MAAC,uBAAoB,SAAO,MAC1B,0BAAAC;AAAA,MAACM;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,WAAU;AAAA,QAEV;AAAA,0BAAAP,MAACQ,OAAA,EAAK,WAAU,WAAU;AAAA,UAAE;AAAA;AAAA;AAAA,IAE9B,GACF;AAAA,IACA,gBAAAR;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,kBAAkB,CAAC,MAAM;AACvB,cAAI,OAAO,YAAY,KAAM;AAC7B,YAAE,eAAe;AACjB,iBAAO,OAAO,OAAO;AACrB,iBAAO,UAAU;AAAA,QACnB;AAAA,QAEC,gBAAM,IAAI,CAAC,CAAC,MAAM,GAAG,MACpB,gBAAAA,MAAC,oBAA2B,UAAU,MAAO,OAAO,UAAU,KAC3D,oBAAU,IAAI,KADM,GAEvB,CACD;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;AAgBA,SAAS,SAAS;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAM8B;AAC5B,QAAM,SAAS,SAAS,MAAM,KAAK,GAAG;AACtC,MAAI;AACF,WACE,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,UAAU,IAAI;AAAA,QACrB;AAAA,QACA;AAAA,QACA,UAAU,QAAQ,MAAM,IAAI,KAAK,MAAS;AAAA;AAAA,IAC5C;AAEJ,SAAO,KAAK,WACV,gBAAAA,MAAC,eAAY,OAAO,UAAU,IAAI,GAAG,QAAgB,IACnD;AACN;AAGA,SAAS,SAAS,EAAE,OAAO,MAAM,QAAQ,MAAM,KAAK,QAAQ,GAAe;AACzE,QAAM,UAAU,MACb,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAgC,EACnD,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,QAAQ;AACtD,SACE,gBAAAC,OAAC,SAAI,WAAU,qCACZ;AAAA,UAAM,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,MACzB,gBAAAD;AAAA,MAAC;AAAA;AAAA,QAEC;AAAA,QACA,KAAK,IAAI;AAAA,QACT,QAAQ,KAAK,IAAI,CAAC;AAAA,QAClB;AAAA,QACA;AAAA;AAAA,MALK,IAAI;AAAA,IAMX,CACD;AAAA,IACA,OAAO,IAAI,CAAC,MACX,gBAAAA,MAAC,cAA8B,OAAO,UAAU,CAAC,GAAG,QAAQ,KAA3CM,WAAU,CAAC,CAAmC,CAChE;AAAA,IACA,QAAQ,gBAAAN,MAAC,aAAU,OAAO,SAAS,QAAQ,MAAM;AAAA,IACjD,WACC,gBAAAC;AAAA,MAACM;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,WAAU;AAAA,QACV,SAAS;AAAA,QAET;AAAA,0BAAAP,MAACQ,OAAA,EAAK,WAAU,WAAU;AAAA,UAAE;AAAA;AAAA;AAAA,IAE9B;AAAA,KAEJ;AAEJ;AAGA,SAAS,WAAW,OAAoB;AACtC,QAAM,UAAUC,WAAU,MAAM,cAAc;AAC9C,QAAM,QAAQ,UAAU,aAAa,OAAO,IAAI,CAAC;AACjD,QAAM,OAAOC,WAAU,MAAM,KAAK,EAAE,QAAQ;AAC5C,QAAM,CAAC,SAAS,UAAU,IAAU,iBAAwB,IAAI;AAChE,QAAM,CAAC,UAAU,WAAW,IAAU,iBAAS,KAAK;AACpD,QAAM,UAAU,WAAW,OAAO,SAAS,aAAa,YAAY;AACpE,QAAM,EAAE,QAAQ,MAAM,OAAO,IAAIC,eAAc,MAAM,OAAO,KAAK;AACjE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,YAAY,YAAY,SAAS;AAAA,IAC5C,WAAW;AAAA,IACX,SACE,WAAW,CAAC,YAAY,SAAS,KAAK,MAAM,YAAY,IAAI,IAAI;AAAA,EACpE;AACF;AAOA,SAAS,eAAe,OAAoB;AAC1C,QAAM,SAAe,eAAO,MAAM,KAAK;AACvC,SAAO,UAAU,MAAM;AACvB,SAAO;AAAA,IACL,KAAK,MAAM,OAAO;AAAA,IAClB,QAAQ,CAAC,SAAkB;AACzB,aAAO,UAAU;AACjB,YAAM,SAAS,IAAI;AAAA,IACrB;AAAA,EACF;AACF;AAOA,SAAS,eACP,OACA,EAAE,KAAK,OAAO,GACd;AACA,QAAM,UAAUN,gBAAe;AAC/B,SAAO,CAAC,WAAsC;AAC5C,QAAI,CAAC,UAAU,CAAC,SAAS,UAAW;AACpC,UAAM,EAAE,QAAQ,MAAM,QAAQ,IAAI;AAClC,UAAM,QAAQM,eAAc,IAAI,GAAG,KAAK,EAAE,OAAO;AAAA,MAAQ,CAAC,GAAG,QAC3D,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAAA,IAC3B;AACA,eAAW,OAAO;AAChB,cACG,UAAU;AAAA,QACT,QAAQ,EAAE,QAAQ,MAAM,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC,EAAG;AAAA,QACxD,SAAS,CAAC,MAAM,GAAG,CAAC;AAAA,MACtB,CAAC,EACA,KAAK,CAAC,CAAC,KAAK,MAAM;AACjB,YAAI,MAAO,QAAO,cAAc,IAAI,GAAG,OAAO,KAAK,KAAK,CAAC;AAAA,MAC3D,CAAC,EAEA,MAAM,MAAM,MAAS;AAAA,EAC5B;AACF;AAEO,SAAS,sBAAsB,OAAwC;AAC5E,QAAM,EAAE,IAAI,OAAO,OAAO,IAAI;AAC9B,QAAM,IAAI,WAAW,KAAK;AAC1B,QAAM,WAAW,CAAC,MAAM,YAAY,CAAC,MAAM;AAC3C,QAAM,OAAO,MAAM,SAAS,IAAI,KAAK;AACrC,QAAM,SAAS,eAAe,KAAK;AACnC,QAAM,UAAU,eAAe,EAAE,OAAO,MAAM;AAC9C,QAAM,MAAM,CAAC,KAAa,WAAsC;AAC9D,WAAO,OAAO,QAAQ,OAAO,IAAI,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;AAEzD,QAAI,QAAQ,EAAG,SAAQ,MAAM;AAAA,EAC/B;AACA,QAAM,cAAc,EAAE,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,IAAI;AAE9D,SACE,gBAAAX;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT,OAAO,MAAM;AAAA,MACb,aAAa,MAAM;AAAA,MACnB,UAAU,MAAM;AAAA,MAChB,OAAO,WAAW,MAAM,SAAS;AAAA,MAEjC,0BAAAC,OAAC,SAAI,WAAU,eACb;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,OAAO,EAAE;AAAA,YACT,QAAQ,EAAE,KAAK,CAAC;AAAA,YAChB;AAAA,YACA;AAAA;AAAA,QACF;AAAA,QACA,gBAAAC;AAAA,UAACW;AAAA,UAAA;AAAA,YACC,MAAM,gBAAgB;AAAA,YACtB,cAAc,CAAC,MAAM;AACnB,kBAAI,EAAG;AACP,gBAAE,WAAW,IAAI;AACjB,mBAAK;AAAA,YACP;AAAA,YAEA;AAAA,8BAAAZ,MAAC,iBAAc,SAAO,MACpB,0BAAAA,MAAC,SACC,0BAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO,EAAE;AAAA,kBACT,MAAM,EAAE;AAAA,kBACR,QAAQ,EAAE;AAAA,kBACV,MAAM,WAAW,EAAE,aAAa;AAAA,kBAChC,KAAK,WAAW,MAAM;AAAA,kBACtB,SAAS,WAAW,EAAE,UAAU;AAAA;AAAA,cAClC,GACF,GACF;AAAA,cACA,gBAAAA;AAAA,gBAACa;AAAA,gBAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAM;AAAA,kBAEL,yBAAe,EAAE,YAAY,QAC5B,gBAAAb;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAM;AAAA,sBACN;AAAA,sBACA,UAAU,EAAE,KAAK,EAAE,OAAO;AAAA,sBAC1B,QAAQ,CAAC,QAAQ;AACf;AAAA,0BACE,EAAE;AAAA,0BACF,SAAS,KAAK,WAAW,MAAS;AAAA,wBACpC;AACA,0BAAE,WAAW,IAAI;AAAA,sBACnB;AAAA;AAAA,kBACF;AAAA;AAAA,cAEJ;AAAA;AAAA;AAAA,QACF;AAAA,QACC,EAAE,aACD,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,IAAI,GAAG,EAAE;AAAA,YACT,OAAM;AAAA,YACN,OAAO,EAAE;AAAA,YACT,aAAY;AAAA,YACZ,UAAU,MAAM;AAAA,YAChB,UAAU,MAAM;AAAA,YAChB,UAAU,CAAC,MACT,OAAO,OAAO,SAAS,OAAO,IAAI,GAAG,EAAE,OAAO,KAAK,CAAC;AAAA,YAEtD,QAAQ;AAAA,YAER,WAAW,EAAE;AAAA;AAAA,QACf;AAAA,SAEJ;AAAA;AAAA,EACF;AAEJ;AAGA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMuB;AACrB,MAAI,CAAC,MAAM,CAAC;AACV,WACE,gBAAAA,MAAC,OAAE,WAAU,iCAAgC,6CAE7C;AAEJ,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,OAAM;AAAA,MACN,aAAa;AAAA,MACb,WAAW;AAAA,MACX,gBAAgB,WAAW,MAAM,CAAC,CAAC;AAAA,MACnC,OAAO;AAAA,MACP,UAAU,CAAC,SAAS,IAAI,GAAG,IAAiC;AAAA,MAC5D,QAAQ;AAAA;AAAA,EACV;AAEJ;;;AE3eA,SAAS,iBAAiB;AAoCpB,gBAAAc,aAAA;AA/BN,SAAS,iBAAiB,OAA+B;AACvD,SAAO,UAAU,UAAU,UAAU,UAAU,QAAQ;AACzD;AAEO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoC;AAClC,QAAM,QAAQ,WAAW,SAAS;AAClC,QAAM,YAAY,iBAAiB,SAAS,SAAS;AACrD,QAAM,SACJ,OAAO,SAAS,WAAW,WAAW,QAAQ,SAAS;AAEzD,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB,SAAS;AAAA,MAEzB,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,UAC3C;AAAA,UACA,QAAQ,MAAM,SAAS,IAAI,KAAK;AAAA,UAChC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,KAAK,eAAe;AAAA,UACpB,KAAK,eAAe;AAAA;AAAA,MACtB;AAAA;AAAA,EACF;AAEJ;;;ACzDA,SAAS,iBAAiB;AAiCpB,gBAAAC,aAAA;AA5BN,SAAS,mBAAmB,OAAiC;AAC3D,SAAO,UAAU,WAAW,WAAW;AACzC;AAEO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoC;AAClC,QAAM,QAAQ,WAAW,SAAS;AAClC,QAAM,cAAc,mBAAmB,SAAS,WAAW;AAE3D,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB,SAAS;AAAA,MAEzB,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,UAC3C;AAAA,UACA,QAAQ,MAAM,SAAS,IAAI,KAAK;AAAA,UAChC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;;;AC3CA,SAAS,qBAAqB;AAqCxB,gBAAAC,aAAA;AAhCN,SAASC,oBAAmB,OAAiC;AAC3D,SAAO,UAAU,WAAW,WAAW;AACzC;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoC;AAClC,QAAM,QAAQ,WAAW,SAAS;AAClC,QAAM,cAAcA,oBAAmB,SAAS,WAAW;AAC3D,QAAM,WACJ,OAAO,SAAS,aAAa,WAAW,QAAQ,WAAW;AAC7D,QAAM,SACJ,OAAO,SAAS,WAAW,WAAW,QAAQ,SAAS;AAEzD,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB,SAAS;AAAA,MAEzB,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC,UAAU;AAAA,UACV,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,UAC3C;AAAA,UACA,QAAQ,MAAM,SAAS,IAAI,KAAK;AAAA,UAChC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,KAAK,eAAe;AAAA,UACpB,KAAK,eAAe;AAAA;AAAA,MACtB;AAAA;AAAA,EACF;AAEJ;;;AClDI,SACY,OAAAE,OADZ,QAAAC,cAAA;AANG,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AACF,GAA2C;AACzC,MAAI,CAAC,SAAS,CAAC,YAAa,QAAO;AACnC,SACE,gBAAAA,OAAC,SAAI,WAAU,aACZ;AAAA,aAAS,gBAAAD,MAAC,OAAE,WAAU,2BAA2B,iBAAM;AAAA,IACvD,eACC,gBAAAA,MAAC,OAAE,WAAU,iCAAiC,uBAAY;AAAA,KAE9D;AAEJ;;;ACdA,SAAS,WAAAE,gBAAe;AAMxB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA0ES,gBAAAC,OACV,QAAAC,cADU;AA9DhB,SAAS,aACP,UACA,eACgB;AAChB,SAAO,SAAS,IAAI,CAAC,QAAQ,UAAU;AACrC,UAAM,MAAM,gBACR,eAAe,QAAQ,aAAa,IACpC;AACJ,WAAO;AAAA,MACL;AAAA,MACA,OAAO,QAAQ,SAAY,OAAO,GAAG,IAAI,OAAO,KAAK;AAAA,MACrD,OAAO,eAAe,QAAQ,eAAe,KAAK;AAAA,IACpD;AAAA,EACF,CAAC;AACH;AAGA,SAAS,kBAAkB,QAA+C;AACxE,MAAI,CAAC,OAAO,WAAY,QAAO;AAC/B,SAAO;AAAA,IACL,OAAO,OAAO,SAAS;AAAA,IACvB,MAAM;AAAA,IACN,YAAY,OAAO;AAAA,IACnB,UAAU,OAAO;AAAA,IACjB,GAAI,OAAO,YAAY,IAAI,EAAE,cAAc,OAAO,YAAY,EAAE,IAAI,CAAC;AAAA,EACvE;AACF;AAIA,SAAS,iBACP,SACA,UACA,eACA,UACyB;AACzB,QAAM,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,UAAU,QAAQ;AACvD,MAAI,CAAC,UAAU,CAAC,cAAe,QAAO,CAAC;AACvC,QAAM,YACJ,eAAe,SAAS,OAAO,KAAK,GAAG,aAAa,KAAK;AAC3D,SAAO,EAAE,CAAC,aAAa,GAAG,UAAU;AACtC;AAEA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAQuB;AACrB,SACE,gBAAAA,OAAC,SAAI,WAAU,aACZ;AAAA,aAAS,gBAAAD,MAAC,SAAM,SAAS,IAAK,iBAAM;AAAA,IACrC,gBAAAC,OAAC,UAAO,OAAO,aAAa,eAAe,UAAU,UACnD;AAAA,sBAAAD,MAAC,iBAAc,IACb,0BAAAA,MAAC,eAAY,aAAY,oBAAmB,GAC9C;AAAA,MACA,gBAAAA,MAAC,iBACE,kBAAQ,IAAI,CAAC,MACZ,gBAAAA,MAAC,cAAyB,OAAO,EAAE,OAChC,YAAE,SADY,EAAE,KAEnB,CACD,GACH;AAAA,OACF;AAAA,IACC,eACC,gBAAAA,MAAC,OAAE,WAAU,iCAAiC,uBAAY;AAAA,KAE9D;AAEJ;AAKA,SAAS,eACP,UACA,eACmC;AACnC,QAAM,SAAU,WAAW,aAAa,KAAK,CAAC;AAG9C,MAAI,CAAC,cAAe,QAAO;AAC3B,SAAO,EAAE,CAAC,aAAa,GAAG,EAAE,gBAAgB,EAAE,QAAQ,KAAK,EAAE,GAAG,GAAG,OAAO;AAC5E;AAGA,SAAS,cACP,gBACA,UACA,SACA,eACA,MACgE;AAChE,QAAM,QAAQ,iBAAiB,gBAAgB,MAAM,aAAa;AAClE,MAAI,QAAQ,EAAG,QAAO,EAAE,OAAO,IAAI,OAAO,IAAI,WAAW,KAAK;AAC9D,SAAO;AAAA,IACL,OAAO,QAAQ,KAAK,GAAG,SAAS;AAAA,IAChC,OAAO,QAAQ,KAAK,GAAG,SAAS;AAAA,IAChC,WAAW,kBAAkB,SAAS,KAAK,CAAC;AAAA,EAC9C;AACF;AAEO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2C;AACzC,QAAM,EAAE,UAAU,UAAU,UAAU,IAAI,qBAAqB;AAC/D,QAAM,oBACJ,UAAU,2BAA2B;AAEvC,QAAM,WAAWE,SAAQ,MAAM,eAAe,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC;AAC3E,QAAM,gBAAgBA;AAAA,IACpB,MAAM,iBAAiB,cAAc;AAAA,IACrC,CAAC,cAAc;AAAA,EACjB;AACA,QAAM,UAAUA;AAAA,IACd,MAAM,aAAa,UAAU,aAAa;AAAA,IAC1C,CAAC,UAAU,aAAa;AAAA,EAC1B;AAEA,QAAM,OAAQ,SAAqC,CAAC;AACpD,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,SAAS,WAAW,EAAG,QAAO;AAElC,QAAM,cAAc,eAAe,UAAU,aAAa;AAE1D,SACE,gBAAAD,OAAC,SAAI,WAAU,aACb;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa,OAAO;AAAA,QACpB,UAAU,YAAY;AAAA,QACtB,UAAU,CAAC,aACT,SAAS,iBAAiB,SAAS,UAAU,eAAe,QAAQ,CAAC;AAAA;AAAA,IAEzE;AAAA,IACC,OAAO,aACN,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,OAAO;AAAA,QACd,aAAa;AAAA,QACb,SAAU,SAAS,WAAsB;AAAA,QACzC,aAAW;AAAA,QAEX,0BAAAA;AAAA,UAAC;AAAA;AAAA,YACC,QAAQ,OAAO;AAAA,YACf;AAAA,YACA;AAAA,YACA;AAAA,YACA,UAAU;AAAA,YACV,SAAS;AAAA,YACT,UAAU;AAAA,YAGV,UAAU;AAAA;AAAA,QACZ;AAAA;AAAA,IACF;AAAA,KAEJ;AAEJ;;;AChOA,SAAS,YAAY,sBAAsB;AAC3C,SAAS,MAAAG,YAAU;AA0CT,SACE,OAAAC,OADF,QAAAC,cAAA;AArCH,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoC;AAClC,QAAM,UAAU,mBAAmB,gBAAgB,SAAS,aAAa,CAAC,CAAC;AAC3E,QAAM,aAAa,SAAS,gBAAgB;AAC5C,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,OAAO,WAAW,SAAS;AAAA,MAC3B;AAAA,MACA,SAAS,SAAS;AAAA,MAElB,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,OAAO,UAAU,UAAa,UAAU,OAAO,KAAK,OAAO,KAAK;AAAA,UAChE,eAAe,CAAC,MAAM,SAAS,CAAC;AAAA,UAChC,QAAQ,MAAM,SAAS,IAAI,KAAK;AAAA,UAChC,UAAU,YAAY;AAAA,UACtB;AAAA,UACA,WAAWE,KAAG,cAAc,sBAAsB;AAAA,UAEjD,kBAAQ,IAAI,CAAC,MACZ,gBAAAD,OAAC,WAAoB,WAAU,mCAC7B;AAAA,4BAAAD,MAAC,kBAAe,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,IAAI,EAAE,KAAK,IAAI;AAAA,YACvD,EAAE;AAAA,eAFO,EAAE,KAGd,CACD;AAAA;AAAA,MACH;AAAA;AAAA,EACF;AAEJ;;;AClDA,SAAS,YAAAG,iBAAgB;AACzB,SAAS,MAAAC,YAAU;AA8CT,SACE,OAAAC,OADF,QAAAC,cAAA;AAzCH,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoC;AAClC,QAAM,UAAU,mBAAmB,gBAAgB,SAAS,aAAa,CAAC,CAAC;AAC3E,QAAM,SAAS,IAAI,IAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,IAAI,MAAM,IAAI,CAAC,CAAC;AACpE,QAAM,SAAS,CAAC,GAAW,OAAgB;AACzC,UAAM,OAAO,QACV,IAAI,CAAC,MAAM,EAAE,KAAK,EAClB,OAAO,CAAC,MAAO,MAAM,IAAI,KAAK,OAAO,IAAI,CAAC,CAAE;AAC/C,aAAS,IAAI;AAAA,EACf;AACA,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,OAAO,WAAW,SAAS;AAAA,MAC3B;AAAA,MACA,SAAS,SAAS;AAAA,MAElB,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,MAAK;AAAA,UACL,WAAWE;AAAA,YACT;AAAA,YACA,SAAS,gBAAgB,gBAAgB;AAAA,UAC3C;AAAA,UACA,QAAQ,MAAM,SAAS,IAAI,KAAK;AAAA,UAE/B,kBAAQ,IAAI,CAAC,MACZ,gBAAAD,OAAC,WAAoB,WAAU,mCAC7B;AAAA,4BAAAD;AAAA,cAACG;AAAA,cAAA;AAAA,gBACC,IAAI,GAAG,EAAE,IAAI,EAAE,KAAK;AAAA,gBACpB,SAAS,OAAO,IAAI,EAAE,KAAK;AAAA,gBAC3B,iBAAiB,CAAC,OAAO,OAAO,EAAE,OAAO,OAAO,IAAI;AAAA,gBACpD,UAAU,YAAY;AAAA;AAAA,YACxB;AAAA,YACC,EAAE;AAAA,eAPO,EAAE,KAQd,CACD;AAAA;AAAA,MACH;AAAA;AAAA,EACF;AAEJ;;;ACHM,gBAAAC,aAAA;AA9CN,IAAM,aAA6B;AAAA,EACjC,MAAM,CAAC,EAAE,QAAQ,CAAC,UAAU,MAAM,GAAG,QAAQ,CAAC,MAAM,MAAM,EAAE,CAAC;AAC/D;AAIA,SAAS,YAAY,MAAyD;AAC5E,QAAM,OAAO,KAAK,YAAY,QAAQ,KAAK,QAAQ,CAAC,GAAG,MAAM,YAAY;AACzE,SAAO,MAAM;AACf;AAIA,SAAS,kBAAkB,OAA8B;AACvD,QAAM,SAAU,MAAM,WAAW,aAAa,KAAK,CAAC;AAIpD,QAAM,YAAY,YAAY,MAAM,cAAc;AAClD,QAAM,SAAS,MAAM,WAAW,aAAa;AAC7C,SAAO;AAAA,IACL,GAAG,MAAM;AAAA,IACT,eAAe,UAAU;AAAA,IACzB,eAAe;AAAA,MACb,GAAG;AAAA,MACH,QAAQ,EAAE,cAAc,OAAO,GAAG,OAAO,OAAO;AAAA,MAChD,MAAM;AAAA,QACJ,cAAc;AAAA,QACd,GAAI,YAAY,EAAE,oBAAoB,UAAU,IAAI,CAAC;AAAA,QACrD,GAAG,OAAO;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,qBACd,OAC2B;AAC3B,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,MAAM;AAAA,MACf,OAAO,MAAM;AAAA,MACb,aAAa,MAAM;AAAA,MACnB,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM,SAAS;AAAA,MAExB,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACE,GAAG;AAAA,UACJ,UAAU,kBAAkB,KAAK;AAAA,UACjC,SAAS,EAAE,GAAG,MAAM,SAAS,SAAS,SAAS;AAAA;AAAA,MACjD;AAAA;AAAA,EACF;AAEJ;;;AC/DA;AAAA,EACE,UAAAC;AAAA,EACA,cAAAC;AAAA,EACA,UAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,eAAAC;AAAA,OACK;AACP,SAAS,QAAAC,OAAM,KAAAC,UAAS;AAsBpB,SAEI,OAAAC,OAFJ,QAAAC,cAAA;AAdJ,SAAS,KAAK;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMuB;AACrB,SACE,gBAAAA,OAACC,SAAA,EAAO,OAAO,SAAS,QAAW,eAAe,UAChD;AAAA,oBAAAF,MAACG,gBAAA,EAAc,cAAY,OAAO,WAChC,0BAAAH,MAACI,cAAA,EAAY,aAAa,MAAM,YAAY,GAAG,GACjD;AAAA,IACA,gBAAAJ,MAACK,gBAAA,EACE,gBAAM,IAAI,CAAC,MACV,gBAAAL,MAACM,aAAA,EAAyB,OAAO,EAAE,OAChC,YAAE,SADY,EAAE,KAEnB,CACD,GACH;AAAA,KACF;AAEJ;AAGA,SAAS,YAAY,OAAwD;AAC3E,SAAO,OAAO,QAAQ,MAAM,OAAO,cAAc,CAAC,CAAC,EAChD,OAAO,CAAC,CAAC,KAAK,CAAC,MAAM,QAAQ,MAAM,QAAQ,EAAE,SAAS,MAAM,EAC5D,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,EAAE;AAC9D;AAKA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAQuB;AACrB,QAAM,EAAE,CAAC,WAAW,GAAG,GAAG,GAAG,KAAK,IAAI;AACtC,SACE,gBAAAL,OAAC,SAAI,WAAU,mDACb;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO,UAAU;AAAA,UACf,CAAC,MAAM,EAAE,UAAU,eAAe,EAAE,EAAE,SAAS;AAAA,QACjD;AAAA,QACA,UAAU,CAAC,SAAS,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC;AAAA,QACnD,WAAU;AAAA;AAAA,IACZ;AAAA,IACA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,QACP,UAAU,CAAC,MAAM,IAAI,EAAE,GAAG,OAAO,CAAC,WAAW,GAAG,EAAE,CAAC;AAAA,QACnD,WAAU;AAAA;AAAA,IACZ;AAAA,IACC,CAAC,UACA,gBAAAA;AAAA,MAACO;AAAA,MAAA;AAAA,QACC,OAAM;AAAA,QACN,eAAa;AAAA,QACb,SAAS,MAAM,IAAI,IAAI;AAAA,QAEvB,0BAAAP,MAACQ,IAAA,EAAE;AAAA;AAAA,IACL;AAAA,KAEJ;AAEJ;AAIA,SAAS,aAAa,OAAoB;AACxC,QAAM,EAAE,OAAO,UAAU,UAAU,QAAQ,IAAI;AAC/C,QAAM,aAAa,MAAM,eAAe;AAGxC,QAAM,UAAU;AAAA,IACd,cAAc,CAAC;AAAA,IACf,SAAS,aAAa,CAAC;AAAA,EACzB;AACA,QAAM,QACJ,SAAS,OAAO,UAAU,WAAY,QAAoB,CAAC;AAC7D,QAAM,YAAY,YAAY,KAAK;AACnC,QAAM,OAAO,UAAU,OAAO,CAAC,MAAM,EAAE,EAAE,SAAS,MAAM;AACxD,QAAM,SAAS,YAAY;AAC3B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,CAAC,UAAU,KAAK,SAAS,KAAK,QAAQ,SAAS;AAAA,EACzD;AACF;AAEO,SAAS,oBAAoB,OAAwC;AAC1E,QAAM,EAAE,IAAI,UAAU,OAAO,WAAW,QAAQ,IAAI;AACpD,QAAM,EAAE,SAAS,OAAO,WAAW,MAAM,QAAQ,OAAO,IACtD,aAAa,KAAK;AACpB,QAAM,MAAM,CAAC,SACX,SAAS,OAAO,KAAK,IAAI,EAAE,SAAS,OAAO,MAAS;AAEtD,SACE,gBAAAR;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT;AAAA,MACA,OAAO,WAAW,SAAS;AAAA,MAC3B,SAAS,SAAS;AAAA,MAElB,0BAAAC,OAAC,SAAI,WAAU,eACZ;AAAA,eAAO,KAAK,KAAK,EAAE,SAAS,KAC3B,gBAAAD,MAAC,SAAI,WAAU,8BACZ,iBAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,MAAM,MACtC,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,aAAa;AAAA,YACb;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,UAPK;AAAA,QAQP,CACD,GACH;AAAA,QAED,UACC,gBAAAC;AAAA,UAACQ;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS,MAAM,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,EAAE,MAAM,CAAC;AAAA,YAElE;AAAA,8BAAAT,MAACU,OAAA,EAAK,WAAU,eAAc;AAAA,cAAE;AAAA;AAAA;AAAA,QAElC;AAAA,SAEJ;AAAA;AAAA,EACF;AAEJ;;;AC1KA;AAAA,EACE,aAAAC;AAAA,EACA,qBAAAC;AAAA,EACA;AAAA,EACA,qBAAAC;AAAA,EACA;AAAA,OACK;AAgBA,IAAM,qBAAgC;AAAA,EAC3C,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,OAAO;AAAA;AAAA,IACP,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,EACR;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,EACX;AAAA,EACA,SAAS;AAAA,IACP,SAAS;AAAA;AAAA,EACX;AAAA,EACA,SAAS;AAAA,IACP,SAAS;AAAA,EACX;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,EACX;AACF;AAaA,SAAS,oBACP,YACA,gBACA,UACe;AAEf,MAAI,SAAS,UAAU,GAAG;AACxB,WAAO,SAAS,UAAU;AAAA,EAC5B;AAIA,QAAM,OAAO,aAAa,cAAc;AACxC,QAAM,qBACJ,mBAAmB,IAAI,IAAI,WAAW,YAAY,CAAC;AACrD,MAAI,sBAAsB,SAAS,kBAAkB,GAAG;AACtD,WAAO,SAAS,kBAAkB;AAAA,EACpC;AAEA,SAAO;AACT;AAQA,SAAS,cACP,gBACA,UACsB;AACtB,QAAM,cAAc,eAAe,aAAa;AAChD,QAAM,iBAAiB,eAAe,cAAc;AAEpD,MAAI,CAAC,eAAe,CAAC,eAAgB,QAAO;AAE5C,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,MACL,GAAI,eAAe,EAAE,eAAe,YAAY;AAAA,MAChD,GAAI,kBAAkB,EAAE,gBAAgB,eAAe;AAAA,IACzD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAI,eAAe,EAAE,eAAe,YAAY;AAAA;AAAA,IAChD,GAAG;AAAA;AAAA,IACH,gBAAgB;AAAA,MACd,GAAI,kBAAkB,CAAC;AAAA;AAAA,MACvB,GAAI,SAAS,cAAc,KAAK,CAAC;AAAA;AAAA,IACnC;AAAA,EACF;AACF;AAqBA,SAAS,oBACP,UACA,gBACA,UACe;AACf,MAAI,OAAO,aAAa,WAAY,QAAO;AAC3C,MAAI,OAAO,aAAa;AACtB,WAAO,oBAAoB,UAAU,gBAAgB,QAAQ;AAC/D,SAAO;AACT;AAGA,SAAS,oBAAoB,QAAqC;AAChE,SACE,OAAO,SAAS,WAChB,OAAO,OAAO,SAAS,YACvB,CAAC,CAAC,OAAO,OAAO;AAEpB;AAGA,SAAS,oBAAoB,QAAqC;AAChE,SACE,OAAO,SAAS,WAChB,OAAO,OAAO,SAAS,YACvB,CAAC,MAAM,QAAQ,OAAO,OAAO,IAAI;AAErC;AAGA,SAAS,kBAAkB,QAAqC;AAC9D,QAAM,QAAS,OACZ;AACH,SACE,OAAO,SAAS,YAChB,CAAC,OAAO,cACR,OAAO,UAAU,YACjB,UAAU,QACT,MAA6B,SAAS;AAE3C;AAGA,SAAS,kBAAkB,QAAqC;AAC9D,SAAO,OAAO,SAAS,WAAW,MAAM,QAAQ,OAAO,OAAO,IAAI;AACpE;AAGA,SAAS,aAAa,QAAqC;AACzD,SAAO,OAAO,SAAS,YAAY,OAAO,SAAS,WAAW,CAAC,CAAC,OAAO;AACzE;AAGA,SAAS,eAAe,UAA0B,YAA4B;AAC5E,SAAO,SAAS,UAAU,KAAK,SAAS,iBAAiB;AAC3D;AAIA,SAAS,iBAAiB,QAAoC;AAC5D,MAAI,OAAO,WAAY,QAAO;AAC9B,MAAI,kBAAkB,MAAM,EAAG,QAAO;AACtC,SAAO;AACT;AAGA,SAAS,gBAAgB,QAA2C;AAClE,MAAI,oBAAoB,MAAM,EAAG,QAAO;AACxC,MAAI,kBAAkB,MAAM,EAAG,QAAO;AACtC,MAAI,oBAAoB,MAAM,EAAG,QAAO;AACxC,SAAO;AACT;AAGA,SAAS,2BACP,QACA,UACe;AACf,MAAI,QAAQ,MAAM,EAAG,QAAO,eAAe,UAAU,aAAa;AAClE,MAAID,mBAAkB,MAAM;AAC1B,WAAO,eAAe,UAAU,gBAAgB;AAClD,MAAIC,mBAAkB,MAAM,EAAE,SAAS;AACrC,WAAO,eAAe,UAAU,cAAc;AAEhD,MAAIF,WAAU,MAAM,KAAK,aAAa,MAAM;AAC1C,WAAO,eAAe,UAAU,kBAAkB;AACpD,MAAI,OAAO,SAAS;AAClB,WAAO,eAAe,UAAU,iBAAiB,MAAM,CAAC;AAC1D,QAAM,cAAc,gBAAgB,MAAM;AAC1C,SAAO,cAAc,eAAe,UAAU,WAAW,IAAI;AAC/D;AAGA,SAAS,sBACP,QACA,UACQ;AACR,QAAM,OAAO,aAAa,MAAM;AAChC,QAAM,SAAS,OAAO;AACtB,QAAM,aACH,UAAU,mBAAmB,IAAI,IAAI,MAAM,KAC5C,mBAAmB,IAAI,GAAG,WAC1B;AACF,SAAO,SAAS,UAAU,KAAK,SAAS,iBAAiB;AAC3D;AAEO,SAAS,cACd,gBACA,UACA,UACQ;AACR,QAAM,oBAAoB,cAAc,gBAAgB,QAAQ;AAChE,QAAM,WAAW,oBAAoB,aAAa;AAClD,MAAI,UAAU;AACZ,UAAM,WAAW,oBAAoB,UAAU,gBAAgB,QAAQ;AACvE,QAAI,SAAU,QAAO;AAAA,EACvB;AACA,SACE,2BAA2B,gBAAgB,QAAQ,KACnD,sBAAsB,gBAAgB,QAAQ;AAElD;AAkBO,SAAS,wBAAwB,MAAsB;AAC5D,SAAO,mBAAmB,IAAI,GAAG,WAAW;AAC9C;;;ACpMO,IAAM,kBAAkC;AAAA;AAAA,EAE7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,eAAe;AAAA,EACf,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,UAAU;AAAA,EACV,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,SAAS;AAAA,EACT,UAAU;AAAA,EACV,OAAO;AAAA,EACP,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,kBAAkB;AACpB;;;ACrIA,SAAS,UAAAG,SAAQ,aAAAC,YAAW,eAAAC,oBAAmB;AAC/C,SAAS,UAAAC,gBAAc;AAyCf,SAUI,OAAAC,OAVJ,QAAAC,cAAA;AArCD,SAAS,4BAA4B;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA+C;AAC7C,QAAM,iBAAiB;AACvB,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,MAAM,eAAe,OAAO;AAElC,QAAM,aAAa,eAAe,UAAU,WAAW;AAEvD,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,YAAU;AAAA,MACV,OAAO;AAAA,QACL,SAAS;AAAA,QACT,qBAAqB;AAAA,QACrB,KAAK,GAAG,GAAG;AAAA,QACX;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,QACA,aACC,gBAAAA,OAAC,SAAI,WAAU,6CACb;AAAA,0BAAAD;AAAA,YAACE;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,UAAU,YAAY,UAAU;AAAA,cAChC,SAAS;AAAA,cACT,OAAM;AAAA,cACN,WAAU;AAAA,cAEV,0BAAAF,MAACG,YAAA,EAAU,WAAU,WAAU;AAAA;AAAA,UACjC;AAAA,UACA,gBAAAH;AAAA,YAACE;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,UAAU,YAAY,SAAS,QAAQ;AAAA,cACvC,SAAS;AAAA,cACT,OAAM;AAAA,cACN,WAAU;AAAA,cAEV,0BAAAF,MAACI,cAAA,EAAY,WAAU,WAAU;AAAA;AAAA,UACnC;AAAA,WACF;AAAA,QAED,aACC,gBAAAJ;AAAA,UAACE;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,MAAK;AAAA,YACL;AAAA,YACA,SAAS;AAAA,YACT,OAAM;AAAA,YACN,WAAU;AAAA,YAEV,0BAAAF,MAACK,SAAA,EAAO,WAAU,eAAc;AAAA;AAAA,QAClC;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;ACnFA,SAAgB,YAAAC,kBAAgB;AAChC,SAAS,MAAM,UAAU,aAAa,mBAAmB;;;ACIzD,SAAS,mBAAmB;AAiBtB,gBAAAC,aAAA;AAfC,SAAS,gBAAgB;AAAA,EAC9B;AACF,GAE8B;AAC5B,MAAI,UAAU,EAAG,QAAO;AACxB,QAAM,QACJ,UAAU,IAAI,4BAA4B,GAAG,KAAK;AACpD,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,OAAO;AAAA,MACP,WAAU;AAAA,MAEV,0BAAAA,MAAC,eAAY,WAAU,eAAc;AAAA;AAAA,EACvC;AAEJ;;;ADXU,SAEE,OAAAC,OAFF,QAAAC,cAAA;AATH,SAAS,kBAAkB;AAAA,EAChC;AACF,GAAiD;AAC/C,QAAM,CAAC,QAAQ,SAAS,IAAIC,WAAiB,OAAO,CAAC,EAAE,GAAG;AAC1D,QAAM,QAAQ,OAAO,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,IAAI,SAAS,OAAO,CAAC,EAAE;AACxE,SACE,gBAAAD,OAAC,QAAK,OAAc,eAAe,WACjC;AAAA,oBAAAD,MAAC,YAAS,WAAU,QACjB,iBAAO,IAAI,CAAC,MACX,gBAAAC,OAAC,eAAwB,OAAO,EAAE,KAAK,WAAU,WAC9C;AAAA,QAAE;AAAA,MACH,gBAAAD,MAAC,mBAAgB,OAAO,EAAE,YAAY;AAAA,SAFtB,EAAE,GAGpB,CACD,GACH;AAAA,IACC,OAAO,IAAI,CAAC,MACX,gBAAAA,MAAC,eAAwB,OAAO,EAAE,KAAK,WAAU,aAC9C,YAAE,WADa,EAAE,GAEpB,CACD;AAAA,KACH;AAEJ;;;AEvBA,SAAgB,YAAAG,kBAAgB;AAChC;AAAA,EACE,UAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAgBO,gBAAAC,OAGA,QAAAC,cAHA;AAZP,SAAS,qBAAqB;AAAA,EACnC;AACF,GAAiD;AAC/C,QAAM,CAAC,QAAQ,SAAS,IAAIC,WAAiB,OAAO,CAAC,EAAE,GAAG;AAC1D,QAAM,QAAQ,OAAO,KAAK,CAAC,MAAM,EAAE,QAAQ,MAAM,IAAI,SAAS,OAAO,CAAC,EAAE;AACxE,QAAM,SAAS,UAAU,OAAO,OAAO,SAAS,CAAC,EAAE;AACnD,SACE,gBAAAD,OAAC,WAAQ,OAAc,eAAe,WACpC;AAAA,oBAAAD,MAAC,eAAY,WAAU,cACpB,iBAAO,IAAI,CAAC,MACX,gBAAAC,OAAC,eAAwB,OAAO,EAAE,KAChC;AAAA,sBAAAA,OAAC,kBACC;AAAA,wBAAAD,MAAC,oBAAiB;AAAA,QAGlB,gBAAAC,OAAC,gBAAa,WAAU,oCACrB;AAAA,YAAE;AAAA,UACH,gBAAAD,MAAC,mBAAgB,OAAO,EAAE,YAAY;AAAA,WACxC;AAAA,SACF;AAAA,MACA,gBAAAA,MAAC,oBAAiB;AAAA,SAVF,EAAE,GAWpB,CACD,GACH;AAAA,IACC,OAAO,IAAI,CAAC,MACX,gBAAAA,MAAC,kBAA2B,OAAO,EAAE,KAAK,WAAU,aACjD,YAAE,WADgB,EAAE,GAEvB,CACD;AAAA,IACD,gBAAAC,OAAC,SAAI,WAAU,6BACb;AAAA,sBAAAD,MAAC,eAAY,SAAO,MAClB,0BAAAA,MAACG,UAAA,EAAO,SAAQ,WAAU,MAAK,MAAK,kBAEpC,GACF;AAAA,MAEC,CAAC,UACA,gBAAAH,MAAC,eAAY,SAAO,MAClB,0BAAAA,MAACG,UAAA,EAAO,MAAK,MAAK,kBAAI,GACxB;AAAA,OAEJ;AAAA,KACF;AAEJ;;;AChDU,SAEE,OAAAC,OAFF,QAAAC,cAAA;AAVH,SAAS,sBAAsB;AAAA,EACpC;AACF,GAAiD;AAC/C,SACE,gBAAAD,MAAC,SAAI,WAAU,aACZ,iBAAO,IAAI,CAAC,MACX,gBAAAC;AAAA,IAAC;AAAA;AAAA,MAEC,WAAU;AAAA,MAEV;AAAA,wBAAAA,OAAC,YAAO,WAAU,mFACf;AAAA,YAAE;AAAA,UACH,gBAAAD,MAAC,mBAAgB,OAAO,EAAE,YAAY;AAAA,WACxC;AAAA,QACA,gBAAAA,MAAC,SAAI,WAAU,aAAa,YAAE,SAAQ;AAAA;AAAA;AAAA,IAPjC,EAAE;AAAA,EAQT,CACD,GACH;AAEJ;;;ACDO,IAAM,oBAAsC;AAAA,EACjD,mBAAmB;AAAA,EACnB;AAAA,EACA,qBAAqB;AAAA,EACrB,yBAAyB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AACF;AAQO,SAAS,iBAAiB,SAAqC;AACpE,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,OAAO,QAAQ,OAAO,CAAC,EAAE,YAAY,IAAI,QAAQ,MAAM,CAAC;AAC9D,SAAO,GAAG,IAAI;AAChB;;;AC3CA,SAAgB,WAAAE,gBAAe;AAE/B,SAAS,eAAe;AACxB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA0FE,gBAAAC,aAAA;AAzDT,SAAS,kBACP,eACA,UACA,UACiB;AACjB,QAAM,iBAAiB,SAAS,cAAc,KAAK,CAAC;AACpD,QAAM,eAAe,WAAW,cAAc,KAAK,CAAC;AACpD,SAAO,EAAE,GAAG,eAAe,GAAG,gBAAgB,GAAG,aAAa;AAChE;AAGA,SAAS,sBACP,OACA,SACA,mBACQ;AACR,MAAI,sBAAsB,MAAO,QAAO;AACxC,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,MAAI,YAAY,MAAO,QAAO;AAC9B,SAAO;AACT;AAKA,IAAM,oBAAoB;AAAA,EACxB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,MAAM;AACR;AAWA,SAAS,gBACP,QACA,UACA,eACoB;AACpB,QAAM,YAAY,WAAW,YAAY,KAAK,cAAc;AAC5D,MAAI,aAAa,EAAE,aAAa,oBAAoB;AAClD;AAAA,MACE,kDAAkD,SAAS;AAAA,IAC7D;AAAA,EACF;AACA,QAAM,QACJ,aAAa,aAAa,oBACrB,YACD;AACN,MAAI,UAAU,OAAQ,QAAO;AAC7B,SAAO,gBAAAA,MAAC,SAAI,WAAW,kBAAkB,KAAK,GAAI,kBAAO;AAC3D;AAGA,SAAS,wBACP,UACA,UACsE;AACtE,SAAO;AAAA,IACL,aAAa,WAAW,kBAAkB,KAAK,iBAAiB,QAAQ;AAAA,IACxE,aACE,WAAW,kBAAkB,KAAK,oBAAoB,QAAQ;AAAA,EAClE;AACF;AAGA,SAAS,kBACP,cACA,eACA,UACA,UACA;AACA,SAAO;AAAA,IACL,UAAU,aAAa,YAAY,cAAc,YAAY;AAAA,IAC7D,UAAU,aAAa,YAAY,cAAc,YAAY;AAAA,EAC/D;AACF;AAEO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB;AAAA,EACA,WAAW;AAAA,EACX;AACF,GAAsD;AAGpD,QAAM,WAAWC,SAAQ,MAAM,mBAAmB,QAAQ,GAAG,CAAC,QAAQ,CAAC;AACvE,QAAM,QAAQ,cAAc,WAAW,QAAQ;AAC/C,QAAM,EAAE,aAAa,YAAY,IAAI;AAAA,IACnC;AAAA,IACA;AAAA,EACF;AAEA,QAAM,SAAS,cAAc,UAAU,UAAU,QAAQ;AACzD,QAAM,gBAAgB,kBAAkB,eAAe,UAAU,QAAQ;AAEzE,MAAI,cAAc,OAAQ,QAAO;AAEjC,QAAM,eAAe,WAAW,cAAc,KAAK,CAAC;AACpD,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA,WAAW,YAAY;AAAA,IACvB,cAAc;AAAA,EAChB;AACA,QAAM,SACJ,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,IAAI,GAAG,QAAQ,IAAI,SAAS;AAAA,MAC5B,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,MAChB,SAAS;AAAA,MACT;AAAA,MACA;AAAA;AAAA,EACF;AAGF,SAAO,gBAAgB,QAAQ,UAAU,aAAa;AACxD;;;ACxLA,SAAS,YAAAE,YAAU,aAAAC,YAAW,WAAAC,WAAS,eAAAC,cAAa,UAAAC,eAAc;AAClE,SAAS,eAAe;AAExB;AAAA,EACE,qBAAAC;AAAA,EACA,uBAAAC;AAAA,EACA;AAAA,EACA,uBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACrBP,SAAS,uBAAAC,4BAA2B;;;ACPpC,SAAS,2BAA2B;AAU7B,SAAS,OAAO,GAA4C;AACjE,MAAI,MAAM,OAAW,QAAO,CAAC;AAC7B,QAAM,MAAM,MAAM,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC;AACrC,SAAO,IAAI,IAAI,CAAC,SAAU,OAAO,SAAS,WAAW,EAAE,MAAM,KAAK,IAAI,IAAK;AAC7E;AAGO,SAAS,YAAY,OAAuB;AACjD,SAAO,MAAM,QAAQ,MAAM,IAAI,EAAE,QAAQ,OAAO,IAAI;AACtD;AAGO,SAAS,aAAa,WAA2B;AACtD,SAAO,IAAI,YAAY,SAAS,CAAC;AACnC;AAIO,SAAS,iBACd,WACA,QACA,UACiB;AACjB,QAAM,WAAW,oBAAoB,MAAM,EAAE,SAAS,KAAK,CAAC;AAC5D,SAAO;AAAA,IACL,SAAS,SAAS,IAAI,eAAe,KAAK,SAAS,eAAe;AAAA,EACpE;AACF;AAIO,SAAS,cAAc,QAAiB,SAA+B;AAC5E,MAAI,UAAU,QAAQ,WAAW,GAAI,QAAO,CAAC;AAC7C,MAAI,OAAO,WAAW,SAAU,QAAO,CAAC,EAAE,SAAS,SAAS,OAAO,CAAC;AACpE,MAAI,MAAM,QAAQ,MAAM,EAAG,QAAO;AAClC,SAAO,CAAC;AACV;;;ADvBA,SAAS,YAAY,UAA6B,MAAuB;AACvE,SAAO,CAAC,EACN,SAAS,QAAQ,IAAI,KACrB,SAAS,aAAa,IAAI,KAC1B,SAAS,OAAO,IAAI,KACpB,SAAS,YAAY,IAAI;AAE7B;AAEA,SAAS,iBACP,MACA,MACA,UACO;AACP,QAAM,aAAa;AAAA,IACjB,GAAG,OAAO,KAAK,SAAS,SAAS,CAAC,CAAC;AAAA,IACnC,GAAG,OAAO,KAAK,SAAS,cAAc,CAAC,CAAC;AAAA,IACxC,GAAG,OAAO,KAAK,SAAS,QAAQ,CAAC,CAAC;AAAA,IAClC,GAAG,OAAO,KAAK,SAAS,aAAa,CAAC,CAAC;AAAA,EACzC;AACA,QAAM,IAAI;AAAA,IACR,WAAW,IAAI,eAAe,IAAI,mBAAmB,WAAW,KAAK,IAAI,CAAC;AAAA,EAC5E;AACF;AAEA,SAAS,aACP,WACA,MACA,UACA,UACA,QACA,KACM;AACN,QAAM,OAAO,iBAAiB,WAAW,QAAQ,QAAQ;AACzD,MAAI,KAAK,WAAW,EAAG;AACvB,QAAM,UAAU,aAAa,SAAS;AACtC,QAAM,QAAQ,KAAK,SAAS;AAC5B,aAAW,OAAO,MAAM;AACtB,QAAI,CAAC,YAAY,UAAU,IAAI,IAAI,GAAG;AACpC,uBAAiB,SAAS,IAAI,MAAM,QAAQ;AAAA,IAC9C;AACA,UAAM,KAAK,SAAS,QAAQ,IAAI,IAAI;AACpC,QAAI,CAAC,GAAI;AACT,UAAM,MAAwB;AAAA,MAC5B,UAAU;AAAA,MACV,MAAM;AAAA,MACN,MAAM,IAAI;AAAA,IACZ;AACA,QAAI,KAAK,GAAG,cAAc,GAAG,OAAO,GAAG,GAAG,OAAO,CAAC;AAAA,EACpD;AACF;AAEA,SAAS,YACP,MACA,UACA,QACA,KACM;AACN,aAAW,OAAO,OAAO,OAAO,eAAe,CAAC,GAAG;AACjD,QAAI,CAAC,YAAY,UAAU,IAAI,IAAI,GAAG;AACpC,uBAAiB,QAAQ,IAAI,MAAM,QAAQ;AAAA,IAC7C;AACA,UAAM,KAAK,SAAS,OAAO,IAAI,IAAI;AACnC,QAAI,CAAC,GAAI;AACT,UAAM,MAAwB,EAAE,UAAU,MAAM,MAAM,IAAI,MAAM,IAAI,KAAK;AACzE,QAAI,KAAK,GAAG,GAAG,MAAM,GAAG,CAAC;AAAA,EAC3B;AACF;AAOO,SAAS,cACd,QACA,MACA,UACA,UACA,uBACc;AACd,QAAM,MAAoB,CAAC;AAC3B,MAAI,CAAC,SAAU,QAAO;AAKtB,aAAW,aAAa,OAAO,KAAKC,qBAAoB,MAAM,CAAC,GAAG;AAChE,iBAAa,WAAW,MAAM,UAAU,UAAU,QAAQ,GAAG;AAAA,EAC/D;AACA,MAAI,uBAAuB;AACzB,gBAAY,MAAM,UAAU,QAAQ,GAAG;AAAA,EACzC;AACA,SAAO;AACT;;;AE7GA,SAAS,aAAAC,YAAW,WAAAC,WAAS,UAAAC,SAAQ,YAAAC,kBAAgB;AACrD,SAAS,uBAAAC,4BAA2B;AA2BpC,SAAS,MAAM,OAAwB;AACrC,MAAI;AACF,WAAO,KAAK,UAAU,KAAK,KAAK;AAAA,EAClC,QAAQ;AACN,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;AAEA,SAAS,uBACP,QACA,MACA,UACA,UACA,KACM;AACN,aAAW,aAAa,OAAO,KAAKC,qBAAoB,MAAM,CAAC,GAAG;AAChE,UAAM,OAAO,iBAAiB,WAAW,QAAQ,QAAQ;AACzD,UAAM,UAAU,aAAa,SAAS;AACtC,UAAM,QAAQ,KAAK,SAAS;AAC5B,eAAW,OAAO,MAAM;AACtB,YAAM,KAAK,SAAS,IAAI,IAAI;AAC5B,UAAI,CAAC,GAAI;AAET,YAAM,MAAwB;AAAA,QAC5B,UAAU;AAAA,QACV,MAAM;AAAA,QACN,MAAM,IAAI;AAAA,MACZ;AACA,UAAI,KAAK;AAAA,QACP,IAAI,cAAc,OAAO,IAAI,IAAI,IAAI;AAAA,QACrC,KAAK,MAAM,KAAK;AAAA,QAChB;AAAA,QACA,KAAK,MAAM,GAAG,OAAO,GAAG;AAAA,MAC1B,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,SAAS,sBACP,QACA,MACA,UACA,KACM;AACN,aAAW,OAAO,OAAO,OAAO,eAAe,CAAC,GAAG;AACjD,UAAM,KAAK,SAAS,IAAI,IAAI;AAC5B,QAAI,CAAC,GAAI;AACT,UAAM,MAAwB,EAAE,UAAU,MAAM,MAAM,IAAI,MAAM,IAAI,KAAK;AACzE,UAAM,QAAQ,IAAI,YACd,IAAI,UAAU,IAAI,CAAC,MAAM,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,IACjD,MAAM,IAAI;AACd,QAAI,KAAK;AAAA,MACP,IAAI,aAAa,IAAI,IAAI;AAAA,MACzB,KAAK;AAAA,MACL,SAAS;AAAA,MACT,KAAK,MAAM,GAAG,MAAM,GAAG;AAAA,IACzB,CAAC;AAAA,EACH;AACF;AAEA,SAAS,kBACP,QACA,MACA,UACA,UACA,QACa;AACb,QAAM,MAAmB,CAAC;AAC1B,MAAI,SAAS,YAAY;AACvB,2BAAuB,QAAQ,MAAM,SAAS,YAAY,UAAU,GAAG;AAAA,EACzE;AACA,MAAI,SAAS,aAAa,QAAQ;AAChC,0BAAsB,QAAQ,MAAM,SAAS,WAAW,GAAG;AAAA,EAC7D;AACA,SAAO;AACT;AASO,SAAS,mBACd,QACA,MACA,UACA,UACA,QAC0B;AAC1B,QAAM,CAAC,SAAS,UAAU,IAAIC,WAAgC,CAAC,CAAC;AAGhE,QAAM,aAAaC,QAA+B,CAAC,CAAC;AAEpD,QAAM,aACJ,aAAa,SAAS,cAAc,SAAS,aACzC,kBAAkB,QAAQ,MAAM,UAAU,UAAU,MAAM,IAC1D,CAAC;AACP,QAAM,UAAU,IAAI,IAAI,WAAW,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AACnD,QAAM,YAAY,WAAW,IAAI,CAAC,MAAM,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,KAAK,GAAG;AAEpE,EAAAC,WAAU,MAAM;AACd,eAAW,KAAK,YAAY;AAC1B,UAAI,WAAW,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAK;AACxC,iBAAW,QAAQ,EAAE,EAAE,IAAI,EAAE;AAE7B,iBAAW,CAAC,OAAO;AAAA,QACjB,GAAG;AAAA,QACH,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,SAAS,MAAM,QAAQ,CAAC,EAAE;AAAA,MAClD,EAAE;AACF,YAAM,SAAS,CAAC,WAAyB;AACvC,YAAI,WAAW,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAK;AACxC,mBAAW,CAAC,OAAO;AAAA,UACjB,GAAG;AAAA,UACH,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,SAAS,OAAO,OAAO;AAAA,QAC/C,EAAE;AAAA,MACJ;AACA,QAAE,IAAI,EACH,KAAK,CAAC,MAAM,OAAO,cAAc,GAAG,EAAE,OAAO,CAAC,CAAC,EAC/C,MAAM,MAAM,OAAO,CAAC,CAAC,CAAC;AAAA,IAC3B;AAAA,EAEF,GAAG,CAAC,SAAS,CAAC;AAGd,QAAM,UAAU,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG;AAC5C,EAAAA,WAAU,MAAM;AACd,eAAW,CAAC,MAAM;AAChB,YAAM,OAAO,OAAO,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,MAAM,QAAQ,IAAI,EAAE,CAAC;AAC/D,aAAO,KAAK,WAAW,OAAO,KAAK,CAAC,EAAE,SAClC,IACA,OAAO,YAAY,IAAI;AAAA,IAC7B,CAAC;AACD,eAAW,MAAM,OAAO,KAAK,WAAW,OAAO,GAAG;AAChD,UAAI,CAAC,QAAQ,IAAI,EAAE,EAAG,QAAO,WAAW,QAAQ,EAAE;AAAA,IACpD;AAAA,EAEF,GAAG,CAAC,OAAO,CAAC;AAEZ,MAAI,eAAe;AACnB,QAAM,YAA0B,CAAC;AACjC,aAAW,KAAK,YAAY;AAC1B,UAAM,QAAQ,QAAQ,EAAE,EAAE;AAC1B,QAAI,CAAC,SAAS,MAAM,QAAQ,EAAE,OAAO,MAAM,SAAS;AAClD,qBAAe;AACf;AAAA,IACF;AACA,cAAU,KAAK,GAAG,MAAM,MAAM;AAAA,EAChC;AAIA,QAAM,WAAW,UACd,IAAI,CAAC,MAAM,GAAG,EAAE,OAAO,KAAS,EAAE,OAAO,EAAE,EAC3C,KAAK,GAAG;AAEX,QAAM,cAAcC,UAAQ,MAAM,WAAW,CAAC,QAAQ,CAAC;AAEvD,SAAO,EAAE,aAAa,aAAa;AACrC;;;ACnMO,SAAS,gBACd,YACA,YACgC;AAChC,QAAM,aAAa,OAAO,QAAQ,UAAU;AAE5C,MAAI,CAAC,cAAc,WAAW,WAAW,EAAG,QAAO;AAEnD,QAAM,WAAW,IAAI,IAAI,UAAU;AACnC,QAAM,MAAM,IAAI,IAAI,UAAU;AAE9B,QAAM,UAA0C,CAAC;AACjD,aAAW,QAAQ,YAAY;AAC7B,UAAM,OAAO,IAAI,IAAI,IAAI;AACzB,QAAI,KAAM,SAAQ,KAAK,CAAC,MAAM,IAAI,CAAC;AAAA,EACrC;AAEA,QAAM,YAAY,WAAW,OAAO,CAAC,CAAC,IAAI,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC;AACnE,SAAO,CAAC,GAAG,SAAS,GAAG,SAAS;AAClC;;;AJmBA,IAAM,oBAAoB,oBAAI,IAAI,CAAC,QAAQ,QAAQ,WAAW,CAAC;AAK/D,SAAS,kBAAkB,UAAuC;AAChE,SACE,SAAS,WAAW,UAAa,kBAAkB,IAAI,SAAS,MAAM;AAE1E;AAOA,SAAS,iBACP,WACA,YACS;AACT,QAAM,WAAW,WAAW,SAAS;AACrC,MAAI,CAAC,SAAU,QAAO;AAItB,SACE,SAAS,SAAS,aAClBC,mBAAkB,QAAQ,KAC1B,kBAAkB,QAAQ,KAC1B,SAAS,SAAS,UAClB,SAAS,OAAO,SAAS,UACxB,SAAS,cAAc,GACpB,cAAc;AAEtB;AAQA,SAAS,sBACP,SACA,cACA,aACA,qBAKO;AACP,QAAM,WAAW,OAAO,KAAK,OAAO,EAAE;AACtC,QAAM,YAAY,OAAO,KAAK,YAAY,EAAE;AAE5C,MAAI,CAAC,eAAe,WAAW,GAAG;AAChC,UAAM,cAAc,OAAO;AAAA,MACzB,OAAO,QAAQ,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,oBAAoB,SAAS,CAAC,CAAC;AAAA,IACzE;AACA,UAAM,YAAY,OAAO;AAAA,MACvB,OAAO,QAAQ,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,oBAAoB,SAAS,CAAC,CAAC;AAAA,IAC1E;AACA,WAAO,EAAE,uBAAuB,MAAM,aAAa,UAAU;AAAA,EAC/D;AAEA,MAAI,eAAe,WAAW,WAAW;AACvC,UAAM,cAAc,OAAO;AAAA,MACzB,OAAO,QAAQ,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,oBAAoB,SAAS,CAAC,CAAC;AAAA,IACzE;AACA,UAAM,YAAY,OAAO;AAAA,MACvB,OAAO,QAAQ,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,oBAAoB,SAAS,CAAC,CAAC;AAAA,IAC1E;AACA,WAAO,EAAE,uBAAuB,OAAO,aAAa,UAAU;AAAA,EAChE;AAEA,SAAO;AACT;AAQA,SAAS,iBAAiB,MAMT;AACf,QAAM,EAAE,QAAQ,MAAM,YAAY,aAAa,YAAY,IAAI;AAE/D,QAAM,OAAO,iBAAiB,QAAQ,iBAAiB,IAAI,CAAC,EAAE;AAC9D,SAAO,iBAAiB,MAAM,YAAY,aAAa,eAAe,CAAC,CAAC;AAC1E;AAwFO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,cAAc;AAAA,EACd,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AACX,GAA8C;AAG5C,QAAM,oBAAoBC;AAAA,IACxB,MAAM,YAAY,QAAQ,WAAW;AAAA,IACrC,CAAC,QAAQ,WAAW;AAAA,EACtB;AAOA,QAAM,OAAOC;AAAA,IAA8B,MACzC;AAAA,MACEC,qBAAoB,MAAM,iBAAiB;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,EAAE,CAAC;AAEH,QAAM,CAAC,cAAc,eAAe,IAAID;AAAA,IACtC,MAAM;AAAA,EACR;AACA,QAAM,CAAC,yBAAyB,0BAA0B,IAAIA,WAAS,KAAK;AAE5E,QAAM,CAAC,eAAe,gBAAgB,IAAIA;AAAA,IACxC,MAAM;AACJ,YAAM,QAAQE,qBAAoB,iBAAiB;AACnD,YAAM,QAAQ,OAAO,KAAK,KAAK;AAC/B,aAAO,OAAO;AAAA,QACZ,OAAO,QAAQ,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,CAAC,UAAU,WAAW,IAAIF,WAA8B,MAAM,IAAI;AAIxE,QAAM,cAAcG,QAAO,QAAQ;AACnC,cAAY,UAAU;AAEtB,QAAM,CAAC,gBAAgB,iBAAiB,IAAIH,WAA8B,CAAC,CAAC;AAI5E,QAAM,iBAAiBD;AAAA,IACrB,MAAM,cAAc,mBAAmB,QAAQ;AAAA,IAC/C,CAAC,mBAAmB,QAAQ;AAAA,EAC9B;AAEA,QAAM,oBAAoBA,UAAQ,MAAM;AACtC,UAAMK,cAAaF,qBAAoB,cAAc;AACrD,UAAM,WAAW,SAAS,YAAY,KAAK,eAAe,YAAY;AACtE,UAAM,aAAa,MAAM,QAAQ,QAAQ,IACpC,WACD;AACJ,WAAO,gBAAgBE,aAAY,UAAU;AAAA,EAC/C,GAAG,CAAC,gBAAgB,QAAQ,CAAC;AAE7B,QAAM,CAAC,qBAAqB,sBAAsB,IAAIJ,WAAS,KAAK;AAepE,QAAM,SAASG,QAAoB,oBAAI,IAAI,CAAC;AAC5C,QAAM,CAAC,SAAS,UAAU,IAAIH,WAAkC,CAAC,CAAC;AAClE,QAAM,CAAC,iBAAiB,kBAAkB,IAAIA,WAAS,KAAK;AAE5D,QAAM,aAAaE,qBAAoB,cAAc;AAIrD,EAAAG,WAAU,MAAM;AACd,QAAI,CAAC,qBAAqB;AACxB,YAAM,cAAc,OAAO,QAAQ,UAAU,EAAE;AAAA,QAC7C,CAAC,CAAC,WAAW,QAAQ,MACnB,KAAK,SAAS,MAAM,UACpB,gBAAgB,QAAQ,MAAM;AAAA,MAClC;AAEA,UAAI,eAAe,UAAU;AAC3B,iBAAS,QAAQ;AAAA,MACnB;AACA,6BAAuB,IAAI;AAAA,IAC7B;AAAA,EACF,GAAG,CAAC,qBAAqB,YAAY,MAAM,UAAU,QAAQ,CAAC;AAI9D,EAAAA,WAAU,MAAM;AACd,UAAM,uBAAuB,OAAO,KAAK,UAAU;AACnD,UAAM,eAAe,OAAO,KAAK,QAAQ,EAAE;AAAA,MACzC,CAAC,MAAM,CAAC,qBAAqB,SAAS,CAAC;AAAA,IACzC;AAEA,QAAI,aAAa,SAAS,GAAG;AAC3B,YAAM,cAAc,EAAE,GAAG,SAAS;AAClC,mBAAa,QAAQ,CAAC,MAAM;AAC1B,eAAO,YAAY,CAAC;AAAA,MACtB,CAAC;AACD,kBAAY,WAAW;AACvB,UAAI,SAAU,UAAS,WAAW;AAAA,IACpC;AAAA,EACF,GAAG,CAAC,YAAY,UAAU,QAAQ,CAAC;AAMnC,QAAM,cAAcF;AAAA,IAClB,IAAI,IAAI,OAAO,KAAKD,qBAAoB,iBAAiB,CAAC,CAAC;AAAA,EAC7D;AACA,EAAAG,WAAU,MAAM;AACd,UAAM,QAAQ,OAAO,KAAK,UAAU;AACpC,UAAM,WAAW,MAAM,OAAO,CAAC,MAAM,CAAC,YAAY,QAAQ,IAAI,CAAC,CAAC;AAChE,gBAAY,UAAU,IAAI,IAAI,KAAK;AACnC,QAAI,SAAS,WAAW,EAAG;AAC3B,UAAM,SAASJ,qBAAoB,UAAU;AAAA,MAC3C,YAAY,OAAO,YAAY,SAAS,IAAI,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AAAA,IACxE,CAAC;AACD,QAAI,QAAQ,QAAQ,QAAQ,EAAG;AAC/B,gBAAY,MAAM;AAClB,QAAI,SAAU,UAAS,MAAM;AAAA,EAC/B,GAAG,CAAC,YAAY,UAAU,QAAQ,CAAC;AAKnC,QAAM,cAAcE,QAAO,IAAI;AAC/B,EAAAE,WAAU,MAAM;AACd,QAAI,QAAQ,YAAY,SAAS,IAAI,EAAG;AACxC,gBAAY,UAAU;AAKtB,UAAM,UAAU;AAAA,MACdJ,qBAAoB,MAAM,iBAAiB;AAAA,MAC3C;AAAA,IACF;AACA,gBAAY,OAAO;AAEnB,UAAM,sBAAsB,OAAO,KAAK,UAAU;AAClD,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,QAAI,QAAQ;AACV,sBAAgB,OAAO,WAAW;AAClC,uBAAiB,OAAO,SAAS;AACjC,UAAI,OAAO,uBAAuB;AAChC,mCAA2B,IAAI;AAAA,MACjC;AAAA,IACF;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,aAAaF;AAAA,IACjB,MAAM,CAAC,QAAQ,UAAU,YAAY;AAAA,IACrC,CAAC,UAAU,YAAY;AAAA,EACzB;AAIA,QAAM,cAAcA,UAAQ,MAAM;AAChC,QAAI,qBAAqB,OAAO,KAAK,cAAc,EAAE,SAAS,GAAG;AAC/D,aAAO,EAAE,GAAG,UAAU,GAAG,eAAe;AAAA,IAC1C;AACA,WAAO;AAAA,EACT,GAAG,CAAC,UAAU,gBAAgB,iBAAiB,CAAC;AAKhD,QAAM,aAAaA;AAAA,IACjB,MACE,cAAc,gBAAgB,aAAa,YAAY,UAAU,MAAM;AAAA,IACzE,CAAC,gBAAgB,aAAa,YAAY,UAAU,MAAM;AAAA,EAC5D;AACA,QAAM,EAAE,aAAa,aAAa,IAAI;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAOA,QAAM,aAAaA,UAAQ,MAAM;AAC/B,UAAM,SAAS,iBAAiB;AAAA,MAC9B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO;AAAA,MACL,aAAa;AAAA,MACb,QAAQ,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO;AAAA,MACnC,SAAS,OAAO,WAAW;AAAA,IAC7B;AAAA,EACF,GAAG,CAAC,gBAAgB,aAAa,YAAY,aAAa,WAAW,CAAC;AACtE,QAAM,EAAE,SAAS,YAAY,IAAI;AAKjC,QAAM,wBAAwBI,QAAO,kBAAkB;AACvD,wBAAsB,UAAU;AAChC,EAAAE,WAAU,MAAM;AACd,0BAAsB,UAAU,WAAW,QAAQ,WAAW,OAAO;AAAA,EACvE,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,oBAAoBC;AAAA,IACxB,CAAC,WAAmB,UAAe;AACjC,UAAI,SAAU;AAId,aAAO,QAAQ,IAAI,SAAS;AAE5B,YAAM,YAAY,iBAAiB,WAAW,UAAU;AAMxD,UAAI,qBAAqB,CAAC,WAAW;AACnC,0BAAkB,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,EAAE;AAC7D;AAAA,MACF;AAEA,YAAM,UAAU,EAAE,GAAG,UAAU,CAAC,SAAS,GAAG,MAAM;AAClD,kBAAY,OAAO;AAEnB,UAAI,CAAC,aAAa;AAChB,cAAM,qBAAqB,CAAC,gBAAgB;AAC5C,YAAI,sBAAsB,SAAU,UAAS,OAAO;AAAA,MACtD;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAKA,QAAM,oBAAoBA;AAAA,IACxB,CAAC,cAAsB;AACrB,UAAI,CAAC,kBAAmB;AACxB,UAAI,eAAe,SAAS,MAAM,OAAW;AAE7C,YAAM,UAAU,EAAE,GAAG,UAAU,GAAG,eAAe;AACjD,kBAAY,OAAO;AACnB,wBAAkB,CAAC,SAAS;AAC1B,cAAM,UAAU,EAAE,GAAG,KAAK;AAC1B,eAAO,QAAQ,SAAS;AACxB,eAAO;AAAA,MACT,CAAC;AAED,UAAI,CAAC,eAAe,SAAU,UAAS,OAAO;AAAA,IAChD;AAAA,IACA,CAAC,aAAa,mBAAmB,gBAAgB,UAAU,QAAQ;AAAA,EACrE;AAEA,QAAM,kBAAkBA;AAAA,IACtB,CAAC,cAAsB;AACrB,UAAI,SAAU;AAGd,UAAI,OAAO,QAAQ,IAAI,SAAS,GAAG;AACjC;AAAA,UAAW,CAAC,SACV,KAAK,SAAS,IAAI,OAAO,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,KAAK;AAAA,QACxD;AAAA,MACF;AAEA,wBAAkB,SAAS;AAI3B,YAAM,SAAS,YAAY;AAE3B,UAAI,CAAC,eAAe,gBAAgB,UAAU;AAC5C,iBAAS,MAAM;AAAA,MACjB;AAEA,UAAI,QAAQ;AACV,cAAM,aACJ,qBAAqB,eAAe,SAAS,MAAM;AACrD,cAAM,aAAa,aACf,EAAE,GAAG,QAAQ,CAAC,SAAS,GAAG,eAAe,SAAS,EAAE,IACpD;AACJ,eAAO,WAAW,UAAU;AAAA,MAC9B;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAaA,aAAY,MAAM;AAGnC,uBAAmB,IAAI;AAIvB,QAAI,CAAC,cAAc,CAAC,kBAAmB;AAIvC,QAAI,aAAc;AAElB,UAAM,YACJ,qBAAqB,OAAO,KAAK,cAAc,EAAE,SAAS,IACtD,EAAE,GAAG,UAAU,GAAG,eAAe,IACjC;AAEN,UAAM,eAAe,EAAE,GAAG,eAAe,GAAG,UAAU;AAItD,UAAM,aAAa,iBAAiB;AAAA,MAClC,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,WAAW,WAAW,KAAK,UAAU;AAEvC,YAAM,UAA+B,CAAC;AACtC,iBAAW,OAAO,OAAO,KAAK,SAAS,GAAG;AACxC,YAAI,CAAC,QAAQ,UAAU,GAAG,GAAG,aAAa,GAAG,CAAC,GAAG;AAC/C,kBAAQ,GAAG,IAAI,UAAU,GAAG;AAAA,QAC9B;AAAA,MACF;AACA,YAAM,OAAO,aAAa,cAAc,SAAS;AACjD,eAAS,cAAc,SAAS,IAAI;AACpC,wBAAkB,CAAC,CAAC;AAAA,IACtB;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,eAAeA,aAAY,MAAM;AACrC,gBAAY,EAAE,GAAG,aAAa,CAAC;AAC/B,sBAAkB,CAAC,CAAC;AACpB,WAAO,UAAU,oBAAI,IAAI;AACzB,eAAW,CAAC,CAAC;AACb,uBAAmB,KAAK;AACxB,eAAW;AAAA,EACb,GAAG,CAAC,cAAc,QAAQ,CAAC;AAE3B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AhDtnBA;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAyHH,SAIE,OAAAC,OAJF,QAAAC,cAAA;AAnHJ,SAAS,oBAAoB,OAAoC;AAC/D,SAAO;AAAA,IACL,UAAU,MAAM,YAAY;AAAA,IAC5B,UAAU,MAAM,YAAY;AAAA,IAC5B,aAAa,MAAM,eAAe;AAAA,IAClC,cAAc,MAAM,gBAAgB;AAAA,IACpC,mBAAmB,MAAM,qBAAqB;AAAA,IAC9C,YAAY,MAAM,cAAc;AAAA,IAChC,qBAAqB,MAAM,uBAAuB;AAAA,IAClD,iBAAiB,MAAM,mBAAmB;AAAA,IAC1C,mBAAmB,MAAM,qBAAqB;AAAA,EAChD;AACF;AAGA,SAAS,qBAAqB,OAAoC;AAChE,SAAO;AAAA,IACL,WAAW,MAAM,aAAa;AAAA,IAC9B,aAAa,MAAM,eAAe;AAAA,IAClC,SAAS,MAAM,WAAW;AAAA,IAC1B,UAAU,MAAM,YAAa,CAAC;AAAA,EAChC;AACF;AAKA,IAAM,WAAW,CAAC,SAChB;AAOF,SAAS,oBACP,UACA,QACA,UACA,YACA;AACA,QAAM,QAAQ,aAAaC,oBAAmB;AAE9C,QAAM,kBAAkBC;AAAA,IACtB,CAAC,MAA2B,WAAW,MAAM,CAAC,CAAC;AAAA,IAC/C,CAAC,UAAU,KAAK;AAAA,EAClB;AAEA,QAAM,gBAAgBA;AAAA,IACpB,CAAC,WAAmB,MAClB,SAAS,WAAW,MAAM,CAAC,CAAC;AAAA,IAC9B,CAAC,QAAQ,KAAK;AAAA,EAChB;AAEA,QAAM,kBAAkBA;AAAA,IACtB,CAAC,GAAwB,SAA8B,SACrD,WAAW,MAAM,CAAC,GAAG,MAAM,OAAO,GAAG,IAAI;AAAA,IAC3C,CAAC,UAAU,KAAK;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,iBAAiB,WAAW,kBAAkB;AAAA,IAC9C,eAAe,SAAS,gBAAgB;AAAA,IACxC,iBAAiB,WAAW,kBAAkB;AAAA,EAChD;AACF;AAGA,SAAS,cACP,QACiC;AACjC,QAAM,MAAM,oBAAI,IAAgC;AAChD,aAAW,SAAS,QAAQ;AAC1B,QAAIC,QAAM,eAAe,KAAK,KAAK,MAAM,OAAO,MAAM;AACpD,UAAI,IAAI,OAAO,MAAM,GAAG,GAAG,KAAK;AAAA,IAClC;AAAA,EACF;AACA,SAAO;AACT;AAKA,IAAM,eAA2C;AAMjD,SAAS,mBACP,KACA,YACQ;AACR,MAAI,IAAI,QAAS,QAAO,IAAI;AAC5B,MAAI,IAAI,UAAU,IAAI,OAAO,SAAS,GAAG;AACvC,WAAO,MAAM;AAAA,MACX,EAAE,QAAQ,WAAW;AAAA,MACrB,CAAC,GAAG,MAAM,aAAa,IAAI,SAAS,CAAC,KAAK,MAAM;AAAA,IAClD,EAAE,KAAK,GAAG;AAAA,EACZ;AACA,SAAO,UAAU,UAAU;AAC7B;AAOA,SAAS,YACP,OACA,KACA,SACoB;AACpB,MAAI,CAAC,MAAO,QAAO;AACnB,SACE,gBAAAH;AAAA,IAAC;AAAA;AAAA,MAEC,WAAU;AAAA,MAEV;AAAA,wBAAAD,MAAC,YAAO,WAAU,kDACf,iBACH;AAAA,QACC;AAAA;AAAA;AAAA,IANI,SAAS,GAAG;AAAA,EAOnB;AAEJ;AAEA,SAAS,gBACP,KACA,UACA,eAC0D;AAC1D,QAAM,YAAY,IAAI,OACnB,IAAI,CAAC,SAAS,SAAS,IAAI,IAAI,CAAC,EAChC,OAAO,CAAC,OAAiC,MAAM,IAAI;AACtD,MAAI,UAAU,WAAW,EAAG,QAAO;AAEnC,QAAM,SAAS,IAAI,OAAO;AAC1B,QAAM,SAAS,IAAI,OAAO,KAAK,GAAG;AAIlC,QAAM,QACJ,IAAI,YAAY,SACZ;AAAA,IACE,SAAS;AAAA,IACT,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,KAAK,GAAG,MAAM;AAAA,EAChB,IACA;AAAA,IACE,SAAS;AAAA,IACT,qBAAqB,mBAAmB,KAAK,UAAU,MAAM;AAAA,IAC7D,KAAK,GAAG,MAAM;AAAA,EAChB;AAEN,QAAM,QACJ,gBAAAA,MAAC,SAA0B,OACxB,uBADO,OAAO,MAAM,EAEvB;AAGF,SAAO;AAAA,IACL,SAAS,YAAY,IAAI,OAAO,QAAQ,KAAK;AAAA,IAC7C,QAAQ,IAAI;AAAA,EACd;AACF;AAGA,SAAS,sBACP,QACA,QACsB;AACtB,QAAM,SAA+B,CAAC;AACtC,aAAW,SAAS,QAAQ;AAC1B,QACEI,QAAM,eAAe,KAAK,KAC1B,MAAM,OAAO,QACb,CAAC,OAAO,IAAI,OAAO,MAAM,GAAG,CAAC,GAC7B;AACA,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;AAOA,SAAS,UACP,SACA,UACA,eACA,QACsB;AACtB,QAAM,WAAiC,CAAC;AACxC,aAAW,OAAO,SAAS;AACzB,UAAM,SAAS,gBAAgB,KAAK,UAAU,aAAa;AAC3D,eAAW,QAAQ,IAAI,OAAQ,QAAO,IAAI,IAAI;AAC9C,QAAI,UAAU,KAAM,UAAS,KAAK,OAAO,OAAO;AAAA,EAClD;AACA,SAAO;AACT;AAMA,SAAS,mBACP,QACA,SACA,eACsB;AACtB,QAAM,SAAS,oBAAI,IAAY;AAC/B,QAAM,WAAW;AAAA,IACf;AAAA,IACA,cAAc,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,EACF;AACA,SAAO,SAAS,OAAO,sBAAsB,QAAQ,MAAM,CAAC;AAC9D;AAwBA,SAAS,aACP,eACA,SACyB;AACzB,SAAO,eAAe,YAAY;AACpC;AASA,SAAS,oBACP,eACA,oBACS;AACT,SAAO,uBAAuB,eAAe,mBAAmB;AAClE;AAEA,SAAS,kBAAkB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKY;AACV,SACE,qBACA,gBACA,aACA,sBAAsB;AAE1B;AAGA,SAAS,mBACP,mBACA,iBACA,WACS;AACT,MAAI,sBAAsB,SAAU,QAAO;AAC3C,MAAI,gBAAiB,QAAO;AAC5B,SAAO,sBAAsB,eAAe,CAAC,CAAC;AAChD;AAIA,SAAS,YAAY,SAAyB;AAC5C,QAAM,QAAQ,QAAQ,MAAM,GAAG,EAAE,CAAC,KAAK;AACvC,SAAO,MAAM,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG;AACrD;AAMA,SAAS,eACP,WACA,aACA,aACA,OACsB;AAKtB,QAAM,WAAW,YAAY;AAAA,IAC3B,CAAC,MAAM,YAAY,EAAE,OAAO,MAAM;AAAA,EACpC;AACA,MAAI,SAAS,WAAW,EAAG,QAAO;AAKlC,QAAM,gBAAgB,IAAI;AAAA,KACvB,eAAe,CAAC,GACd,OAAO,CAAC,MAAM,YAAY,EAAE,OAAO,MAAM,SAAS,EAClD,IAAI,CAAC,MAAM,EAAE,OAAO;AAAA,EACzB;AACA,QAAM,SAAS,SACZ,OAAO,CAAC,MAAM,cAAc,IAAI,EAAE,OAAO,CAAC,EAC1C,IAAI,CAAC,MAAM,EAAE,OAAO;AACvB,QAAM,OAAO,QACT,SACG,OAAO,CAAC,MAAM,CAAC,cAAc,IAAI,EAAE,OAAO,CAAC,EAC3C,IAAI,CAAC,MAAM,EAAE,OAAO,IACvB,CAAC;AACL,QAAM,MAAM,CAAC,GAAG,QAAQ,GAAG,IAAI;AAC/B,SAAO,IAAI,SAAS,IAAI,MAAM;AAChC;AAGA,SAAS,gBACP,KACA,aACQ;AACR,MAAI,YAAY,WAAW,EAAG,QAAO;AACrC,QAAM,QAAQ,IAAI,IAAI,IAAI,KAAK,QAAQ,CAAC,QAAQ,IAAI,MAAM,CAAC;AAC3D,SAAO,YAAY,OAAO,CAAC,MAAM,MAAM,IAAI,YAAY,EAAE,OAAO,CAAC,CAAC,EAAE;AACtE;AAUA,SAAS,gBACP,WACA,UAC4C;AAC5C,QAAM,UAAU,UAAU;AAAA,IACxB,CAAC,QAAQ,eAAe,IAAI,MAAM,QAAQ,EAAE;AAAA,EAC9C;AACA,SAAO,EAAE,SAAS,WAAW,CAAC,QAAQ,KAAK,OAAO,EAAE;AACtD;AAGA,SAAS,sBACP,WACA,UACa;AACb,QAAM,SAAS,oBAAI,IAAY;AAC/B,QAAM,EAAE,SAAS,UAAU,IAAI,gBAAgB,WAAW,QAAQ;AAClE,MAAI,UAAW,QAAO;AACtB,YAAU,QAAQ,CAAC,KAAK,MAAM;AAC5B,QAAI,QAAQ,CAAC,EAAG;AAChB,eAAW,OAAO,IAAI,KAAM,YAAW,KAAK,IAAI,OAAQ,QAAO,IAAI,CAAC;AAAA,EACtE,CAAC;AACD,SAAO;AACT;AAIA,SAAS,qBACP,WACA,SACqB;AACrB,QAAM,aAAa,UAAU,iBAAiB,OAAO,CAAC;AACtD,MAAI,OAAO,eAAe,YAAY;AACpC,WAAO;AAAA,EACT;AACA,SAAO,kBAAkB;AAC3B;AAOA,SAAS,kBAAkB;AAAA,EACzB;AACF,GAE8B;AAC5B,MAAI,UAAU,EAAG,QAAO;AACxB,SACE,gBAAAH,OAAC,OAAE,WAAU,sDACX;AAAA,oBAAAD,MAACK,cAAA,EAAY,WAAU,oBAAmB;AAAA,IACzC,UAAU,IACP,kEACA,GAAG,KAAK;AAAA,KACd;AAEJ;AAIA,SAAS,gBAAgB;AAAA,EACvB;AACF,GAE8B;AAC5B,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,SACE,gBAAAL,MAAC,SAAI,WAAU,aACZ,mBAAS,IAAI,CAAC,KAAK,MAClB,gBAAAC;AAAA,IAAC;AAAA;AAAA,MAEC,MAAK;AAAA,MACL,WAAU;AAAA,MAEV;AAAA,wBAAAD,MAACK,cAAA,EAAY,WAAU,oBAAmB;AAAA,QACzC;AAAA;AAAA;AAAA,IALI;AAAA,EAMP,CACD,GACH;AAEJ;AAWA,SAAS,qBACP,QACA,WACA,eACA,aACA,UACA,eACsB;AACtB,QAAM,WAAW,cAAc,MAAM;AACrC,QAAM,SAAS,oBAAI,IAAY;AAC/B,QAAM,EAAE,SAAS,UAAU,IAAI,gBAAgB,WAAW,QAAQ;AAIlE,QAAM,QAAQ,UAAU,IAAI,CAAC,KAAK,WAAW;AAAA,IAC3C;AAAA,IACA,MAAM,UAAU,IAAI,MAAM,UAAU,eAAe,MAAM;AAAA,EAC3D,EAAE;AACF,QAAM,WAAW,sBAAsB,QAAQ,MAAM;AAIrD,MAAI,WAAW;AACb,WAAO,CAAC,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,GAAG,GAAG,QAAQ;AAAA,EACtD;AAEA,QAAM,SAAuB,MAC1B,OAAO,CAAC,MAAM,QAAQ,EAAE,KAAK,CAAC,EAC9B,IAAI,CAAC,OAAO;AAAA,IACX,KAAK,SAAS,EAAE,KAAK;AAAA,IACrB,OAAO,UAAU,EAAE,KAAK,EAAE;AAAA,IAC1B,SAAS,EAAE;AAAA,IACX,YAAY,gBAAgB,UAAU,EAAE,KAAK,GAAG,WAAW;AAAA,EAC7D,EAAE;AAEJ,SAAO,CAAC,gBAAAL,MAAC,iBAAgC,UAAd,aAA8B,GAAI,GAAG,QAAQ;AAC1E;AA2BA,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2C;AACzC,MAAI,iBAAiB;AACnB,WAAO,gBAAAA,MAAC,SAAI,OAAO,EAAE,SAAS,WAAW,GAAI,UAAS;AAAA,EACxD;AACA,SACE,gBAAAC,OAAC,eAAY,KAAI,MACd;AAAA;AAAA,IACA,uBACC,gBAAAD,MAAC,+BAAoB,YAAY,UAAU,QAAQ,gBAAgB;AAAA,IAErE,gBAAAA,MAAC,qBAAkB,OAAO,kBAAkB;AAAA,IAC5C,gBAAAA,MAAC,mBAAgB,UAAU,iBAAiB;AAAA,IAC3C,eACC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ;AAAA,QACR,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,KAEJ;AAEJ;AAsKO,SAAS,uBACd,OACoB;AACpB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EACb,IAAI;AAOJ,QAAM,oBAAoBM,YAAW,iBAAiB;AACtD,QAAM,aAAa,sBAAsB;AAEzC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,oBAAoB,KAAK;AAE7B,QAAM,EAAE,WAAW,aAAa,SAAS,SAAS,IAChD,qBAAqB,KAAK;AAE5B,QAAM,EAAE,iBAAiB,eAAe,gBAAgB,IACtD,oBAAoB,UAAU,QAAQ,UAAU,UAAU;AAE5D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,cAAc;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,QAAQ;AAAA,IACR;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,MAAM;AAAA,IACnB,aAAa,MAAM;AAAA,IACnB;AAAA,IACA,QAAQ;AAAA,EACV,CAAC;AAKD,QAAM,uBACJ,SAAS,aAAa,GACrB;AACH,QAAM,gBAAiCC;AAAA,IACrC,OAAO;AAAA,MACL,GAAI,uBAAuB,EAAE,gBAAgB,qBAAqB,IAAI,CAAC;AAAA,MACvE,GAAK,SAAS,oBAAoB,KAAyB,CAAC;AAAA,IAC9D;AAAA,IACA,CAAC,sBAAsB,QAAQ;AAAA,EACjC;AAIA,QAAM,oBAAoBA;AAAA,IACxB,OAAO,EAAE,GAAG,mBAAmB,GAAG,UAAU;AAAA,IAC5C,CAAC,SAAS;AAAA,EACZ;AAMA,QAAM,iBAAiBJ;AAAA,IACrB,CAACK,WACC,gBAAAR;AAAA,MAAC;AAAA;AAAA,QACE,GAAGQ;AAAA,QACJ,WAAW;AAAA,QACX;AAAA,QACA,aAAa;AAAA,QACb,qBAAqB;AAAA;AAAA,IACvB;AAAA,IAEF,CAAC,mBAAmB,UAAU;AAAA,EAChC;AAEA,QAAM,WAAW,aAAa,mBAAmB,WAAW;AAK5D,QAAM,2BAA2B;AAAA,IAC/B;AAAA,IACA;AAAA,EACF;AAEA,QAAM,eAAeD;AAAA,IACnB,OAAO;AAAA,MACL,UAAU;AAAA,MACV,WAAW;AAAA,MACX;AAAA,MACA,iBAAiB;AAAA,IACnB;AAAA,IACA,CAAC,gBAAgB,mBAAmB,UAAU,wBAAwB;AAAA,EACxE;AAEA,QAAM,oBAAoB,qBAAqB,MAAM,iBAAiB;AACtE,QAAM,kBAAkB,mBAAmB,MAAM,eAAe;AAChE,QAAM,mBAAmB,kBAAkB;AAAA,IACzC;AAAA,IACA;AAAA,IACA,WAAW,CAAC,CAAC;AAAA,IACb;AAAA,EACF,CAAC;AACD,QAAM,kBAAkBJ;AAAA,IACtB,CAAC,cACC;AAAA,MACE;AAAA,MACA;AAAA,MACA,QAAQ,SAAS;AAAA,IACnB;AAAA,IACF,CAAC,mBAAmB,0BAA0B,OAAO;AAAA,EACvD;AAIA,QAAM,SAASI;AAAA,IACb,MACE,kBAAkB,QAAQ,CAAC,CAAC,WAAW,QAAQ,MAAM;AAKnD,YAAM,OACJ,SAAS,SAAS,IAAI,WAAW,KAAK,SAAS,WAAW;AAC5D,YAAM,EAAE,SAAS,QAAQ,IAAI,eAAe,MAAM,QAAQ;AAC1D,UAAI,CAAC,QAAS,QAAO,CAAC;AACtB,aAAO;AAAA,QACL,gBAAAP;AAAA,UAAC;AAAA;AAAA,YAEC;AAAA,YACA;AAAA,YACA,OAAO,YAAY,SAAS;AAAA,YAC5B,UAAU,CAAC,MAAM,kBAAkB,WAAW,CAAC;AAAA,YAC/C,QACE,mBAAmB,MAAM,gBAAgB,SAAS,IAAI;AAAA,YAExD,UAAU,gBAAgB,gBAAgB,SAAS;AAAA,YACnD,UAAU,YAAY,CAAC;AAAA,YACvB;AAAA,YACA;AAAA,YACA,UAAU,SAAS,SAAS;AAAA,YAC5B,UAAU;AAAA,YACV;AAAA,YACA,UAAU;AAAA,YACV;AAAA,YACA,WAAW;AAAA,cACT;AAAA,cACA;AAAA,cACA,MAAM;AAAA,cACN,gBAAgB,SAAS;AAAA,YAC3B;AAAA;AAAA,UAtBK;AAAA,QAuBP;AAAA,MACF;AAAA,IACF,CAAC;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,QAAM,eAAe,SAAS,aAAa;AAC3C,QAAM,UAAU,cAAc;AAC9B,QAAM,YAAY,cAAc;AAEhC,QAAM,gBAAgB,cAAc,OAAO;AAE3C,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA,cAAc;AAAA,EAChB;AAKA,QAAM,eAAeO,UAAQ,MAAM;AACjC,QAAI,aAAa,UAAU,SAAS,GAAG;AACrC,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,QAEA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,QAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,aAAO,mBAAmB,QAAQ,SAAS,aAAa;AAAA,IAC1D;AACA,WAAO;AAAA,EACT,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAID,QAAM,mBAAmBA,UAAQ,MAAM;AACrC,QAAI,CAAC,WAAW,UAAU,YAAY,WAAW,EAAG,QAAO;AAC3D,UAAM,SAAS,sBAAsB,WAAW,QAAQ;AACxD,QAAI,OAAO,SAAS,EAAG,QAAO;AAC9B,WAAO,YAAY,OAAO,CAAC,MAAM,OAAO,IAAI,YAAY,EAAE,OAAO,CAAC,CAAC,EAAE;AAAA,EACvE,GAAG,CAAC,WAAW,aAAa,QAAQ,CAAC;AAKrC,QAAM,kBAAkBA,UAAQ,MAAM;AACpC,QAAI,sBAAsB,YAAY,CAAC,gBAAiB,QAAO,CAAC;AAChE,WAAO,YAAY,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO;AAAA,EACzE,GAAG,CAAC,aAAa,mBAAmB,eAAe,CAAC;AAEpD,SACE,gBAAAP,MAAC,kBAAkB,UAAlB,EAA2B,OAAO,cACjC,0BAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,cAAc;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH,GACF;AAEJ;;;AqDviCA,SAAS,WAAAS,iBAAe;AAExB;AAAA,EACE,uBAAAC;AAAA,EACA,iBAAAC;AAAA,OACK;AAeA,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AACF,GAAsD;AACpD,QAAM,iBAAiBC;AAAA,IACrB,MAAMC,eAAc,QAAQ,QAAQ;AAAA,IACpC,CAAC,QAAQ,QAAQ;AAAA,EACnB;AAEA,QAAM,oBAAoBD,UAAQ,MAAM;AACtC,UAAM,aAAaE,qBAAoB,cAAc;AACrD,UAAM,WAAW,SAAS,YAAY,KAAK,eAAe,YAAY;AACtE,UAAM,aAAa,MAAM,QAAQ,QAAQ,IACpC,WACD;AACJ,WAAO,gBAAgB,YAAY,UAAU;AAAA,EAC/C,GAAG,CAAC,gBAAgB,QAAQ,CAAC;AAE7B,SAAO,EAAE,gBAAgB,kBAAkB;AAC7C;","names":["cn","jsx","jsxs","cn","React","useId","cn","jsx","jsxs","cn","React","useId","React","useId","Input","cn","jsx","React","useId","Input","cn","React","useId","cn","jsx","jsxs","cn","React","useId","React","cn","jsx","jsxs","emptyMessage","cn","React","Check","ChevronsUpDown","X","cn","Button","Command","CommandEmpty","CommandGroup","CommandInput","CommandItem","CommandList","Popover","PopoverContent","PopoverTrigger","Fragment","jsx","jsxs","X","emptyMessage","Command","CommandInput","CommandList","CommandEmpty","CommandGroup","CommandItem","Check","cn","TriggerIcons","ChevronsUpDown","Popover","PopoverTrigger","Button","PopoverContent","React","cn","Input","X","Badge","jsx","jsxs","jsx","jsxs","cn","Input","React","Plus","X","cn","Badge","Button","Input","jsx","jsxs","Input","X","Badge","cn","Button","Plus","React","useCallback","useEffect","useId","useState","ChevronsUpDown","cn","jsx","jsxs","ChevronsUpDown","useState","useEffect","useCallback","React","useId","cn","Button","jsx","jsxs","useMemo","jsx","jsxs","React","useCallback","useContext","useMemo","AlertCircle","stripFormItemIds","jsx","jsx","jsx","useCallback","jsx","useCallback","useRef","jsx","useRef","label","jsx","useCallback","useState","jsx","jsxs","jsx","useMemo","jsx","jsxs","useMemo","useMemo","useState","ChevronDown","ChevronRight","Card","Collapsible","CollapsibleContent","jsx","jsxs","Fragment","jsx","useMemo","useCallback","useMemo","Plus","Button","ChevronDown","Button","jsx","jsxs","jsx","jsxs","jsx","jsxs","resolveLayout","useCallback","useMemo","Button","Plus","useCallback","useRef","useState","jsx","useState","useCallback","useRef","React","ChevronsUpDown","X","cn","codingKey","Badge","Button","CodedValueDisplay","Popover","PopoverContent","PopoverTrigger","useCallback","useEffect","useRef","useState","useEffect","useState","codingKey","useEffect","useMemo","useState","codingKey","Check","cn","codingKey","Command","CommandEmpty","CommandGroup","CommandInput","CommandItem","CommandList","jsx","jsxs","jsx","React","jsx","jsxs","CodedValueDisplay","Badge","X","TriggerIcons","ChevronsUpDown","codingKey","Popover","PopoverTrigger","Button","cn","PopoverContent","React","Plus","X","cn","bindingOf","codingKey","codingsByList","conceptOf","useTerminology","Badge","Button","Popover","PopoverContent","jsx","jsxs","Badge","cn","X","useTerminology","codingKey","Button","Plus","bindingOf","conceptOf","codingsByList","Popover","PopoverContent","jsx","jsx","jsx","resolveGranularity","jsx","jsxs","useMemo","jsx","jsxs","useMemo","cn","jsx","jsxs","cn","Checkbox","cn","jsx","jsxs","cn","Checkbox","jsx","Button","IconButton","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","Plus","X","jsx","jsxs","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","IconButton","X","Button","Plus","bindingOf","isNullableBoolean","extractEnumValues","Trash2","ChevronUp","ChevronDown","Button","jsx","jsxs","Button","ChevronUp","ChevronDown","Trash2","useState","jsx","jsx","jsxs","useState","useState","Button","jsx","jsxs","useState","Button","jsx","jsxs","useMemo","jsx","useMemo","useState","useEffect","useMemo","useCallback","useRef","isNullableBoolean","getSchemaProperties","applySchemaDefaults","getSchemaProperties","getSchemaProperties","useEffect","useMemo","useRef","useState","getSchemaProperties","getSchemaProperties","useState","useRef","useEffect","useMemo","isNullableBoolean","useMemo","useState","applySchemaDefaults","getSchemaProperties","useRef","properties","useEffect","useCallback","jsx","jsxs","stripFormItemIds","useCallback","React","AlertCircle","useContext","useMemo","props","useMemo","getSchemaProperties","resolveSchema","useMemo","resolveSchema","getSchemaProperties"]}