import { onBeforeUnmount } from "vue";
import { ref, watchEffect, onUnmounted, type Ref } from "vue";
type Callback = (...args: any[]) => void;
type Callable = (...args: any[]) => Function;
interface Subscription {
callback: Callback;
once: boolean;
}
export function useToggleEvents(
initialValue: boolean = false
): [Callable, Callable, () => void, Ref<boolean>] {
const booleanValue = ref(initialValue);
const callbacksTrue: Subscription[] = [];
const callbacksFalse: Subscription[] = [];
const register = (
callbacks: Subscription[],
callback: Callback,
once = false
) => {
const subscription = { callback, once };
callbacks.push(subscription);
return () => {
const index = callbacks.indexOf(subscription);
if (index !== -1) {
callbacks.splice(index, 1);
}
};
};
const registerTrueCallback = (
callback: Callback,
options = { once: false }
) => {
return register(callbacksTrue, callback, options.once);
};
const registerFalseCallback = (
callback: Callback,
options = { once: false }
) => {
return register(callbacksFalse, callback, options.once);
};
const toggleBooleanValue = () => {
booleanValue.value = !booleanValue.value;
};
const triggerCallbacks = (value: boolean, callbacks: Subscription[]) => {
callbacks.forEach(subscription => {
subscription.callback(value);
if (subscription.once) {
const index = callbacks.indexOf(subscription);
if (index !== -1) {
callbacks.splice(index, 1);
}
}
});
};
watchEffect(() => {
const callbacks = booleanValue.value ? callbacksTrue : callbacksFalse;
triggerCallbacks(booleanValue.value, callbacks);
});
onUnmounted(() => {
callbacksTrue.length = 0;
callbacksFalse.length = 0;
});
return [
registerTrueCallback,
registerFalseCallback,
toggleBooleanValue,
booleanValue,
];
}