diff --git a/src/index.ts b/src/index.ts index 131a2af..1d750f5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,28 +4,36 @@ import { addHandlers } from "./handlers"; import "./jsx"; import type { Flow, FlowsContext, FlowsOptions, TrackingEvent, FlowStep } from "./types"; -let instances: FlowState[] = []; +const instances = new Map(); const context: FlowsContext = {}; let observer: MutationObserver | null = null; export const startFlow = (flowId: string): void => { - if (instances.some((state) => state.flowId === flowId)) return; + if (instances.has(flowId)) return; const state = new FlowState({ flowId }, context); - instances.push(state); + instances.set(flowId, state); state.render(); }; +export const endFlow = (flowId: string): void => { + const state = instances.get(flowId); + if (!state) return; + if (state.hasNextStep) state.finish(); + else state.cancel(); + instances.delete(flowId); +}; + export const identifyUser = (userId: string): void => { context.userId = userId; }; export const getCurrentStep = (flowId: string): FlowStep | null => { - const state = instances.find((s) => s.flowId === flowId); + const state = instances.get(flowId); if (!state) return null; return state.currentStep ?? null; }; export const nextStep = (flowId: string, action?: number): void => { - const state = instances.find((s) => s.flowId === flowId); + const state = instances.get(flowId); if (!state) return; state.nextStep(action).render(); }; @@ -35,13 +43,16 @@ export const init = (options: FlowsOptions): void => { context.onNextStep = options.onNextStep; context.onPrevStep = options.onPrevStep; context.tracking = options.tracking; - context.flowsById = options.flows?.reduce( - (acc, flow) => { - acc[flow.id] = flow; - return acc; - }, - {} as Record, - ); + context.flowsById = { + ...context.flowsById, + ...options.flows?.reduce( + (acc, flow) => { + acc[flow.id] = flow; + return acc; + }, + {} as Record, + ), + }; const handleClick = (event: MouseEvent): void => { const eventTarget = event.target; @@ -67,36 +78,43 @@ export const init = (options: FlowsOptions): void => { }); if (eventTarget.matches(".flows-back")) { - const flow = instances.find((state) => state.flowElement?.element.contains(eventTarget)); - if (!flow) return; - flow.prevStep().render(); + const flow = Array.from(instances.values()).find( + (s) => s.flowElement?.element.contains(eventTarget), + ); + flow?.prevStep().render(); } if (eventTarget.matches(".flows-continue")) { - const flow = instances.find((state) => state.flowElement?.element.contains(eventTarget)); - if (!flow) return; - flow.nextStep().render(); + const flow = Array.from(instances.values()).find( + (s) => s.flowElement?.element.contains(eventTarget), + ); + flow?.nextStep().render(); } if (eventTarget.matches(".flows-option")) { const action = Number(eventTarget.getAttribute("data-action")); if (Number.isNaN(action)) return; - const flow = instances.find((state) => state.flowElement?.element.contains(eventTarget)); - if (!flow) return; - flow.nextStep(action).render(); + const flow = Array.from(instances.values()).find( + (s) => s.flowElement?.element.contains(eventTarget), + ); + flow?.nextStep(action).render(); } if (eventTarget.matches(".flows-finish")) { - instances = instances.filter((state) => { - if (!state.flowElement?.element.contains(eventTarget)) return true; - state.finish(); - return false; - }); + const flow = Array.from(instances.values()).find( + (s) => s.flowElement?.element.contains(eventTarget), + ); + if (flow) { + flow.finish(); + instances.delete(flow.flowId); + } } if (eventTarget.matches(".flows-cancel")) { - instances = instances.filter((state) => { - if (!state.flowElement?.element.contains(eventTarget)) return true; - state.cancel(); - return false; - }); + const flow = Array.from(instances.values()).find( + (s) => s.flowElement?.element.contains(eventTarget), + ); + if (flow) { + flow.cancel(); + instances.delete(flow.flowId); + } } }; const handleSubmit = (event: SubmitEvent): void => {