{"version":3,"file":"useSelectableRow.mjs","sources":["../../../../../../src/components/va-data-table/hooks/useSelectableRow.ts"],"sourcesContent":["import { Ref, computed, watch, ref, PropType, ExtractPropTypes } from 'vue'\n\nimport { getItemKey } from './useRows'\nimport { useSelectableProp, useItemsTrackByProp } from './useCommonProps'\n\nimport type { DataTableRow, DataTableItem, DataTableSelectMode, DataTableItemKey } from '../types'\n\nexport const useSelectableProps = {\n  ...useSelectableProp,\n  ...useItemsTrackByProp,\n  modelValue: { type: Array as PropType<(DataTableItem | DataTableItemKey)[]> },\n  selectMode: { type: String as PropType<DataTableSelectMode>, default: 'multiple' },\n}\n\nexport type TEmits = 'update:modelValue' | 'selectionChange'\nexport type TSelectionChange = {\n  currentSelectedItems: (DataTableItem | DataTableItemKey)[],\n  previousSelectedItems: (DataTableItem | DataTableItemKey)[],\n}\nexport type TSelectableEmits = (event: TEmits, arg: (DataTableItem | DataTableItemKey)[] | TSelectionChange) => void\n\nexport const useSelectableRow = (\n  paginatedRows: Ref<DataTableRow[]>,\n  props: ExtractPropTypes<typeof useSelectableProps>,\n  emit: TSelectableEmits,\n) => {\n  const selectedItemsFallback = ref<(DataTableItem | DataTableItemKey)[]>([])\n\n  const selectedItemsSync = computed<(DataTableItem | DataTableItemKey)[]>({\n    get () {\n      if (props.modelValue === undefined) {\n        return selectedItemsFallback.value\n      } else {\n        return props.modelValue\n      }\n    },\n\n    set (modelValue) {\n      if (props.modelValue === undefined) {\n        selectedItemsFallback.value = modelValue\n      }\n\n      emit('update:modelValue', modelValue)\n    },\n  })\n\n  const prevSelectedRowIndex = ref(-1)\n\n  // clear all the selected rows when the `select-mode`'s value changes from multiple to single\n  // (though it's safe enough to leave a selected item when changing from single to multiple\n  watch(() => props.selectMode, (newSelectMode, oldSelectMode) => {\n    if (newSelectMode === 'single' && oldSelectMode === 'multiple') {\n      selectedItemsSync.value = []\n      setPrevSelectedRowIndex(-1)\n    }\n  })\n\n  // watch for rows changes (happens when filtering is applied e.g.)\n  watch(paginatedRows, () => { setPrevSelectedRowIndex(-1) })\n\n  // emit the \"selection-change\" event each time the selection changes\n  watch(selectedItemsSync, (currentSelectedItems, previousSelectedItems = []) => {\n    emit('selectionChange', {\n      currentSelectedItems,\n      previousSelectedItems,\n    })\n  }, { immediate: true })\n\n  // if user provide `props.itemsTrackBy !== ''` than `selectedItemsSync` and `props.modelValue`\n  // would be the array with keys (received from `props.itemsTrackBy`)\n  // else they would be the array with source (`DataTableItem` type)\n  const getKey = (source: DataTableItem) => getItemKey(source, props.itemsTrackBy)\n\n  const noRowsSelected = computed(() => (\n    !paginatedRows.value.some(({ source }) => selectedItemsSync.value.includes(getKey(source)))\n  ))\n\n  const allRowsSelected = computed(() => {\n    if (paginatedRows.value.length === 0) { return false }\n\n    return paginatedRows.value.every(({ source }) => selectedItemsSync.value.includes(getKey(source)))\n  })\n\n  const severalRowsSelected = computed(() => !noRowsSelected.value && !allRowsSelected.value)\n\n  function isRowSelected (row: DataTableRow) {\n    return selectedItemsSync.value.includes(getKey(row.source))\n  }\n\n  function selectAllRows () {\n    selectedItemsSync.value = [...new Set([\n      ...selectedItemsSync.value,\n      ...paginatedRows.value.map(row => getKey(row.source)),\n    ])]\n  }\n\n  function unselectAllRows () {\n    const paginatedRowsKeys = paginatedRows.value.map(row => getKey(row.source))\n\n    selectedItemsSync.value = selectedItemsSync.value\n      .filter((item) => !paginatedRowsKeys.includes(item))\n  }\n\n  // The one calling this function must guarantee that the row isn't already selected\n  function selectRow (row: DataTableRow) {\n    selectedItemsSync.value = [...selectedItemsSync.value, getKey(row.source)]\n  }\n\n  function selectOnlyRow (row: DataTableRow) {\n    selectedItemsSync.value = [getKey(row.source)]\n  }\n\n  // The one calling this function must guarantee that the row is selected\n  function unselectRow (row: DataTableRow) {\n    const index = selectedItemsSync.value.findIndex(item => item === getKey(row.source))\n\n    selectedItemsSync.value = [\n      ...selectedItemsSync.value.slice(0, index),\n      ...selectedItemsSync.value.slice(index + 1),\n    ]\n  }\n\n  function setPrevSelectedRowIndex (rowInitialIndex: number) {\n    if (rowInitialIndex === -1) {\n      prevSelectedRowIndex.value = -1\n    } else {\n      const prevSelectedRow = paginatedRows.value.find(row => row.initialIndex === rowInitialIndex)\n\n      prevSelectedRow\n        ? prevSelectedRowIndex.value = paginatedRows.value.indexOf(prevSelectedRow)\n        : prevSelectedRowIndex.value = -1\n    }\n  }\n\n  function getRowsToSelect (targetIndex: number) {\n    let start\n    let end\n\n    if (isRowSelected(paginatedRows.value[prevSelectedRowIndex.value])) {\n      start = Math.min(prevSelectedRowIndex.value, targetIndex)\n      end = Math.max(prevSelectedRowIndex.value, targetIndex)\n    } else {\n      start = Math.min(prevSelectedRowIndex.value + 1, targetIndex)\n      end = Math.max(prevSelectedRowIndex.value - 1, targetIndex)\n    }\n\n    return paginatedRows.value.slice(start, end + 1)\n  }\n\n  function mergeSelection (rowsToSelect: DataTableRow[]) {\n    const rowsToSelectedItems = rowsToSelect.map(row => getKey(row.source))\n\n    if (noRowsSelected.value) {\n      selectedItemsSync.value = rowsToSelectedItems\n      return\n    }\n\n    const isInternalSelection = rowsToSelectedItems.every(item => selectedItemsSync.value.includes(item))\n\n    if (isInternalSelection) {\n      selectedItemsSync.value = selectedItemsSync.value.filter(item => !rowsToSelectedItems.includes(item))\n      return\n    }\n\n    selectedItemsSync.value = [...new Set([\n      ...selectedItemsSync.value,\n      ...rowsToSelectedItems,\n    ])]\n  }\n\n  function toggleRowSelection (row: DataTableRow) {\n    if (!props.selectable) {\n      return\n    }\n\n    if (isRowSelected(row)) {\n      unselectRow(row)\n      props.selectMode === 'single' ? setPrevSelectedRowIndex(-1) : setPrevSelectedRowIndex(row.initialIndex)\n    } else {\n      props.selectMode === 'single' ? selectOnlyRow(row) : selectRow(row)\n      setPrevSelectedRowIndex(row.initialIndex)\n    }\n  }\n\n  function ctrlSelectRow (row: DataTableRow) {\n    if (!props.selectable) {\n      return\n    }\n\n    toggleRowSelection(row)\n  }\n\n  function shiftSelectRows (row: DataTableRow) {\n    if (!props.selectable) {\n      return\n    }\n\n    if (props.selectMode === 'single' || prevSelectedRowIndex.value === -1) {\n      return toggleRowSelection(row)\n    }\n\n    const targetIndex = paginatedRows.value.indexOf(row)\n    mergeSelection(getRowsToSelect(targetIndex))\n    setPrevSelectedRowIndex(-1)\n  }\n\n  function toggleBulkSelection () {\n    if (allRowsSelected.value) {\n      unselectAllRows()\n    } else {\n      selectAllRows()\n    }\n\n    setPrevSelectedRowIndex(-1)\n  }\n\n  return {\n    ctrlSelectRow,\n    shiftSelectRows,\n    toggleRowSelection,\n    toggleBulkSelection,\n    isRowSelected,\n    noRowsSelected,\n    severalRowsSelected,\n    allRowsSelected,\n  }\n}\n"],"names":[],"mappings":"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"}