import type { ComputedRef, Ref, } from 'vue' import type { PillNavItem, SidebarBadgeTone, SidebarToolSection, SidebarToolSectionAction, SelectOption, SettingsModalSchema, TopBarSettingsConfig, } from '../types' import type { AccessPolicy } from '../permissions' import type { FieldCondition, FieldValidation, FormFieldSchema, FormFieldType, FormSchema, FormSectionSchema, } from '../types/form-builder' import type { WellConcentration } from './useDoseCalculator' export type ControlOptionValue = string | number | boolean export type ControlOption = ControlOptionValue | SelectOption export type ControlPrimitive = string | number | boolean export type ControlShorthand = ControlPrimitive | readonly ControlOption[] export type ControlInput = ControlDefinition | ControlShorthand export interface ControlSectionConfig { id?: string label?: string title?: string description?: string subtitle?: string icon?: string | string[] iconColor?: string iconBg?: string badge?: string | number badgeTone?: SidebarBadgeTone actions?: SidebarToolSectionAction[] columns?: 1 | 2 | 3 condition?: FieldCondition /** The access policy. */ access?: AccessPolicy defaultOpen?: boolean showToggle?: boolean } export interface ControlViewConfig { label?: string icon?: string to?: string href?: string disabled?: boolean children?: PillNavItem['children'] } export interface ControlSidebarConfig extends Omit { enabled?: boolean } export interface ControlDefinition { type?: FormFieldType label?: string default?: unknown defaultValue?: unknown placeholder?: string hint?: string icon?: string | string[] iconColor?: string iconBg?: string size?: 'sm' | 'md' | 'lg' disabled?: boolean readonly?: boolean required?: boolean | string min?: number | { value: number; message: string } max?: number | { value: number; message: string } minLength?: number | { value: number; message: string } maxLength?: number | { value: number; message: string } email?: boolean | string pattern?: string | { value: string; message: string } validation?: FieldValidation condition?: FieldCondition /** The access policy. */ access?: AccessPolicy options?: readonly ControlOption[] section?: string sectionLabel?: string sectionDescription?: string sectionSubtitle?: string view?: string order?: number colSpan?: number props?: Record sidebar?: boolean | ControlSidebarConfig } export type ControlSchema = Record export type ControlFormSchema = Extract export interface ControlSchemaOptions { view?: string views?: Record section?: string sectionLabel?: string sections?: Record columns?: 1 | 2 | 3 submitLabel?: string cancelLabel?: string showCancel?: boolean } export interface ControlWorkspaceOptions extends ControlSchemaOptions { initialValues?: Record topBarSettings?: Omit } export interface ControlModelSectionConfig extends ControlSectionConfig { controls: ControlSchema sidebar?: boolean | ControlSidebarConfig } export interface ControlModelViewConfig extends ControlViewConfig { controls?: ControlSchema section?: string sectionLabel?: string sectionDescription?: string sections?: Record } export interface ControlModel extends Omit { controls?: ControlSchema sections?: Record views?: Record /** Optional SDK component bindings returned with generated component props for custom workspace slots. */ componentBindings?: ControlComponentBindingsConfig /** Alias for componentBindings in raw control models. */ components?: ControlComponentBindingsConfig /** Optional ControlWorkspaceView componentProps mapping returned with the generated controls/options. */ componentProps?: ControlComponentPropsMap /** Optional named componentProps mappings returned for multiple SDK components. */ componentPropsById?: ControlComponentPropsByIdMap } export interface ControlModelBinding { controls: ControlSchema controlOptions: ControlWorkspaceOptions componentBindings?: ControlComponentBindingsConfig componentProps?: ControlComponentPropsMap componentPropsById?: ControlComponentPropsByIdMap } export interface ControlSidebarBinding { panels: Record forms: Record viewIds: string[] viewItems: PillNavItem[] defaultView: string } export interface ControlFormBinding { schema: ControlFormSchema } export interface ControlSettingsBinding { schema: SettingsModalSchema } export interface ControlTopBarSettingsBinding { showSettings: true settingsConfig: TopBarSettingsConfig } export interface ControlWorkspaceFormBinding extends ControlFormBinding { modelValue: Record 'onUpdate:modelValue': (values: Record) => void } export interface ControlWorkspaceSidebarBinding extends ControlSidebarBinding { activeView: string modelValue: Record 'onUpdate:modelValue': (values: Record) => void values: Record 'onUpdate:values': (values: Record) => void } export interface ControlWorkspaceTopBarSettingsBinding extends ControlTopBarSettingsBinding { onSettingsValuesChange: (values: Record) => void } export interface ControlWorkspacePillNavBinding { items: PillNavItem[] currentItemId: string onSelect: (item: PillNavItem) => void } export interface ControlWorkspaceTopBarBinding extends ControlWorkspaceTopBarSettingsBinding { pillNav: PillNavItem[] currentPillId: string onPillSelect: (item: PillNavItem) => void } export type ControlWorkspaceAppTopBarPillBinding = ControlWorkspaceTopBarBinding export interface ControlWorkspaceComponentBindings { form: ControlWorkspaceFormBinding sidebar: ControlWorkspaceSidebarBinding topBar: ComputedRef topBarSettings: ControlWorkspaceTopBarSettingsBinding pillNav: ControlWorkspacePillNavBinding componentBindings: ComputedRef componentBindingsById: ComputedRef componentProps: ComputedRef> componentPropsById: ComputedRef>> } export type ControlComponentPropSource = Record> = | (keyof TValues & string) | ((values: TValues) => unknown) export type ControlComponentPropsMap = Record> = | readonly (keyof TValues & string)[] | Record> export type ControlComponentPropsByIdMap = Record> = Record> export interface ControlComponentBindingConfig = Record> { id?: string component: string props?: ControlComponentPropsMap } export interface ControlComponentBindingRecordConfig = Record> { component: string props?: ControlComponentPropsMap } export type ControlComponentBindingsConfig = Record> = | readonly ControlComponentBindingConfig[] | Record> export interface ControlComponentBinding { id: string component: string props: Record } export type ControlComponentBindingsById = Record export interface WellPlateControlPropsOptions = Record> { selectedWells?: ControlComponentPropSource format?: ControlComponentPropSource wells?: ControlComponentPropSource disabled?: ControlComponentPropSource readonly?: ControlComponentPropSource showLegend?: ControlComponentPropSource /** @deprecated WellPlate `showSampleTypeIndicator` is a no-op since MINT 1.3; removed in MINT 1.4. */ showSampleTypeIndicator?: ControlComponentPropSource /** Listener for WellPlate v-model updates. Set false to keep generated props one-way. */ onUpdateModelValue?: ((values: TValues) => (wellIds: string[]) => void) | false } export interface DoseCalculatorControlPropsOptions = Record> { mode?: ControlComponentPropSource targetWells?: ControlComponentPropSource /** Control value key used by the default apply-to-wells handler. */ wells?: ControlComponentPropSource disabled?: ControlComponentPropSource molecularWeight?: ControlComponentPropSource /** Listener for DoseCalculator apply-to-wells. Set false to keep generated props one-way. */ onApplyToWells?: ((values: TValues) => (results: WellConcentration[]) => void) | false } export interface WellPlateDoseControlPropsOptions = Record> { plateId?: string doseId?: string plate?: WellPlateControlPropsOptions dose?: DoseCalculatorControlPropsOptions } export interface DoseDesignControlModelOptions { viewId?: string viewLabel?: string sectionId?: string sectionLabel?: string sectionDescription?: string selectedWells?: readonly string[] plateFormat?: number plateFormats?: readonly number[] doseMode?: 'serial' | 'dilution' | 'conversion' doseModes?: readonly ('serial' | 'dilution' | 'conversion')[] disabled?: boolean includeMolecularWeight?: boolean molecularWeight?: number componentProps?: WellPlateDoseControlPropsOptions } export interface UseControlSchemaReturn { controls: TControls fields: FormFieldSchema[] formSchema: ControlFormSchema form: ControlFormBinding settingsSchema: SettingsModalSchema settings: ControlSettingsBinding topBarSettingsConfig: TopBarSettingsConfig topBarSettings: ControlTopBarSettingsBinding sidebarPanels: Record viewIds: string[] viewItems: PillNavItem[] defaultView: string sectionSchemas: Record sidebar: ControlSidebarBinding initialValues: ControlValues sectionSchema: (sectionId: string) => ControlFormSchema } export interface UseControlWorkspaceReturn extends Omit, 'form' | 'sidebar' | 'topBarSettings'> { schema: UseControlSchemaReturn values: ControlValues & Record activeView: Ref form: ControlWorkspaceFormBinding sidebar: ControlWorkspaceSidebarBinding topBar: ComputedRef pillNav: ControlWorkspacePillNavBinding topBarSettings: ControlWorkspaceTopBarSettingsBinding bindings: ControlWorkspaceComponentBindings componentBindings: ComputedRef componentBindingsById: ComputedRef componentProps: ComputedRef> componentPropsById: ComputedRef>> setActiveView: (viewId: string) => void setValues: (values: Record) => void resetValues: (values?: Record) => void getComponentProps: ( mapping?: ControlComponentPropsMap & Record> ) => Record getComponentPropsById: ( mappings?: ControlComponentPropsByIdMap & Record> ) => Record> getComponentBindings: ( bindings?: ControlComponentBindingsConfig & Record> ) => ControlComponentBinding[] getComponentBindingsById: ( bindings?: ControlComponentBindingsConfig & Record> ) => ControlComponentBindingsById } export type ControlValues = { [K in keyof TControls]: ControlValue } type ControlValue = TControl extends { default: infer TDefault } ? TDefault : TControl extends { defaultValue: infer TDefaultValue } ? TDefaultValue : TControl extends readonly [infer First, ...unknown[]] ? OptionValue : TControl extends ControlPrimitive ? TControl : unknown type OptionValue = TOption extends SelectOption ? TValue : TOption