           (when (om/get-state owner [:open?])
             (bs-p/panel
              {:header (dom/div "["
-                               (dom/button {:on-click #(om/set-state! owner [:tool] :timeline)} "Timeline")
-                               "] | ["
-                               (dom/button {:on-click #(om/set-state! owner [:tool] :states)} "States")
-                               "] | ["
-                               (dom/button {:on-click #(om/set-state! owner [:tool] :query)} "Expression Watch")
+                               (dom/button {:style    {:cursor "pointer"}
+                                            :on-click #(om/set-state! owner [:tool] :timeline)} "Timeline")
+                               "]  ["
+                               (dom/button {:style    {:cursor "pointer"}
+                                            :on-click #(om/set-state! owner [:tool] :components)} "Components")
+                               "]  ["
+                               (dom/button {:style    {:cursor "pointer"}
+                                            :on-click #(om/set-state! owner [:tool] :states)} "States")
+                               "]  ["
+                               (dom/button {:style    {:cursor "pointer"}
+                                            :on-click #(om/set-state! owner [:tool] :query)} "Expression Watch")
                                "] - Dato Debugger " (dom/small "(" log-count " states)"))}
              (case (om/get-state owner [:tool])
-               :states   (dom/div
-                          (dom/h3 "Click a slot to restore a state")
-                          (dom/ul
-                           (for [slot-idx (range 0 10)]
-                             (let [local-storage-name (str "dato_save_state_" slot-idx)
-                                   existing-db        (js/localStorage.getItem local-storage-name)]
-                               (dom/li {:style    {:cursor "pointer"}
-                                        :on-click #(restore-save-state! owner slot-idx)} (if existing-db
-                                                                                           (dom/strong "Slot " slot-idx)
-                                                                                           "No state saved"))))))
-               :query    (dom/div
-                          (g/grid
-                           {}
-                           (g/row
-                            {}
-                            (g/col
-                             {:xs 0 :sm 2 :md 2 :lg 2}
+               :states     (dom/div
+                            (dom/h3 "Click a slot to restore a state")
+                            (dom/ul
+                             (for [slot-idx (range 0 10)]
+                               (let [local-storage-name (str "dato_save_state_" slot-idx)
+                                     existing-db        (js/localStorage.getItem local-storage-name)]
+                                 (dom/li {:style    {:cursor "pointer"}
+                                          :on-click #(restore-save-state! owner slot-idx)} (if existing-db
+                                          (dom/strong "Slot " slot-idx)
+                                          "No state saved"))))))
+               :query      (dom/div
+                            (g/grid
+                             {}
                              (g/row
                               {}
                               (g/col
-                               {:xs 12 :sm 12 :md 12 :lg 12}
-                               (dom/input {:placeholder "Search Expressions"})))
-                             (g/row
-                              {}
-                              (g/col
-                               {:xs 12 :sm 12 :md 12 :lg 12}
-                               (dom/ul
-                                (for [[idx query] (map-indexed vector (om/get-state owner [:query]))
-                                      :let [current-query? (= (:title query) (om/get-state owner [:current-query]))
-                                            title (str idx ". " (:title query))]]
-                                  (dom/li {:style    {:cursor "pointer"}
-                                           :on-click #(om/set-state! owner [:current-query] idx)}
-                                          (if current-query?
-                                            (dom/strong title)
-                                            title)))))))
-                            (g/col {:xs 3 :sm 3 :md 3 :lg 3}
-                                   (let [current-query (om/get-state owner [:query (om/get-state owner [:current-query])])]
-                                     (dom/div
-                                      (when (false? (:valid? current-query))
-                                        (dom/pre "Invalid code"))
-                                      (dom/input {:placeholder "Query title"
-                                                  :value "Current Session"})
-                                      (dom/textarea {:placeholder "Expression (cljs code)"
-                                                     :value       (:str current-query)
-                                                     :on-change   (fn [event]
-                                                                    (let [str-value (.. event -target -value)
-                                                                          valid? (try (compile-expr str-value identity)
-                                                                                      true
-                                                                                      (catch js/Error e
-                                                                                        false))]
-                                                                      (om/update-state! owner [:queries (om/get-state owner [:current-query])] (fn [s]
-                                                                                                                                                 (merge s
-                                                                                                                                                        {:str    str-value
-                                                                                                                                                         :valid? valid?})))))
-                                                     :style       {:width  "100%"
-                                                                   :height "100%"}}))))
-                            (g/col {:xs 12 :sm 7 :md 7 :lg 7}
-                                   (when-let [current-query (om/get-state owner [:query (om/get-state owner [:current-query])])]
-                                     (dom/pre
-                                      (binding [*print-length* 10]
-                                        (let [query-results ((:fn current-query) db)]
-                                          (with-out-str (pp/pprint query-results))))))))))
-               :editor   (dom/div
-                          "Code editor"
-                          (dom/link {:rel      "stylesheet"
-                                     :property "stylesheet"
-                                     :href     "/css/vendor/codemirror/codemirror.css"})
-                          (dom/div {:className "editor"}))
-               :timeline (dom/div
-                          (dom/h3 (pr-str (get-in log [selected-state-idx :tx/intent])))
-                          (dom/div
-                           (dom/input {:type      "range"
-                                       :min       0
-                                       :max       (max 0 (dec (count (:log data))))
-                                       :value     (om/get-state owner [:states :selected])
-                                       :on-change #(let [idx (reader/read-string (.. % -target -value))]
-                                                     (om/set-state! owner [:states :selected] idx)
-                                                     (set-app-state! idx))})
-                           (dom/button {:on-click #(play-all-states!)
-                                        :disabled (not (pos? log-count))} "> Play All")
-                           (dom/div {:style {:float "right"
-                                             :width "50%"}}
-                                    (dom/pre (pr-str (get-in selected-state [:tx :tx-data]))))
-                           (dom/ul
-                            {:className "event-history"}
-                            (let [int (->> (:log data)
-                                           (map-indexed vector)
-                                           (reduce (fn [run [idx next]]
-                                                     (let [cnt        (count run)
-                                                           last-event (:tx/intent (nth run (dec cnt)))
-                                                           selected?  (= idx selected-state-idx)]
-                                                       (if (= last-event (:tx/intent next))
-                                                         (-> run
-                                                             (update-in [(dec cnt) :count] inc)
-                                                             (update-in [(dec cnt) :selected?] #(or selected? %)))
-                                                         (conj run (-> next
-                                                                       (assoc :count 1)
-                                                                       (assoc :selected? selected?)))))) [{}]))]
-                              (for [tx int]
-                                (dom/li (if (:selected? tx)
-                                          (dom/strong (pr-str (:tx/intent tx)))
-                                          (pr-str (:tx/intent tx)))
-                                        (when (pos? (dec (:count tx))) (str " x " (:count tx))))))))))))))))))
+                               {:xs 0 :sm 2 :md 2 :lg 2}
+                               (g/row
+                                {}
+                                (g/col
+                                 {:xs 12 :sm 12 :md 12 :lg 12}
+                                 (dom/input {:placeholder "Search Expressions"})))
+                               (g/row
+                                {}
+                                (g/col
+                                 {:xs 12 :sm 12 :md 12 :lg 12}
+                                 (dom/ul
+                                  (for [[idx query] (map-indexed vector (om/get-state owner [:query]))
+                                        :let [current-query? (= (:title query) (om/get-state owner [:current-query]))
+                                              title (str idx ". " (:title query))]]
+                                    (dom/li {:style    {:cursor "pointer"}
+                                             :on-click #(om/set-state! owner [:current-query] idx)}
+                                            (if current-query?
+                                              (dom/strong title)
+                                              title)))))))
+                              (g/col {:xs 3 :sm 3 :md 3 :lg 3}
+                                     (let [current-query (om/get-state owner [:query (om/get-state owner [:current-query])])]
+                                       (dom/div
+                                        (when (false? (:valid? current-query))
+                                          (dom/pre "Invalid code"))
+                                        (dom/input {:placeholder "Query title"
+                                                    :value "Current Session"})
+                                        (dom/textarea {:placeholder "Expression (cljs code)"
+                                                       :value       (:str current-query)
+                                                       :on-change   (fn [event]
+                                                                      (let [str-value (.. event -target -value)
+                                                                            valid? (try (compile-expr str-value identity)
+                                                                                        true
+                                                                                        (catch js/Error e
+                                                                                          false))]
+                                                                        (om/update-state! owner [:queries (om/get-state owner [:current-query])] (fn [s]
+                                                                                                                                                   (merge s
+                                                                                                                                                          {:str    str-value
+                                                                                                                                                           :valid? valid?})))))
+                                                       :style       {:width  "100%"
+                                                                     :height "100%"}}))))
+                              (g/col {:xs 12 :sm 7 :md 7 :lg 7}
+                                     (when-let [current-query (om/get-state owner [:query (om/get-state owner [:current-query])])]
+                                       (dom/pre
+                                        (binding [*print-length* 10]
+                                          (let [query-results ((:fn current-query) db)]
+                                            (with-out-str (pp/pprint query-results))))))))))
+               :editor     (dom/div
+                            "Code editor"
+                            (dom/link {:rel      "stylesheet"
+                                       :property "stylesheet"
+                                       :href     "/css/vendor/codemirror/codemirror.css"})
+                            (dom/div {:className "editor"}))
+               :components (dom/div
+                            "Component States"
+                            (dom/link {:rel      "stylesheet"
+                                       :property "stylesheet"
+                                       :href     "/css/vendor/codemirror/codemirror.css"})
+                            (dom/div {:className "state"}
+                                     (let [components        (state-watcher-coms @state-watchers)
+                                           inspected-com-key (om/get-state owner [:inspected-com-key])]
+                                       (dom/div
+                                        (dom/input {:on-change   #(om/set-state! owner [:com-name-filter] (.. % -target -value))
+                                                    :value        (om/get-state owner [:com-name-filter])
+                                                    :placeholder "Component Display Name"})
+                                        (dom/div
+                                         {:style {:float "right"
+                                                  :width "50%"}}
+                                         (if inspected-com-key
+                                           (dom/h4 (com-name @state-watchers inspected-com-key) "(" inspected-com-key ")")
+                                           (dom/h4 "No component"))
+                                         (when-let [inspected-com-key (om/get-state owner [:inspected-com-key])]
+                                           (let [com-states  (com-state @state-watchers inspected-com-key)
+                                                 dato-state* (:dato com-states)
+                                                 dato-state  (when dato-state*
+                                                               (dsu/touch+ dato-state*))
+                                                 om-state    (:om com-states)]
+                                             (dom/div
+                                              "Dato/Recorded"
+                                              (dom/pre (with-out-str (pp/pprint dato-state)))
+                                              "Om/Transient"
+                                              (dom/pre (with-out-str (pp/pprint (->
+                                                                                 om-state
+                                                                                 (dissoc :dato.lib.db/listener-key)
+                                                                                 (dissoc :dato.lib.db/listener-keys)))))))))
+                                        (dom/ul
+                                         (for [com-key components
+                                               :let [com-name (com-name @state-watchers com-key)]
+                                               :when (and com-name
+                                                          (let [filter (om/get-state owner [:com-name-filter])]
+                                                            (if (string/blank? filter)
+                                                              true
+                                                              (.match (string/lower-case com-name) filter))))]
+                                           (let [com-owner  (com-owner @state-watchers com-key)
+                                                 owner-node (when com-owner (om/get-node com-owner))]
+                                             (dom/li {:style    {:cursor "pointer"}
+                                                      ;; Someday we'll figure this out...
+                                                      :on-mouse-enter #(when owner-node (highlight-node! owner-node))
+                                                      :on-mouse-leave #(when owner-node (unhighlight-node! owner-node))
+                                                      :on-click #(om/set-state! owner [:inspected-com-key] com-key)} com-name "(" com-key ")"))))))))
+               :timeline   (dom/div
+                            (dom/h3 (pr-str (get-in log [selected-state-idx :tx/intent])))
+                            (dom/div
+                             (dom/input {:type      "range"
+                                         :min       0
+                                         :max       (max 0 (dec (count (:log data))))
+                                         :value     (om/get-state owner [:states :selected])
+                                         :on-change #(let [idx (reader/read-string (.. % -target -value))]
+                                                       (om/set-state! owner [:states :selected] idx)
+                                                       (set-app-state! idx))})
+                             (dom/button {:on-click #(play-all-states!)
+                                          :disabled (not (pos? log-count))} "> Play All")
+                             (dom/div {:style {:float "right"
+                                               :width "50%"}}
+                                      (dom/pre (pr-str (get-in selected-state [:tx :tx-data]))))
+                             (dom/ul
+                              {:className "event-history"}
+                              (let [int (->> (:log data)
+                                             (map-indexed vector)
+                                             (reduce (fn [run [idx next]]
+                                                       (let [cnt        (count run)
+                                                             last-event (:tx/intent (nth run (dec cnt)))
+                                                             selected?  (= idx selected-state-idx)]
+                                                         (if (= last-event (:tx/intent next))
+                                                           (-> run
+                                                               (update-in [(dec cnt) :count] inc)
+                                                               (update-in [(dec cnt) :selected?] #(or selected? %)))
+                                                           (conj run (-> next
+                                                                         (assoc :count 1)
+                                                                         (assoc :selected? selected?)))))) [{}]))]
+                                (for [tx int]
+                                  (dom/li (if (:selected? tx)
+                                            (dom/strong (pr-str (:tx/intent tx)))
+                                            (pr-str (:tx/intent tx)))
+                                          (when (pos? (dec (:count tx))) (str " x " (:count tx))))))))))))))))))

                        :ns      'dato.debug}
                    cb))))

(defn history-com [data owner opts]
  (reify
    om/IDisplayName

            [cljs.reader :as reader]
            [clojure.string :as string]
            [dato.lib.core :as dato]
            [dato.datascript-utils :as dsu]
            [dato.debug.components.keyboard-listener :as keyboard]
            [goog.dom.classes :as gclass]
            [om-bootstrap.panel :as bs-p]
            [om-bootstrap.grid :as g]
            [om.core :as om :include-macros true]
