UNPKG

@uppy/provider-views

Version:

View library for Uppy remote provider plugins.

123 lines (108 loc) 3.33 kB
/* eslint-disable no-param-reassign */ import type { PartialTree, PartialTreeFile, PartialTreeFolder, PartialTreeFolderNode, PartialTreeId, } from '@uppy/core' import shallowClone from './shallowClone.js' /* FROM | TO root | root folder | folder folder ✅︎ | folder ✅︎ file | file ✅︎ file | file ✅︎ folder | folder ✅︎ file | file ✅︎ file | file file | file */ const percolateDown = ( tree: PartialTree, id: PartialTreeId, shouldMarkAsChecked: boolean, ) => { const children = tree.filter( (item) => item.type !== 'root' && item.parentId === id, ) as (PartialTreeFolderNode | PartialTreeFile)[] children.forEach((item) => { item.status = shouldMarkAsChecked && !(item.type === 'file' && item.restrictionError) ? 'checked' : 'unchecked' percolateDown(tree, item.id, shouldMarkAsChecked) }) } /* FROM | TO root | root folder | folder folder | folder [▬] ('partial' status) file | file folder | folder ✅︎ file ✅︎ | file ✅︎ file | file file | file */ const percolateUp = (tree: PartialTree, id: PartialTreeId) => { const folder = tree.find((item) => item.id === id) as PartialTreeFolder if (folder.type === 'root') return const validChildren = tree.filter( (item) => // is a child item.type !== 'root' && item.parentId === folder.id && // does pass validations !(item.type === 'file' && item.restrictionError), ) as (PartialTreeFile | PartialTreeFolderNode)[] const areAllChildrenChecked = validChildren.every( (item) => item.status === 'checked', ) const areAllChildrenUnchecked = validChildren.every( (item) => item.status === 'unchecked', ) if (areAllChildrenChecked) { folder.status = 'checked' } else if (areAllChildrenUnchecked) { folder.status = 'unchecked' } else { folder.status = 'partial' } percolateUp(tree, folder.parentId) } const afterToggleCheckbox = ( oldTree: PartialTree, clickedRange: string[], ): PartialTree => { const tree: PartialTree = shallowClone(oldTree) if (clickedRange.length >= 2) { // We checked two or more items const newlyCheckedItems = tree.filter( (item) => item.type !== 'root' && clickedRange.includes(item.id), ) as (PartialTreeFile | PartialTreeFolderNode)[] newlyCheckedItems.forEach((item) => { if (item.type === 'file') { item.status = item.restrictionError ? 'unchecked' : 'checked' } else { item.status = 'checked' } }) newlyCheckedItems.forEach((item) => { percolateDown(tree, item.id, true) }) percolateUp(tree, newlyCheckedItems[0].parentId) } else { // We checked exactly one item const clickedItem = tree.find((item) => item.id === clickedRange[0]) as | PartialTreeFile | PartialTreeFolderNode clickedItem.status = clickedItem.status === 'checked' ? 'unchecked' : 'checked' percolateDown(tree, clickedItem.id, clickedItem.status === 'checked') percolateUp(tree, clickedItem.parentId) } return tree } export default afterToggleCheckbox