diff --git a/editor2/package.json b/editor2/package.json index 0e5974c3..59a7431c 100644 --- a/editor2/package.json +++ b/editor2/package.json @@ -23,6 +23,7 @@ "@nextjournal/lezer-clojure": "^1.0.0", "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-avatar": "^1.0.3", + "@radix-ui/react-hover-card": "^1.0.6", "@radix-ui/react-menubar": "^1.0.3", "@radix-ui/react-popover": "^1.0.6", "@radix-ui/react-tooltip": "^1.0.6", diff --git a/editor2/src/main/maria/editor/code/completions.cljs b/editor2/src/main/maria/editor/code/completions.cljs index 219e78bb..c8cabb3e 100644 --- a/editor2/src/main/maria/editor/code/completions.cljs +++ b/editor2/src/main/maria/editor/code/completions.cljs @@ -85,7 +85,8 @@ {".cm-tooltip.cm-tooltip-autocomplete" {:border "none" :background-color "white" - :box-shadow "2px 2px 8px 0 rgba(0,0,0,.2)"} + :box-shadow "2px 2px 8px 0 rgba(0,0,0,.2)" + :z-index 10} ".cm-tooltip.cm-tooltip-autocomplete > ul" {:min-width "min(250px, 95vw)"} ".cm-tooltip.cm-tooltip-autocomplete > ul > li" diff --git a/editor2/src/main/maria/editor/code/show_values.cljs b/editor2/src/main/maria/editor/code/show_values.cljs index ebfdd790..1bc6e79a 100644 --- a/editor2/src/main/maria/editor/code/show_values.cljs +++ b/editor2/src/main/maria/editor/code/show_values.cljs @@ -331,18 +331,21 @@ loader)) - (fn [opts x] - (when (cells/cell? x) - (show-cell opts x))) + (handles-keys #{:maria/cells} + (fn [opts x] + (when (cells/cell? x) + (show-cell opts x)))) (handles-keys #{:react-element} + ;; show react elements directly (fn [opts x] (when (react/isValidElement x) x))) (handles-keys #{:hiccup} - (fn [opts x] (when (:hiccup (meta x)) - (v/x x)))) + (fn [opts x] + (when (:hiccup (meta x)) + (v/x x)))) (handles-keys #{:TeX} ;; THIS IS TEMPORARY FOR TESTING @@ -393,13 +396,14 @@ ExceptionInfo show-error })) - (fn [opts x] - (when (instance? js/Error x) - (show-error opts x))) - - (fn [opts x] - (when (fn? x) - (show-function opts x))) + (handles-keys #{:error} + (fn [opts x] + (when (instance? js/Error x) + (show-error opts x)))) + (handles-keys #{:function} + (fn [opts x] + (when (fn? x) + (show-function opts x)))) (handles-keys #{:cljs.core/IWatchable} (fn [opts x] (when (satisfies? IWatchable x) @@ -427,23 +431,84 @@ (mapcat second) (get-in ctx [::ns-viewers (repl/current-ns-name ctx)]))) +(defn first-index [pred coll] + (reduce (fn [out i] + (if (pred (nth coll i)) + (reduced i) + i)) + 0 + (range (count coll)))) + +(defn last-index [pred coll] + (max 0 (- (count coll) + (inc (first-index pred (reverse coll)))))) + +(defn insert [where pred coll x] + (let [i (case where :before (first-index pred coll) + :after (inc (last-index pred coll)))] + (concat (take i coll) + x + (drop i coll)))) + (defn add-global-viewers! "Adds viewers to the global list of viewers, before/after the given viewer-key. See builtin-viewers to see what viewer-keys can be referred to" [ctx where viewer-key added-viewers] {:pre [(#{:before :after} where)]} - (let [!viewers (:!viewers ctx) - viewers (or @!viewers builtin-viewers) - i (reduce (fn [not-found i] - (if (contains? (::keys (meta (nth viewers i))) viewer-key) - (reduced i) - not-found)) - ::not-found - (range (count viewers))) - i (case where :before i :after (inc i))] - (if (= ::not-found i) - (js/console.warn (str "Viewer not found: " viewer-key)) - (reset! !viewers (concat (take i viewers) - added-viewers - (drop i viewers)))) + (let [!viewers (:!viewers ctx)] + (->> (insert where + (comp viewer-key ::keys meta) + (or @!viewers builtin-viewers) + added-viewers) + (reset! !viewers)) ctx)) + +(comment + + (for [where [:before :after]] + (insert where + (comp :foo ::keys meta) + [nil + nil + (handles-keys #{:foo} (fn [])) + nil + (handles-keys #{:foo} (fn []))] + [:X])) + + (= [2 4] ((juxt first-index last-index) :foo [#{:bar} + #{:bar} + #{:foo} + #{:bar} + #{:foo} + #{:bar}])) + + (= [0 0] + ;; not-found + ((juxt first-index last-index) :foo [#{:bar}])) + + (= [0 0] + ;; first entry + ((juxt first-index last-index) :foo [#{:foo}])) + + (= [1 1] + ;; midpoint + ((juxt first-index last-index) :foo [#{:bar} #{:foo} #{:bar}])) + + (= [2 2] + ;; does not matter how many are trailing + ((juxt first-index last-index) :foo [#{:bar} #{:bar} + #{:foo} + #{:bar} #{:bar}]) + ((juxt first-index last-index) :foo [#{:bar} #{:bar} + #{:foo}]) + ((juxt first-index last-index) :foo [#{:bar} #{:bar} + #{:foo} + #{:bar} #{:bar} #{:bar}])) + (= [2 5] + ;; selects last occurrence + ((juxt first-index last-index) :foo [#{:bar} #{:bar} + #{:foo} + #{:bar} #{:bar} + #{:foo}]))) + + diff --git a/editor2/src/main/maria/editor/views.cljs b/editor2/src/main/maria/editor/views.cljs index 17fbef3e..bb4c3d8b 100644 --- a/editor2/src/main/maria/editor/views.cljs +++ b/editor2/src/main/maria/editor/views.cljs @@ -1,5 +1,6 @@ (ns maria.editor.views (:require ["@radix-ui/react-tooltip" :as Tooltip] + ["@radix-ui/react-hover-card" :as HoverCard] [clojure.string :as str] [maria.cloud.markdown :as markdown] [maria.ui :as ui] @@ -40,11 +41,15 @@ (ui/defview doc-tooltip [m trigger] (when m - [:> Tooltip/Provider - [:> Tooltip/Root {:delayDuration 300} - [:> Tooltip/Trigger {:asChild true} trigger] - [:> Tooltip/Portal - [:> Tooltip/Content - [:> Tooltip/Arrow {:class "fill-white"}] - [:div.bg-white.rounded.shadow-md.p-3 {:class "max-w-[400px]"} - (show-doc m)]]]]])) \ No newline at end of file + [:> HoverCard/Root {:openDelay 0 + :closeDelay 100} + [:> HoverCard/Trigger {:asChild true} trigger] + [:el HoverCard/Portal + [:el.z-50.relative.overflow-y-auto.bg-white.rounded.shadow-lg.p-4 HoverCard/Content + {:avoid-collisions true + :collision-padding 10 + :style {:max-height "var(--radix-hover-card-content-available-height)" + :max-width "var(--radix-hover-card-content-available-width)"}} + [:> HoverCard/Arrow {:class "fill-white"}] + [:div #_{:class "max-w-[600px]"} + (show-doc m)]]]])) \ No newline at end of file diff --git a/editor2/src/maria.cloud.css b/editor2/src/maria.cloud.css index 39dafe06..30963539 100644 --- a/editor2/src/maria.cloud.css +++ b/editor2/src/maria.cloud.css @@ -16,6 +16,11 @@ --code-bool: #987aa0; --code-brackets: #9f9f9f; } +@layer base { + .prose code::before, .prose code::after { + content: none; + } +} @layer utilities { @@ -56,7 +61,7 @@ @apply ml-5; } -.ProseMirror code { +.ProseMirror code, .prose code { @apply bg-black/5 py-[2px] px-[2px]; } diff --git a/editor2/yarn.lock b/editor2/yarn.lock index 6fc98cc4..67db4811 100644 --- a/editor2/yarn.lock +++ b/editor2/yarn.lock @@ -1150,6 +1150,22 @@ "@radix-ui/react-primitive" "1.0.3" "@radix-ui/react-use-callback-ref" "1.0.1" +"@radix-ui/react-hover-card@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-hover-card/-/react-hover-card-1.0.6.tgz#ea4b5c02e9f145b278cbcacaf5200f80d44cba22" + integrity sha512-2K3ToJuMk9wjwBOa+jdg2oPma+AmLdcEyTNsG/iC4BDVG3E0/mGCjbY8PEDSLxJcUi+nJi2QII+ec/4kWd88DA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-dismissable-layer" "1.0.4" + "@radix-ui/react-popper" "1.1.2" + "@radix-ui/react-portal" "1.0.3" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-controllable-state" "1.0.1" + "@radix-ui/react-id@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.0.tgz#8d43224910741870a45a8c9d092f25887bb6d11e"