Skip to content

Commit

Permalink
feat: allow linking data row sub rows selection
Browse files Browse the repository at this point in the history
  • Loading branch information
Bryan Lee committed May 24, 2022
1 parent 6f10317 commit ca59b49
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 27 deletions.
90 changes: 64 additions & 26 deletions src/lib/plugins/addSelectedRows.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { DataBodyRow, type BodyRow } from '$lib/bodyRows';
import type { NewTablePropSet, TablePlugin } from '$lib/types/TablePlugin';
import { recordSetStore, type RecordSetStore } from '$lib/utils/store';
import { keyed } from 'svelte-keyed';
import { derived, type Readable, type Updater, type Writable } from 'svelte/store';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export interface SelectedRowsConfig<Item> {
initialSelectedDataIds?: Record<string, boolean>;
linkDataSubRows?: boolean;
}

export interface SelectedRowsState<Item> {
Expand All @@ -30,58 +30,88 @@ export type SelectedRowsPropSet = NewTablePropSet<{

const isAllSubRowsSelectedForRow = <Item>(
row: BodyRow<Item>,
$selectedDataIds: Record<string, boolean>
$selectedDataIds: Record<string, boolean>,
linkDataSubRows: boolean
): boolean => {
if (row instanceof DataBodyRow) {
return $selectedDataIds[row.dataId] === true;
if (!linkDataSubRows || row.subRows === undefined) {
return $selectedDataIds[row.dataId] === true;
}
}
if (row.subRows === undefined) {
return false;
}
return row.subRows.every((subRow) => isAllSubRowsSelectedForRow(subRow, $selectedDataIds));
return row.subRows.every((subRow) =>
isAllSubRowsSelectedForRow(subRow, $selectedDataIds, linkDataSubRows)
);
};

const isSomeSubRowsSelectedForRow = <Item>(
row: BodyRow<Item>,
$selectedDataIds: Record<string, boolean>
$selectedDataIds: Record<string, boolean>,
linkDataSubRows: boolean
): boolean => {
if (row instanceof DataBodyRow) {
return $selectedDataIds[row.dataId] === true;
if (!linkDataSubRows || row.subRows === undefined) {
return $selectedDataIds[row.dataId] === true;
}
}
if (row.subRows === undefined) {
return false;
}
return row.subRows.some((subRow) => isAllSubRowsSelectedForRow(subRow, $selectedDataIds));
return row.subRows.some((subRow) =>
isAllSubRowsSelectedForRow(subRow, $selectedDataIds, linkDataSubRows)
);
};

const updateSelectedDataIds = <Item>(
const writeSelectedDataIds = <Item>(
row: BodyRow<Item>,
value: boolean,
$selectedDataIds: Record<string, boolean>
$selectedDataIds: Record<string, boolean>,
linkDataSubRows: boolean
): void => {
if (row instanceof DataBodyRow) {
$selectedDataIds[row.dataId] = value;
if (!linkDataSubRows) {
return;
}
}
if (row.subRows === undefined) {
return;
}
row.subRows.forEach((subRow) => {
updateSelectedDataIds(subRow, value, $selectedDataIds);
writeSelectedDataIds(subRow, value, $selectedDataIds, linkDataSubRows);
});
};

const getIsSelectedStoreForDisplayRow = <Item>(
const getRowIsSelectedStore = <Item>(
row: BodyRow<Item>,
selectedDataIds: RecordSetStore<string>
selectedDataIds: RecordSetStore<string>,
linkDataSubRows: boolean
): Writable<boolean> => {
const { subscribe } = derived(selectedDataIds, ($selectedDataIds) =>
isAllSubRowsSelectedForRow(row, $selectedDataIds)
);
const { subscribe } = derived(selectedDataIds, ($selectedDataIds) => {
if (row instanceof DataBodyRow) {
if (!linkDataSubRows) {
return $selectedDataIds[row.dataId] === true;
}
if ($selectedDataIds[row.dataId] === true) {
return true;
}
}
return isAllSubRowsSelectedForRow(row, $selectedDataIds, linkDataSubRows);
});
const update = (fn: Updater<boolean>) => {
selectedDataIds.update(($selectedDataIds) => {
const oldValue = isAllSubRowsSelectedForRow(row, $selectedDataIds);
const oldValue = isAllSubRowsSelectedForRow(row, $selectedDataIds, linkDataSubRows);
const $updatedSelectedDataIds = { ...$selectedDataIds };
updateSelectedDataIds(row, fn(oldValue), $updatedSelectedDataIds);
writeSelectedDataIds(row, fn(oldValue), $updatedSelectedDataIds, linkDataSubRows);
if (row.parentRow !== undefined && row.parentRow instanceof DataBodyRow) {
$updatedSelectedDataIds[row.parentRow.dataId] = isAllSubRowsSelectedForRow(
row.parentRow,
$updatedSelectedDataIds,
linkDataSubRows
);
}
return $updatedSelectedDataIds;
});
};
Expand All @@ -94,7 +124,10 @@ const getIsSelectedStoreForDisplayRow = <Item>(
};

export const addSelectedRows =
<Item>({ initialSelectedDataIds = {} }: SelectedRowsConfig<Item> = {}): TablePlugin<
<Item>({
initialSelectedDataIds = {},
linkDataSubRows = false,
}: SelectedRowsConfig<Item> = {}): TablePlugin<
Item,
SelectedRowsState<Item>,
Record<string, never>,
Expand All @@ -104,19 +137,16 @@ export const addSelectedRows =
const selectedDataIds = recordSetStore(initialSelectedDataIds);

const getRowState = (row: BodyRow<Item>): SelectedRowsRowState => {
const isSelected =
row instanceof DataBodyRow
? keyed(selectedDataIds, row.dataId)
: getIsSelectedStoreForDisplayRow(row, selectedDataIds);
const isSelected = getRowIsSelectedStore(row, selectedDataIds, linkDataSubRows);
const isSomeSubRowsSelected = derived(
[isSelected, selectedDataIds],
([$isSelected, $selectedDataIds]) => {
if ($isSelected) return false;
return isSomeSubRowsSelectedForRow(row, $selectedDataIds);
return isSomeSubRowsSelectedForRow(row, $selectedDataIds, linkDataSubRows);
}
);
const isAllSubRowsSelected = derived(selectedDataIds, ($selectedDataIds) => {
return isAllSubRowsSelectedForRow(row, $selectedDataIds);
return isAllSubRowsSelectedForRow(row, $selectedDataIds, linkDataSubRows);
});
return {
isSelected,
Expand All @@ -132,8 +162,16 @@ export const addSelectedRows =
hooks: {
'tbody.tr': (row) => {
const props = derived(selectedDataIds, ($selectedDataIds) => {
const someSubRowsSelected = isSomeSubRowsSelectedForRow(row, $selectedDataIds);
const allSubRowsSelected = isAllSubRowsSelectedForRow(row, $selectedDataIds);
const someSubRowsSelected = isSomeSubRowsSelectedForRow(
row,
$selectedDataIds,
linkDataSubRows
);
const allSubRowsSelected = isAllSubRowsSelectedForRow(
row,
$selectedDataIds,
linkDataSubRows
);
const selected =
row instanceof DataBodyRow
? $selectedDataIds[row.dataId] === true
Expand Down
3 changes: 2 additions & 1 deletion src/routes/index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import { getDistinct } from '$lib/utils/array';
import SelectIndicator from './_SelectIndicator.svelte';
const data = readable(createSamples(50));
const data = readable(createSamples(50, 2));
const table = createTable(data, {
subRows: addSubRows({
Expand All @@ -48,6 +48,7 @@
}),
select: addSelectedRows({
initialSelectedDataIds: { 1: true },
linkDataSubRows: true,
}),
orderColumns: addColumnOrder(),
hideColumns: addHiddenColumns(),
Expand Down

0 comments on commit ca59b49

Please sign in to comment.