Skip to content

Commit

Permalink
use event dispatching on stacked modal class instead of onclose property
Browse files Browse the repository at this point in the history
  • Loading branch information
mattjennings committed Nov 3, 2024
1 parent 7c668a8 commit 56ee009
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 16 deletions.
26 changes: 16 additions & 10 deletions src/lib/modal-stack.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,23 @@ export class ModalStack {

this.stack.push(modal)

modal.onclose = () => {
if (modal.exitBeforeEnter) {
this.transitioning = true
modal.addEventListener(
'close',
() => {
if (modal.exitBeforeEnter) {
this.transitioning = true
}

if (this.stack.indexOf(modal) > -1) {
this.stack.splice(this.stack.indexOf(modal), 1)
}

this.action = 'pop'
},
{
once: true
}

if (this.stack.indexOf(modal) > -1) {
this.stack.splice(this.stack.indexOf(modal), 1)
}

this.action = 'pop'
}
)

return modal.promise
}
Expand Down
11 changes: 5 additions & 6 deletions src/lib/stacked-modal.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface ModalProps<ReturnValue = any> extends Record<string, any> {

type CloseFn<R> = (...args: R extends void ? [] : [result: R]) => boolean

export class StackedModal<R = any> {
export class StackedModal<R = any> extends EventTarget {
private static _idCounter = 0
private _props: Record<string, any>
private result = createDeferredPromise<R>()
Expand All @@ -32,6 +32,7 @@ export class StackedModal<R = any> {
props?: Record<string, any>
}
) {
super()
this.id = id || (StackedModal._idCounter++).toString()
this.component = component
this._props = props ?? {}
Expand All @@ -58,18 +59,18 @@ export class StackedModal<R = any> {
id: this.id,
index: this.index,
isOpen: this.isOpen,
close: this.close.bind(this) as CloseFn<R>
close: this.close as CloseFn<R>
}
}

close(...args: R extends void ? [] : [result: R]) {
close = (...args: R extends void ? [] : [result: R]) => {
if (this.onBeforeClose?.() === false) {
return false
}

const value = args[0]

this.onclose?.()
this.dispatchEvent(new CustomEvent('close', { detail: value }))
this.result.resolve(value as R)

return true
Expand All @@ -80,8 +81,6 @@ export class StackedModal<R = any> {
}

onBeforeClose?: () => boolean | void

onclose?: () => void
}

function createDeferredPromise<T>() {
Expand Down
File renamed without changes.
11 changes: 11 additions & 0 deletions src/tests/modal.spec.ts → src/tests/stacked-modal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ const FakeComponent = class {} as any as ModalComponent<ModalProps<{ foo: 'bar'
const modals = new ModalStack()

describe('close', () => {
test('emits close event', async () => {
const fn = vi.fn()

const modal = new StackedModal(modals, { component: FakeComponent })
modal.addEventListener('close', fn)

modal.close()

expect(fn).toHaveBeenCalled()
})

test('returns the value from modal.close()', async () => {
const modal = new StackedModal(modals, { component: FakeComponent })
modals.stack[0] = modal
Expand Down

0 comments on commit 56ee009

Please sign in to comment.