{"version":3,"file":"builder.mjs","sourceRoot":"","sources":["../../src/ui/builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,wBAAwB;AA8B9D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,aAAa,CAI3B,IAAc,EACd,MAAoB,EACpB,OAAa,EAAqB;IAElC,OAAO,CAAC,GAAG,IAA2D,EAAE,EAAE;QACxE,kCAAkC;QAClC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YAElC,yEAAyE;YACzE,+CAA+C;YAC/C,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,IAAI,YAAY,CAAC,CAAC;YACxD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,wCAAwC;QACxC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CACtB,CAAC,WAAW,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;YAC1B,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC9B,OAAO;oBACL,GAAG,WAAW;oBACd,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC;iBACnB,CAAC;YACJ,CAAC;YAED,OAAO,WAAW,CAAC;QACrB,CAAC,EACD,EAAE,IAAI,EAAE,CACT,CAAC;QAEF,yEAAyE;QACzE,+CAA+C;QAC/C,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,IAAI,YAAY,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import type { Struct } from '@metamask/superstruct';\nimport { assertStruct, isPlainObject } from '@metamask/utils';\n\nimport type { Component } from './components';\nimport type { NodeType } from './nodes';\n\n/**\n * A function that builds a {@link Component}. This infers the proper args type\n * from the given node.\n *\n * @internal\n */\ntype NodeBuilder<Node extends Component, Keys extends (keyof Node)[]> =\n  Omit<Node, 'type'> extends Record<string, never>\n    ? (...args: []) => Node\n    : (...args: [Omit<Node, 'type'>] | NodeArrayType<Node, Keys>) => Node;\n\n/**\n * Map from an array of node keys to the corresponding array type.\n *\n * @example\n * type Node = { type: 'node'; a: string; b: number; c: boolean };\n * type Keys = ['a', 'b', 'c'];\n *\n * type NodeArray = NodeArrayType<Node, Keys>; // [string, number, boolean]\n * @internal\n */\ntype NodeArrayType<Node extends Component, Keys extends (keyof Node)[]> = {\n  [Key in keyof Keys]: Node[Keys[Key]];\n};\n\n/**\n * A function that returns a function to \"build\" a {@link Component}. It infers\n * the type of the component from the given struct, and performs validation on\n * the created component.\n *\n * The returned function can handle the node arguments in two ways:\n * 1. As a single object, with the keys corresponding to the node's properties,\n * excluding the `type` property.\n * 2. As an array of arguments, with the order corresponding to the given keys.\n *\n * @param type - The type of the component to build.\n * @param struct - The struct to use to validate the component.\n * @param keys - The keys of the component to use as arguments to the builder.\n * The order of the keys determines the order of the arguments.\n * @returns A function that builds a component of the given type.\n * @internal\n */\nexport function createBuilder<\n  Node extends Component,\n  Keys extends (keyof Node)[] = [],\n>(\n  type: NodeType,\n  struct: Struct<Node>,\n  keys: Keys = [] as unknown as Keys,\n): NodeBuilder<Node, Keys> {\n  return (...args: [Omit<Node, 'type'>] | NodeArrayType<Node, Keys> | []) => {\n    // Node passed as a single object.\n    if (args.length === 1 && isPlainObject(args[0])) {\n      const node = { ...args[0], type };\n\n      // The user could be passing invalid values to the builder, so we need to\n      // validate them as per the component's struct.\n      assertStruct(node, struct, `Invalid ${type} component`);\n      return node;\n    }\n\n    // Node passed as an array of arguments.\n    const node = keys.reduce<Partial<Component>>(\n      (partialNode, key, index) => {\n        if (args[index] !== undefined) {\n          return {\n            ...partialNode,\n            [key]: args[index],\n          };\n        }\n\n        return partialNode;\n      },\n      { type },\n    );\n\n    // The user could be passing invalid values to the builder, so we need to\n    // validate them as per the component's struct.\n    assertStruct(node, struct, `Invalid ${type} component`);\n    return node;\n  };\n}\n"]}