From 17d6979251e2ff51b033e9adc524c9473493ea73 Mon Sep 17 00:00:00 2001 From: thiagomajesk Date: Mon, 20 Mar 2023 22:53:15 -0300 Subject: [PATCH] Add open/close delays to portal --- assets/hooks/portal.js | 32 +++++++++++++++----------------- lib/swish/dialog.ex | 6 ++++-- lib/swish/tag.ex | 6 ++++-- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/assets/hooks/portal.js b/assets/hooks/portal.js index 3182089..281be3d 100644 --- a/assets/hooks/portal.js +++ b/assets/hooks/portal.js @@ -12,7 +12,7 @@ import { getAttributeOrThrow, parseInteger } from "../utils/attribute" * * * `data-update` - the operation to be executed, it can be either: origin (default), append or prepend. * * `data-target` - the DOM element where the portal is going to be placed. - * * `data-destroy-delay` - delay to remove teleported elements in ms after closing the portal + * * `data-close-delay` - delay in ms to close the open portal. */ // Cache a list of possible DOM events that we want to forward @@ -43,16 +43,15 @@ export default { clone: null, target: null, update: null, - eventsTimeout: null, - destroyTimeout: null, - destroyDelay: null, + closeDelay: null, + closeTimeout: null, mounted() { const targetSelector = getAttributeOrThrow(this.el, "data-target"); this.target = document.querySelector(targetSelector); this.update = getAttributeOrThrow(this.el, "data-update"); - this.destroyDelay = getAttributeOrThrow(this.el, "data-destroy-delay", parseInteger); + this.closeDelay = getAttributeOrThrow(this.el, "data-close-delay", parseInteger); this.el.addEventListener("portal:open", this.handleOpen.bind(this)); this.el.addEventListener("portal:close", this.handleClose.bind(this)); @@ -62,27 +61,26 @@ export default { this.clone.remove(); // Removes the timeouts just to be sure - clearTimeout(this.eventsTimeout); - clearTimeout(this.destroyTimeout); + clearTimeout(this.closeTimeout); }, handleOpen() { - let clone = this.el.content.cloneNode(true); - this.clone = clone.firstElementChild; + this.clone = this.el.content.cloneNode(true).firstElementChild; - // Teleports clone to target - updates[this.update](this.target, this.clone) + // Opens the portal and teleports clone to target. + // Await a little before opening so animation ca be properly displayed. + updates[this.update](this.target, this.clone); // Await until next tick to register the forwarded events - this.eventsTimeout = setTimeout(() => forwardEvents(this.el, this.clone), 0) + forwardEvents(this.el, this.clone) }, handleClose() { // Cache old clone to avoid race conditions - let clone = this.clone + const clone = this.clone - // Await a little before removing the element so animations can be properly displayed. - // Ideally this shoud be configurable in the future so the user has more control over it. - this.destroyTimeout = setTimeout(() => clone.remove(), this.destroyDelay); - } + // Closes the portal and removes the cloned element. + // Await a little before closing so animations can be properly displayed. + this.closeTimeout = setTimeout(() => clone.remove(), this.closeDelay); + }, } diff --git a/lib/swish/dialog.ex b/lib/swish/dialog.ex index 430218a..da7e7f1 100644 --- a/lib/swish/dialog.ex +++ b/lib/swish/dialog.ex @@ -187,7 +187,8 @@ defmodule Swish.Dialog do attr(:dialog, Dialog, required: true) attr(:target, :string, default: "body") attr(:update, :string, values: ~w(prepend append origin), default: "origin") - attr(:destroy_delay, :integer, default: 500) + attr(:open_delay, :integer, default: 150) + attr(:close_delay, :integer, default: 300) slot(:inner_block, required: true) @@ -197,7 +198,8 @@ defmodule Swish.Dialog do id={@dialog.portal_id} target={@target} update={@update} - destroy_delay={@destroy_delay} + open_delay={@open_delay} + close_delay={@close_delay} aria-hidden="true" phx-mounted={@dialog.open && show(@dialog)} > diff --git a/lib/swish/tag.ex b/lib/swish/tag.ex index 1b7bc9f..1f38dfd 100644 --- a/lib/swish/tag.ex +++ b/lib/swish/tag.ex @@ -79,7 +79,8 @@ defmodule Swish.Tag do attr :id, :string, required: true attr :target, :string, default: "body" attr :update, :string, values: ~w(prepend append origin), default: "origin" - attr :destroy_delay, :integer, default: 500 + attr :open_delay, :integer, default: 0 + attr :close_delay, :integer, default: 0 attr :rest, :global slot :inner_block, required: true @@ -90,7 +91,8 @@ defmodule Swish.Tag do phx-hook="Swish.Portal" data-target={@target} data-update={@update} - data-destroy-delay={@destroy_delay} + data-open-delay={@open_delay} + data-close-delay={@close_delay} {@rest} > <%= render_slot(@inner_block) %>