Member Junction
    Preparing search index...

    Module @memberjunction/interactive-component-types - v5.49.0

    @memberjunction/interactive-component-types

    Type definitions and interfaces for MemberJunction's Interactive Components system, enabling dynamic, data-driven UI components with AI capabilities.

    The @memberjunction/interactive-component-types package provides the foundational types and interfaces for building interactive components in MemberJunction. These components are designed to be dynamically generated, data-aware, and AI-enhanced, allowing for rich user experiences with minimal configuration.

    graph TD
        A["InteractiveComponentSpec
    (Component Definition)"] --> B["ComponentInitFunction"] B --> C["Props & Events"] B --> D["SimpleDataContext"] B --> E["SimpleMetadata"] B --> F["SimpleRunView / RunQuery"] B --> G["SimpleAITools"] G --> H["ExecutePrompt
    (LLM Calls)"] G --> I["EmbedText
    (Vector Embeddings)"] G --> J["VectorService
    (Similarity / KNN)"] A --> K["ComponentObject
    (Runtime Interface)"] K --> L["Standard Methods
    (print, refresh, isDirty)"] K --> M["Custom Methods
    (RegisterMethod)"] style A fill:#2d6a9f,stroke:#1a4971,color:#fff style B fill:#7c5295,stroke:#563a6b,color:#fff style G fill:#2d8659,stroke:#1a5c3a,color:#fff style K fill:#b8762f,stroke:#8a5722,color:#fff style H fill:#2d8659,stroke:#1a5c3a,color:#fff style I fill:#2d8659,stroke:#1a5c3a,color:#fff style J fill:#2d8659,stroke:#1a5c3a,color:#fff
    • Dynamic Component Generation -- Type-safe specifications for runtime component creation
    • Data Context Management -- Support for both static and dynamic data loading
    • AI Tool Integration -- Built-in interfaces for AI operations within components
    • Framework Agnostic -- Core types that work across React, Angular, and other frameworks
    • Vector Operations -- Support for similarity calculations and vector-based data operations
    • Metadata Access -- Direct access to MemberJunction's metadata system
    npm install @memberjunction/interactive-component-types
    

    Provides AI capabilities to interactive components:

    interface SimpleAITools {
    // Execute LLM prompts for qualitative analysis
    ExecutePrompt: (params: SimpleExecutePromptParams) => Promise<SimpleExecutePromptResult>

    // Generate vector embeddings for similarity calculations
    EmbedText: (params: SimpleEmbedTextParams) => Promise<SimpleEmbedTextResult>

    // Vector operations service for KNN, similarity scoring, etc.
    VectorService: SimpleVectorService
    }

    Parameters for executing AI prompts within components:

    interface SimpleExecutePromptParams {
    // System prompt to set context
    systemPrompt: string;

    // Optional conversation history
    messages?: Array<{message: string, role: 'user' | 'assistant'}>;

    // Preferred models in order of preference
    preferredModels?: string[];

    // Model power selection: 'lowest' | 'medium' | 'highest'
    modelPower?: 'lowest' | 'medium' | 'highest';

    // Optional user context
    contextUser?: UserInfo;
    }

    Parameters for generating text embeddings:

    interface SimpleEmbedTextParams {
    // Single string or array of strings to embed
    textToEmbed: string | string[];

    // Model size selection
    modelSize: 'small' | 'medium';

    // Optional user context
    contextUser?: UserInfo;
    }

    Access to MemberJunction's metadata system:

    interface SimpleMetadata {
    // Array of all entity metadata
    Entities: EntityInfo[];

    // Get entity object for CRUD operations
    GetEntityObject(entityName: string, contextUser?: UserInfo): Promise<BaseEntity>;
    }

    Execute database views dynamically:

    interface SimpleRunView {
    // Run a single view
    RunView: (params: RunViewParams, contextUser?: UserInfo) => Promise<RunViewResult>

    // Run multiple views in parallel
    RunViews: (params: RunViewParams[], contextUser?: UserInfo) => Promise<RunViewResult[]>
    }

    Execute predefined queries:

    interface SimpleRunQuery {
    // Run a predefined query with parameters
    RunQuery: (params: RunQueryParams, contextUser?: UserInfo) => Promise<RunQueryResult>
    }

    Interactive components receive initialization functions with access to all tools:

    type ComponentInitFunction = (
    props: ComponentInitProps,
    events: ComponentEvents,
    data: SimpleDataContext,
    metadata: SimpleMetadata,
    runView: SimpleRunView,
    runQuery: SimpleRunQuery,
    ai: SimpleAITools
    ) => Promise<void>;
    // In your interactive component initialization
    async function initComponent(props, events, data, metadata, runView, runQuery, ai) {
    // Execute a prompt for data analysis
    const analysisResult = await ai.ExecutePrompt({
    systemPrompt: 'You are a data analyst. Analyze the provided dataset.',
    messages: [
    { message: 'What are the key trends?', role: 'user' }
    ],
    modelPower: 'medium'
    });

    if (analysisResult.success) {
    console.log('Analysis:', analysisResult.result);

    // Parse JSON if available
    if (analysisResult.resultObject) {
    const insights = analysisResult.resultObject;
    // Use insights in your component
    }
    }

    // Generate embeddings for similarity matching
    const embedResult = await ai.EmbedText({
    textToEmbed: ['Product A description', 'Product B description'],
    modelSize: 'small'
    });

    // Use vector service for similarity calculations
    const similarity = ai.VectorService.cosineSimilarity(
    embedResult.result[0],
    embedResult.result[1]
    );

    console.log('Product similarity:', similarity);
    }
    async function loadComponentData(props, events, data, metadata, runView) {
    // Get entity metadata
    const userEntity = metadata.Entities.find(e => e.Name === 'Users');

    // Run a view to get data
    const viewResult = await runView.RunView({
    EntityName: 'Users',
    ExtraFilter: "Status = 'Active'",
    OrderBy: 'LastName, FirstName',
    MaxRows: 100
    });

    if (viewResult.Success) {
    const users = viewResult.Results;
    // Process users data
    }

    // Create/update an entity
    const newUser = await metadata.GetEntityObject('Users');
    newUser.NewRecord();
    newUser.Set('FirstName', 'John');
    newUser.Set('LastName', 'Doe');
    await newUser.Save();
    }
    async function loadDashboardData(props, events, data, metadata, runView) {
    // Run multiple views in parallel for better performance
    const [salesData, customerData, productData] = await runView.RunViews([
    { EntityName: 'Sales', ExtraFilter: "Date >= '2024-01-01'" },
    { EntityName: 'Customers', ExtraFilter: "Active = 1" },
    { EntityName: 'Products', OrderBy: 'Name' }
    ]);

    // All data loaded in parallel
    console.log('Sales:', salesData.Results);
    console.log('Customers:', customerData.Results);
    console.log('Products:', productData.Results);
    }

    The ComponentObject interface defines the structure returned by compiled components, providing both the React component and method accessors:

    interface ComponentObject {
    // The React component function
    component: Function;

    // Standard methods (all optional)
    print?: () => void;
    refresh?: () => void;
    getCurrentDataState?: () => any;
    getDataStateHistory?: () => Array<{ timestamp: Date; state: any }>;
    validate?: () => boolean | { valid: boolean; errors?: string[] };
    isDirty?: () => boolean;
    reset?: () => void;
    scrollTo?: (target: string | HTMLElement | { top?: number; left?: number }) => void;
    focus?: (target?: string | HTMLElement) => void;

    // Dynamic method access
    invokeMethod?: (methodName: string, ...args: any[]) => any;
    hasMethod?: (methodName: string) => boolean;
    }

    Components receive callbacks that enable interaction with their container:

    interface ComponentCallbacks {
    // Open an entity record in the container
    OpenEntityRecord: (entityName: string, key: CompositeKey) => void;

    // Register a method that can be called by the container
    RegisterMethod: (methodName: string, handler: Function) => void;
    }
    1. Component registers methods during initialization using the RegisterMethod callback
    2. Runtime stores methods in an internal registry Map
    3. ComponentObject exposes methods with type-safe accessors for standard methods
    4. Containers call methods directly or via invokeMethod() for custom methods
    function DataTableComponent({ callbacks, data, userState }) {
    const [tableData, setTableData] = React.useState(data);
    const [hasChanges, setHasChanges] = React.useState(false);
    const [selectedRows, setSelectedRows] = React.useState([]);

    React.useEffect(() => {
    if (callbacks?.RegisterMethod) {
    // Register standard methods
    callbacks.RegisterMethod('getCurrentDataState', () => ({
    data: tableData,
    selectedRows: selectedRows,
    totalCount: tableData.length
    }));

    callbacks.RegisterMethod('isDirty', () => hasChanges);

    callbacks.RegisterMethod('validate', () => {
    if (tableData.length === 0) {
    return { valid: false, errors: ['Table cannot be empty'] };
    }
    return true;
    });

    callbacks.RegisterMethod('reset', () => {
    setTableData(data);
    setSelectedRows([]);
    setHasChanges(false);
    });

    // Register custom business logic methods
    callbacks.RegisterMethod('exportSelectedRows', () => {
    return selectedRows.map(idx => tableData[idx]);
    });

    callbacks.RegisterMethod('deleteSelected', () => {
    const newData = tableData.filter((_, idx) => !selectedRows.includes(idx));
    setTableData(newData);
    setHasChanges(true);
    setSelectedRows([]);
    });
    }
    }, [callbacks, tableData, selectedRows, hasChanges]);

    return <div>{/* Table UI */}</div>;
    }
    // After component compilation
    const componentObject = compiledComponent as ComponentObject;

    // Use standard methods with type safety
    if (componentObject.isDirty && componentObject.isDirty()) {
    console.log('Component has unsaved changes');

    const validation = componentObject.validate?.();
    if (validation === true || validation?.valid) {
    // Safe to proceed
    const currentState = componentObject.getCurrentDataState?.();
    await saveData(currentState);
    } else {
    console.error('Validation failed:', validation?.errors);
    }
    }

    // Use custom methods via invokeMethod
    if (componentObject.hasMethod?.('exportSelectedRows')) {
    const selectedData = componentObject.invokeMethod('exportSelectedRows');
    await exportToFile(selectedData);
    }

    // Reset the component
    componentObject.reset?.();

    Components can declare their supported methods in the spec for static discovery:

    interface ComponentSpec {
    name: string;
    code: string;

    // Optional method declarations for discovery/documentation
    methods?: Array<{
    name: string;
    category?: 'standard' | 'custom';
    description?: string;
    parameters?: Array<{
    name: string;
    type: string; // Free-form type description
    required?: boolean;
    description?: string;
    }>;
    returnType?: string; // Free-form type description
    }>;
    }

    Example declaration:

    const spec: ComponentSpec = {
    name: 'DataTable',
    code: '...',
    methods: [
    {
    name: 'getCurrentDataState',
    category: 'standard',
    description: 'Returns current table data and selection state',
    returnType: '{data: any[], selectedRows: number[], totalCount: number}'
    },
    {
    name: 'exportSelectedRows',
    category: 'custom',
    description: 'Exports currently selected rows',
    returnType: 'any[]'
    },
    {
    name: 'deleteSelected',
    category: 'custom',
    description: 'Deletes selected rows from the table'
    }
    ]
    };
    1. AI Agent Integration: AI agents can introspect component state for analysis
    2. Validation & State Management: Containers can check dirty state and validate before saving
    3. Custom Business Logic: Components can expose domain-specific operations
    4. Framework Agnostic: Works across Angular, React, and other frameworks
    5. Type Safety: Standard methods have full TypeScript support
    6. Discoverability: Method declarations enable static analysis without runtime

    The package includes comprehensive types for component specifications:

    • InteractiveComponentSpec: Full component specification including metadata, props, and initialization
    • ComponentDataRequirement: Defines data loading requirements
    • ComponentOption: Configuration options for components
    • ComponentLibraryDependency: External library dependencies
    • ComponentSpecCategory: Component categorization and metadata

    The included SimpleVectorService provides:

    • Cosine Similarity: Calculate similarity between vectors
    • Euclidean Distance: Measure distance between points
    • K-Nearest Neighbors (KNN): Find similar items
    • Clustering: Group similar items together
    • Dimensionality Reduction: PCA and t-SNE support
    1. Model Selection: Use modelPower parameter wisely - 'lowest' for simple tasks, 'highest' for complex analysis
    2. Batch Operations: Use RunViews for parallel data loading instead of sequential RunView calls
    3. Embedding Caching: Cache embeddings when possible as they're deterministic for the same input
    4. Error Handling: Always check success flags in AI operation results
    5. JSON Parsing: Use resultObject when expecting structured data from AI prompts

    All interfaces are fully typed with TypeScript, providing:

    • IntelliSense support in IDEs
    • Compile-time type checking
    • Better code documentation
    • Reduced runtime errors

    The /forms subpath provides the form-role contract for components that declare componentRole: 'form' — the substrate that lets MJ render runtime-author forms inside Explorer with the same toolbar / save / delete behavior as a CodeGen-generated Angular form.

    Export Purpose
    FormHostProps What the host wrapper passes a form-role React component (entity name, primary key, record snapshot, mode, permissions).
    FormEventNames / FormBeforeSaveArgs / etc. Standard event names + payload types the component emits via callbacks.NotifyEvent.
    FormMethodNames Standard methods the component registers (RequestSave, RequestCancel) so the host toolbar can drive its save flow.
    isFormRole(spec) Type-guard: does this ComponentSpec declare componentRole: 'form'?
    CuratedFormSchema, buildCuratedFormSchema(entityName, provider) Curated, LLM-friendly view of an entity's schema for form authoring — FK references resolved to {entity, displayField}, value lists annotated with allowedValues, audit/virtual/computed fields stripped.
    buildDefaultFormScaffold(entityName, provider) Produces a working form-role ComponentSpec that mirrors the CodeGen Angular default layout. Used as the baseline by the Form Builder agent and the dashboard's "New form" flow.
    buildFixtureFormHostProps(schema, mode?) Synthesizes type-appropriate fixture values for live-preview rendering when no real BaseEntity is available (used by Component Studio preview + the chat artifact viewer's fallback mode).
    getDeclaredFormEntityName(spec) Resolves the entity a form binds to from spec.entityName or spec.dataRequirements.entities[0].name. Pure helper shared by every form-role consumer.

    See /plans/interactive-forms/phase-2-runtime-loop.md for the full architecture, lifecycle, and security model (Create / Modify / Activate / Revert + ownership checks).

    • @memberjunction/core: Core MemberJunction types and interfaces
    • @memberjunction/ai-vectors-memory: Vector operations and similarity calculations

    ISC

    Classes

    ComponentSpec
    ComponentSpecRuntime
    SimpleEntityFieldInfo
    SimpleEntityInfo
    SimpleQueryFieldInfo

    Interfaces

    AfterEventArgs
    BaseEventArgs
    CancelableEventArgs
    ComponentCallbacks
    ComponentChangeRequest
    ComponentDataRequirements
    ComponentEvent
    ComponentEventParameter
    ComponentLibraryDependency
    ComponentMethodInfo
    ComponentObject
    ComponentProperty
    ComponentStyles
    ComponentTestResult
    ComponentTypeDefinition
    ComponentTypeProperty
    ComponentUtilities
    ConstraintViolation
    CustomComponentMethod
    PropertyConstraint
    SimpleAITools
    SimpleEmbedTextParams
    SimpleEmbedTextResult
    SimpleExecutePromptParams
    SimpleExecutePromptResult
    SimpleGeoDataEngine
    SimpleGeoPointResolution
    SimpleMetadata
    SimpleMLListModelsFilter
    SimpleMLModelInfo
    SimpleMLPrediction
    SimpleMLScoreResult
    SimpleMLTools
    SimpleRunQuery
    SimpleRunView
    SimpleSearch
    SimpleSearchFilters
    SimpleSearchParams
    SimpleSearchProviderInfo
    SimpleSearchResult
    SimpleSearchResultItem
    SimpleSearchSourceCounts

    Type Aliases

    ComponentEntityDataRequirement
    ComponentEntitySimplePermission
    ComponentExample
    ComponentOption
    ComponentPrintFunction
    ComponentQueryDataRequirement
    ComponentQueryParameterValue
    ComponentRefreshFunction
    ComponentRole
    SimpleDataContext

    Functions

    BuildComponentCode
    BuildComponentCompleteCode