import type { RefObject } from 'react' /** * Tool type determines which pipeline a tool participates in. * - 'data': transforms widget data (default) * - 'config': transforms widget config/option */ export type ToolType = 'data' | 'config' export interface WidgetsStoreProps { /** Unique identifier for the widget */ id: string /** Type of widget */ type: string /** Widget data - flexible to accommodate different widget types */ data: unknown /** Original pre-pipeline data. Used by NoData to distinguish * "no data from API" from "pipeline tools filtered everything out". * Set automatically by executeToolPipeline — not a component prop. */ sourceData?: unknown /** Loading state */ isLoading: boolean /** Fetching state (e.g., for async data) */ isFetching: boolean /** Error message if any */ error?: { title?: string message?: string } /** Whether widget is visible */ visible?: boolean /** Reference to the widget ui instance */ refUI?: RefObject /** Registered tools for the widget's transformation pipeline */ registeredTools?: ToolRegistration[] /** Formatter function for widget values */ formatter?: (value: number) => string /** Formatter function for widget label/category values */ labelFormatter?: (value: string | number) => string | number /** Locale for number formatting (e.g., 'en-US', 'es-ES', 'fr-FR') */ locale?: string } /** * Tool transformation function type * Can be synchronous or asynchronous to support remote operations */ export type ToolTransformFunction = (data: unknown) => unknown /** * Tool registration for widget pipeline * * @example Basic tool registration * ```typescript * registerTool(widgetId, { * id: 'searcher', * order: 10, * enabled: true, * fn: (data) => filterData(data), * }) * ``` * * @example Tool with dependencies * ```typescript * registerTool(widgetId, { * id: 'lock-selection', * order: 20, * enabled: true, * fn: (data) => lockData(data), * disables: ['searcher', 'relative-data'], // Disable these when active * }) * ``` * * Dependency Management: * - Multiple tools can disable the same target (reference counting) * - Target is only re-enabled when ALL disabling tools are inactive * - Original enabled state is preserved and restored * - Circular dependencies are detected and throw errors */ export interface ToolRegistration { /** Unique tool identifier (e.g., 'searcher', 'relative-data') */ id: string /** Execution priority - lower numbers execute first */ order: number /** Transformation function */ fn: ToolTransformFunction /** Whether tool is currently enabled */ enabled: boolean /** 'data' (default) transforms data, 'config' transforms widget config/option */ type?: ToolType /** * Array of tool IDs to disable when this tool is active. * During pipeline execution, if this tool is enabled, any tools listed * in this array will be excluded from the pipeline. * * @example * ```typescript * disables: ['searcher', 'relative-data'] * ``` */ disables?: string[] } /** * Base widget state interface */ export type BaseWidgetState = WidgetsStoreProps & T /** * Union type for all widget states */ export type WidgetState = BaseWidgetState /** * Widget store state with tool registration */ export interface WidgetStoreState { /** Map of widget id to widget state */ widgets: Record } /** * Widget store actions */ export interface WidgetStoreActions { /** * Add or update a widget in the store * @param id - Widget ID * @param widget - Widget state properties to merge (accepts any object structure) * @template T - Type of the widget state for type-safe access */ // eslint-disable-next-line @typescript-eslint/no-explicit-any setWidget: (id: WidgetState['id'], widget: Partial) => void /** * Remove a widget from the store * @param id - Widget ID to remove */ removeWidget: (id: WidgetState['id']) => void /** * Clear all widgets */ clearWidgets: () => void /** * Get widget by ID * @param id - Widget ID * @returns Widget state or undefined if not found */ getWidget: ( id: WidgetState['id'], ) => T | undefined /** * Register a tool with the widget's transformation pipeline * @param widgetId - Widget ID * @param tool - Tool registration object */ registerTool: (widgetId: string, tool: ToolRegistration) => void /** * Unregister a tool from the widget's transformation pipeline * @param widgetId - Widget ID * @param toolId - Tool ID to remove */ unregisterTool: (widgetId: string, toolId: string) => void /** * Set tool enabled state * @param widgetId - Widget ID * @param toolId - Tool ID * @param enabled - Whether tool should be enabled */ setToolEnabled: (widgetId: string, toolId: string, enabled: boolean) => void /** * Trigger pipeline re-execution by bumping the registeredTools reference. * @param widgetId - Widget ID */ triggerToolPipeline: (widgetId: string) => void /** * Execute the tool transformation pipeline * Supports both synchronous and asynchronous tools * @param widgetId - Widget ID * @param sourceData - Original data to transform */ executeToolPipeline: (widgetId: string, sourceData: unknown) => Promise /** * Execute the config transformation pipeline * Applies config-type tools to the base config, then sets the result on the widget * @param widgetId - Widget ID * @param baseConfig - Base config to transform */ executeConfigPipeline: (widgetId: string, baseConfig: object) => Promise } /** * Complete widget store interface */ export type WidgetStore = WidgetStoreState & WidgetStoreActions