90 lines
2.4 KiB
TypeScript
90 lines
2.4 KiB
TypeScript
import { computed, ref } from 'vue';
|
|
|
|
export interface PickerSelectionOptions {
|
|
multiple: boolean;
|
|
}
|
|
|
|
export function usePickerSelection(options: () => PickerSelectionOptions) {
|
|
const multiSet = ref<Set<string>>(new Set());
|
|
const singleId = ref<string | null>(null);
|
|
|
|
const multiple = computed(() => options().multiple);
|
|
|
|
function has(userId: string): boolean {
|
|
if (multiple.value) return multiSet.value.has(userId);
|
|
return singleId.value === userId;
|
|
}
|
|
|
|
function toggle(userId: string) {
|
|
if (multiple.value) {
|
|
if (multiSet.value.has(userId)) multiSet.value.delete(userId);
|
|
else multiSet.value.add(userId);
|
|
multiSet.value = new Set(multiSet.value);
|
|
} else {
|
|
singleId.value = singleId.value === userId ? null : userId;
|
|
}
|
|
}
|
|
|
|
function addMany(userIds: readonly string[]) {
|
|
if (!multiple.value) {
|
|
singleId.value = userIds[0] ?? singleId.value;
|
|
return;
|
|
}
|
|
for (const id of userIds) multiSet.value.add(id);
|
|
multiSet.value = new Set(multiSet.value);
|
|
}
|
|
|
|
function removeMany(userIds: readonly string[]) {
|
|
if (!multiple.value) {
|
|
if (singleId.value && userIds.includes(singleId.value)) singleId.value = null;
|
|
return;
|
|
}
|
|
for (const id of userIds) multiSet.value.delete(id);
|
|
multiSet.value = new Set(multiSet.value);
|
|
}
|
|
|
|
function clear(preserveIds?: readonly string[]) {
|
|
const keep = new Set((preserveIds ?? []).map(String));
|
|
if (multiple.value) {
|
|
const next = new Set<string>();
|
|
for (const id of multiSet.value) {
|
|
if (keep.has(id)) next.add(id);
|
|
}
|
|
multiSet.value = next;
|
|
} else if (singleId.value && !keep.has(singleId.value)) singleId.value = null;
|
|
}
|
|
|
|
function reset(initial: string | string[] | null | undefined) {
|
|
if (multiple.value) {
|
|
const ids = Array.isArray(initial) ? initial.map(String) : [];
|
|
multiSet.value = new Set(ids);
|
|
} else {
|
|
singleId.value = typeof initial === 'string' ? initial : null;
|
|
}
|
|
}
|
|
|
|
const selectedIds = computed<string[]>(() => {
|
|
if (multiple.value) return [...multiSet.value];
|
|
return singleId.value ? [singleId.value] : [];
|
|
});
|
|
|
|
const size = computed(() => selectedIds.value.length);
|
|
|
|
function commit(): string | string[] | null {
|
|
if (multiple.value) return [...multiSet.value];
|
|
return singleId.value;
|
|
}
|
|
|
|
return {
|
|
selectedIds,
|
|
size,
|
|
has,
|
|
toggle,
|
|
addMany,
|
|
removeMany,
|
|
clear,
|
|
reset,
|
|
commit
|
|
};
|
|
}
|