commit
569f1577a1
|
@ -12,5 +12,6 @@
|
||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (2)" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -57,3 +57,8 @@ src
|
||||||
```
|
```
|
||||||
|
|
||||||
Continue to [Navigation](Navigation.md) to learn how to switch between panels of a larger app.
|
Continue to [Navigation](Navigation.md) to learn how to switch between panels of a larger app.
|
||||||
|
|
||||||
|
---
|
||||||
|
Previous: [CoEffects](coeffects.md)
|
||||||
|
Up: [Index](README.md)
|
||||||
|
Next: [Navigation](Navigation.md)
|
||||||
|
|
|
@ -393,6 +393,6 @@ the mechanism by which event handlers are executed. That knowledge will give us
|
||||||
to then, as a next step, better understand coeffects and effects. We'll soon be writing our own.
|
to then, as a next step, better understand coeffects and effects. We'll soon be writing our own.
|
||||||
|
|
||||||
---
|
---
|
||||||
Up: [Index](Readme.md)
|
Up: [Index](README.md)
|
||||||
Next: [Interceptors](Interceptors.md)
|
Next: [Interceptors](Interceptors.md)
|
||||||
|
|
||||||
|
|
|
@ -355,3 +355,8 @@ usage:
|
||||||
Create a PR to include yours in this list.
|
Create a PR to include yours in this list.
|
||||||
|
|
||||||
XXX maybe put this list into the Wiki, so editable by all.
|
XXX maybe put this list into the Wiki, so editable by all.
|
||||||
|
|
||||||
|
---
|
||||||
|
Previous: [Interceptors](Interceptors.md)
|
||||||
|
Up: [Index](README.md)
|
||||||
|
Next: [CoEffects](coeffects.md)
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
|
||||||
|
### Question
|
||||||
|
|
||||||
|
How can I inspect the contents of `app-db`? Perhaps from figwheel.
|
||||||
|
|
||||||
|
### Short Answer
|
||||||
|
|
||||||
|
If at a REPL, inspect: `re-frame.db/app-db`.
|
||||||
|
|
||||||
|
If at the js console, that's `window.re_frame.db.app_db.state`.
|
||||||
|
|
||||||
|
You are [using clj-devtools](https://github.com/binaryage/cljs-devtools), right?
|
||||||
|
If not, stop everything and immediately make that happen.
|
||||||
|
|
||||||
|
### Better Answer
|
||||||
|
|
||||||
|
Are you sure you need to?
|
||||||
|
|
||||||
|
First, you seldom want to inspect all of `app-db`.
|
||||||
|
And, second, inspecting via figwheel will be clumsy.
|
||||||
|
|
||||||
|
Instead, you probably want to inspect a part of `app-db`. And you probably want
|
||||||
|
to inspect it in the GUI itself.
|
||||||
|
|
||||||
|
Here is a useful technique from @escherize. Add something like this to
|
||||||
|
the hiccup of your view ...
|
||||||
|
```clj
|
||||||
|
[:pre (with-out-str (pprint @interesting))]
|
||||||
|
```
|
||||||
|
This assumes that `@interesting` is the value (ratom or subscription) you want to observe (note the @ in front).
|
||||||
|
|
||||||
|
`pprint` output is nice to read, but not compact. For a more compact view, do this:
|
||||||
|
```clj
|
||||||
|
[:pre (pr-str @some-atom)] ;; using pr-str instead of pprint
|
||||||
|
```
|
||||||
|
|
||||||
|
If you choose to use `pprint` then you'll need to `require` it in at the top of your view.cljs:
|
||||||
|
```clj
|
||||||
|
[cljs.pprint :refer [pprint]]
|
||||||
|
```
|
||||||
|
|
||||||
|
@yogthos' [excellent json-html library](https://github.com/yogthos/json-html) has an
|
||||||
|
even slicker presentation (at the expense of more screen real estate, and the
|
||||||
|
need to include specific CSS).
|
||||||
|
|
||||||
|
Finally, combining the short and long answers, you could even do this:
|
||||||
|
```clj
|
||||||
|
[:pre (with-out-str (pprint @re-frame.db/app-db))] ;; see everything!
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```clj
|
||||||
|
[:pre (with-out-str (pprint (:part @re-frame.db/app-db)))] ;; see a part of it!
|
||||||
|
```
|
||||||
|
|
||||||
|
You definitely have [clj-devtools](https://github.com/binaryage/cljs-devtools) installed now, right?
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
Up: [FAQ Index](README.md)
|
|
@ -0,0 +1,27 @@
|
||||||
|
### Question
|
||||||
|
|
||||||
|
I use logging method X, how can I make re-frame use my method?
|
||||||
|
|
||||||
|
### Answer
|
||||||
|
|
||||||
|
re-frame makes use of the logging functions: `warn`, `log`, `error`, `group` and `groupEnd`.
|
||||||
|
|
||||||
|
By default, these functions map directly to the js/console equivalents, but you can
|
||||||
|
override that by providing your own set or subset of these functions using
|
||||||
|
`re-frame.core/set-loggers!` like this:
|
||||||
|
```clj
|
||||||
|
(defn my-warn
|
||||||
|
[& args]
|
||||||
|
(post-warning-somewhere (apply str args)))
|
||||||
|
|
||||||
|
(defn my-log
|
||||||
|
[& args]
|
||||||
|
(write-to-datadog (apply str args)))
|
||||||
|
|
||||||
|
(re-frame.core/set-loggers! {:warn my-warn
|
||||||
|
:log my-log
|
||||||
|
...})
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
Up: [FAQ Index](README.md)
|
|
@ -0,0 +1,21 @@
|
||||||
|
### Question
|
||||||
|
|
||||||
|
If I `dispatch` a js event object (from a view), it is nullified
|
||||||
|
by the time it gets to the event-handler. What gives?
|
||||||
|
|
||||||
|
### Answer
|
||||||
|
|
||||||
|
So there's two things to say about this:
|
||||||
|
- if you want to `dispatch` a js event object to a re-frame
|
||||||
|
event handler, you must call `(.persist event)` before the `dispatch`.
|
||||||
|
React recycles events (using a pool), and re-frame event handlers
|
||||||
|
run async. [Find out more here](https://facebook.github.io/react/docs/events.html)
|
||||||
|
|
||||||
|
- it is probably more idiomatic to extract the salient data from the event
|
||||||
|
and `dispatch` that, rather than the js event object itself. When you
|
||||||
|
`dispatch` pure, simple cljs data (ie. rather than js objects) testing
|
||||||
|
and debugging will become easier.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
Up: [FAQ Index](README.md)
|
|
@ -0,0 +1,14 @@
|
||||||
|
## Frequently Asked Questions
|
||||||
|
|
||||||
|
1. [How can I Inspect app-db?](Inspecting-app-db.md)
|
||||||
|
2. [How do I use logging method X](Logging.md)
|
||||||
|
3. [Dispatched Events Are Null](Null-Dispatched-Events.md)
|
||||||
|
4.
|
||||||
|
6. [Why implement re-frame in `.cljc` files](Why-CLJC.md)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Want To Add An FAQ?
|
||||||
|
|
||||||
|
We'd like that. Please supply a PR. Or just open an issue. Many Thanks!!
|
|
@ -0,0 +1,20 @@
|
||||||
|
### Question
|
||||||
|
|
||||||
|
Why is re-frame implemented in `.cljc` files? Aren't ClojureScript
|
||||||
|
files meant to be `.cljs`?
|
||||||
|
|
||||||
|
### Answer
|
||||||
|
|
||||||
|
So tests can be run on both the JVM and the JS platforms,
|
||||||
|
re-frame's implementation is mostly in `.cljc` files.
|
||||||
|
|
||||||
|
The trailing `c` in `.cljc` stands for `common`.
|
||||||
|
|
||||||
|
Necessary interop for each platform can be found in
|
||||||
|
`interop.clj` (for the JVM) and `interop.cljs` (for JS).
|
||||||
|
|
||||||
|
See also: https://github.com/Day8/re-frame-test
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
Up: [FAQ Index](README.md)
|
|
@ -380,3 +380,8 @@ To use them, first require them:
|
||||||
(:require
|
(:require
|
||||||
[re-frame.core :refer [debug path]])
|
[re-frame.core :refer [debug path]])
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
Previous: [Effectful Handlers](EffectfulHandlers.md)
|
||||||
|
Up: [Index](README.md)
|
||||||
|
Next: [Effects](Effects.md)
|
||||||
|
|
|
@ -216,8 +216,8 @@ The next Tutorial will show you how.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
Previous: [Interceptors](Interceptors.md)
|
Previous: [Namespaced Keywords](Namespaced-Keywords.md)
|
||||||
Up: [Index](Readme.md)
|
Up: [Index](README.md)
|
||||||
Next: [Talking To Servers](Talking-To-Servers.md)
|
Next: [Talking To Servers](Talking-To-Servers.md)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,3 +19,8 @@ fiction. I can have the keyword `:panel1/edit` even though
|
||||||
|
|
||||||
Naturally, you'll take advantage of this by using keyword namespaces
|
Naturally, you'll take advantage of this by using keyword namespaces
|
||||||
which are both unique and descriptive.
|
which are both unique and descriptive.
|
||||||
|
|
||||||
|
---
|
||||||
|
Previous: [Navigation](Navigation.md)
|
||||||
|
Up: [Index](README.md)
|
||||||
|
Next: [Loading Initial Data](Loading-Initial-Data.md)
|
|
@ -19,6 +19,7 @@ When the user does something navigation-ish (selects a tab, a dropdown or someth
|
||||||
```
|
```
|
||||||
|
|
||||||
A high level reagent view has a subscription to :active-panel and will switch to the associated panel.
|
A high level reagent view has a subscription to :active-panel and will switch to the associated panel.
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:active-panel
|
:active-panel
|
||||||
|
@ -43,7 +44,12 @@ A high level reagent view has a subscription to :active-panel and will switch to
|
||||||
(condp = @active ;; or you could look up in a map
|
(condp = @active ;; or you could look up in a map
|
||||||
:panel1 [panel1]
|
:panel1 [panel1]
|
||||||
:panel2 [panel2])])))
|
:panel2 [panel2])])))
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Continue to [Namespaced Keywords](Namespaced-Keywords.md) to reduce clashes on ids.
|
Continue to [Namespaced Keywords](Namespaced-Keywords.md) to reduce clashes on ids.
|
||||||
|
|
||||||
|
---
|
||||||
|
Previous: [Basic App Structure](Basic-App-Structure.md)
|
||||||
|
Up: [Index](README.md)
|
||||||
|
Next: [Namespaced Keywords](Namespaced-Keywords.md)
|
||||||
|
|
|
@ -18,4 +18,11 @@
|
||||||
|
|
||||||
1. [Loading Initial Data](Loading-Initial-Data.md)
|
1. [Loading Initial Data](Loading-Initial-Data.md)
|
||||||
2. [Talking To Servers](Talking-To-Servers.md)
|
2. [Talking To Servers](Talking-To-Servers.md)
|
||||||
3. [Subscribing to External Data](Subscribing-To-External-Data.md)
|
3. [Subscribing to External Data](Subscribing-To-External-Data.md)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Miscellaneous:
|
||||||
|
1. [FAQs](FAQs/README.md)
|
||||||
|
2. [Using Stateful JS Components](Using-Stateful-JS-Components.md)
|
||||||
|
3. [The re-frame Logo](The-ref-frame-logo.md)
|
||||||
|
|
|
@ -236,3 +236,6 @@ data into HTML and nothing more. they absolutely do not do imperative stuff.
|
||||||
|
|
||||||
Use one of the two alternatives described above.
|
Use one of the two alternatives described above.
|
||||||
|
|
||||||
|
---
|
||||||
|
Previous: [Talking to Servers](Talking-To-Servers.md)
|
||||||
|
Up: [Index](README.md)
|
||||||
|
|
|
@ -113,6 +113,7 @@ In the 2nd version, we use the alternative registration function, `reg-event-fx`
|
||||||
You may soon feel confident enough to write your own.
|
You may soon feel confident enough to write your own.
|
||||||
|
|
||||||
Here's our rewrite:
|
Here's our rewrite:
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
(ns my.app.events
|
(ns my.app.events
|
||||||
(:require
|
(:require
|
||||||
|
@ -138,3 +139,7 @@ Notes:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
Previous: [Loading Initial Data](Loading-Initial-Data.md)
|
||||||
|
Up: [Index](README.md)
|
||||||
|
Next: [Subscribing to External Data](Subscribing-To-External-Data.md)
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
## The re-frame Logo
|
||||||
|
|
||||||
|
![logo](/images/logo/re-frame_256w.png?raw=true)
|
||||||
|
|
||||||
|
### Who
|
||||||
|
|
||||||
|
Created by the mysterious, deep thinker, known only as @martinklepsch.
|
||||||
|
|
||||||
|
Some say he appears on high value stamps in Germany and that he once <br>
|
||||||
|
punched a horse to the ground. Others say he loves recursion so much that, <br>
|
||||||
|
in his wallet, he carries a photograph of his wallet.
|
||||||
|
|
||||||
|
All we know for sure is that he wields [Sketch.app](https://www.sketchapp.com/) like Bruce Lee <br>
|
||||||
|
wielded nunchucks.
|
||||||
|
|
||||||
|
### Genesis Theories
|
||||||
|
|
||||||
|
Great, unexplained works encourage fan theories, and the re-frame <br>
|
||||||
|
logo is no exception.
|
||||||
|
|
||||||
|
One noisy group thinks @martinklepsch simply wanted to <br>
|
||||||
|
`Put the 'f' back into infinity`. They have t-shirts.
|
||||||
|
|
||||||
|
Another group speculates that he created the logo as a bifarious <br>
|
||||||
|
rainbow homage to Frank Lloyd Wright's masterpiece, the Guggenheim <br>
|
||||||
|
Museum. A classic case of premature abstraction and over engineering <br>
|
||||||
|
if you ask me. Their theory, not the Guggenheim.
|
||||||
|
|
||||||
|
![](/images/logo/Guggenheim.jpg)
|
||||||
|
|
||||||
|
The infamous "Bad Touch" faction look at the logo and see the cljs <br>
|
||||||
|
logo mating noisily with re-frame's official architecture diagram. <br>
|
||||||
|
Attend one of their parties and you have a 50% chance of arrest.
|
||||||
|
|
||||||
|
![](/images/logo/Genesis.png)
|
||||||
|
|
||||||
|
The Functional Fundamentalists, a stern bunch, see the logo as a <br>
|
||||||
|
flowing poststructuralist rebuttal of OO's vowel duplication and <br>
|
||||||
|
horizontal adjacency. Their alternative approach, FF, is apparently <br>
|
||||||
|
fine because "everyone loves a fricative".
|
||||||
|
|
||||||
|
For his part, @martinklepsch has never confirmed any theory, teasing <br>
|
||||||
|
us instead with coded clues like "Will you please stop emailing me" <br>
|
||||||
|
and "Why did you say I hit a horse?".
|
||||||
|
|
||||||
|
### Assets Where?
|
||||||
|
|
||||||
|
Within this repo, look in `/images/logo/`
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
## Using Stateful JS Components
|
||||||
|
|
||||||
|
You know what's good for you, and you know what's right. But it
|
||||||
|
doesn't matter - the wickedness of the temptation is too much.
|
||||||
|
|
||||||
|
The JS world is brimming with shiny component baubles: D3,
|
||||||
|
Google Maps, Chosen, etc.
|
||||||
|
|
||||||
|
But they are salaciously stateful and mutative. And, you,
|
||||||
|
raised in a pure, functional home, with caring, immutable parents,
|
||||||
|
know they are wrong. But, my, how you still yearn for the sweet
|
||||||
|
thrill of that forbidden fruit.
|
||||||
|
|
||||||
|
I won't tell, if you don't. But careful plans must be made ...
|
||||||
|
|
||||||
|
|
||||||
|
### The overall plan
|
||||||
|
|
||||||
|
To use a stateful js component, you'll need to write two Reagent components:
|
||||||
|
- an **outer component** responsible for sourcing data via a subscription or r/atom or cursor, etc.
|
||||||
|
- an **inner component** responsible for wrapping and manipulating the stateful JS component via lifecycle functions.
|
||||||
|
|
||||||
|
The pattern involves the outer component, which sources data, supplying this data to the inner component **via props**.
|
||||||
|
|
||||||
|
### Example Using Google Maps
|
||||||
|
|
||||||
|
```cljs
|
||||||
|
(defn gmap-inner []
|
||||||
|
(let [gmap (atom nil)
|
||||||
|
options (clj->js {"zoom" 9})
|
||||||
|
update (fn [comp]
|
||||||
|
(let [{:keys [latitude longitude]} (reagent/props comp)
|
||||||
|
latlng (js/google.maps.LatLng. latitude longitude)]
|
||||||
|
(.setPosition (:marker @gmap) latlng)
|
||||||
|
(.panTo (:map @gmap) latlng)))]
|
||||||
|
|
||||||
|
(reagent/create-class
|
||||||
|
{:reagent-render (fn []
|
||||||
|
[:div
|
||||||
|
[:h4 "Map"]
|
||||||
|
[:div#map-canvas {:style {:height "400px"}}]])
|
||||||
|
|
||||||
|
:component-did-mount (fn [comp]
|
||||||
|
(let [canvas (.getElementById js/document "map-canvas")
|
||||||
|
gm (js/google.maps.Map. canvas options)
|
||||||
|
marker (js/google.maps.Marker. (clj->js {:map gm :title "Drone"}))]
|
||||||
|
(reset! gmap {:map gm :marker marker}))
|
||||||
|
(update comp))
|
||||||
|
|
||||||
|
:component-did-update update
|
||||||
|
:display-name "gmap-inner"})))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(defn gmap-outer []
|
||||||
|
(let [pos (subscribe [:current-position])] ;; obtain the data
|
||||||
|
(fn []
|
||||||
|
[gmap-inner @pos])))
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- `gmap-outer` obtains data via a subscription. It is quite simple - trivial almost.
|
||||||
|
- it then passes this data __as a prop__ to `gmap-inner`. This inner component has the job of wrapping/managing the stateful js component (Gmap in our case above)
|
||||||
|
- when the data (delivered by the subscription) to the outer layer changes, the inner layer, `gmap-inner`, will be given a new prop - `@pos` in the case above.
|
||||||
|
- when the inner component is given new props, its entire set of lifecycle functions will be engaged.
|
||||||
|
- the renderer for the inner layer ALWAYS renders the same, minimal container hiccup for the component. Even though the `props` have changed, the same hiccup is output. So it will appear to React as if nothing changes from one render to the next. No work to be done. React/Reagent will leave the DOM untouched.
|
||||||
|
- but this inner component has other lifecycle functions and this is where the real work is done.
|
||||||
|
- for example, after the renderer is called (which ignores its props), `component-did-update` will be called. In this function, we don't ignore the props, and we use them to update/mutate the stateful JS component.
|
||||||
|
- the props passed (in this case `@pos`) in must be a map, otherwise `(reagent/props comp)` will return nil.
|
||||||
|
|
||||||
|
### Pattern Discovery
|
||||||
|
|
||||||
|
This pattern has been independently discovered by many. To my knowledge,
|
||||||
|
[this description of the Container/Component pattern](https://medium.com/@learnreact/container-components-c0e67432e005#.3ic1uipvu)
|
||||||
|
is the first time it was written up.
|
||||||
|
|
||||||
|
### Code Credit
|
||||||
|
|
||||||
|
The example gmaps code above was developed by @jhchabran in this gist:
|
||||||
|
https://gist.github.com/jhchabran/e09883c3bc1b703a224d#file-2_google_map-cljs
|
||||||
|
|
||||||
|
### D3 Examples
|
||||||
|
|
||||||
|
D3 (from @zachcp):
|
||||||
|
- Blog Post: http://zachcp.org/blog/2015/reagent-d3/
|
||||||
|
- Code: https://github.com/zachcp/simplecomponent
|
||||||
|
- Example: http://zachcp.github.io/simplecomponent/
|
||||||
|
|
||||||
|
|
||||||
|
### Advanced Lifecycle Methods
|
||||||
|
|
||||||
|
If you mess around with lifecycle methods, you'll probably want to read Martin's explanations:
|
||||||
|
https://www.martinklepsch.org/posts/props-children-and-component-lifecycle-in-reagent.html
|
|
@ -267,3 +267,7 @@ In note form:
|
||||||
5. We must have previously registered a cofx handler via `reg-cofx`
|
5. We must have previously registered a cofx handler via `reg-cofx`
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
Previous: [Effects](Effects.md)
|
||||||
|
Up: [Index](README.md)
|
||||||
|
Next: [Basic App Structure](Basic-App-Structure.md)
|
||||||
|
|
|
@ -1,40 +1,7 @@
|
||||||
## The re-frame Logo
|
|
||||||
|
|
||||||
![logo](/images/logo/re-frame_256w.png?raw=true)
|
![logo](/images/logo/re-frame_256w.png?raw=true)
|
||||||
|
|
||||||
Created by the mysterious @martinklepsch
|
Created via [Sketch.app](https://www.sketchapp.com/). See the file `re-frame-logo.sketch`
|
||||||
|
|
||||||
Some say he appears on high value stamps in Germany and that he once
|
|
||||||
punched a horse to the ground. Others say he loves recursion so much
|
|
||||||
that his wallet contains a photograph of his wallet.
|
|
||||||
|
|
||||||
All we know for sure is that he wields [Sketch.app](https://www.sketchapp.com/) like
|
|
||||||
Bruce Lee wielded nunchucks.
|
|
||||||
|
|
||||||
## Genesis Theories
|
|
||||||
|
|
||||||
Great, unexplained works encourage fan theories, and the re-frame logo
|
|
||||||
is no exception.
|
|
||||||
|
|
||||||
Some speculate @martinklepsch created it as a bifarious rainbow homage
|
|
||||||
to Frank Lloyd Wright's Guggenheim.
|
|
||||||
|
|
||||||
![](Guggenheim.jpg)
|
|
||||||
|
|
||||||
Others see the cljs logo mating noisily with re-frame's official
|
|
||||||
architecture diagram.
|
|
||||||
|
|
||||||
![](Genesis.png)
|
|
||||||
|
|
||||||
Yet others see a poststructuralist rebuttal of OO's
|
|
||||||
vowel duplication and horizontal adjacency. Their T-shirts claim:
|
|
||||||
> He's put the 'f' back into infinity
|
|
||||||
|
|
||||||
For his part, Martin has never confirmed any theory, teasing us instead with coded clues
|
|
||||||
like "Will you please stop emailing me" and "Why did you say I hit a horse?".
|
|
||||||
|
|
||||||
### Notes
|
|
||||||
|
|
||||||
Use [Sketch.app](https://www.sketchapp.com/) to update the `re-frame-logo.sketch` file.
|
|
||||||
|
|
||||||
Unfortunately the gradients are not exported properly so we can't provide an SVG here for now.
|
Unfortunately the gradients are not exported properly so we can't provide an SVG here for now.
|
||||||
|
|
Loading…
Reference in New Issue