{"version":3,"sources":["../src/hooks/use-tree.ts"],"sourcesContent":["import { randomId } from \"@copilotkit/shared\";\nimport { useCallback, useReducer } from \"react\";\n\nexport type TreeNodeId = string;\n\nexport interface TreeNode {\n  id: TreeNodeId;\n  value: string;\n  children: TreeNode[];\n  parentId?: TreeNodeId;\n  categories: Set<string>;\n}\n\nexport type Tree = TreeNode[];\n\nexport interface UseTreeReturn {\n  tree: Tree;\n  addElement: (value: string, categories: string[], parentId?: TreeNodeId) => TreeNodeId;\n  printTree: (categories: string[]) => string;\n  removeElement: (id: TreeNodeId) => void;\n}\n\nconst findNode = (nodes: Tree, id: TreeNodeId): TreeNode | undefined => {\n  for (const node of nodes) {\n    if (node.id === id) {\n      return node;\n    }\n    const result = findNode(node.children, id);\n    if (result) {\n      return result;\n    }\n  }\n  return undefined;\n};\n\nconst removeNode = (nodes: Tree, id: TreeNodeId): Tree => {\n  return nodes.reduce((result: Tree, node) => {\n    if (node.id !== id) {\n      const newNode = { ...node, children: removeNode(node.children, id) };\n      result.push(newNode);\n    }\n    return result;\n  }, []);\n};\n\nconst addNode = (nodes: Tree, newNode: TreeNode, parentId?: TreeNodeId): Tree => {\n  if (!parentId) {\n    return [...nodes, newNode];\n  }\n  return nodes.map((node) => {\n    if (node.id === parentId) {\n      return { ...node, children: [...node.children, newNode] };\n    } else if (node.children.length) {\n      return { ...node, children: addNode(node.children, newNode, parentId) };\n    }\n    return node;\n  });\n};\n\nconst treeIndentationRepresentation = (index: number, indentLevel: number): string => {\n  if (indentLevel === 0) {\n    return (index + 1).toString();\n  } else if (indentLevel === 1) {\n    return String.fromCharCode(65 + index); // 65 is the ASCII value for 'A'\n  } else if (indentLevel === 2) {\n    return String.fromCharCode(97 + index); // 97 is the ASCII value for 'a'\n  } else {\n    return \"-\";\n  }\n};\n\nconst printNode = (node: TreeNode, prefix = \"\", indentLevel = 0): string => {\n  const indent = \" \".repeat(3).repeat(indentLevel);\n\n  const prefixPlusIndentLength = prefix.length + indent.length;\n  const subsequentLinesPrefix = \" \".repeat(prefixPlusIndentLength);\n\n  const valueLines = node.value.split(\"\\n\");\n\n  const outputFirstLine = `${indent}${prefix}${valueLines[0]}`;\n  const outputSubsequentLines = valueLines\n    .slice(1)\n    .map((line) => `${subsequentLinesPrefix}${line}`)\n    .join(\"\\n\");\n\n  let output = `${outputFirstLine}\\n`;\n  if (outputSubsequentLines) {\n    output += `${outputSubsequentLines}\\n`;\n  }\n\n  const childPrePrefix = \" \".repeat(prefix.length);\n\n  node.children.forEach(\n    (child, index) =>\n      (output += printNode(\n        child,\n        `${childPrePrefix}${treeIndentationRepresentation(index, indentLevel + 1)}. `,\n        indentLevel + 1,\n      )),\n  );\n  return output;\n};\n\n// Action types\ntype Action =\n  | {\n      type: \"ADD_NODE\";\n      value: string;\n      parentId?: string;\n      id: string;\n      categories: string[];\n    }\n  | { type: \"REMOVE_NODE\"; id: string };\n\n// Reducer function\nfunction treeReducer(state: Tree, action: Action): Tree {\n  switch (action.type) {\n    case \"ADD_NODE\": {\n      const { value, parentId, id: newNodeId } = action;\n      const newNode: TreeNode = {\n        id: newNodeId,\n        value,\n        children: [],\n        categories: new Set(action.categories),\n      };\n\n      try {\n        return addNode(state, newNode, parentId);\n      } catch (error) {\n        console.error(`Error while adding node with id ${newNodeId}: ${error}`);\n        return state;\n      }\n    }\n    case \"REMOVE_NODE\":\n      return removeNode(state, action.id);\n    default:\n      return state;\n  }\n}\n\n// useTree hook\nconst useTree = (): UseTreeReturn => {\n  const [tree, dispatch] = useReducer(treeReducer, []);\n\n  const addElement = useCallback(\n    (value: string, categories: string[], parentId?: string): TreeNodeId => {\n      const newNodeId = randomId(); // Generate new ID outside of dispatch\n      dispatch({\n        type: \"ADD_NODE\",\n        value,\n        parentId,\n        id: newNodeId,\n        categories: categories,\n      });\n      return newNodeId; // Return the new ID\n    },\n    [],\n  );\n\n  const removeElement = useCallback((id: TreeNodeId): void => {\n    dispatch({ type: \"REMOVE_NODE\", id });\n  }, []);\n\n  const printTree = useCallback(\n    (categories: string[]): string => {\n      const categoriesSet = new Set(categories);\n\n      let output = \"\";\n      tree.forEach((node, index) => {\n        // if the node does not have any of the desired categories, continue to the next node\n        if (!setsHaveIntersection(categoriesSet, node.categories)) {\n          return;\n        }\n\n        // add a new line before each node except the first one\n        if (index !== 0) {\n          output += \"\\n\";\n        }\n\n        output += printNode(node, `${treeIndentationRepresentation(index, 0)}. `);\n      });\n      return output;\n    },\n    [tree],\n  );\n\n  return { tree, addElement, printTree, removeElement };\n};\n\nexport default useTree;\n\nfunction setsHaveIntersection<T>(setA: Set<T>, setB: Set<T>): boolean {\n  const [smallerSet, largerSet] = setA.size <= setB.size ? [setA, setB] : [setB, setA];\n\n  for (let item of smallerSet) {\n    if (largerSet.has(item)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n"],"mappings":"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","names":[]}