Files
mai-bot/dashboard/src/lib/field-hooks.ts
DrSmoothl aea87e18f1 feat: enhance bot configuration with new sections and JSON field hooks
- Added support for new configuration sections: relationship, database, maisaka, mcp, and plugin_runtime.
- Introduced complex field hooks for handling JSON configurations in chat talk value rules, expression learning lists, and more.
- Updated the field hooks to include schema metadata for better UI representation.
- Refactored the bot configuration page to utilize a more dynamic approach for managing section values and state.
- Improved the configuration schema generation to ensure all top-level sections have UI metadata.
- Added tests to validate the new configuration schema and ensure proper functionality of the JSON field hooks.
2026-04-03 02:46:07 +08:00

102 lines
2.4 KiB
TypeScript

import type { ReactNode } from 'react'
import type { ConfigSchema, FieldSchema } from '@/types/config-schema'
/**
* Hook type for field-level customization
*/
export type FieldHookType = 'replace' | 'wrapper'
/**
* Props passed to a FieldHookComponent
*/
export interface FieldHookComponentProps {
fieldPath: string
value: unknown
onChange?: (value: unknown) => void
children?: ReactNode
schema?: ConfigSchema | FieldSchema
}
/**
* A React component that can be registered as a field hook
*/
export type FieldHookComponent = React.FC<FieldHookComponentProps>
/**
* Registry entry for a field hook
*/
interface FieldHookEntry {
component: FieldHookComponent
type: FieldHookType
}
/**
* Registry for managing field-level hooks
* Supports two types of hooks:
* - replace: Completely replaces the default field renderer
* - wrapper: Wraps the default field renderer with additional functionality
*/
export class FieldHookRegistry {
private hooks: Map<string, FieldHookEntry> = new Map()
/**
* Register a hook for a specific field path
* @param fieldPath The field path (e.g., 'chat.talk_value')
* @param component The React component to register
* @param type The hook type ('replace' or 'wrapper')
*/
register(
fieldPath: string,
component: FieldHookComponent,
type: FieldHookType = 'replace'
): void {
this.hooks.set(fieldPath, { component, type })
}
/**
* Get a registered hook for a specific field path
* @param fieldPath The field path to look up
* @returns The hook entry if found, undefined otherwise
*/
get(fieldPath: string): FieldHookEntry | undefined {
return this.hooks.get(fieldPath)
}
/**
* Check if a hook is registered for a specific field path
* @param fieldPath The field path to check
* @returns True if a hook is registered, false otherwise
*/
has(fieldPath: string): boolean {
return this.hooks.has(fieldPath)
}
/**
* Unregister a hook for a specific field path
* @param fieldPath The field path to unregister
*/
unregister(fieldPath: string): void {
this.hooks.delete(fieldPath)
}
/**
* Clear all registered hooks
*/
clear(): void {
this.hooks.clear()
}
/**
* Get all registered field paths
* @returns Array of registered field paths
*/
getAllPaths(): string[] {
return Array.from(this.hooks.keys())
}
}
/**
* Singleton instance of the field hook registry
*/
export const fieldHooks = new FieldHookRegistry()