import { ComputedRef, Ref } from 'vue'; import { PillNavItem, SidebarBadgeTone, SidebarToolSection, SidebarToolSectionAction, SelectOption, SettingsModalSchema, TopBarSettingsConfig } from '../types'; import { AccessPolicy } from '../permissions'; import { FieldCondition, FieldValidation, FormFieldSchema, FormFieldType, FormSchema, FormSectionSchema } from '../types/form-builder'; import { 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; export {};