mirror of
https://github.com/penpot/penpot.git
synced 2025-04-13 07:21:40 -05:00
commit
0aeb966b11
32 changed files with 1024 additions and 226 deletions
|
@ -64,19 +64,23 @@
|
|||
(persistent!
|
||||
(reduce #(assoc! %1 (getter %2) %2) (transient {}) coll)))
|
||||
|
||||
(defn index-of
|
||||
[coll v]
|
||||
(defn index-of-pred
|
||||
[coll pred]
|
||||
(loop [c (first coll)
|
||||
coll (rest coll)
|
||||
index 0]
|
||||
(if (nil? c)
|
||||
nil
|
||||
(if (= c v)
|
||||
(if (pred c)
|
||||
index
|
||||
(recur (first coll)
|
||||
(rest coll)
|
||||
(inc index))))))
|
||||
|
||||
(defn index-of
|
||||
[coll v]
|
||||
(index-of-pred coll #(= % v)))
|
||||
|
||||
(defn remove-nil-vals
|
||||
"Given a map, return a map removing key-value
|
||||
pairs when value is `nil`."
|
||||
|
|
|
@ -135,6 +135,19 @@
|
|||
::grid-x
|
||||
::grid-color]))
|
||||
|
||||
;; Interactions
|
||||
|
||||
(s/def ::event-type #{:click}) ; In the future we will have more options
|
||||
(s/def ::action-type #{:navigate})
|
||||
(s/def ::destination uuid?)
|
||||
|
||||
(s/def ::interaction
|
||||
(s/keys :req-un [::event-type
|
||||
::action-type
|
||||
::destination]))
|
||||
|
||||
(s/def ::interactions (s/coll-of ::interaction :kind vector?))
|
||||
|
||||
;; Page Data related
|
||||
(s/def ::blocked boolean?)
|
||||
(s/def ::collapsed boolean?)
|
||||
|
@ -194,7 +207,8 @@
|
|||
::stroke-width
|
||||
::stroke-alignment
|
||||
::text-align
|
||||
::width ::height]))
|
||||
::width ::height
|
||||
::interactions]))
|
||||
|
||||
(s/def ::minimal-shape
|
||||
(s/keys :req-un [::type ::name]
|
||||
|
|
|
@ -26,12 +26,19 @@ You can deactivate debug mode with
|
|||
(-debug! <option>) ; to disable only one
|
||||
```
|
||||
|
||||
There are also some useful functions:
|
||||
## Debug state and objects
|
||||
|
||||
There are also some useful functions to visualize the global state or any
|
||||
complex object:
|
||||
|
||||
```clojure
|
||||
(dump-state) ; to print in console all the global state
|
||||
(dump-objects) ; to print in console all objects in workspace
|
||||
(ns uxbox.util.debug)
|
||||
(logjs <msg> <var>) ; to print the value of a variable
|
||||
(tap <fn>) ; to include a function with side effect (e.g. logjs) in a transducer.
|
||||
|
||||
(ns uxbox.main.store)
|
||||
(dump-state) ; to print in console all the global state
|
||||
(dump-objects) ; to print in console all objects in workspace
|
||||
```
|
||||
|
||||
|
||||
|
|
1
frontend/resources/images/icons/interaction.svg
Normal file
1
frontend/resources/images/icons/interaction.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 500 500"><defs/><rect width="484.4" height="484.4" x="-492" y="-492" stroke="#64666a" stroke-width="15.6" rx="242.2" transform="scale(-1)"/><path fill="#64666a" fill-rule="evenodd" d="M343 250c0 12-9 21-20 21H145c-11 0-20-9-20-21s9-21 20-21h178c11 0 20 9 20 21z" clip-rule="evenodd"/><path fill="#64666a" fill-rule="evenodd" d="M309 269c10-11 10-27 0-38l-68-70c-8-8-8-22 0-30s21-8 29 0l97 100c11 11 11 27 0 38l-97 100c-8 8-21 8-29 0s-8-22 0-30z" clip-rule="evenodd"/></svg>
|
After Width: | Height: | Size: 539 B |
1
frontend/resources/images/icons/navigate.svg
Normal file
1
frontend/resources/images/icons/navigate.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500"><path d="M436.58 250c0 23.2-18.35 42.009-40.991 42.009h-354.6C18.353 292.009 0 273.2 0 250c0-23.2 18.352-42.008 40.99-42.008h354.599c22.64 0 40.99 18.808 40.99 42.008z"/><path d="M368.395 287.862c20.447-20.893 20.447-54.83 0-75.724l-137.27-140.28c-16.087-16.438-16.087-43.14 0-59.579 16.02-16.372 41.946-16.372 57.967 0l195.575 199.86c20.444 20.892 20.444 54.83 0 75.723l-195.575 199.86c-16.02 16.371-41.947 16.371-57.968 0-16.086-16.438-16.086-43.141 0-59.579z"/></svg>
|
After Width: | Height: | Size: 536 B |
|
@ -1,5 +1,4 @@
|
|||
{
|
||||
|
||||
"dashboard.grid.delete" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard/project.cljs:61", "src/uxbox/main/ui/dashboard/grid.cljs:92" ],
|
||||
"translations" : {
|
||||
|
@ -259,7 +258,7 @@
|
|||
}
|
||||
},
|
||||
"ds.search.placeholder" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:174" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard/sidebar.cljs:168" ],
|
||||
"translations" : {
|
||||
"en" : "Search...",
|
||||
"fr" : "Rechercher..."
|
||||
|
@ -329,28 +328,28 @@
|
|||
}
|
||||
},
|
||||
"errors.auth.unauthorized" : {
|
||||
"used-in" : [ "src/uxbox/main/data/auth.cljs:56" ],
|
||||
"used-in" : [ "src/uxbox/main/data/auth.cljs:57" ],
|
||||
"translations" : {
|
||||
"en" : "Username or password seems to be wrong.",
|
||||
"fr" : "Le nom d'utilisateur ou le mot de passe semble être faux."
|
||||
}
|
||||
},
|
||||
"errors.generic" : {
|
||||
"used-in" : [ "src/uxbox/main/ui.cljs:175" ],
|
||||
"used-in" : [ "src/uxbox/main/ui.cljs:179" ],
|
||||
"translations" : {
|
||||
"en" : "Something wrong has happened.",
|
||||
"fr" : "Quelque chose c'est mal passé."
|
||||
}
|
||||
},
|
||||
"errors.network" : {
|
||||
"used-in" : [ "src/uxbox/main/ui.cljs:169" ],
|
||||
"used-in" : [ "src/uxbox/main/ui.cljs:173" ],
|
||||
"translations" : {
|
||||
"en" : "Unable to connect to backend server.",
|
||||
"fr" : "Impossible de se connecter au serveur principal."
|
||||
}
|
||||
},
|
||||
"header.sitemap" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:99" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:74" ],
|
||||
"translations" : {
|
||||
"en" : null,
|
||||
"fr" : null
|
||||
|
@ -580,7 +579,7 @@
|
|||
}
|
||||
},
|
||||
"settings.password" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/header.cljs:34" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/header.cljs:36" ],
|
||||
"translations" : {
|
||||
"en" : "PASSWORD",
|
||||
"fr" : "MOT DE PASSE"
|
||||
|
@ -622,14 +621,14 @@
|
|||
}
|
||||
},
|
||||
"settings.profile" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/header.cljs:30" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/header.cljs:32" ],
|
||||
"translations" : {
|
||||
"en" : "PROFILE",
|
||||
"fr" : "PROFIL"
|
||||
}
|
||||
},
|
||||
"settings.profile.lang" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:89" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:88" ],
|
||||
"translations" : {
|
||||
"en" : "Default language",
|
||||
"fr" : "Langue par défaut"
|
||||
|
@ -643,109 +642,127 @@
|
|||
}
|
||||
},
|
||||
"settings.profile.section-basic-data" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:63" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:62" ],
|
||||
"translations" : {
|
||||
"en" : "Name, username and email",
|
||||
"fr" : "Nom, nom d'utilisateur et adresse email"
|
||||
}
|
||||
},
|
||||
"settings.profile.section-theme-data" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:98" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:97" ],
|
||||
"translations" : {
|
||||
"en" : "Default theme",
|
||||
"fr" : "Thème par défaut"
|
||||
}
|
||||
},
|
||||
"settings.profile.your-avatar" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:143" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:142" ],
|
||||
"translations" : {
|
||||
"en" : "Your avatar",
|
||||
"fr" : "Votre avatar"
|
||||
}
|
||||
},
|
||||
"settings.profile.your-email" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:84" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:83" ],
|
||||
"translations" : {
|
||||
"en" : null,
|
||||
"fr" : null
|
||||
}
|
||||
},
|
||||
"settings.profile.your-name" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:72" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:71" ],
|
||||
"translations" : {
|
||||
"en" : "Your name",
|
||||
"fr" : "Votre nom complet"
|
||||
}
|
||||
},
|
||||
"settings.update-settings" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/notifications.cljs:42", "src/uxbox/main/ui/settings/password.cljs:102", "src/uxbox/main/ui/settings/profile.cljs:110" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/settings/notifications.cljs:42", "src/uxbox/main/ui/settings/password.cljs:102", "src/uxbox/main/ui/settings/profile.cljs:109" ],
|
||||
"translations" : {
|
||||
"en" : "Update settings",
|
||||
"fr" : "Mettre à jour les paramètres"
|
||||
}
|
||||
},
|
||||
"viewer.empty-state" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer.cljs:43" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer.cljs:44" ],
|
||||
"translations" : {
|
||||
"en" : "No frames found on the page."
|
||||
}
|
||||
},
|
||||
"viewer.frame-not-found" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer.cljs:47" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer.cljs:48" ],
|
||||
"translations" : {
|
||||
"en" : "Frame not found."
|
||||
}
|
||||
},
|
||||
"viewer.header.dont-show-interactions" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:40" ],
|
||||
"translations" : {
|
||||
"en" : "Don't show interactions"
|
||||
}
|
||||
},
|
||||
"viewer.header.edit-page" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:112" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:137" ],
|
||||
"translations" : {
|
||||
"en" : "Edit page"
|
||||
}
|
||||
},
|
||||
"viewer.header.fullscreen" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:123" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:148" ],
|
||||
"translations" : {
|
||||
"en" : "Full Screen"
|
||||
}
|
||||
},
|
||||
"viewer.header.share.copy-link" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:64" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:86" ],
|
||||
"translations" : {
|
||||
"en" : "Copy link"
|
||||
}
|
||||
},
|
||||
"viewer.header.share.create-link" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:72" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:94" ],
|
||||
"translations" : {
|
||||
"en" : "Create link"
|
||||
}
|
||||
},
|
||||
"viewer.header.share.placeholder" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:62" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:84" ],
|
||||
"translations" : {
|
||||
"en" : "Share link will apear here"
|
||||
}
|
||||
},
|
||||
"viewer.header.share.remove-link" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:70" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:92" ],
|
||||
"translations" : {
|
||||
"en" : "Remove link"
|
||||
}
|
||||
},
|
||||
"viewer.header.share.subtitle" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:66" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:88" ],
|
||||
"translations" : {
|
||||
"en" : "Anyone with the link will have access"
|
||||
}
|
||||
},
|
||||
"viewer.header.share.title" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:50", "src/uxbox/main/ui/viewer/header.cljs:52", "src/uxbox/main/ui/viewer/header.cljs:58" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:72", "src/uxbox/main/ui/viewer/header.cljs:74", "src/uxbox/main/ui/viewer/header.cljs:80" ],
|
||||
"translations" : {
|
||||
"en" : "Share link"
|
||||
}
|
||||
},
|
||||
"viewer.header.show-interactions" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:44" ],
|
||||
"translations" : {
|
||||
"en" : "Show interactions"
|
||||
}
|
||||
},
|
||||
"viewer.header.show-interactions-on-click" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:48" ],
|
||||
"translations" : {
|
||||
"en" : "Show interactions on click"
|
||||
}
|
||||
},
|
||||
"viewer.header.sitemap" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:97" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/viewer/header.cljs:121" ],
|
||||
"translations" : {
|
||||
"en" : "Sitemap"
|
||||
}
|
||||
|
@ -799,117 +816,123 @@
|
|||
}
|
||||
},
|
||||
"workspace.header.menu.hide-grid" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:119" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:94" ],
|
||||
"translations" : {
|
||||
"en" : "Hide grid"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.hide-layers" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:126" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:101" ],
|
||||
"translations" : {
|
||||
"en" : "Hide layers"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.hide-libraries" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:140" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:115" ],
|
||||
"translations" : {
|
||||
"en" : "Hide libraries"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.hide-palette" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:133" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:108" ],
|
||||
"translations" : {
|
||||
"en" : "Hide color palette"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.hide-rules" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:112" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:87" ],
|
||||
"translations" : {
|
||||
"en" : "Hide rules"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.show-grid" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:120" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:95" ],
|
||||
"translations" : {
|
||||
"en" : "Show grid"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.show-layers" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:127" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:102" ],
|
||||
"translations" : {
|
||||
"en" : "Show layers"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.show-libraries" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:141" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:116" ],
|
||||
"translations" : {
|
||||
"en" : "Show libraries"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.show-palette" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:134" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:109" ],
|
||||
"translations" : {
|
||||
"en" : "Show color palette"
|
||||
}
|
||||
},
|
||||
"workspace.header.menu.show-rules" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:113" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:88" ],
|
||||
"translations" : {
|
||||
"en" : "Show rules"
|
||||
}
|
||||
},
|
||||
"workspace.header.viewer" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:176" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:153" ],
|
||||
"translations" : {
|
||||
"en" : "View mode (Ctrl + P)",
|
||||
"fr" : "Mode visualisation (Ctrl + P)"
|
||||
}
|
||||
},
|
||||
"workspace.library.all" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:122" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:121" ],
|
||||
"translations" : {
|
||||
"en" : "All libraries"
|
||||
}
|
||||
},
|
||||
"workspace.library.icons" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:172" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:171" ],
|
||||
"translations" : {
|
||||
"en" : "Icons"
|
||||
}
|
||||
},
|
||||
"workspace.library.images" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:177" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:176" ],
|
||||
"translations" : {
|
||||
"en" : "Images"
|
||||
}
|
||||
},
|
||||
"workspace.library.libraries" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:154" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:153" ],
|
||||
"translations" : {
|
||||
"en" : "Libraries"
|
||||
}
|
||||
},
|
||||
"workspace.library.own" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:123" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:122" ],
|
||||
"translations" : {
|
||||
"en" : "My libraries"
|
||||
}
|
||||
},
|
||||
"workspace.library.store" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:124" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/libraries.cljs:123" ],
|
||||
"translations" : {
|
||||
"en" : "Store libraries"
|
||||
}
|
||||
},
|
||||
"workspace.options.color" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:88" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:89" ],
|
||||
"translations" : {
|
||||
"en" : "Color",
|
||||
"fr" : "Couleur"
|
||||
}
|
||||
},
|
||||
"workspace.options.design" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options.cljs:76" ],
|
||||
"translations" : {
|
||||
"en" : "Design"
|
||||
}
|
||||
},
|
||||
"workspace.options.fill" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:51" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:69", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:446" ],
|
||||
"translations" : {
|
||||
"en" : "Fill",
|
||||
"fr" : "Fond"
|
||||
|
@ -922,33 +945,121 @@
|
|||
},
|
||||
"unused" : true
|
||||
},
|
||||
|
||||
"workspace.options.font-options.decoration": "Decoration",
|
||||
"workspace.options.font-options.none": "None",
|
||||
"workspace.options.font-options.underline": "Underline",
|
||||
"workspace.options.font-options.strikethrough": "Strikethrough",
|
||||
"workspace.options.font-options.align-left": "Align left",
|
||||
"workspace.options.font-options.align-center": "Align center",
|
||||
"workspace.options.font-options.align-right": "Align right",
|
||||
"workspace.options.font-options.align-justify": "Justify",
|
||||
"workspace.options.font-options.line-height": "Line height",
|
||||
"workspace.options.font-options.letter-spacing": "Letter Spacing",
|
||||
"workspace.options.font-options.vertical-align": "Vertical align",
|
||||
"workspace.options.font-options.align-top": "Align top",
|
||||
"workspace.options.font-options.align-middle": "Align middle",
|
||||
"workspace.options.font-options.align-bottom": "Align bottom",
|
||||
"workspace.options.font-options.text-case": "Case",
|
||||
"workspace.options.font-options.uppercase": "Uppercase",
|
||||
"workspace.options.font-options.lowercase": "Lowercase",
|
||||
"workspace.options.font-options.titlecase": "Titlecase",
|
||||
|
||||
"workspace.options.font-options" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:85" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:452" ],
|
||||
"translations" : {
|
||||
"en" : "Text",
|
||||
"fr" : "TODO"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.align-bottom" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:357" ],
|
||||
"translations" : {
|
||||
"en" : "Align bottom"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.align-center" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:171" ],
|
||||
"translations" : {
|
||||
"en" : "Align center"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.align-justify" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:181" ],
|
||||
"translations" : {
|
||||
"en" : "Justify"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.align-left" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:166" ],
|
||||
"translations" : {
|
||||
"en" : "Align left"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.align-middle" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:352" ],
|
||||
"translations" : {
|
||||
"en" : "Align middle"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.align-right" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:176" ],
|
||||
"translations" : {
|
||||
"en" : "Align right"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.align-top" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:347" ],
|
||||
"translations" : {
|
||||
"en" : "Align top"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.decoration" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:378" ],
|
||||
"translations" : {
|
||||
"en" : "Decoration"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.letter-spacing" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:304" ],
|
||||
"translations" : {
|
||||
"en" : "Letter Spacing"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.line-height" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:292" ],
|
||||
"translations" : {
|
||||
"en" : "Line height"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.lowercase" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:427" ],
|
||||
"translations" : {
|
||||
"en" : "Lowercase"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.none" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:381", "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:417" ],
|
||||
"translations" : {
|
||||
"en" : "None"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.strikethrough" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:393" ],
|
||||
"translations" : {
|
||||
"en" : "Strikethrough"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.text-case" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:414" ],
|
||||
"translations" : {
|
||||
"en" : "Case"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.titlecase" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:432" ],
|
||||
"translations" : {
|
||||
"en" : "Titlecase"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.underline" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:387" ],
|
||||
"translations" : {
|
||||
"en" : "Underline"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.uppercase" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:422" ],
|
||||
"translations" : {
|
||||
"en" : "Uppercase"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-options.vertical-align" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:344" ],
|
||||
"translations" : {
|
||||
"en" : "Vertical align"
|
||||
}
|
||||
},
|
||||
"workspace.options.font-weight" : {
|
||||
"translations" : {
|
||||
"en" : "Font Size & Weight",
|
||||
|
@ -957,7 +1068,7 @@
|
|||
"unused" : true
|
||||
},
|
||||
"workspace.options.grid-options" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:75" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:76" ],
|
||||
"translations" : {
|
||||
"en" : "Grid settings",
|
||||
"fr" : "Paramètres de la grille"
|
||||
|
@ -977,6 +1088,18 @@
|
|||
},
|
||||
"unused" : true
|
||||
},
|
||||
"workspace.options.navigate-to" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/interactions.cljs:51" ],
|
||||
"translations" : {
|
||||
"en" : "Navigate to"
|
||||
}
|
||||
},
|
||||
"workspace.options.none" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/interactions.cljs:64" ],
|
||||
"translations" : {
|
||||
"en" : "None"
|
||||
}
|
||||
},
|
||||
"workspace.options.opacity" : {
|
||||
"translations" : {
|
||||
"en" : "Opacity",
|
||||
|
@ -985,21 +1108,27 @@
|
|||
"unused" : true
|
||||
},
|
||||
"workspace.options.position" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:144", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:126" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:135", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:126" ],
|
||||
"translations" : {
|
||||
"en" : "Position",
|
||||
"fr" : "Position"
|
||||
}
|
||||
},
|
||||
"workspace.options.prototype" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options.cljs:85" ],
|
||||
"translations" : {
|
||||
"en" : "Prototype"
|
||||
}
|
||||
},
|
||||
"workspace.options.radius" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:188" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:183" ],
|
||||
"translations" : {
|
||||
"en" : "Radius",
|
||||
"fr" : "TODO"
|
||||
}
|
||||
},
|
||||
"workspace.options.rotation" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:164" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:159" ],
|
||||
"translations" : {
|
||||
"en" : "Rotation",
|
||||
"fr" : "TODO"
|
||||
|
@ -1012,67 +1141,79 @@
|
|||
},
|
||||
"unused" : true
|
||||
},
|
||||
"workspace.options.select-a-shape" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/interactions.cljs:45" ],
|
||||
"translations" : {
|
||||
"en" : "Select a shape, artboard or group to drag a connection to other artboard."
|
||||
}
|
||||
},
|
||||
"workspace.options.select-artboard" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/interactions.cljs:57" ],
|
||||
"translations" : {
|
||||
"en" : "Select artboard"
|
||||
}
|
||||
},
|
||||
"workspace.options.size" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:78", "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:92", "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:120", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:101" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:79", "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:107", "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:101" ],
|
||||
"translations" : {
|
||||
"en" : "Size",
|
||||
"fr" : "Taille"
|
||||
}
|
||||
},
|
||||
"workspace.options.size-presets" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:81" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/frame.cljs:83" ],
|
||||
"translations" : {
|
||||
"en" : "Size presets"
|
||||
}
|
||||
},
|
||||
"workspace.options.stroke" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:81", "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:142" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:109", "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:173" ],
|
||||
"translations" : {
|
||||
"en" : "Stroke",
|
||||
"fr" : null
|
||||
}
|
||||
},
|
||||
"workspace.options.stroke.center" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:128" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:159" ],
|
||||
"translations" : {
|
||||
"en" : "Center"
|
||||
}
|
||||
},
|
||||
"workspace.options.stroke.dashed" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:136" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:167" ],
|
||||
"translations" : {
|
||||
"en" : "Dashed",
|
||||
"fr" : "Tiré"
|
||||
}
|
||||
},
|
||||
"workspace.options.stroke.dotted" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:135" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:166" ],
|
||||
"translations" : {
|
||||
"en" : "Dotted",
|
||||
"fr" : "Pointillé"
|
||||
}
|
||||
},
|
||||
"workspace.options.stroke.inner" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:129" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:160" ],
|
||||
"translations" : {
|
||||
"en" : "Inside"
|
||||
}
|
||||
},
|
||||
"workspace.options.stroke.mixed" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:137" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:168" ],
|
||||
"translations" : {
|
||||
"en" : "Mixed",
|
||||
"fr" : "Mixte"
|
||||
}
|
||||
},
|
||||
"workspace.options.stroke.outer" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:130" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:161" ],
|
||||
"translations" : {
|
||||
"en" : "Outside"
|
||||
}
|
||||
},
|
||||
"workspace.options.stroke.solid" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:134" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:165" ],
|
||||
"translations" : {
|
||||
"en" : "Solid",
|
||||
"fr" : "Solide"
|
||||
|
@ -1092,6 +1233,12 @@
|
|||
},
|
||||
"unused" : true
|
||||
},
|
||||
"workspace.options.use-play-button" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/interactions.cljs:47" ],
|
||||
"translations" : {
|
||||
"en" : "Use the play button at the header to run the prototype view."
|
||||
}
|
||||
},
|
||||
"workspace.sidebar.icons" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/icons.cljs:88" ],
|
||||
"translations" : {
|
||||
|
@ -1107,7 +1254,7 @@
|
|||
"unused" : true
|
||||
},
|
||||
"workspace.sidebar.sitemap" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/sitemap.cljs:130" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/sidebar/sitemap.cljs:140" ],
|
||||
"translations" : {
|
||||
"en" : "Pages",
|
||||
"fr" : "Pages"
|
||||
|
@ -1211,7 +1358,7 @@
|
|||
}
|
||||
},
|
||||
"workspace.viewport.click-to-close-path" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/drawarea.cljs:335" ],
|
||||
"used-in" : [ "src/uxbox/main/ui/workspace/drawarea.cljs:360" ],
|
||||
"translations" : {
|
||||
"en" : "Click to close the path"
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
@import 'main/partials/sidebar-align-options';
|
||||
@import 'main/partials/sidebar-element-options';
|
||||
@import 'main/partials/sidebar-icons';
|
||||
@import 'main/partials/sidebar-interactions';
|
||||
@import 'main/partials/sidebar-layers';
|
||||
@import 'main/partials/sidebar-sitemap';
|
||||
@import 'main/partials/sidebar-document-history';
|
||||
|
|
|
@ -7,12 +7,9 @@
|
|||
|
||||
.element-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.element-icons {
|
||||
background-color: $color-gray-60;
|
||||
border: 1px solid $color-gray-60;
|
||||
|
@ -307,6 +304,10 @@
|
|||
margin-left: auto;
|
||||
}
|
||||
|
||||
&.dropdown-separator:not(:last-child) {
|
||||
border-bottom: 1px solid $color-gray-10;
|
||||
}
|
||||
|
||||
&.dropdown-label:not(:first-child) {
|
||||
border-top: 1px solid $color-gray-10;
|
||||
}
|
||||
|
@ -488,6 +489,29 @@
|
|||
}
|
||||
}
|
||||
|
||||
.navigate-icon {
|
||||
background-color: $color-gray-60;
|
||||
cursor: pointer;
|
||||
margin-left: $small;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
|
||||
svg {
|
||||
height: 16px;
|
||||
fill: $color-gray-30;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
svg {
|
||||
stroke: $color-gray-10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-icon {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
|
|
|
@ -4,3 +4,21 @@
|
|||
//
|
||||
// Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
||||
// Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
.interactions-help {
|
||||
font-size: $fs12;
|
||||
margin: 0 $medium;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.interactions-help-icon {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
margin: $medium auto;
|
||||
|
||||
svg {
|
||||
fill: $color-gray-40;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,11 +111,13 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tool-window-content {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.element-list {
|
||||
|
|
|
@ -42,6 +42,30 @@
|
|||
}
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
a {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
|
||||
svg {
|
||||
fill: $color-gray-30;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
svg {
|
||||
fill: $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sitemap-zone {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
@ -88,7 +112,7 @@
|
|||
.options-zone {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
width: 300px;
|
||||
width: 350px;
|
||||
justify-content: flex-end;
|
||||
position: relative;
|
||||
|
||||
|
@ -223,6 +247,40 @@
|
|||
|
||||
}
|
||||
|
||||
.custom-select-dropdown {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
z-index: 12;
|
||||
width: 200px;
|
||||
max-height: 30rem;
|
||||
min-width: 7rem;
|
||||
overflow-y: auto;
|
||||
|
||||
background-color: $color-white;
|
||||
border-radius: $br-small;
|
||||
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
|
||||
|
||||
li {
|
||||
color: $color-gray-60;
|
||||
cursor: pointer;
|
||||
font-size: $fs14;
|
||||
display: flex;
|
||||
padding: $small $small $small 25px;
|
||||
|
||||
&.selected {
|
||||
background-image: url(/images/icons/tick.svg);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 5% 48%;
|
||||
background-size: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $color-primary-lighter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.zoom-dropdown {
|
||||
left : 150px;
|
||||
top: 45px;
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
(def icon-empty (icon-xref :icon-empty))
|
||||
(def image (icon-xref :image))
|
||||
(def infocard (icon-xref :infocard))
|
||||
(def interaction (icon-xref :interaction))
|
||||
(def layers (icon-xref :layers))
|
||||
(def letter-spacing (icon-xref :letter-spacing))
|
||||
(def line (icon-xref :line))
|
||||
|
@ -66,6 +67,7 @@
|
|||
(def mail (icon-xref :mail))
|
||||
(def minus (icon-xref :minus))
|
||||
(def move (icon-xref :move))
|
||||
(def navigate (icon-xref :navigate))
|
||||
(def options (icon-xref :options))
|
||||
(def organize (icon-xref :organize))
|
||||
(def palette (icon-xref :palette))
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
(s/def ::file (s/keys :req-un [::id ::name]))
|
||||
(s/def ::page (s/keys :req-un [::id ::name ::cp/data]))
|
||||
|
||||
(s/def ::interactions-mode #{:hide :show :show-on-click})
|
||||
|
||||
(s/def ::bundle
|
||||
(s/keys :req-un [::project ::file ::page]))
|
||||
|
||||
|
@ -45,7 +47,10 @@
|
|||
(ptk/reify ::initialize
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc state :viewer-local {:zoom 1 :page-id page-id}))
|
||||
(assoc state :viewer-local {:zoom 1
|
||||
:page-id page-id
|
||||
:interactions-mode :hide
|
||||
:show-interactions? false}))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
|
@ -178,6 +183,52 @@
|
|||
(when (< index (dec total))
|
||||
(rx/of (rt/nav :viewer pparams (assoc qparams :index (inc index)))))))))
|
||||
|
||||
(defn set-interactions-mode
|
||||
[mode]
|
||||
(us/verify ::interactions-mode mode)
|
||||
(ptk/reify ::set-interactions-mode
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc-in [:viewer-local :interactions-mode] mode)
|
||||
(assoc-in [:viewer-local :show-interactions?] (case mode
|
||||
:hide false
|
||||
:show true
|
||||
:show-on-click false))))))
|
||||
|
||||
(declare flash-done)
|
||||
|
||||
(def flash-interactions
|
||||
(ptk/reify ::flash-interactions
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:viewer-local :show-interactions?] true))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [stopper (rx/filter (ptk/type? ::flash-interactions) stream)]
|
||||
(->> (rx/of flash-done)
|
||||
(rx/delay 1000)
|
||||
(rx/take-until stopper))))))
|
||||
|
||||
(def flash-done
|
||||
(ptk/reify ::flash-done
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:viewer-local :show-interactions?] false))))
|
||||
|
||||
;; --- Navigation
|
||||
|
||||
(defn go-to-frame
|
||||
[frame-id]
|
||||
(us/verify ::us/uuid frame-id)
|
||||
(ptk/reify ::go-to-frame
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page-id (get-in state [:viewer-local :page-id])
|
||||
frames (get-in state [:viewer-data :frames])
|
||||
index (d/index-of-pred frames #(= (:id %) frame-id))]
|
||||
(rx/of (rt/nav :viewer {:page-id page-id} {:index index}))))))
|
||||
|
||||
;; --- Shortcuts
|
||||
|
||||
|
|
|
@ -68,13 +68,16 @@
|
|||
:element-options
|
||||
:rules})
|
||||
|
||||
(s/def ::options-mode #{:design :prototype})
|
||||
|
||||
(def workspace-default
|
||||
{:zoom 1
|
||||
:flags #{}
|
||||
:selected #{}
|
||||
:drawing nil
|
||||
:drawing-tool nil
|
||||
:tooltip nil})
|
||||
:tooltip nil
|
||||
:options-mode :design})
|
||||
|
||||
(def initialize-layout
|
||||
(ptk/reify ::initialize-layout
|
||||
|
@ -243,6 +246,16 @@
|
|||
(conj flags flag)))))]
|
||||
(reduce reduce-fn state flags)))))
|
||||
|
||||
;; --- Set element options mode
|
||||
|
||||
(defn set-options-mode
|
||||
[mode]
|
||||
(us/assert ::options-mode mode)
|
||||
(ptk/reify ::set-options-mode
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:workspace-local :options-mode] mode))))
|
||||
|
||||
;; --- Tooltip
|
||||
|
||||
(defn assign-cursor-tooltip
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
|
@ -110,3 +111,34 @@
|
|||
[:& shape-wrapper {:shape item
|
||||
:key (:id item)}]))]))
|
||||
|
||||
(mf/defc frame-svg
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [objects frame zoom] :or {zoom 1} :as props}]
|
||||
(let [modifier (-> (gpt/point (:x frame) (:y frame))
|
||||
(gpt/negate)
|
||||
(gmt/translate-matrix))
|
||||
|
||||
frame-id (:id frame)
|
||||
modifier-ids (concat [frame-id] (cp/get-children frame-id objects))
|
||||
|
||||
update-fn (fn [state shape-id]
|
||||
(-> state
|
||||
(assoc-in [shape-id :modifiers :displacement] modifier)))
|
||||
objects (reduce update-fn objects modifier-ids)
|
||||
frame (assoc-in frame [:modifiers :displacement] modifier )
|
||||
|
||||
width (* (:width frame) zoom)
|
||||
height (* (:height frame) zoom)
|
||||
vbox (str "0 0 " (:width frame 0) " " (:height frame 0))
|
||||
frame-wrapper (mf/use-memo (mf/deps objects)
|
||||
#(frame-wrapper objects))]
|
||||
|
||||
[:svg {:view-box vbox
|
||||
:width width
|
||||
:height height
|
||||
:version "1.1"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:xmlns "http://www.w3.org/2000/svg"}
|
||||
[:& frame-wrapper {:shape frame
|
||||
:view-box vbox}]]))
|
||||
|
||||
|
|
|
@ -14,7 +14,10 @@
|
|||
[beicon.core :as rx]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.store :as st]))
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.common.uuid :as uuid]))
|
||||
|
||||
;; ---- Global refs
|
||||
|
||||
(def route
|
||||
(l/derived :route st/state))
|
||||
|
@ -28,6 +31,8 @@
|
|||
(def profile
|
||||
(l/derived :profile st/state))
|
||||
|
||||
;; ---- Workspace refs
|
||||
|
||||
(def workspace-local
|
||||
(l/derived :workspace-local st/state))
|
||||
|
||||
|
@ -79,6 +84,15 @@
|
|||
(vec))))]
|
||||
(l/derived selector st/state =)))
|
||||
|
||||
(def frames
|
||||
(letfn [(selector [data]
|
||||
(->> (get-in data [:objects uuid/zero])
|
||||
:shapes
|
||||
(map #(get-in data [:objects %]))
|
||||
(filter #(= (:type %) :frame))
|
||||
(sort-by :name)))]
|
||||
(l/derived selector workspace-data)))
|
||||
|
||||
(defn is-child-selected?
|
||||
[id]
|
||||
(letfn [(selector [state]
|
||||
|
@ -120,3 +134,21 @@
|
|||
|
||||
(def current-transform
|
||||
(l/derived :transform workspace-local))
|
||||
|
||||
(def options-mode
|
||||
(l/derived :options-mode workspace-local))
|
||||
|
||||
;; ---- Viewer refs
|
||||
|
||||
(def viewer-data-ref
|
||||
(l/derived :viewer-data st/state))
|
||||
|
||||
(def viewer-local-ref
|
||||
(l/derived :viewer-local st/state))
|
||||
|
||||
(def interactions-mode
|
||||
(l/derived :interactions-mode viewer-local-ref))
|
||||
|
||||
(def show-interactions?
|
||||
(l/derived :show-interactions? viewer-local-ref))
|
||||
|
||||
|
|
|
@ -17,13 +17,15 @@
|
|||
[uxbox.main.ui.shapes.bounding-box :refer [bounding-box]]
|
||||
[uxbox.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]]))
|
||||
|
||||
;; --- Circle Wrapper
|
||||
;; --- Circle Wrapper for workspace
|
||||
|
||||
(declare circle-shape)
|
||||
|
||||
(mf/defc circle-wrapper
|
||||
[{:keys [shape] :as props}]
|
||||
(let [selected (mf/deref refs/selected-shapes)
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
selected? (contains? selected (:id shape))
|
||||
on-mouse-down #(common/on-mouse-down % shape)
|
||||
on-context-menu #(common/on-context-menu % shape)]
|
||||
|
@ -32,6 +34,36 @@
|
|||
:on-context-menu on-context-menu}
|
||||
[:& circle-shape {:shape shape}]]))
|
||||
|
||||
;; --- Circle Wrapper for viewer
|
||||
|
||||
(mf/defc circle-viewer-wrapper
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
{:keys [id x y width height]} shape
|
||||
transform (geom/transform-matrix shape)
|
||||
|
||||
show-interactions? (mf/deref refs/show-interactions?)
|
||||
|
||||
on-mouse-down (mf/use-callback
|
||||
(mf/deps shape)
|
||||
#(common/on-mouse-down-viewer % shape))]
|
||||
|
||||
[:g.shape {:on-mouse-down on-mouse-down
|
||||
:cursor (when (:interactions shape) "pointer")}
|
||||
[:*
|
||||
[:& circle-shape {:shape shape}]
|
||||
(when (and (:interactions shape) show-interactions?)
|
||||
[:> "rect" #js {:x (- x 1)
|
||||
:y (- y 1)
|
||||
:width (+ width 2)
|
||||
:height (+ height 2)
|
||||
:transform transform
|
||||
:fill "#31EFB8"
|
||||
:stroke "#31EFB8"
|
||||
:strokeWidth 1
|
||||
:fillOpacity 0.2}])]]))
|
||||
|
||||
;; --- Circle Shape
|
||||
|
||||
(mf/defc circle-shape
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
[uxbox.common.data :as d]
|
||||
[uxbox.common.spec :as us]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.data.viewer :as dv]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.keyboard :as kbd]
|
||||
|
@ -66,10 +67,24 @@
|
|||
(st/emit! (dw/start-move-selected)))))))
|
||||
|
||||
|
||||
;; --- Workspace context menu
|
||||
(defn on-context-menu
|
||||
[event shape]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(let [position (dom/get-client-position event)]
|
||||
(st/emit!(dw/show-shape-context-menu {:position position
|
||||
:shape shape}))))
|
||||
(st/emit! (dw/show-shape-context-menu {:position position
|
||||
:shape shape}))))
|
||||
|
||||
|
||||
;; --- Interaction actions (in viewer mode)
|
||||
|
||||
(defn on-mouse-down-viewer
|
||||
[event {:keys [interactions] :as shape}]
|
||||
(let [interaction (first (filter #(= (:action-type % :click)) interactions))]
|
||||
(case (:action-type interaction)
|
||||
:navigate
|
||||
(let [frame-id (:destination interaction)]
|
||||
(st/emit! (dv/go-to-frame frame-id)))
|
||||
nil)))
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
(declare frame-shape)
|
||||
(declare translate-to-frame)
|
||||
|
||||
;; ---- Frame Wrapper for workspace
|
||||
|
||||
(defn frame-wrapper-memo-equals?
|
||||
[np op]
|
||||
(let [n-shape (aget np "shape")
|
||||
|
@ -114,6 +116,20 @@
|
|||
{:shape (geom/transform-shape shape)
|
||||
:childs childs}]])))))
|
||||
|
||||
;; ;; --- Frame Wrapper for viewer
|
||||
;;
|
||||
;; (mf/defc frame-viewer-wrapper
|
||||
;; {::mf/wrap-props false}
|
||||
;; [props]
|
||||
;; (let [shape (unchecked-get props "shape")
|
||||
;; on-mouse-down (mf/use-callback
|
||||
;; (mf/deps shape)
|
||||
;; #(common/on-mouse-down-viewer % shape))]
|
||||
;; [:g.shape {:on-mouse-down on-mouse-down}
|
||||
;; [:& rect-shape {:shape shape}]]))
|
||||
|
||||
;; ---- Frame shape
|
||||
|
||||
(defn frame-shape
|
||||
[shape-wrapper]
|
||||
(mf/fnc frame-shape
|
||||
|
|
|
@ -14,25 +14,60 @@
|
|||
[uxbox.main.ui.shapes.common :as common]
|
||||
[uxbox.util.interop :as itr]))
|
||||
|
||||
|
||||
;; --- Icon Wrapper
|
||||
;; --- Icon Wrapper for workspace
|
||||
|
||||
(declare icon-shape)
|
||||
|
||||
(mf/defc icon-wrapper
|
||||
[{:keys [shape frame] :as props}]
|
||||
(let [selected (mf/deref refs/selected-shapes)
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
frame (unchecked-get props "frame")
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
selected? (contains? selected (:id shape))
|
||||
on-mouse-down #(common/on-mouse-down % shape)]
|
||||
[:g.shape {:class (when selected? "selected")
|
||||
:on-mouse-down on-mouse-down}
|
||||
[:& icon-shape {:shape (geom/transform-shape frame shape)}]]))
|
||||
|
||||
;; --- Icon Wrapper for viewer
|
||||
|
||||
(mf/defc icon-viewer-wrapper
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
frame (unchecked-get props "frame")
|
||||
|
||||
{:keys [x y width height]} shape
|
||||
transform (geom/transform-matrix shape)
|
||||
|
||||
show-interactions? (mf/deref refs/show-interactions?)
|
||||
|
||||
on-mouse-down (mf/use-callback
|
||||
(mf/deps shape)
|
||||
#(common/on-mouse-down-viewer % shape))]
|
||||
[:g.shape {:on-mouse-down on-mouse-down
|
||||
:cursor (when (:interactions shape) "pointer")}
|
||||
[:*
|
||||
[:& icon-shape {:shape (geom/transform-shape frame shape)}]
|
||||
(when (and (:interactions shape) show-interactions?)
|
||||
[:> "rect" #js {:x (- x 1)
|
||||
:y (- y 1)
|
||||
:width (+ width 2)
|
||||
:height (+ height 2)
|
||||
:transform transform
|
||||
:fill "#31EFB8"
|
||||
:stroke "#31EFB8"
|
||||
:strokeWidth 1
|
||||
:fillOpacity 0.2}])]]))
|
||||
|
||||
;; --- Icon Shape
|
||||
|
||||
(mf/defc icon-shape
|
||||
[{:keys [shape] :as props}]
|
||||
(let [{:keys [id x y width height metadata rotation content] :as shape} shape
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
{:keys [id x y width height metadata rotation content]} shape
|
||||
transform (when (and rotation (pos? rotation))
|
||||
(str/format "rotate(%s %s %s)"
|
||||
rotation
|
||||
|
|
|
@ -17,13 +17,15 @@
|
|||
[uxbox.util.interop :as itr]
|
||||
[uxbox.util.geom.matrix :as gmt]))
|
||||
|
||||
;; --- Image Wrapper
|
||||
;; --- Image Wrapper for workspace
|
||||
|
||||
(declare image-shape)
|
||||
|
||||
(mf/defc image-wrapper
|
||||
[{:keys [shape] :as props}]
|
||||
(let [selected (mf/deref refs/selected-shapes)
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
selected? (contains? selected (:id shape))
|
||||
on-mouse-down (mf/use-callback
|
||||
(mf/deps shape)
|
||||
|
@ -38,18 +40,48 @@
|
|||
:on-context-menu on-context-menu}
|
||||
[:& image-shape {:shape shape}]]))
|
||||
|
||||
;; --- Image Wrapper for viewer
|
||||
|
||||
(mf/defc image-viewer-wrapper
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
{:keys [x y width height]} shape
|
||||
transform (geom/transform-matrix shape)
|
||||
|
||||
show-interactions? (mf/deref refs/show-interactions?)
|
||||
|
||||
on-mouse-down (mf/use-callback
|
||||
(mf/deps shape)
|
||||
#(common/on-mouse-down-viewer % shape))]
|
||||
[:g.shape {:on-mouse-down on-mouse-down
|
||||
:cursor (when (:interactions shape) "pointer")}
|
||||
[:*
|
||||
[:& image-shape {:shape shape}]
|
||||
(when (and (:interactions shape) show-interactions?)
|
||||
[:> "rect" #js {:x (- x 1)
|
||||
:y (- y 1)
|
||||
:width (+ width 2)
|
||||
:height (+ height 2)
|
||||
:transform transform
|
||||
:fill "#31EFB8"
|
||||
:stroke "#31EFB8"
|
||||
:strokeWidth 1
|
||||
:fillOpacity 0.2}])]]))
|
||||
|
||||
;; --- Image Shape
|
||||
|
||||
(mf/defc image-shape
|
||||
[{:keys [shape] :as props}]
|
||||
(let [{:keys [id x y width height rotation metadata]} shape
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
{:keys [id x y width height rotation metadata]} shape
|
||||
transform (geom/transform-matrix shape)
|
||||
uri (if (or (> (:thumb-width metadata) width)
|
||||
(> (:thumb-height metadata) height))
|
||||
(:thumb-uri metadata)
|
||||
(:uri metadata))
|
||||
|
||||
|
||||
props (-> (attrs/extract-style-attrs shape)
|
||||
(itr/obj-assign!
|
||||
#js {:x x
|
||||
|
|
|
@ -19,13 +19,15 @@
|
|||
[uxbox.main.ui.shapes.bounding-box :refer [bounding-box]]
|
||||
[uxbox.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]]))
|
||||
|
||||
;; --- Path Wrapper
|
||||
;; --- Path Wrapper for workspace
|
||||
|
||||
(declare path-shape)
|
||||
|
||||
(mf/defc path-wrapper
|
||||
[{:keys [shape] :as props}]
|
||||
(let [selected (mf/deref refs/selected-shapes)
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
selected? (contains? selected (:id shape))
|
||||
on-mouse-down (mf/use-callback
|
||||
(mf/deps shape)
|
||||
|
@ -44,6 +46,35 @@
|
|||
:on-context-menu on-context-menu}
|
||||
[:& path-shape {:shape shape :background? true}]]))
|
||||
|
||||
;; --- Path Wrapper for viewer
|
||||
|
||||
(mf/defc path-viewer-wrapper
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
{:keys [x y width height]} (geom/shape->rect-shape shape)
|
||||
transform (geom/transform-matrix shape)
|
||||
|
||||
show-interactions? (mf/deref refs/show-interactions?)
|
||||
|
||||
on-mouse-down (mf/use-callback
|
||||
(mf/deps shape)
|
||||
#(common/on-mouse-down-viewer % shape))]
|
||||
[:g.shape {:on-mouse-down on-mouse-down
|
||||
:cursor (when (:interactions shape) "pointer")}
|
||||
[:*
|
||||
[:& path-shape {:shape shape}]
|
||||
(when (and (:interactions shape) show-interactions?)
|
||||
[:> "rect" #js {:x (- x 1)
|
||||
:y (- y 1)
|
||||
:width (+ width 2)
|
||||
:height (+ height 2)
|
||||
:transform transform
|
||||
:fill "#31EFB8"
|
||||
:stroke "#31EFB8"
|
||||
:strokeWidth 1
|
||||
:fillOpacity 0.2}])]]))
|
||||
|
||||
;; --- Path Shape
|
||||
|
||||
(defn- render-path
|
||||
|
@ -68,8 +99,11 @@
|
|||
(recur buffer (inc index)))))))
|
||||
|
||||
(mf/defc path-shape
|
||||
[{:keys [shape background?] :as props}]
|
||||
(let [{:keys [id x y width height]} (geom/shape->rect-shape shape)
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
background? (unchecked-get props "background?")
|
||||
{:keys [id x y width height]} (geom/shape->rect-shape shape)
|
||||
transform (geom/transform-matrix shape)
|
||||
pdata (render-path shape)
|
||||
props (-> (attrs/extract-style-attrs shape)
|
||||
|
|
|
@ -17,17 +17,17 @@
|
|||
[uxbox.util.interop :as itr]
|
||||
[uxbox.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]]))
|
||||
|
||||
;; --- Rect Wrapper
|
||||
|
||||
(declare rect-shape)
|
||||
|
||||
;; --- Rect Wrapper for workspace
|
||||
|
||||
(mf/defc rect-wrapper
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
on-mouse-down (mf/use-callback
|
||||
(mf/deps shape)
|
||||
#(common/on-mouse-down % shape))
|
||||
on-mouse-down (mf/use-callback
|
||||
(mf/deps shape)
|
||||
#(common/on-mouse-down % shape))
|
||||
on-context-menu (mf/use-callback
|
||||
(mf/deps shape)
|
||||
#(common/on-context-menu % shape))]
|
||||
|
@ -35,6 +35,36 @@
|
|||
:on-context-menu on-context-menu}
|
||||
[:& rect-shape {:shape shape}]]))
|
||||
|
||||
;; --- Rect Wrapper for viewer
|
||||
|
||||
(mf/defc rect-viewer-wrapper
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
{:keys [x y width height]} shape
|
||||
transform (geom/transform-matrix shape)
|
||||
|
||||
show-interactions? (mf/deref refs/show-interactions?)
|
||||
|
||||
on-mouse-down (mf/use-callback
|
||||
(mf/deps shape)
|
||||
#(common/on-mouse-down-viewer % shape))]
|
||||
|
||||
[:g.shape {:on-mouse-down on-mouse-down
|
||||
:cursor (when (:interactions shape) "pointer")}
|
||||
[:*
|
||||
[:& rect-shape {:shape shape}]
|
||||
(when (and (:interactions shape) show-interactions?)
|
||||
[:> "rect" #js {:x (- x 1)
|
||||
:y (- y 1)
|
||||
:width (+ width 2)
|
||||
:height (+ height 2)
|
||||
:transform transform
|
||||
:fill "#31EFB8"
|
||||
:stroke "#31EFB8"
|
||||
:strokeWidth 1
|
||||
:fillOpacity 0.2}])]]))
|
||||
|
||||
;; --- Rect Shape
|
||||
|
||||
(mf/defc rect-shape
|
||||
|
|
|
@ -39,15 +39,17 @@
|
|||
(dom/stop-propagation event)
|
||||
(common/on-mouse-down event shape)))
|
||||
|
||||
;; --- Text Wrapper
|
||||
;; --- Text Wrapper for workspace
|
||||
|
||||
(declare text-shape-html)
|
||||
(declare text-shape-edit)
|
||||
(declare text-shape)
|
||||
|
||||
(mf/defc text-wrapper
|
||||
[{:keys [shape] :as props}]
|
||||
(let [{:keys [id x1 y1 content group]} shape
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
{:keys [id x1 y1 content group]} shape
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
edition (mf/deref refs/selected-edition)
|
||||
edition? (= edition id)
|
||||
|
@ -72,6 +74,35 @@
|
|||
[:& text-shape {:shape shape
|
||||
:selected? selected?}])]))
|
||||
|
||||
;; --- Text Wrapper for viewer
|
||||
|
||||
(mf/defc text-viewer-wrapper
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
{:keys [x y width height]} shape
|
||||
transform (geom/transform-matrix shape)
|
||||
|
||||
show-interactions? (mf/deref refs/show-interactions?)
|
||||
|
||||
on-mouse-down (mf/use-callback
|
||||
(mf/deps shape)
|
||||
#(common/on-mouse-down-viewer % shape))]
|
||||
[:g.shape {:on-mouse-down on-mouse-down
|
||||
:cursor (when (:interactions shape) "pointer")}
|
||||
[:*
|
||||
[:& text-shape {:shape shape}]
|
||||
(when (and (:interactions shape) show-interactions?)
|
||||
[:> "rect" #js {:x (- x 1)
|
||||
:y (- y 1)
|
||||
:width (+ width 2)
|
||||
:height (+ height 2)
|
||||
:transform transform
|
||||
:fill "#31EFB8"
|
||||
:stroke "#31EFB8"
|
||||
:strokeWidth 1
|
||||
:fillOpacity 0.2}])]]))
|
||||
|
||||
;; --- Text Editor Rendering
|
||||
|
||||
(defn- generate-root-styles
|
||||
|
@ -342,8 +373,11 @@
|
|||
(render-text-node root)))
|
||||
|
||||
(mf/defc text-shape
|
||||
[{:keys [shape selected?] :as props}]
|
||||
(let [{:keys [id x y width height rotation content]} shape]
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
shape (unchecked-get props "selected?")
|
||||
{:keys [id x y width height rotation content]} shape]
|
||||
[:foreignObject {:x x
|
||||
:y y
|
||||
:transform (geom/transform-matrix shape)
|
||||
|
|
|
@ -17,13 +17,15 @@
|
|||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.common.exceptions :as ex]
|
||||
[uxbox.main.data.viewer :as dv]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.components.dropdown :refer [dropdown]]
|
||||
[uxbox.main.ui.hooks :as hooks]
|
||||
[uxbox.main.ui.keyboard :as kbd]
|
||||
[uxbox.main.ui.messages :refer [messages]]
|
||||
[uxbox.main.ui.viewer.header :refer [header]]
|
||||
[uxbox.main.ui.viewer.thumbnails :refer [thumbnails-panel frame-svg]]
|
||||
[uxbox.main.ui.viewer.thumbnails :refer [thumbnails-panel]]
|
||||
[uxbox.main.ui.viewer.frame-viewer :refer [frame-viewer-svg]]
|
||||
[uxbox.util.data :refer [classnames]]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.i18n :as i18n :refer [t tr]])
|
||||
|
@ -46,9 +48,9 @@
|
|||
[:span (t locale "viewer.frame-not-found")]]
|
||||
|
||||
:else
|
||||
[:& frame-svg {:frame frame
|
||||
:zoom zoom
|
||||
:objects objects}])]))
|
||||
[:& frame-viewer-svg {:frame frame
|
||||
:zoom zoom
|
||||
:objects objects}])]))
|
||||
|
||||
(mf/defc viewer-content
|
||||
[{:keys [data local index] :as props}]
|
||||
|
@ -56,6 +58,13 @@
|
|||
|
||||
[toggle-fullscreen fullscreen?] (hooks/use-fullscreen container)
|
||||
|
||||
on-click
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [mode (get local :interactions-mode)]
|
||||
(when (= mode :show-on-click)
|
||||
(st/emit! dv/flash-interactions))))
|
||||
|
||||
on-mouse-wheel
|
||||
(fn [event]
|
||||
(when (kbd/ctrl? event)
|
||||
|
@ -65,7 +74,6 @@
|
|||
(st/emit! dv/decrease-zoom)
|
||||
(st/emit! dv/increase-zoom)))))
|
||||
|
||||
|
||||
on-mount
|
||||
(fn []
|
||||
;; bind with passive=false to allow the event to be cancelled
|
||||
|
@ -88,7 +96,7 @@
|
|||
:fullscreen? fullscreen?
|
||||
:local local
|
||||
:index index}]
|
||||
[:div.viewer-content
|
||||
[:div.viewer-content {:on-click on-click}
|
||||
(when (:show-thumbnails local)
|
||||
[:& thumbnails-panel {:index index
|
||||
:data data}])
|
||||
|
@ -99,20 +107,14 @@
|
|||
|
||||
;; --- Component: Viewer Page
|
||||
|
||||
(def viewer-data-ref
|
||||
(l/derived :viewer-data st/state))
|
||||
|
||||
(def viewer-local-ref
|
||||
(l/derived :viewer-local st/state))
|
||||
|
||||
(mf/defc viewer-page
|
||||
[{:keys [page-id index token] :as props}]
|
||||
(mf/use-effect
|
||||
(mf/deps page-id token)
|
||||
#(st/emit! (dv/initialize page-id token)))
|
||||
|
||||
(let [data (mf/deref viewer-data-ref)
|
||||
local (mf/deref viewer-local-ref)]
|
||||
(let [data (mf/deref refs/viewer-data-ref)
|
||||
local (mf/deref refs/viewer-local-ref)]
|
||||
(when data
|
||||
[:& viewer-content {:index index
|
||||
:local local
|
||||
|
|
104
frontend/src/uxbox/main/ui/viewer/frame_viewer.cljs
Normal file
104
frontend/src/uxbox/main/ui/viewer/frame_viewer.cljs
Normal file
|
@ -0,0 +1,104 @@
|
|||
;; 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 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.main.ui.viewer.frame-viewer
|
||||
"The main container for a frame in viewer mode"
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.main.ui.shapes.frame :as frame]
|
||||
[uxbox.main.ui.shapes.circle :as circle]
|
||||
[uxbox.main.ui.shapes.icon :as icon]
|
||||
[uxbox.main.ui.shapes.image :as image]
|
||||
[uxbox.main.ui.shapes.path :as path]
|
||||
[uxbox.main.ui.shapes.rect :as rect]
|
||||
[uxbox.main.ui.shapes.text :as text]
|
||||
[uxbox.main.ui.shapes.group :as group]))
|
||||
|
||||
(declare shape-wrapper)
|
||||
|
||||
(defn frame-wrapper
|
||||
[objects]
|
||||
(mf/fnc frame-wrapper
|
||||
[{:keys [shape] :as props}]
|
||||
(let [childs (mapv #(get objects %)
|
||||
(:shapes shape))
|
||||
shape-wrapper (mf/use-memo (mf/deps objects)
|
||||
#(shape-wrapper objects))
|
||||
frame-shape (mf/use-memo (mf/deps objects)
|
||||
#(frame/frame-shape shape-wrapper))
|
||||
shape (geom/transform-shape shape)]
|
||||
[:& frame-shape {:shape shape :childs childs}])))
|
||||
|
||||
(defn group-wrapper
|
||||
[objects]
|
||||
(mf/fnc group-wrapper
|
||||
[{:keys [shape frame] :as props}]
|
||||
(let [children (mapv #(get objects %)
|
||||
(:shapes shape))
|
||||
shape-wrapper (mf/use-memo (mf/deps objects)
|
||||
#(shape-wrapper objects))
|
||||
group-shape (mf/use-memo (mf/deps objects)
|
||||
#(group/group-shape shape-wrapper))]
|
||||
[:& group-shape {:frame frame
|
||||
:shape shape
|
||||
:children children}])))
|
||||
|
||||
(defn shape-wrapper
|
||||
[objects]
|
||||
(mf/fnc shape-wrapper
|
||||
[{:keys [frame shape] :as props}]
|
||||
(let [group-wrapper (mf/use-memo (mf/deps objects) #(group-wrapper objects))]
|
||||
(when (and shape (not (:hidden shape)))
|
||||
(let [shape (geom/transform-shape frame shape)
|
||||
opts #js {:shape shape}]
|
||||
(case (:type shape)
|
||||
:curve [:> path/path-viewer-wrapper opts]
|
||||
:text [:> text/text-viewer-wrapper opts]
|
||||
:icon [:> icon/icon-viewer-wrapper opts]
|
||||
:rect [:> rect/rect-viewer-wrapper opts]
|
||||
:path [:> path/path-viewer-wrapper opts]
|
||||
:image [:> image/image-viewer-wrapper opts]
|
||||
:circle [:> circle/circle-viewer-wrapper opts]
|
||||
:group [:> group-wrapper {:shape shape :frame frame}]
|
||||
nil))))))
|
||||
|
||||
(mf/defc frame-viewer-svg
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [objects frame zoom] :or {zoom 1} :as props}]
|
||||
(let [modifier (-> (gpt/point (:x frame) (:y frame))
|
||||
(gpt/negate)
|
||||
(gmt/translate-matrix))
|
||||
|
||||
frame-id (:id frame)
|
||||
modifier-ids (concat [frame-id] (cp/get-children frame-id objects))
|
||||
|
||||
update-fn (fn [state shape-id]
|
||||
(-> state
|
||||
(assoc-in [shape-id :modifiers :displacement] modifier)))
|
||||
objects (reduce update-fn objects modifier-ids)
|
||||
frame (assoc-in frame [:modifiers :displacement] modifier )
|
||||
|
||||
width (* (:width frame) zoom)
|
||||
height (* (:height frame) zoom)
|
||||
vbox (str "0 0 " (:width frame 0) " " (:height frame 0))
|
||||
frame-wrapper (mf/use-memo (mf/deps objects)
|
||||
#(frame-wrapper objects))]
|
||||
|
||||
[:svg {:view-box vbox
|
||||
:width width
|
||||
:height height
|
||||
:version "1.1"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:xmlns "http://www.w3.org/2000/svg"}
|
||||
[:& frame-wrapper {:shape frame
|
||||
:view-box vbox}]]))
|
||||
|
|
@ -24,6 +24,28 @@
|
|||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.util.webapi :as wapi]))
|
||||
|
||||
(mf/defc interactions-menu
|
||||
[{:keys [interactions-mode] :as props}]
|
||||
(let [show-dropdown? (mf/use-state false)
|
||||
locale (i18n/use-locale)
|
||||
on-select-mode #(st/emit! (dv/set-interactions-mode %))]
|
||||
[:div.header-icon
|
||||
[:a {:on-click #(swap! show-dropdown? not)} i/eye
|
||||
[:& dropdown {:show @show-dropdown?
|
||||
:on-close #(swap! show-dropdown? not)}
|
||||
[:ul.custom-select-dropdown
|
||||
[:li {:key :hide
|
||||
:class (classnames :selected (= interactions-mode :hide))
|
||||
:on-click #(on-select-mode :hide)}
|
||||
(t locale "viewer.header.dont-show-interactions")]
|
||||
[:li {:key :show
|
||||
:class (classnames :selected (= interactions-mode :show))
|
||||
:on-click #(on-select-mode :show)}
|
||||
(t locale "viewer.header.show-interactions")]
|
||||
[:li {:key :show-on-click
|
||||
:class (classnames :selected (= interactions-mode :show-on-click))
|
||||
:on-click #(on-select-mode :show-on-click)}
|
||||
(t locale "viewer.header.show-interactions-on-click")]]]]]))
|
||||
|
||||
(mf/defc share-link
|
||||
[{:keys [page] :as props}]
|
||||
|
@ -77,6 +99,8 @@
|
|||
total (count frames)
|
||||
on-click #(st/emit! dv/toggle-thumbnails-panel)
|
||||
|
||||
interactions-mode (:interactions-mode local)
|
||||
|
||||
locale (i18n/use-locale)
|
||||
|
||||
profile (mf/deref refs/profile)
|
||||
|
@ -105,6 +129,7 @@
|
|||
[:span.counters (str (inc index) " / " total)]]
|
||||
|
||||
[:div.options-zone
|
||||
[:& interactions-menu {:interactions-mode interactions-mode}]
|
||||
(when-not anonymous?
|
||||
[:& share-link {:page (:page data)}])
|
||||
(when-not anonymous?
|
||||
|
@ -127,4 +152,3 @@
|
|||
i/full-screen)]
|
||||
]]))
|
||||
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.data.viewer :as dv]
|
||||
[uxbox.main.ui.components.dropdown :refer [dropdown']]
|
||||
|
@ -78,37 +77,6 @@
|
|||
[:div.thumbnails-list-inside {:style {:right (str (* @offset 152) "px")}}
|
||||
children]]])))
|
||||
|
||||
(mf/defc frame-svg
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [objects frame zoom] :or {zoom 1} :as props}]
|
||||
(let [modifier (-> (gpt/point (:x frame) (:y frame))
|
||||
(gpt/negate)
|
||||
(gmt/translate-matrix))
|
||||
|
||||
frame-id (:id frame)
|
||||
modifier-ids (concat [frame-id] (cp/get-children frame-id objects))
|
||||
|
||||
update-fn (fn [state shape-id]
|
||||
(-> state
|
||||
(assoc-in [shape-id :modifiers :displacement] modifier)))
|
||||
objects (reduce update-fn objects modifier-ids)
|
||||
frame (assoc-in frame [:modifiers :displacement] modifier )
|
||||
|
||||
width (* (:width frame) zoom)
|
||||
height (* (:height frame) zoom)
|
||||
vbox (str "0 0 " (:width frame 0) " " (:height frame 0))
|
||||
frame-wrapper (mf/use-memo (mf/deps objects)
|
||||
#(exports/frame-wrapper objects))]
|
||||
|
||||
[:svg {:view-box vbox
|
||||
:width width
|
||||
:height height
|
||||
:version "1.1"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:xmlns "http://www.w3.org/2000/svg"}
|
||||
[:& frame-wrapper {:shape frame
|
||||
:view-box vbox}]]))
|
||||
|
||||
(mf/defc thumbnails-summary
|
||||
[{:keys [on-toggle-expand on-close total] :as props}]
|
||||
[:div.thumbnails-summary
|
||||
|
@ -122,7 +90,7 @@
|
|||
[:div.thumbnail-item {:on-click #(on-click % index)}
|
||||
[:div.thumbnail-preview
|
||||
{:class (classnames :selected selected?)}
|
||||
[:& frame-svg {:frame frame :objects objects}]]
|
||||
[:& exports/frame-svg {:frame frame :objects objects}]]
|
||||
[:div.thumbnail-info
|
||||
[:span.name (:name frame)]]])
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
[uxbox.main.ui.workspace.sidebar.options.image :as image]
|
||||
[uxbox.main.ui.workspace.sidebar.options.text :as text]
|
||||
[uxbox.main.ui.workspace.sidebar.options.page :as page]
|
||||
[uxbox.main.ui.workspace.sidebar.options.interactions :refer [interactions-menu]]
|
||||
[uxbox.main.ui.components.tab-container :refer [tab-container tab-element]]
|
||||
[uxbox.util.i18n :refer [tr]]))
|
||||
|
||||
;; --- Options
|
||||
|
@ -45,29 +47,43 @@
|
|||
:image [:& image/options {:shape shape}]
|
||||
nil)])
|
||||
|
||||
(mf/defc shape-options-wrapper
|
||||
[{:keys [shape-id page-id] :as props}]
|
||||
(let [shape-iref (-> (mf/deps shape-id page-id)
|
||||
(mf/use-memo
|
||||
#(-> (l/in [:objects shape-id])
|
||||
(l/derived refs/workspace-data))))
|
||||
shape (mf/deref shape-iref)]
|
||||
[:& shape-options {:shape shape}]))
|
||||
|
||||
(mf/defc options-toolbox
|
||||
{:wrap [mf/memo]}
|
||||
[{:keys [page selected] :as props}]
|
||||
(let [close #(st/emit! (udw/toggle-layout-flag :element-options))
|
||||
selected (mf/deref refs/selected-shapes)]
|
||||
[:div.element-options.tool-window
|
||||
;; [:div.tool-window-bar
|
||||
;; [:div.tool-window-icon i/options]
|
||||
;; [:span (tr "ds.settings.element-options")]
|
||||
;; [:div.tool-window-close {:on-click close} i/close]]
|
||||
[:& align-options]
|
||||
[:div.tool-window-content
|
||||
[:div.element-options
|
||||
(if (= (count selected) 1)
|
||||
[:& shape-options-wrapper {:shape-id (first selected)
|
||||
:page-id (:id page)}]
|
||||
[:& page/options {:page page}])]]]))
|
||||
on-change-tab #(st/emit! (udw/set-options-mode %))
|
||||
|
||||
options-mode (mf/deref refs/options-mode)
|
||||
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
shape-id (first selected)
|
||||
page-id (:id page)
|
||||
shape-iref (-> (mf/deps shape-id page-id)
|
||||
(mf/use-memo
|
||||
#(-> (l/in [:objects shape-id])
|
||||
(l/derived refs/workspace-data))))
|
||||
shape (mf/deref shape-iref)]
|
||||
|
||||
[:div.tool-window
|
||||
;; [:div.tool-window-bar
|
||||
;; [:div.tool-window-icon i/options]
|
||||
;; [:span (tr "ds.settings.element-options")]
|
||||
;; [:div.tool-window-close {:on-click close} i/close]]
|
||||
[:div.tool-window-content
|
||||
[:& tab-container {:on-change-tab on-change-tab :selected options-mode}
|
||||
|
||||
[:& tab-element
|
||||
{:id :design :title (tr "workspace.options.design")}
|
||||
[:div.element-options
|
||||
[:& align-options]
|
||||
[:div
|
||||
(if (= (count selected) 1)
|
||||
[:& shape-options {:shape shape}]
|
||||
[:& page/options {:page page}])]]]
|
||||
|
||||
[:& tab-element
|
||||
{:id :prototype :title (tr "workspace.options.prototype")}
|
||||
[:div.element-options
|
||||
[:& interactions-menu {:shape shape}]]]]
|
||||
]]))
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
delta (if (= attr :x)
|
||||
(gpt/point (math/neg (- pval cval)) 0)
|
||||
(gpt/point 0 (math/neg (- pval cval))))]
|
||||
|
||||
|
||||
;; TODO: Change so not apply the modifiers until blur
|
||||
(st/emit! (udw/set-modifiers #{(:id shape)} {:displacement delta})
|
||||
(udw/apply-modifiers #{(:id shape)}))))
|
||||
|
@ -94,9 +94,7 @@
|
|||
(:name size-preset)
|
||||
[:span (:width size-preset) " x " (:height size-preset)]]))]]]
|
||||
[:span.orientation-icon {on-click #(on-orientation-clicked :vert)} i/size-vert]
|
||||
[:span.orientation-icon {on-click #(on-orientation-clicked :horiz)} i/size-horiz]
|
||||
]
|
||||
|
||||
[:span.orientation-icon {on-click #(on-orientation-clicked :horiz)} i/size-horiz]]
|
||||
|
||||
;; WIDTH & HEIGHT
|
||||
[:div.row-flex
|
||||
|
|
|
@ -14,10 +14,61 @@
|
|||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.colorpicker :as cp]
|
||||
[uxbox.main.ui.components.dropdown :refer [dropdown]]
|
||||
[uxbox.util.data :refer [read-string]]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.i18n :refer [tr]]))
|
||||
|
||||
(mf/defc interactions-menu
|
||||
[{:keys [shape] :as props}]
|
||||
(let [interaction (first (:interactions shape)) ;; TODO: in the future we may have several interactions in one shape
|
||||
destination (first (deref (refs/objects-by-id [(:destination interaction)])))
|
||||
frames (mf/deref refs/frames)
|
||||
show-frames-dropdown? (mf/use-state false)
|
||||
|
||||
on-set-blur
|
||||
#(reset! show-frames-dropdown? false)
|
||||
|
||||
on-select-destination
|
||||
#(if (nil? %)
|
||||
(st/emit! (dw/update-shape (:id shape) {:interactions []}))
|
||||
(st/emit! (dw/update-shape (:id shape) {:interactions [{:event-type :click
|
||||
:action-type :navigate
|
||||
:destination %}]})))
|
||||
|
||||
on-navigate
|
||||
#(st/emit! (dw/select-shapes #{(:id destination)}))]
|
||||
|
||||
(if (not shape)
|
||||
[:*
|
||||
[:div.interactions-help-icon i/interaction]
|
||||
[:div.interactions-help (tr "workspace.options.select-a-shape")]
|
||||
[:div.interactions-help-icon i/play]
|
||||
[:div.interactions-help (tr "workspace.options.use-play-button")]]
|
||||
|
||||
[:div.element-set {:on-blur on-set-blur}
|
||||
[:div.element-set-title
|
||||
[:span (tr "workspace.options.navigate-to")]]
|
||||
[:div.element-set-content
|
||||
[:div.row-flex
|
||||
[:div.custom-select.flex-grow {:on-click #(reset! show-frames-dropdown? true)}
|
||||
(if destination
|
||||
[:span (:name destination)]
|
||||
[:span (tr "workspace.options.select-artboard")])
|
||||
[:span.dropdown-button i/arrow-down]
|
||||
[:& dropdown {:show @show-frames-dropdown?
|
||||
:on-close #(reset! show-frames-dropdown? false)}
|
||||
[:ul.custom-select-dropdown
|
||||
[:li.dropdown-separator {:key nil
|
||||
:on-click #(on-select-destination nil)}
|
||||
(tr "workspace.options.none")]
|
||||
(for [frame frames]
|
||||
(when (not= (:id frame) (:id shape)) ; A frame cannot navigate to itself
|
||||
[:li {:key (:id frame)
|
||||
:on-click #(on-select-destination (:id frame))}
|
||||
(:name frame)]))]]]
|
||||
[:span.navigate-icon {on-click on-navigate} i/navigate]]]])))
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
;; (defn- on-change
|
||||
|
@ -469,25 +520,25 @@
|
|||
|
||||
;; --- Interactions Menu
|
||||
|
||||
(def +initial-form+
|
||||
{:trigger :click
|
||||
:action :show})
|
||||
|
||||
(mf/defc interactions-menu
|
||||
[{:keys [menu shape] :as props}]
|
||||
#_(let [form (mf/use-state nil)
|
||||
interactions (:interactions shape)]
|
||||
[:div.element-set {:key (str (:id menu))}
|
||||
[:div.element-set-title (:name menu)]
|
||||
[:div.element-set-content
|
||||
(if form
|
||||
[:& interactions-form {:form form :shape shape}]
|
||||
[:div
|
||||
[:& interactions-list {:form form :shape shape}]
|
||||
[:input.btn-primary.btn-small
|
||||
{:value "New interaction"
|
||||
:on-click #(reset! form +initial-form+)
|
||||
:type "button"}]])]]))
|
||||
;; (def +initial-form+
|
||||
;; {:trigger :click
|
||||
;; :action :show})
|
||||
;;
|
||||
;; (mf/defc interactions-menu
|
||||
;; [{:keys [menu shape] :as props}]
|
||||
;; #_(let [form (mf/use-state nil)
|
||||
;; interactions (:interactions shape)]
|
||||
;; [:div.element-set {:key (str (:id menu))}
|
||||
;; [:div.element-set-title (:name menu)]
|
||||
;; [:div.element-set-content
|
||||
;; (if form
|
||||
;; [:& interactions-form {:form form :shape shape}]
|
||||
;; [:div
|
||||
;; [:& interactions-list {:form form :shape shape}]
|
||||
;; [:input.btn-primary.btn-small
|
||||
;; {:value "New interaction"
|
||||
;; :on-click #(reset! form +initial-form+)
|
||||
;; :type "button"}]])]]))
|
||||
|
||||
;; --- Not implemented stuff
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
(defn debug-none! [] (reset! *debug* #{}))
|
||||
(defn debug! [option] (swap! *debug* conj option))
|
||||
(defn -debug! [option] (swap! *debug* disj option))
|
||||
(defn debug? [option] (@*debug* option))
|
||||
|
||||
(defn ^:export debug? [option] (@*debug* option))
|
||||
|
||||
(defn ^:export toggle-debug [name] (let [option (keyword name)]
|
||||
(if (debug? option)
|
||||
|
@ -18,7 +18,7 @@
|
|||
(debug! option))))
|
||||
(defn ^:export debug-all [name] (debug-all!))
|
||||
|
||||
(defn tap
|
||||
(defn ^:export tap
|
||||
"Transducer function that can execute a side-effect `effect-fn` per input"
|
||||
[effect-fn]
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
|||
(effect-fn input)
|
||||
(rf result input)))))
|
||||
|
||||
(defn logjs
|
||||
(defn ^:export logjs
|
||||
([str] (tap (partial logjs str)))
|
||||
([str val]
|
||||
(js/console.log str (clj->js val))
|
||||
|
|
Loading…
Add table
Reference in a new issue