Skip to content

Commit 3d9b2e0

Browse files
committed
Add control lab notebook
1 parent d8c601f commit 3d9b2e0

File tree

6 files changed

+106
-31
lines changed

6 files changed

+106
-31
lines changed

notebooks/doc.clj

+33-29
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,49 @@
11
;; # 📓 Doc Browser
22
(ns doc
3-
{:nextjournal.clerk/visibility {:code :hide}}
3+
{:nextjournal.clerk/visibility {:code :hide :result :hide}}
44
(:require [clojure.string :as str]
5-
[nextjournal.clerk :as clerk]))
6-
7-
^{::clerk/visibility {:result :hide}}
8-
(def text-input
9-
{:pred ::clerk/var-from-def
10-
:transform-fn (comp (clerk/update-val (fn [{::clerk/keys [var-from-def]}]
11-
{:var-name (symbol var-from-def) :value @@var-from-def}))
12-
clerk/mark-presented)
13-
:render-fn '(fn [{:keys [var-name value]}]
14-
[:div.my-1.relative
15-
[:input {:type :text
16-
:auto-correct "off"
17-
:spell-check "false"
18-
:placeholder "Filter namespaces…"
19-
:value value
20-
:class "px-3 py-2 relative bg-white bg-white rounded text-base font-sans border border-slate-200 shadow-inner outline-none focus:outline-none focus:ring w-full"
21-
:on-input #(v/clerk-eval `(reset! ~var-name ~(.. % -target -value)))}]
22-
[:button.absolute.right-2.text-xl.cursor-pointer
23-
{:class "top-1/2 -translate-y-1/2"
24-
:on-click #(v/clerk-eval `(reset! ~var-name ~(clojure.string/join "." (drop-last (clojure.string/split value #"\.")))))} ""]])})
25-
26-
^{::clerk/viewer text-input}
5+
[nextjournal.clerk :as clerk]
6+
[nextjournal.clerk.viewer :as viewer]))
7+
8+
(def render-input
9+
'(fn [!query]
10+
(prn :query !query)
11+
[:div.my-1.relative
12+
[:input {:type :text
13+
:auto-correct "off"
14+
:spell-check "false"
15+
:placeholder "Filter namespaces…"
16+
:value @!query
17+
:class "px-3 py-2 relative bg-white bg-white rounded text-base font-sans border border-slate-200 shadow-inner outline-none focus:outline-none focus:ring w-full"
18+
:on-input #(reset! !query (.. % -target -value))}]
19+
[:button.absolute.right-2.text-xl.cursor-pointer
20+
{:class "top-1/2 -translate-y-1/2"
21+
:on-click #(reset! !query (clojure.string/join "." (drop-last (clojure.string/split @!query #"\."))))} ""]]))
22+
23+
^{::clerk/sync true}
2724
(defonce !ns-query (atom "nextjournal.clerk"))
2825
#_(reset! !ns-query "nextjournal.clerk")
2926

27+
28+
!ns-query
29+
30+
^{::clerk/visibility {:result :show}
31+
::clerk/viewer {:render-fn render-input
32+
:transform-fn clerk/mark-presented}}
33+
(viewer/->viewer-eval `!ns-query)
34+
3035
^{::clerk/viewers (clerk/add-viewers
3136
[{:pred seq?
3237
:render-fn '#(into [:div.border.rounded-md.bg-white.shadow.flex.flex-col.mb-1]
33-
(v/inspect-children %2) %1) :page-size 20}
38+
(nextjournal.clerk.render/inspect-children %2) %1) :page-size 20}
3439
{:pred string?
3540
:render-fn '(fn [ns] [:button.text-xs.font-medium.font-sans.cursor-pointer.px-3.py-2.hover:bg-blue-100.text-slate-700.text-left
36-
{:on-click #(v/clerk-eval `(reset! !ns-query ~ns))} ns])}])}
41+
{:on-click #(reset! doc/!ns-query ns)} ns])}])}
42+
43+
^{::clerk/visibility {:result :show}}
3744
(def ns-matches
3845
(filter (partial re-find (re-pattern @!ns-query)) (sort (map str (all-ns)))))
3946

40-
^{::clerk/visibility {:result :hide}}
4147
(defn var->doc-viewer
4248
"Takes a clojure `var` and returns a Clerk viewer to display its documentation."
4349
[var]
@@ -54,11 +60,9 @@
5460

5561
#_(var->doc-viewer #'var->doc-viewer)
5662

57-
^{::clerk/visibility {:result :hide}}
5863
(def var-doc-viewer {:pred ::clerk/var-from-def
5964
:transform-fn (clerk/update-val (comp var->doc-viewer ::clerk/var-from-def))})
6065

61-
^{::clerk/visibility {:result :hide}}
6266
(defn namespace->doc-viewer [ns]
6367
(clerk/html
6468
[:div.text-sm.mt-6
@@ -70,10 +74,10 @@
7074
(map (comp :nextjournal/value var->doc-viewer val))
7175
(into (sorted-map) (-> ns ns-publics)))]))
7276

73-
^{::clerk/visibility {:result :hide}}
7477
(def ns-doc-viewer {:pred #(instance? clojure.lang.Namespace %)
7578
:transform-fn (clerk/update-val namespace->doc-viewer)})
7679

80+
^{::clerk/visibility {:result :show}}
7781
(when-let [ns-name (first ns-matches)]
7882
(clerk/with-viewer ns-doc-viewer (find-ns (symbol ns-name))))
7983

notebooks/viewers/control_lab.clj

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
;; # 🎛 Control Lab 🧑🏼‍🔬
2+
(ns viewer.control-lab
3+
(:require [clojure.string :as str]
4+
[nextjournal.clerk :as clerk]
5+
[nextjournal.clerk.viewer :as viewer]))
6+
7+
;; Experimenting with ways of making controls. We start with two
8+
;; little helper functions, one in sci and one in Clojure.
9+
10+
(def viewer-eval-viewer
11+
{:pred viewer/viewer-eval?
12+
:transform-fn (comp viewer/mark-presented
13+
(viewer/update-val
14+
(fn [x] (cond (viewer/viewer-eval? x) x
15+
(symbol? x) (viewer/->viewer-eval x)
16+
(var? x) (recur (symbol x))
17+
(viewer/var-from-def? x) (recur (:nextjournal.clerk/var-from-def x))))))
18+
:render-fn 'nextjournal.clerk.render/inspect})
19+
20+
(clerk/add-viewers! [viewer-eval-viewer])
21+
22+
(viewer/->viewer-eval
23+
'(defn make-slider [opts]
24+
(fn [!state]
25+
[:input (merge {:type :range :value @!state :on-change #(reset! !state (int (.. % -target -value)))} opts)])))
26+
27+
(defn make-slider
28+
([] (make-slider {}))
29+
([opts] (assoc viewer-eval-viewer :render-fn (list 'make-slider opts))))
30+
31+
;; Let's go through the ways we can use this.
32+
33+
;; 1️⃣ On a var coming from a def
34+
^{::clerk/sync true ::clerk/viewer (make-slider {})}
35+
(defonce !num (atom 0))
36+
37+
;; 2️⃣ On a sharp quoted symbol (works with a fully qualified one as well, ofc).
38+
(clerk/with-viewer (make-slider)
39+
`!num)
40+
41+
;; 3️⃣ On a var
42+
^{::clerk/viewer (make-slider)}
43+
#'!num
44+
45+
;; 4️⃣ On an explicit `ViewerEval` type
46+
(clerk/with-viewer (make-slider)
47+
(viewer/->viewer-eval `!num))
48+
49+
50+
#_#_ ;; TODO: plain (not quoted) symbol
51+
^{::clerk/viewer (make-slider {})}
52+
!num
53+
;; TODO: reactivity with default viewer
54+
(viewer/->viewer-eval `!num)
55+
56+
;; We can customise the slider by passing different opts (that are merged).
57+
58+
(clerk/with-viewer (make-slider {:max 200})
59+
`!num)
60+
61+
;; Or use a completely custom `:render-fn`.
62+
(clerk/with-viewer (assoc viewer-eval-viewer :render-fn '(fn [x] [:h2.bg-green-500.rounded-xl.text-center @x]))
63+
`!num)
64+
65+
@!num
66+

resources/viewer-js-hash

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
38F71uHxJsdbeuJsMnSfkow4eTQ2
1+
41eXh3xrWdsqXCdwuJ43u74YfK4z

src/nextjournal/clerk/builder.clj

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"viewer_d3_require"
3838
"viewers_nested"
3939
"viewer_normalization"
40+
"viewers/control_lab"
4041
"viewers/custom_markdown"
4142
"viewers/grid"
4243
"viewers/html"
@@ -291,7 +292,6 @@
291292
(report-fn {:stage :done :duration duration})))
292293
(report-fn {:stage :finished :state state :duration duration :total-duration (eval/elapsed-ms start)})))
293294

294-
295295
#_(build-static-app! {:ssr? true :index "notebooks/rule_30.clj" :browse? true})
296296
#_(build-static-app! {:paths clerk-docs :bundle? true})
297297
#_(build-static-app! {:paths ["index.clj" "notebooks/rule_30.clj" "notebooks/viewer_api.md"] :bundle? true})

src/nextjournal/clerk/render.cljs

+4
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,10 @@
591591
(js/ws_send (pr-str {:type :swap! :var-name var-name :args [(list 'fn ['_] new-val)]})))
592592
new-val))
593593

594+
(defn clerk-reset! [atom new-val]
595+
(clerk-swap! atom (constantly new-val))
596+
new-val)
597+
594598
(defn swap-clerk-atom! [{:as event :keys [var var-name args]}]
595599
(apply swap! @var args))
596600

src/nextjournal/clerk/sci_env.cljs

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
'nextjournal.clerk.viewer viewer-namespace
8989
'nextjournal.clerk.parser parser-namespace
9090
'clojure.core {'swap! nextjournal.clerk.render/clerk-swap!
91+
'reset! nextjournal.clerk.render/clerk-reset!
9192
'read-string read-string}}
9293
sci.configs.js-interop/namespaces
9394
sci.configs.reagent/namespaces)})

0 commit comments

Comments
 (0)