import { ref, type Ref } from 'vue' export type CheckedItemsInterface = { /** * Массив выбранных элементов */ checkedItems: Ref /** * Метод проверки выбран ли элемент * * @param item - элемент */ isChecked(item: any): boolean /** * Метод очищения выбранных элементов * * @param onCheckItem - хук, срабатывающий после очищения */ clearChecked(onCheckItem?: (items: any[]) => void): void /** * Метод смены типа на одиночный или множественный выбор * * @param newType - тип */ changeType(newType: 'one' | 'many'): void /** * Метод отметки элемента * * @param item - элемент * @param onCheckItem - хук, срабатывающий после отметки элемента * @param canCheckExactItem - callback, устанавливающий можно ли отметить конкретный элемент */ check( item: any, onCheckItem?: (items: any[]) => void, canCheckExactItem?: (item: any) => boolean,): void /** * Метод отметки всех элементов * * @param items - массив элементов * @param onCheckItem - хук, срабатывающий после отметки элемента * @param canCheckExactItem - callback, устанавливающий можно ли отметить конкретный элемент */ checkAll( items: any[], onCheckItem?: (items: any[]) => void, canCheckExactItem?: (item: any) => boolean, ): void } export default function useCheckedItems( defaultCheckedItems: any[] = [], type: 'one' | 'many' = 'many', ): CheckedItemsInterface { const checkedItems: Ref = ref([...defaultCheckedItems]) const isChecked = (item: any) => Boolean(checkedItems.value.find((i) => ( i?.id && i.id === item?.id ))) const clearChecked = (onCheckItem?: (items: any[]) => void) => { checkedItems.value = [] onCheckItem?.(checkedItems.value) } const changeType = (newType: 'one' | 'many') => { clearChecked() type = newType } const check = ( item: any, onCheckItem?: (items: any[]) => void, canCheckExactItem?: (item: any) => boolean, ) => { if (!item?.id) return if (!checkedItems.value.find((c) => (c?.id === item.id))) { if (canCheckExactItem && !canCheckExactItem(item)) return if (type === 'many') checkedItems.value.push(item) else checkedItems.value = [item] } else checkedItems.value = checkedItems.value.filter((c) => (c?.id && c.id !== item.id)) onCheckItem?.(checkedItems.value) } const checkAll = ( items: any[], onCheckItem?: (items: any[]) => void, canCheckExactItem?: (item: any) => boolean, ) => { if (type !== 'many') { clearChecked(onCheckItem) return } items = items.filter((item) => Boolean(item?.id)) if (!items.length) return const checkedIds = checkedItems.value.filter((item) => Boolean(item?.id)).map((item) => item.id) const newIds: any[] = items.map((item) => item.id) items = items.filter((item) => ( !checkedIds.includes(item.id) && (!canCheckExactItem || canCheckExactItem(item)) )) checkedItems.value = [ ...checkedItems.value.filter((item) => ( item?.id && (!newIds.includes(item.id) || (items.length && (!canCheckExactItem || canCheckExactItem?.(item)))) )), ...items, ] onCheckItem?.(checkedItems.value) } return { checkedItems, isChecked, check, clearChecked, checkAll, changeType, } }