| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- package com.weEat.modules
- import com.raquo.laminar.api.L._
- import org.scalajs.dom.document
- import scala.concurrent.ExecutionContext
- import scala.concurrent.Future
- import scala.concurrent.Promise
- import scala.util.Try
- object Overlay {
- implicit val ctx = org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits.global
- object Closed extends Throwable()
- private class _PromiseWrapper[T](promise: Promise[T], root: RootNode)(implicit ctx: ExecutionContext) extends Promise[T] {
- lazy val future = {
- val result = promise.future
- result.onComplete((_) => root.unmount())
- result
- }
- def isCompleted = promise.isCompleted
- def tryComplete(result: Try[T]) = promise.tryComplete(result)
- }
- private def _toLoadingNode(content: Future[Node]) =
- Signal.fromFuture(content) map {
- case Some(node) => node
- case None => div(cls := "loader",
- span(),
- span(),
- span(),
- span(),
- span(),
- span()
- )
- }
-
- private val _backgroundStyle = Seq(
- backgroundColor := "rgba(0, 0, 0, 0.5)",
- position := "fixed",
- textAlign := "center",
- top := "0",
- left := "0",
- bottom := "0",
- right := "0",
- zIndex := 99
- )
- private val _popupWindowStyle = Seq(
- cls := "p-4 position-relative",
- backgroundColor := "#ffffff",
- borderRadius := "1em",
- top := "50%",
- transform := "translateY(-50%)",
- maxHeight := "80%",
- overflowY := "auto",
- display := "inline-block",
- verticalAlign := "middle",
- maxWidth := "50%"
- )
- private def _internal[T](content: Node)(implicit ctx: ExecutionContext) = {
- val promise = Promise[T]()
- val overlay = div(
- _backgroundStyle,
- div(
- _popupWindowStyle,
- content
- )
- )
- overlay.amend(onClick.stopPropagation --> ((event) =>
- if (event.target == overlay.ref) {
- promise.failure(Closed)
- }
- ))
- new _PromiseWrapper(promise, render(document.body, overlay))
- }
- def confirm[T](
- content: Node,
- readyToSubmit: Signal[Boolean] = Val(true)
- )(confirmFn: () => T) = {
- val cancelBtn = button(
- typ := "button",
- cls := "btn btn-light",
- "Cancel"
- )
- val submitBtn = button(
- typ := "button",
- cls := "btn btn-success",
- disabled <-- readyToSubmit.map(!_),
- "Submit"
- )
- val promise = _internal[T](div(
- content,
- div(
- cls := "pt-2 pb-2",
- textAlign := "right",
- cancelBtn,
- submitBtn
- )
- ))
- cancelBtn.amend(
- onClick.stopPropagation --> ((_) => promise.failure(Closed))
- )
- submitBtn.amend(
- onClick.stopPropagation --> ((_) => promise.success(confirmFn()))
- )
- promise.future
- }
- def confirmFuture[T](
- content: Future[Node],
- readyToSubmit: Signal[Boolean] = Val(true)
- )(confirmFn: () => Future[T])(implicit ctx: ExecutionContext) = {
- val cancelBtn = button(
- typ := "button",
- cls := "btn btn-light",
- "Cancel"
- )
- val submitBtn = button(
- typ := "button",
- cls := "btn btn-success",
- disabled <-- readyToSubmit.map(!_),
- "Submit"
- )
- val promise = _internal[T](div(
- child <-- _toLoadingNode(content),
- div(
- cls := "pt-2 pb-2",
- textAlign := "right",
- cancelBtn,
- submitBtn
- )
- ))
- cancelBtn.amend(
- onClick.stopPropagation --> ((_) => {promise.failure(Closed)})
- )
- submitBtn.amend(
- onClick.stopPropagation --> ((_) => {promise.completeWith(confirmFn())})
- )
- promise.future
- }
- }
|