Skip to content

Commit

Permalink
Add open/close delays to portal
Browse files Browse the repository at this point in the history
  • Loading branch information
thiagomajesk authored and viniciusmuller committed Mar 21, 2023
1 parent c734187 commit 17d6979
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 21 deletions.
32 changes: 15 additions & 17 deletions assets/hooks/portal.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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));
Expand All @@ -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);
},
}
6 changes: 4 additions & 2 deletions lib/swish/dialog.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)}
>
Expand Down
6 changes: 4 additions & 2 deletions lib/swish/tag.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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) %>
Expand Down

0 comments on commit 17d6979

Please sign in to comment.