Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…into add-more-handlers-for-`ModalPortal`
  • Loading branch information
FrameMuse committed Dec 10, 2023
2 parents 1f175a4 + 6aea01a commit ef598d3
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 246 deletions.
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
}
},
"dependencies": {
"eventemitter3": "^5.0.0",
"type-fest": "^4.0.0"
},
"devDependencies": {
Expand All @@ -36,7 +35,7 @@
"eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-unused-imports": "^3.0.0",
"rollup": "^2.77.0",
"rollup-plugin-dts": "^4.2.2",
"rollup-plugin-dts": "^6.1.0",
"sass": "^1.53.0",
"tslib": "^2.4.0",
"typescript": "^5.2.2"
Expand Down
39 changes: 39 additions & 0 deletions src/EventEmitter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
MIT License
Copyright (c) 2023 Valery Zinchenko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/

type EventEmitterListener = (...args: never[]) => void

class EventEmitter<Events extends Record<EventName, EventEmitterListener>, EventName extends keyof Events = keyof Events> {
private callbacks: Partial<Record<keyof never, Set<EventEmitterListener>>> = {}

public on<Event extends keyof Events>(event: Event, callback: Events[Event]) {
this.callbacks[event] ??= new Set
this.callbacks[event]?.add(callback as EventEmitterListener)
}
public off<Event extends keyof Events>(event: Event, callback: Events[Event]) {
this.callbacks[event]?.delete(callback as EventEmitterListener)
}
public emit<Event extends keyof Events>(event: Event, ...args: Parameters<Events[Event]>) {
const callbacks = this.callbacks[event]
if (callbacks == null) return

for (const callback of callbacks) callback(...args)
}
}

export default EventEmitter
23 changes: 11 additions & 12 deletions src/ModalController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@ copies or substantial portions of the Software.
*/

import EventEmitter from "eventemitter3"

import EventEmitter from "./EventEmitter"
import { ModalWindow, ModalWindowAny } from "./ModalWindow"
import { ExternalStore, MODAL_WINDOW_PARAMS_EXPLANATION, ModalComponent, ModalComponentProps, ModalNamedComponents, ModalParams, ModalSnapshot, ModalWindowParams } from "./types"


interface ModalControllerEvents {
add: [ModalWindowAny]
remove: [ModalWindowAny]
update: []
add(modalWindow: ModalWindowAny): void
remove(modalWindow: ModalWindowAny): void
update(): void
}

interface ModalControllerConfig<Components extends ModalNamedComponents = ModalNamedComponents> {
Expand Down Expand Up @@ -86,11 +85,11 @@ class ModalController<Config extends Partial<ModalControllerConfig> = ModalContr
* @example
* await Modal.open(MyModal, { id: 1 })
* console.log("Modal was closed")
*
*
* @example
* const modal = Modal.open(MyModal, { id: 1 })
* modal.then(() => console.log("Modal was closed"))
*
*
* @example
* const modal = Modal.open(MyModal, { id: 1 })
* modal.on("close", () => console.log("Modal was closed"))
Expand Down Expand Up @@ -229,13 +228,13 @@ class ModalController<Config extends Partial<ModalControllerConfig> = ModalContr

/**
* Subscribes to `event` with `listener`.
*
*
* @example
* Modal.on("close", () => { })
*
*
* @returns `unsubscribe` method
*/
public on<T extends keyof ModalControllerEvents>(event: T, listener: (...args: ModalControllerEvents[T]) => void) {
public on<T extends keyof ModalControllerEvents>(event: T, listener: ModalControllerEvents[T]) {
this.events.on(event, listener)

return () => {
Expand All @@ -245,9 +244,9 @@ class ModalController<Config extends Partial<ModalControllerConfig> = ModalContr

/**
* Used for container component to get the current state.
*
*
* Observes the state and calls the callback on any changes.
*
*
* @returns `unsubscribe` method to stop observing.
*/
public subscribe(callback: () => void) {
Expand Down
29 changes: 14 additions & 15 deletions src/ModalWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,16 @@ copies or substantial portions of the Software.
*/

import EventEmitter from "eventemitter3"

import Deffered from "./Deffered"
import EventEmitter from "./EventEmitter"
import { ModalComponent, ModalParams } from "./types"
import { cyrb53, serialize } from "./utils"

const MODAL_SEED = Date.now()

interface ModalWindowEvents {
open: []
close: []
open(): void
close(): void
}

const DEFAULT_PARAMS: ModalParams = {
Expand All @@ -43,12 +42,12 @@ const DEFAULT_PARAMS: ModalParams = {
class ModalWindow<CustomParams = unknown> {
/**
* Hash of `serialized` property.
*
*
* Unique id of the modal window.
* If two modals have the same id, they will be treated as the same modal.
*
*
* This is usually used in `key` prop for React components.
*
*
* @note
* This is not the same as `params.id` because `id` is unique for each modal window.
*/
Expand All @@ -62,7 +61,7 @@ class ModalWindow<CustomParams = unknown> {
public params: ModalParams & CustomParams
/**
* Indicates that the `close` method has been called and the modal window is going to be removed.
*
*
* @default
* false
*/
Expand All @@ -88,10 +87,10 @@ class ModalWindow<CustomParams = unknown> {

/**
* Closes the modal window.
*
*
* @note
* This is an arrow function, which prevents `this` from being lost - You can use it without `bind`.
*
*
* @example
* const modal = Modal.open(PopupHello, { title: "Hello" })
* modal.close()
Expand All @@ -108,7 +107,7 @@ class ModalWindow<CustomParams = unknown> {

/**
* Can be used to wait for the modal to be closed before performing an action.
*
*
* @example
* await Modal.open(PopupHello, { title: "Hello" })
* doAnyAction()
Expand All @@ -121,12 +120,12 @@ class ModalWindow<CustomParams = unknown> {
* @example
* const modal = Modal.open(PopupHello, { title: "Hello" })
* modal.on("close", () => { })
*
*
* @note If you want to do something on close, you can use await directly on this instance. For details see `then` method in `ModalWindow`.
*
*
* @returns `unsubscribe` method
*/
on<K extends keyof ModalWindowEvents>(event: K, listener: (...args: ModalWindowEvents[K]) => void) {
on<K extends keyof ModalWindowEvents>(event: K, listener: ModalWindowEvents[K]) {
this.events.on(event, listener)

return () => {
Expand All @@ -137,7 +136,7 @@ class ModalWindow<CustomParams = unknown> {

/**
* This is a workaround for TypeScript.
*
*
* Used if it doesn't matter what type of `CustomParams` is used.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down
3 changes: 0 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,4 @@ export { ModalWindow } from "./ModalWindow"
export { ModalContainer } from "./ModalContainer"
export { useModalWindow, useModalSnapshot } from "./hooks"

export { default as DrawerLayout } from "./layouts/DrawerLayout"
export { default as PopupLayout } from "./layouts/PopupLayout"

export { ModalPortal } from "./ModalPortal"
49 changes: 0 additions & 49 deletions src/layouts/DrawerLayout.tsx

This file was deleted.

49 changes: 0 additions & 49 deletions src/layouts/PopupLayout.tsx

This file was deleted.

10 changes: 0 additions & 10 deletions src/layouts/react-extension.d.ts

This file was deleted.

Loading

0 comments on commit ef598d3

Please sign in to comment.