import { MAX_FEATHER } from "@/masks/feather"; import type { ParamDefinition } from "@/params"; import type { BaseMaskParams, MaskDefaultContext, MaskDefinition, MaskInteractionResult, MaskSnapArgs, MaskSnapResult, MaskType, } from "@/masks/types"; import type { HugeiconsIconProps } from "@hugeicons/react"; import { DefinitionRegistry } from "@/params/registry"; export type MaskIconProps = { icon: HugeiconsIconProps["icon"]; strokeWidth?: number; }; const BASE_MASK_PARAM_DEFINITIONS: ParamDefinition< keyof BaseMaskParams & string >[] = [ { key: "feather", label: "Feather", type: "number", default: 0, min: 0, max: MAX_FEATHER, step: 1, unit: "percent", }, { key: "strokeWidth", label: "Stroke width", type: "number", default: 0, min: 0, max: 100, step: 1, }, { key: "strokeColor", label: "Stroke color", type: "color", default: "#ffffff", }, ]; export interface RegisteredMaskDefinition { type: MaskType; name: string; features: MaskDefinition["features"]; params: ParamDefinition[]; renderer: MaskDefinition["renderer"]; interaction: { getInteraction(args: { params: BaseMaskParams; bounds: Parameters< MaskDefinition["interaction"]["getInteraction"] >[0]["bounds"]; displayScale: number; scaleX: number; scaleY: number; }): MaskInteractionResult; snap?(args: MaskSnapArgs): MaskSnapResult; }; isActive?: (params: BaseMaskParams) => boolean; buildDefault( context: MaskDefaultContext, ): ReturnType["buildDefault"]>; computeParamUpdate( args: Parameters["computeParamUpdate"]>[0], ): ReturnType["computeParamUpdate"]>; icon: MaskIconProps; } export class MasksRegistry extends DefinitionRegistry< MaskType, RegisteredMaskDefinition > { constructor() { super("mask"); } registerMask({ definition, icon, }: { definition: MaskDefinition; icon: MaskIconProps; }): void { const withBaseParams: RegisteredMaskDefinition = { type: definition.type, name: definition.name, features: definition.features, params: [...definition.params, ...BASE_MASK_PARAM_DEFINITIONS], renderer: definition.renderer, interaction: { getInteraction(args) { return definition.interaction.getInteraction(args as never); }, snap: definition.interaction.snap ? (args) => definition.interaction.snap?.(args as never) as never : undefined, }, isActive: definition.isActive ? (params) => definition.isActive?.(params as TParams) ?? true : undefined, buildDefault(context) { return definition.buildDefault(context); }, computeParamUpdate(args) { return definition.computeParamUpdate(args as never); }, icon, }; this.register({ key: definition.type, definition: withBaseParams, }); } } export const masksRegistry = new MasksRegistry();