{"version":3,"file":"canDropItemOnFolder.mjs","sources":["../../../../admin/src/future/utils/canDropItemOnFolder.ts"],"sourcesContent":["import type { FolderNode } from '../../../../shared/contracts/folders';\nimport type { DragItemData } from '../types/dnd';\n\n// TODO: permission-aware droppables — server validates in v1.\n\nexport interface CanDropItemOnFolderParams {\n  items: DragItemData[];\n  targetFolderId: number;\n  folderStructure: FolderNode[];\n}\n\nconst findNode = (nodes: FolderNode[], id: number): FolderNode | null => {\n  for (const node of nodes) {\n    if (node.id === id) {\n      return node;\n    }\n\n    const found = findNode(node.children, id);\n    if (found) {\n      return found;\n    }\n  }\n\n  return null;\n};\n\nconst collectDescendantIds = (node: FolderNode): Set<number> => {\n  const ids = new Set<number>();\n\n  const walk = (current: FolderNode) => {\n    for (const child of current.children) {\n      if (child.id != null) {\n        ids.add(child.id);\n      }\n      walk(child);\n    }\n  };\n\n  walk(node);\n  return ids;\n};\n\nexport const isFolderDescendantOf = (\n  folderStructure: FolderNode[],\n  ancestorId: number,\n  candidateId: number\n): boolean => {\n  if (ancestorId === candidateId) {\n    return true;\n  }\n\n  const ancestorNode = findNode(folderStructure, ancestorId);\n  if (!ancestorNode) {\n    return false;\n  }\n\n  return collectDescendantIds(ancestorNode).has(candidateId);\n};\n\nexport const canDropItemOnFolder = ({\n  items,\n  targetFolderId,\n  folderStructure,\n}: CanDropItemOnFolderParams): boolean => {\n  if (items.length === 0) {\n    return false;\n  }\n\n  const draggedFolderIds = new Set(\n    items\n      .filter((item): item is Extract<DragItemData, { kind: 'folder' }> => item.kind === 'folder')\n      .map((item) => item.id)\n  );\n\n  if (draggedFolderIds.has(targetFolderId)) {\n    return false;\n  }\n\n  for (const folderId of draggedFolderIds) {\n    if (isFolderDescendantOf(folderStructure, folderId, targetFolderId)) {\n      return false;\n    }\n  }\n\n  for (const item of items) {\n    if (item.kind === 'file' && item.folderId === targetFolderId) {\n      return false;\n    }\n\n    if (item.kind === 'folder' && item.parentId === targetFolderId) {\n      return false;\n    }\n  }\n\n  return true;\n};\n"],"names":["findNode","nodes","id","node","found","children","collectDescendantIds","ids","Set","walk","current","child","add","isFolderDescendantOf","folderStructure","ancestorId","candidateId","ancestorNode","has","canDropItemOnFolder","items","targetFolderId","length","draggedFolderIds","filter","item","kind","map","folderId","parentId"],"mappings":"AAWA,MAAMA,QAAAA,GAAW,CAACC,KAAAA,EAAqBC,EAAAA,GAAAA;IACrC,KAAK,MAAMC,QAAQF,KAAAA,CAAO;QACxB,IAAIE,IAAAA,CAAKD,EAAE,KAAKA,EAAAA,EAAI;YAClB,OAAOC,IAAAA;AACT,QAAA;AAEA,QAAA,MAAMC,KAAAA,GAAQJ,QAAAA,CAASG,IAAAA,CAAKE,QAAQ,EAAEH,EAAAA,CAAAA;AACtC,QAAA,IAAIE,KAAAA,EAAO;YACT,OAAOA,KAAAA;AACT,QAAA;AACF,IAAA;IAEA,OAAO,IAAA;AACT,CAAA;AAEA,MAAME,uBAAuB,CAACH,IAAAA,GAAAA;AAC5B,IAAA,MAAMI,MAAM,IAAIC,GAAAA,EAAAA;AAEhB,IAAA,MAAMC,OAAO,CAACC,OAAAA,GAAAA;AACZ,QAAA,KAAK,MAAMC,KAAAA,IAASD,OAAAA,CAAQL,QAAQ,CAAE;YACpC,IAAIM,KAAAA,CAAMT,EAAE,IAAI,IAAA,EAAM;gBACpBK,GAAAA,CAAIK,GAAG,CAACD,KAAAA,CAAMT,EAAE,CAAA;AAClB,YAAA;YACAO,IAAAA,CAAKE,KAAAA,CAAAA;AACP,QAAA;AACF,IAAA,CAAA;IAEAF,IAAAA,CAAKN,IAAAA,CAAAA;IACL,OAAOI,GAAAA;AACT,CAAA;AAEO,MAAMM,oBAAAA,GAAuB,CAClCC,eAAAA,EACAC,UAAAA,EACAC,WAAAA,GAAAA;AAEA,IAAA,IAAID,eAAeC,WAAAA,EAAa;QAC9B,OAAO,IAAA;AACT,IAAA;IAEA,MAAMC,YAAAA,GAAejB,SAASc,eAAAA,EAAiBC,UAAAA,CAAAA;AAC/C,IAAA,IAAI,CAACE,YAAAA,EAAc;QACjB,OAAO,KAAA;AACT,IAAA;IAEA,OAAOX,oBAAAA,CAAqBW,YAAAA,CAAAA,CAAcC,GAAG,CAACF,WAAAA,CAAAA;AAChD;AAEO,MAAMG,sBAAsB,CAAC,EAClCC,KAAK,EACLC,cAAc,EACdP,eAAe,EACW,GAAA;IAC1B,IAAIM,KAAAA,CAAME,MAAM,KAAK,CAAA,EAAG;QACtB,OAAO,KAAA;AACT,IAAA;AAEA,IAAA,MAAMC,mBAAmB,IAAIf,GAAAA,CAC3BY,KAAAA,CACGI,MAAM,CAAC,CAACC,IAAAA,GAA4DA,IAAAA,CAAKC,IAAI,KAAK,QAAA,CAAA,CAClFC,GAAG,CAAC,CAACF,IAAAA,GAASA,KAAKvB,EAAE,CAAA,CAAA;IAG1B,IAAIqB,gBAAAA,CAAiBL,GAAG,CAACG,cAAAA,CAAAA,EAAiB;QACxC,OAAO,KAAA;AACT,IAAA;IAEA,KAAK,MAAMO,YAAYL,gBAAAA,CAAkB;QACvC,IAAIV,oBAAAA,CAAqBC,eAAAA,EAAiBc,QAAAA,EAAUP,cAAAA,CAAAA,EAAiB;YACnE,OAAO,KAAA;AACT,QAAA;AACF,IAAA;IAEA,KAAK,MAAMI,QAAQL,KAAAA,CAAO;AACxB,QAAA,IAAIK,KAAKC,IAAI,KAAK,UAAUD,IAAAA,CAAKG,QAAQ,KAAKP,cAAAA,EAAgB;YAC5D,OAAO,KAAA;AACT,QAAA;AAEA,QAAA,IAAII,KAAKC,IAAI,KAAK,YAAYD,IAAAA,CAAKI,QAAQ,KAAKR,cAAAA,EAAgB;YAC9D,OAAO,KAAA;AACT,QAAA;AACF,IAAA;IAEA,OAAO,IAAA;AACT;;;;"}