mirror of
https://github.com/penpot/penpot.git
synced 2025-06-14 20:51:38 +02:00
145 lines
3.7 KiB
Clojure
145 lines
3.7 KiB
Clojure
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
;;
|
|
;; Copyright (c) 2016-2017 Andrey Antukh <niwi@niwi.nz>
|
|
|
|
(ns uxbox.util.messages
|
|
"Messages notifications."
|
|
(:require
|
|
[beicon.core :as rx]
|
|
[cuerdas.core :as str]
|
|
[lentes.core :as l]
|
|
[potok.core :as ptk]
|
|
[rumext.alpha :as mf]
|
|
[uxbox.builtins.icons :as i]
|
|
[uxbox.util.data :refer [classnames]]
|
|
[uxbox.util.dom :as dom]
|
|
[uxbox.util.timers :as ts]
|
|
[uxbox.util.i18n :refer [tr]]))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; Data Events
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; --- Constants
|
|
|
|
(def +animation-timeout+ 600)
|
|
|
|
;; --- Main API
|
|
|
|
(declare hide)
|
|
(declare show)
|
|
(declare show?)
|
|
|
|
(defn error
|
|
[message & {:keys [timeout] :or {timeout 3000}}]
|
|
(show {:content message
|
|
:type :error
|
|
:timeout timeout}))
|
|
|
|
(defn info
|
|
[message & {:keys [timeout] :or {timeout 3000}}]
|
|
(show {:content message
|
|
:type :info
|
|
:timeout timeout}))
|
|
|
|
(defn dialog
|
|
[message & {:keys [on-accept on-cancel]}]
|
|
(show {:content message
|
|
:on-accept on-accept
|
|
:on-cancel on-cancel
|
|
:timeout js/Number.MAX_SAFE_INTEGER
|
|
:type :dialog}))
|
|
|
|
;; --- Show Event
|
|
|
|
(defn show
|
|
[data]
|
|
(ptk/reify ::show
|
|
ptk/UpdateEvent
|
|
(update [_ state]
|
|
(let [message (assoc data :state :visible)]
|
|
(assoc state :message message)))
|
|
|
|
ptk/WatchEvent
|
|
(watch [_ state s]
|
|
(let [stoper (->> (rx/filter show? s)
|
|
(rx/take 1))]
|
|
(->> (rx/of (hide))
|
|
(rx/delay (:timeout data))
|
|
(rx/take-until stoper))))))
|
|
|
|
(defn show?
|
|
[v]
|
|
(= ::show (ptk/type v)))
|
|
|
|
;; --- Hide Event
|
|
|
|
(defn hide
|
|
[]
|
|
(reify
|
|
ptk/UpdateEvent
|
|
(update [_ state]
|
|
(update state :message assoc :state :hide))
|
|
|
|
ptk/WatchEvent
|
|
(watch [_ state stream]
|
|
(->> (rx/of #(dissoc % :message))
|
|
(rx/delay +animation-timeout+)))))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; UI Components
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; --- Notification Component
|
|
|
|
(mf/defc notification-box
|
|
[{:keys [message on-close] :as message}]
|
|
(let [type (:type message)
|
|
classes (classnames :error (= type :error)
|
|
:info (= type :info)
|
|
:hide-message (= (:state message) :hide)
|
|
:quick true)]
|
|
[:div.message {:class classes}
|
|
[:div.message-body
|
|
[:span.close {:on-click on-close} i/close]
|
|
[:span (:content message)]]]))
|
|
|
|
;; --- Dialog Component
|
|
|
|
(mf/defc dialog-box
|
|
[{:keys [on-accept on-cancel on-close message] :as props}]
|
|
(let [classes (classnames :info true
|
|
:hide-message (= (:state message) :hide))]
|
|
(letfn [(accept [event]
|
|
(dom/prevent-default event)
|
|
(on-accept)
|
|
(ts/schedule 0 on-close))
|
|
|
|
(cancel [event]
|
|
(dom/prevent-default event)
|
|
(when on-cancel
|
|
(on-cancel))
|
|
(ts/schedule 0 on-close))]
|
|
[:div.message {:class classes}
|
|
[:div.message-body
|
|
[:span.close {:on-click cancel} i/close]
|
|
[:span (:content message)]
|
|
[:div.message-action
|
|
[:a.btn-transparent.btn-small
|
|
{:on-click accept}
|
|
(tr "ds.accept")]
|
|
[:a.btn-transparent.btn-small
|
|
{:on-click cancel}
|
|
(tr "ds.cancel")]]]])))
|
|
|
|
;; --- Main Component (entry point)
|
|
|
|
(mf/defc messages-widget
|
|
[{:keys [message] :as props}]
|
|
(case (:type message)
|
|
:error (mf/element notification-box props)
|
|
:info (mf/element notification-box props)
|
|
:dialog (mf/element dialog-box props)
|
|
nil))
|