Skip to content

Commit d8c601f

Browse files
committed
Sketches for Clerk Sync & Controls
1 parent 7539cc2 commit d8c601f

File tree

3 files changed

+134
-1
lines changed

3 files changed

+134
-1
lines changed

notebooks/viewers/controls.clj

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
;; # ⚡️ Clerk Sync and Controls 🎛
2+
3+
(ns viewers.controls
4+
"Demo of Clerk's two-way bindings."
5+
{:nextjournal.clerk/visibility {:code :show :result :show}}
6+
(:require [clojure.core :as core]
7+
[nextjournal.clerk :as clerk]
8+
[nextjournal.clerk.viewer :as viewer]))
9+
10+
;; We `defonce` an atom and tag it with `^::clerk/sync`. This will create a corresponding (reagent) atom in the browser.
11+
^{::clerk/sync true}
12+
(defonce number-atom
13+
(atom 0))
14+
15+
^::clerk/sync
16+
(defonce name-atom
17+
(atom "Sam Gold"))
18+
19+
20+
;; This is showing the state that the JVM has.
21+
@number-atom
22+
23+
@name-atom
24+
25+
#'number-atom
26+
27+
#'name-atom
28+
29+
;; # 1️⃣ `comp` `:render-fn`
30+
31+
(def transform-var
32+
(comp clerk/mark-presented
33+
(clerk/update-val (fn [v] (viewer/->ViewerEval (list 'resolve (list 'quote (symbol v))))))))
34+
35+
(def render-slider
36+
'(fn [state-atom]
37+
[:input {:type :range :value @state-atom :on-change #(swap! state-atom (constantly (int (.. % -target -value))))}]))
38+
39+
(def render-text-input
40+
'(fn [state-atom]
41+
[:input {:type :text :value @state-atom :on-change #(swap! state-atom (constantly (.. % -target -value)))
42+
:class "px-3 py-3 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-sm border border-blueGray-300 outline-none focus:outline-none focus:ring w-full"}]))
43+
44+
45+
^{::clerk/viewer {:render-fn (list 'comp render-slider 'deref) :transform-fn transform-var}}
46+
#'number-atom
47+
48+
@number-atom
49+
50+
^{::clerk/viewer {:render-fn (list 'comp render-text-input 'deref) :transform-fn transform-var}}
51+
#'name-atom
52+
53+
@name-atom
54+
55+
56+
;; ## ⁉️ Sidequest: inspect atom
57+
58+
^{::clerk/viewer {:transform-fn transform-var
59+
:render-fn '#(vector nextjournal.clerk.render/inspect @%)}}
60+
#'number-atom
61+
62+
;; ✅ Fixed with `7539cc2dfc16682cc17203fd4b7a096a6827f77c`
63+
64+
65+
;; # 2️⃣ `::clerk/viewers`
66+
67+
68+
@number-atom
69+
70+
(def var-viewer
71+
{:pred var?
72+
:transform-fn transform-var
73+
:render-fn '(fn [x] [nextjournal.clerk.render/inspect @x])})
74+
75+
76+
^{::clerk/viewers (clerk/add-viewers [(assoc var-viewer :render-fn (list 'comp render-text-input 'deref))])}
77+
#'name-atom
78+
79+
@name-atom
80+
81+
;; It might be more convenient to have a viewer that works on vars from defs and normal vars.
82+
83+
(def convenient-slider
84+
{:transform-fn (comp transform-var (clerk/update-val #(cond-> % (viewer/get-safe % ::clerk/var-from-def) ::clerk/var-from-def)))
85+
:render-fn '(fn [x] (let [state-atom (cond-> x (var? x) deref)]
86+
[:input {:type :range :value @state-atom :on-change #(swap! state-atom (constantly (int (.. % -target -value))))}]))})
87+
88+
;; But this should probably be fixed in a principled way.
89+
90+
91+
^{::clerk/viewer convenient-slider ::clerk/sync true}
92+
(defonce number-atom-2 (atom 99))
93+
94+
^{::clerk/viewer convenient-slider}
95+
#'number-atom-2
96+
97+
@number-atom-2

notebooks/viewers/vars_from_def.clj

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
;; # Var Unwrapping
2+
3+
(ns viewers.vars-from-def
4+
(:require [nextjournal.clerk :as clerk]))
5+
6+
;; There's currently an incosistency regarding automatically
7+
;; unwrapping `::clerk/var-from-def`:
8+
9+
;; If the viewer is a function, we automatically unwrap it:
10+
11+
^{::clerk/viewer #(clerk/with-viewer {:transform-fn (clerk/update-val pr-str)} %)}
12+
(def foo :bar)
13+
14+
;; If the viewer is a map, we don't:
15+
16+
^{::clerk/viewer {:transform-fn (clerk/update-val pr-str)}}
17+
(def foo-2 :bar)
18+
19+
;; This was a kludge to allow to specify viewers on the value of vars, e.g.
20+
21+
^{::clerk/viewer clerk/table}
22+
(def my-table [[1 2] [3 4]])
23+
24+
25+
;; I think we should unwrap the var value always, unless you opt out of it, maybe via:
26+
27+
^{::clerk/viewer {:transform-fn (clerk/update-val pr-str)
28+
::clerk/var-from-def? true}}
29+
(def foo-2 :bar)
30+
31+
32+
^{::clerk/viewer {:transform-fn (clerk/update-val pr-str)}}
33+
(def foo-2 :bar)
34+
35+
;; Maybe the need for this goes away once we give the predicate
36+
;; functions more context to act on.

src/nextjournal/clerk/viewer.cljc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@
689689
#?(:clj (with-viewer :number-hex (System/identityHashCode ideref)))
690690
(if-let [deref-as-map (resolve 'clojure.core/deref-as-map)]
691691
(deref-as-map ideref)
692-
ideref))})))})
692+
(deref ideref)))})))})
693693

694694
(def regex-viewer
695695
{:pred #?(:clj (partial instance? java.util.regex.Pattern) :cljs regexp?)

0 commit comments

Comments
 (0)