import React, { useEffect } from "react";
import { EventType, Handler, SignalEventBus } from "./SignalEvents";
export const SignalEvent = {
on: OnSignalEvent,
off: OffSignalEvent,
emit: emitSignalEvent,
}
/**
* A React hook that lets you subscribe a listener to a event on mount and unsubscribes the event on unmount.
* It allows you to subscribe to a specific SignalEventBus as well, giving you more control.
*
*
* @param event
* An event that is meant to be subscribed to
* @param handler
* A listener that will run when the event is emitted.
* @param signalBus
* Optional SignalEventBus that will handle the signal emitting. If not specified, you can use the Global event bus.
*
* @example
* Here is how to trigger the count state of any component that has a listener to a count event
*
* ```tsx
*
* function onClick(){
* SignalEventBus.Global.emit("count");
* }
*
* //button on click does not need to know about the component its in
* function Btn(){
* return (
*
* )
* }
*
* function Comp(){
* let [count, setCount] = useState(0);
*
* //only counts up by listening to "count" event, regardless of what triggers it
* useSignalEvent("count", ()=>{
* setCount(count + 1);
* })
*
* return (
*
*
Count: {count}
*
*
* )
* }
* function Comp2(){
* let [count, setCount] = useState(0);
*
* //this will be triggered too
* useSignalEvent("count", ()=>{
* setCount(count + 1);
* })
*
* return (
*
*
Count: {count}
*
* )
* }
*
* ```
*/
export function useSignalEvent(event:EventType, handler:Handler, signalBus?:SignalEventBus) : void;
export function useSignalEvent(events:EventType[], handler:Handler, signalBus?:SignalEventBus) : void;
export function useSignalEvent(handler:Handler, signalBus?:SignalEventBus) : void;
export function useSignalEvent(...args:any[]){
let events:EventType[];
// events = useMemo(() => [""], []);
let handler:Handler;
let signalBus:SignalEventBus = SignalEventBus.Global;
if(args[0] instanceof Function){
let [h, s] = args as [Handler, SignalEventBus];
events = [""];
handler = h;
if(s instanceof SignalEventBus) signalBus = s;
}else if(args[0] instanceof Array){
let [ev, h, s] = args as [EventType[], Handler, SignalEventBus];
events = ev;
handler = h;
if(s instanceof SignalEventBus) signalBus = s;
}else{
let [ev, h, s] = args as [EventType, Handler, SignalEventBus];
events = [ev];
handler = h;
if(s instanceof SignalEventBus) signalBus = s;
}
useEffect(()=>{
for(let event of events){
signalBus.on(event, handler);
}
return ()=>{
for(let event of events){
signalBus.off(event, handler);
}
}
},[events, handler, signalBus]);
}
function emitSignalEvent(event:EventType, data?:T, signalBus:SignalEventBus=SignalEventBus.Global){
signalBus.emit(event, data, );
}
function OnSignalEvent(event:EventType, handler:Handler, signalBus:SignalEventBus=SignalEventBus.Global){
useSignalEvent(event, handler, signalBus);
return SignalEvent;
}
function OffSignalEvent(event:EventType, handler:Handler, signalBus:SignalEventBus=SignalEventBus.Global){
signalBus.off(event, handler);
return SignalEvent;
}
/**
* This treats the signalbus as a component which can be placed anywhere in any other component to listen to events
* @param props.handler
* A handler function to run when the event when emitted
* @param props.on
* Event meant to be passed. It can be blank for a nameless event
* @param props.signalBus
* Optional signalbus that will be used to emit the signals. Defaults to the global signal bus if no signal bus is passed.
* @returns
* A component that can be placed in the application, which does not render anything on the DOM.
*
* @example
* Here is how to trigger the count state of any component that has a listener to a count event
*
* ```tsx
*
* function onClick(){
* SignalEventBus.Global.emit("count");
* }
*
* //button on click does not need to know about the component its in
* function Btn(){
* return (
*
* )
* }
*
* function Comp(){
* let [count, setCount] = useState(0);
*
* //only counts up by listening to "count" event, regardless of what triggers it
* function onCount(){
* setCount(count+1);
* }
*
* return (
*
*
*
Count: {count}
*
*
* )
* }
* function Comp2(){
* let [count, setCount] = useState(0);
*
* //this will be triggered too
* function onCount(){
* setCount(count+1);
* }
*
* return (
*