/** * File selection composable * Provides reactive selection management for file manager */ import { ref, computed } from 'vue' import type { Ref, ComputedRef } from 'vue' import { CollectionObject } from '@DocumentsManager/models/collection' import { EntityObject } from '@DocumentsManager/models/entity' type NodeRecord = CollectionObject | EntityObject export interface UseFileSelectionOptions { multiple?: boolean allowFolders?: boolean allowFiles?: boolean } export function useFileSelection(options: UseFileSelectionOptions = {}) { const { multiple = true, allowFolders = true, allowFiles = true, } = options const selectedIds: Ref> = ref(new Set()) const selectedNodes: Ref> = ref(new Map()) const count: ComputedRef = computed(() => selectedIds.value.size) const hasSelection: ComputedRef = computed(() => selectedIds.value.size > 0) const selectedIdArray: ComputedRef = computed(() => Array.from(selectedIds.value)) const selectedNodeArray: ComputedRef = computed(() => Array.from(selectedNodes.value.values())) const selectedCollections: ComputedRef = computed(() => selectedNodeArray.value.filter((node): node is CollectionObject => node instanceof CollectionObject), ) const selectedEntities: ComputedRef = computed(() => selectedNodeArray.value.filter((node): node is EntityObject => node instanceof EntityObject), ) const isSelected = (nodeId: string): boolean => selectedIds.value.has(nodeId) const isTypeAllowed = (node: NodeRecord): boolean => { if (node instanceof CollectionObject && !allowFolders) return false if (node instanceof EntityObject && !allowFiles) return false return true } const select = (node: NodeRecord) => { if (!isTypeAllowed(node)) return if (!multiple) { selectedIds.value.clear() selectedNodes.value.clear() } const nodeId = String(node.identifier) selectedIds.value.add(nodeId) selectedNodes.value.set(nodeId, node) } const deselect = (nodeId: string) => { selectedIds.value.delete(nodeId) selectedNodes.value.delete(nodeId) } const toggle = (node: NodeRecord) => { const nodeId = String(node.identifier) if (isSelected(nodeId)) { deselect(nodeId) return } select(node) } const selectMultiple = (nodes: NodeRecord[]) => { if (!multiple) { const lastNode = nodes[nodes.length - 1] if (lastNode && isTypeAllowed(lastNode)) { selectedIds.value.clear() selectedNodes.value.clear() const nodeId = String(lastNode.identifier) selectedIds.value.add(nodeId) selectedNodes.value.set(nodeId, lastNode) } return } for (const node of nodes) { if (isTypeAllowed(node)) { const nodeId = String(node.identifier) selectedIds.value.add(nodeId) selectedNodes.value.set(nodeId, node) } } } const selectAll = (nodes: NodeRecord[]) => { if (!multiple) return selectMultiple(nodes) } const clear = () => { selectedIds.value.clear() selectedNodes.value.clear() } const setSelection = (nodes: NodeRecord[]) => { clear() selectMultiple(nodes) } return { selectedIds, selectedNodes, count, hasSelection, selectedIdArray, selectedNodeArray, selectedCollections, selectedEntities, isSelected, select, deselect, toggle, selectMultiple, selectAll, clear, setSelection, } } export default useFileSelection