Fork me on GitHub
#reagent
<
2020-01-28
>
Varenya11:01:10

is there a better idiomatic way of adding svgs to clojure/reagent - i am trying to add some custom styles to a svg.

p-himik11:01:45

I ended up writing a macro that converts the SVG file into Hiccup. Another way would be to set dangerouslySetInnerHTML.

mmeix11:01:27

I have a similar thing going (a svg of a music score generated by a js library). I would like to alter the svg - would you mind giving a hint, how yout macro svg-> hiccup works?

Varenya11:01:01

yeah thats not ergonomic

Varenya11:01:17

there isn’t a more idiomatic solution for this?

p-himik11:01:25

What do you mean by "ergonomic" and "idiomatic" in this case?

Varenya11:01:57

ah okay basically giving me a hiccup datastructure which i can manipulate

Varenya11:01:24

manipulating string is awfully hard

p-himik11:01:41

Well, I just mentioned it in the very first answer - it's possible to write a macro that does that for you during the compile time, assuming the SVG is available then.

Varenya11:01:54

which is basically what most macros do - slurping the svg and setting html “dangerously”

Varenya11:01:33

the macro can only turn it into a string not a hiccup datastructure right

p-himik11:01:35

Also, if you really want to change just the styles, you don't need to manipulate anything. You just need to embed that SVG as an <svg> tag and use some CSS.

p-himik11:01:05

@UT4B0A4FQ You did not read my initial message. I explicitly stated that I convert it into Hiccup. Why would that not be possible?

Varenya11:01:27

oh okay .. sorry yeah didn’t see that

Varenya11:01:38

most solution i saw online where turning them to string

Varenya11:01:52

then why do u need to do dangerouslysetInnerHtml ?

Varenya11:01:49

oh sorry i didn’t fully read it again

p-himik11:01:12

Third time's the charm? ;)

Varenya11:01:25

are there any library that do this?

p-himik11:01:26

No need for a library when it takes just 10 lines:

(require '[hickory.core :refer [parse-fragment as-hiccup]]
         '[ :as io])

(defmacro embed-svg [path attrs]
  (assert (string? path))
  (let [svg-vec (-> (io/resource path)
                    slurp
                    parse-fragment
                    first
                    as-hiccup)]
    `(update ~svg-vec 1 merge ~attrs)))

Varenya11:01:49

okay that is pretty cool

Varenya11:01:30

thanks a ton @U2FRKM4TW

👍 8
p-himik12:01:32

@U082WFGJJ Kinda funny how Verovio builds a proper SVG document model and then just turns it into a string just to you have to parse it back to the document model (albeit, probably a different one). Do you use it for MusicXML, by any chance?

mmeix12:01:10

No, not from MusicXML. Verovio’s intended use case is just to generate SVG and/or embed it into normal html

mmeix12:01:21

There is some minor interactivity built in as methods

mmeix12:01:28

CSS is the main mechanism, for example to color notes. But not to alter the notes - this needs some sort of roundtrip, hence my question

andrewboltachev14:01:06

Hello! I've created this function to help me to use hooks in reagent:

(defn with-hooks [hooks-fn main-fn]
  (let [wrapper-2 (fn [almost-reagent-props]
                    [main-fn ((:props almost-reagent-props))])
        classical-c (fn [react-props]
                      (let [reagent-props ((aget react-props "props"))
                            hooks-props (hooks-fn reagent-props)]
                        (r/as-element
                         [wrapper-2
                          {:props
                           (constantly
                            (merge
                             reagent-props
                             hooks-props))}])))
        wrapper (fn [reagent-props]
                  (let [pp {:props (constantly reagent-props)}]
                    [(r/adapt-react-class
                      classical-c) pp]))]
    wrapper))
It's meant to be used like this:
(def my-component
  (with-hooks
    (fn [props]
      {:ref_ (js/React.useRef)})
    (fn [{:keys [ref_]}]
      [:div {:ref ref_} ...])))
while I'm actually using it with ReactDnD (drag'n'drop). It now seems to me that it (the case with drag'n'drop) works slow, probably 'cause of I'm returning values wrapped into`constantly` . This is to not to make reagent's internal calls to clj->js /`js->clj` not to destroy values which are passed around ('cause they go reagent -> react -> reagent). Could anyone suggest better way of "wrapping" values in reagent/react interop or, ultimately, using hooks in reagent?

andrewboltachev14:01:21

Here in this very example (`my-component`) if I'd pass props not wrapped as functions, but as-is then actual ref object would be replaced by e.g. {:current nil} , while what's actually important is the original ref object as I understand