瀏覽代碼

feat(ui): support images lightbox with photoswipe

charlie 4 年之前
父節點
當前提交
f4fb358916

+ 441 - 0
resources/css/photoswipe.css

@@ -0,0 +1,441 @@
+/*! PhotoSwipe main CSS by Dmytro Semenov | photoswipe.com */
+
+.pswp {
+  --pswp-bg: #000;
+  --pswp-placeholder-bg: #222;
+  --pswp-error-text-color: #f7f7f7;
+
+  --pswp-root-z-index: 100000;
+  
+  --pswp-preloader-color: rgba(79, 79, 79, 0.4);
+  --pswp-preloader-color-secondary: rgba(255, 255, 255, 0.9);
+  
+  /* defined via js:
+  --pswp-transition-duration: 333ms; */
+  
+  --pswp-icon-color: #fff;
+  --pswp-icon-color-secondary: #4f4f4f;
+  --pswp-icon-stroke-color: #4f4f4f;
+  --pswp-icon-stroke-width: 2px;
+}
+
+
+/*
+	Styles for basic PhotoSwipe (pswp) functionality (sliding area, open/close transitions)
+*/
+
+.pswp {
+	position: fixed;
+	z-index: var(--pswp-root-z-index);
+	display: none;
+	touch-action: none;
+	outline: 0;
+	opacity: 0.003;
+	contain: layout style size;
+	-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+
+/* Prevents focus outline on the root element,
+  (it may be focused initially) */
+.pswp:focus {
+  outline: 0;
+}
+
+.pswp * {
+  box-sizing: border-box;
+}
+
+.pswp img {
+  max-width: none;
+}
+
+.pswp--open {
+	display: block;
+}
+
+.pswp,
+.pswp__bg {
+	transform: translateZ(0);
+	will-change: opacity;
+}
+
+.pswp__bg {
+  opacity: 0.005;
+	background: var(--pswp-bg);
+}
+
+.pswp,
+.pswp__scroll-wrap {
+	overflow: hidden;
+}
+
+.pswp,
+.pswp__scroll-wrap,
+.pswp__bg,
+.pswp__container,
+.pswp__item,
+.pswp__img,
+.pswp__zoom-wrap {
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+}
+
+.pswp {
+	position: fixed;
+}
+
+.pswp__img,
+.pswp__zoom-wrap {
+	width: auto;
+	height: auto;
+}
+
+.pswp--click-to-zoom.pswp--zoom-allowed .pswp__img {
+	cursor: -webkit-zoom-in;
+	cursor: -moz-zoom-in;
+	cursor: zoom-in;
+}
+
+.pswp--click-to-zoom.pswp--zoomed-in .pswp__img {
+	cursor: move;
+	cursor: -webkit-grab;
+	cursor: -moz-grab;
+	cursor: grab;
+}
+
+.pswp--click-to-zoom.pswp--zoomed-in .pswp__img:active {
+  cursor: -webkit-grabbing;
+  cursor: -moz-grabbing;
+  cursor: grabbing;
+}
+
+/* :active to override grabbing cursor */
+.pswp--no-mouse-drag.pswp--zoomed-in .pswp__img,
+.pswp--no-mouse-drag.pswp--zoomed-in .pswp__img:active,
+.pswp__img {
+	cursor: -webkit-zoom-out;
+	cursor: -moz-zoom-out;
+	cursor: zoom-out;
+}
+
+
+/* Prevent selection and tap highlights */
+.pswp__container,
+.pswp__img,
+.pswp__button {
+	-webkit-user-select: none;
+	-moz-user-select: none;
+	-ms-user-select: none;
+	user-select: none;
+}
+
+.pswp__item {
+	/* z-index for fade transition */
+	z-index: 1;
+	overflow: hidden;
+}
+
+.pswp__hidden {
+	display: none !important;
+}
+
+
+/*
+
+  PhotoSwipe UI
+
+*/
+
+/*
+	Error message appears when image is not loaded
+	(JS option errorMsg controls markup)
+*/
+.pswp__error-msg {
+	position: absolute;
+	top: 50%;
+	left: 0;
+	width: 100%;
+	padding: 0 10px;
+	margin-top: -0.5em;
+	font-size: 1em;
+	line-height: 1;
+	color: var(--pswp-error-text-color);
+	text-align: center;
+}
+
+.pswp__error-msg a {
+  color: var(--pswp-error-text-color);
+  text-decoration: underline;
+}
+
+/*
+class pswp__hide-on-close is applied to elements that
+should hide (for example fade out) when PhotoSwipe is closed
+and show (for example fade in) when PhotoSwipe is opened
+ */
+.pswp .pswp__hide-on-close {
+	opacity: 0.005;
+	will-change: opacity;
+	transition: opacity var(--pswp-transition-duration) cubic-bezier(0.4, 0, 0.22, 1);
+	z-index: 10; /* always overlap slide content */
+	pointer-events: none; /* hidden elements should not be clickable */
+}
+
+/* class pswp--ui-visible is added when opening or closing transition starts */
+.pswp--ui-visible .pswp__hide-on-close {
+	opacity: 1;
+	pointer-events: auto;
+}
+
+/* <button> styles, including css reset */
+.pswp__button {
+	position: relative;
+	display: block;
+	width: 50px;
+	height: 60px;
+	padding: 0;
+	margin: 0;
+	overflow: hidden;
+	cursor: pointer;
+	background: none;
+	border: 0;
+	box-shadow: none;
+	opacity: 0.85;
+	-webkit-appearance: none;
+	-webkit-touch-callout: none;
+}
+
+.pswp__button:hover,
+.pswp__button:active,
+.pswp__button:focus {
+  transition: none;
+  padding: 0;
+  background: none;
+  border: 0;
+  box-shadow: none;
+  opacity: 1;
+}
+
+.pswp__icn {
+  position: absolute;
+  top: 14px;
+  left: 9px;
+  width: 32px;
+  height: 32px;
+  overflow: hidden;
+  pointer-events: none;
+  fill: var(--pswp-icon-color);
+  color: var(--pswp-icon-color-secondary);
+  border-radius: 50%;
+}
+
+.pswp__icn-shadow {
+  stroke: var(--pswp-icon-stroke-color);
+  stroke-width: var(--pswp-icon-stroke-width);
+  fill: none;
+}
+
+.pswp__icn:focus {
+	outline: 0;
+}
+
+/*
+	div element that matches size of large image,
+	large image loads on top of it,
+	used when msrc is not provided
+*/
+div.pswp__img--placeholder,
+.pswp__img--with-bg {
+	background: var(--pswp-placeholder-bg);
+}
+
+.pswp__top-bar {
+	position: absolute;
+	left: 0;
+	top: 0;
+	width: 100%;
+	height: 60px;
+	display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+	z-index: 10;
+
+	/* allow events to pass through top bar itself */
+	pointer-events: none !important;
+}
+.pswp__top-bar > * {
+  pointer-events: auto;
+  /* this makes transition significantly more smooth,
+     even though inner elements are not animated */
+  will-change: opacity;
+}
+
+
+/*
+
+  Close button
+
+*/
+.pswp__button--close {
+  margin-right: 6px;
+}
+
+
+/*
+
+  Arrow buttons
+
+*/
+.pswp__button--arrow {
+  position: absolute;
+  top: 0;
+  width: 75px;
+  height: 100px;
+  top: 50%;
+  margin-top: -50px;
+}
+
+.pswp__button--arrow:disabled {
+  display: none;
+  cursor: default;
+}
+
+.pswp__button--arrow .pswp__icn {
+  top: 50%;
+  margin-top: -30px;
+  width: 60px;
+  height: 60px;
+  background: none;
+  border-radius: 0;
+}
+
+/* Display arrows only when user hovers over them */
+/* .pswp--ui-visible {
+  .pswp__button--arrow, {
+    opacity: 0.75;
+
+    &:hover,
+    &:focus {
+      opacity: 1;
+      outline: none;
+    }
+  }
+} */
+
+.pswp--one-slide .pswp__button--arrow {
+  display: none;
+}
+
+/* hide arrows on touch screens */
+.pswp--touch .pswp__button--arrow {
+  visibility: hidden;
+}
+
+/* show arrows only after mouse was used */
+.pswp--has_mouse .pswp__button--arrow {
+  visibility: visible;
+}
+
+.pswp__button--arrow--prev {
+  right: auto;
+  left: 0px;
+}
+
+.pswp__button--arrow--next {
+  right: 0px;
+}
+.pswp__button--arrow--next .pswp__icn {
+  left: auto;
+  right: 14px;
+  /* flip horizontally */
+  transform: scale(-1, 1);
+}
+
+/*
+
+  Zoom button
+
+*/
+.pswp__button--zoom {
+  display: none;
+}
+
+.pswp--zoom-allowed .pswp__button--zoom {
+  display: block;
+}
+
+/* "+" => "-" */
+.pswp--zoomed-in .pswp__zoom-icn-bar-v {
+  display: none;
+}
+
+
+/*
+
+  Loading indicator
+
+*/
+.pswp__preloader {
+  position: absolute;
+  display: none;
+  width: 24px;
+  height: 24px;
+  pointer-events: none;
+  border: 3px solid var(--pswp-preloader-color);
+  border-left-color: var(--pswp-preloader-color-secondary);
+  border-radius: 50%;
+
+
+  
+
+  /* left:50% / top:50% styles are defined via JS,
+    as size of PhotoSwipe viewport might change visually
+    (because of UI elements like sidebar),
+    use !important if you want to override them */
+}
+
+.pswp__preloader--active {
+  display: block;
+  animation: pswp-fadein 333ms linear, pswp-clockwise 600ms linear infinite;
+}
+
+.pswp__preloader--hiding {
+  animation: pswp-clockwise 600ms linear infinite;
+
+  /* use of !important to override hide-on-close styles */
+  opacity: 0 !important;
+}
+
+
+@keyframes pswp-clockwise {
+  0% { transform: rotate(0deg); }
+  100% { transform: rotate(360deg); }
+}
+
+@keyframes pswp-fadein {
+  0% { opacity: 0; }
+  100% { opacity: 1; }
+}
+
+
+/*
+
+  "1 of 10" counter
+
+*/
+.pswp__counter {
+  height: 30px;
+  margin: 18px 0 0 20px;
+  font-size: 14px;
+  line-height: 30px;
+  color: var(--pswp-icon-color);
+  opacity: 0.85;
+  margin-right: auto; /* align left */
+}
+
+.pswp--one-slide .pswp__counter {
+  display: none;
+}

文件差異過大導致無法顯示
+ 1 - 0
resources/js/photoswipe.js


+ 87 - 68
src/main/frontend/components/block.cljs

@@ -26,6 +26,7 @@
             [frontend.extensions.sci :as sci]
             [frontend.extensions.pdf.assets :as pdf-assets]
             [frontend.extensions.zotero :as zotero]
+            [frontend.extensions.lightbox :as lightbox]
             [frontend.extensions.video.youtube :as youtube]
             [frontend.format.block :as block]
             [frontend.format.mldoc :as mldoc]
@@ -179,23 +180,23 @@
       (ui/resize-provider
        (ui/resize-consumer
         (cond->
-          {:className "resize image-resize"
-           :onSizeChanged (fn [value]
-                            (when (and (not @*resizing-image?)
-                                       (some? @size)
-                                       (not= value @size))
-                              (reset! *resizing-image? true))
-                            (reset! size value))
-           :onMouseUp (fn []
-                        (when (and @size @*resizing-image?)
-                          (when-let [block-id (:block/uuid config)]
-                            (let [size (bean/->clj @size)]
-                              (editor-handler/resize-image! block-id metadata full_text size))))
-                        (when @*resizing-image?
+         {:className "resize image-resize"
+          :onSizeChanged (fn [value]
+                           (when (and (not @*resizing-image?)
+                                      (some? @size)
+                                      (not= value @size))
+                             (reset! *resizing-image? true))
+                           (reset! size value))
+          :onMouseUp (fn []
+                       (when (and @size @*resizing-image?)
+                         (when-let [block-id (:block/uuid config)]
+                           (let [size (bean/->clj @size)]
+                             (editor-handler/resize-image! block-id metadata full_text size))))
+                       (when @*resizing-image?
                           ;; TODO: need a better way to prevent the clicking to edit current block
-                          (js/setTimeout #(reset! *resizing-image? false) 200)))
-           :onClick (fn [e]
-                      (when @*resizing-image? (util/stop e)))}
+                         (js/setTimeout #(reset! *resizing-image? false) 200)))
+          :onClick (fn [e]
+                     (when @*resizing-image? (util/stop e)))}
           (and (:width metadata) (not (util/mobile?)))
           (assoc :style {:width (:width metadata)}))
         [:div.asset-container
@@ -227,7 +228,25 @@
                                                       :full-text   full_text}))})]
                   (state/set-modal! confirm-fn)
                   (util/stop e))))}
-           svg/trash-sm]]])))))
+           svg/trash-sm]
+
+          [:a.delete.ml-1
+           {:title    "maximize image"
+            :on-click (fn [^js e] (let [images (js/document.querySelectorAll ".asset-container img")
+                                        images (to-array images)
+                                        images (if-not (= (count images) 1)
+                                                 (let [^js image (.closest (.-target e) ".asset-container")
+                                                       image (js/image.querySelector "img")]
+                                                   (cons image (remove #(= image %) images)))
+                                                 images)
+                                        images (for [^js it images] {:src (.-src it)
+                                                                     :w (.-naturalWidth it)
+                                                                     :h (.-naturalHeight it)})]
+
+                                    (if (seq images)
+                                      (lightbox/preview-images! images))))}
+
+           (svg/maximize)]]])))))
 
 (rum/defcs asset-link < rum/reactive
   (rum/local nil ::src)
@@ -884,9 +903,9 @@
             (->elem
              :a
              (cond->
-               {:href      (str "file://" path)
-                :data-href path
-                :target    "_blank"}
+              {:href      (str "file://" path)
+               :data-href path
+               :target    "_blank"}
                title
                (assoc :title title))
              (map-inline config label)))
@@ -944,9 +963,9 @@
                     (->elem
                      :a
                      (cond->
-                       {:href      (str "file://" href*)
-                        :data-href href*
-                        :target    "_blank"}
+                      {:href      (str "file://" href*)
+                       :data-href href*
+                       :target    "_blank"}
                        title
                        (assoc :title title))
                      (map-inline config label))))))
@@ -972,8 +991,8 @@
             (->elem
              :a.external-link
              (cond->
-               {:href href
-                :target "_blank"}
+              {:href href
+               :target "_blank"}
                title
                (assoc :title title))
              (map-inline config label))))))
@@ -1205,7 +1224,7 @@
                                   (util/format "[:img {:src \"%s\"}]" (first arguments))
                                   4
                                   (when (and (util/safe-parse-int (nth arguments 1))
-                                           (util/safe-parse-int (nth arguments 2)))
+                                             (util/safe-parse-int (nth arguments 2)))
                                     (util/format "[:img.%s {:src \"%s\" :style {:width %s :height %s}}]"
                                                  (nth arguments 3)
                                                  (first arguments)
@@ -1213,7 +1232,7 @@
                                                  (util/safe-parse-int (nth arguments 2))))
                                   3
                                   (when (and (util/safe-parse-int (nth arguments 1))
-                                           (util/safe-parse-int (nth arguments 2)))
+                                             (util/safe-parse-int (nth arguments 2)))
                                     (util/format "[:img {:src \"%s\" :style {:width %s :height %s}}]"
                                                  (first arguments)
                                                  (util/safe-parse-int (nth arguments 1))
@@ -1306,9 +1325,9 @@
            (when (map? child)
              (let [child (dissoc child :block/meta)
                    config (cond->
-                            (-> config
-                                (assoc :block/uuid (:block/uuid child))
-                                (dissoc :breadcrumb-show?))
+                           (-> config
+                               (assoc :block/uuid (:block/uuid child))
+                               (dissoc :breadcrumb-show?))
                             ref?
                             (assoc :ref-child? true))]
                (rum/with-key (block-container config child)
@@ -1564,21 +1583,21 @@
         priority]
        (if title
          (conj
-           (map-inline config title)
-           (when (and (util/electron?) (not= block-type :default))
-             [:a.prefix-link
-              {:on-click #(case block-type
+          (map-inline config title)
+          (when (and (util/electron?) (not= block-type :default))
+            [:a.prefix-link
+             {:on-click #(case block-type
                             ;; pdf annotation
-                            :annotation (pdf-assets/open-block-ref! t)
-                            (.preventDefault %))}
+                           :annotation (pdf-assets/open-block-ref! t)
+                           (.preventDefault %))}
 
-              [:span.hl-page
-               [:strong.forbid-edit (str "P" (or (:hl-page properties) "?"))]
-               [:label.blank " "]]
+             [:span.hl-page
+              [:strong.forbid-edit (str "P" (or (:hl-page properties) "?"))]
+              [:label.blank " "]]
 
-              (when-let [st (and (= :area (keyword (:hl-type properties)))
-                                 (:hl-stamp properties))]
-                (pdf-assets/area-display t st))]))
+             (when-let [st (and (= :area (keyword (:hl-type properties)))
+                                (:hl-stamp properties))]
+               (pdf-assets/area-display t st))]))
 
          [[:span.opacity-50 "Click here to start writing, type '/' to see all the commands."]])
        [tags])))))
@@ -1739,12 +1758,12 @@
            (not (:block/pre-block? block)))
       (let [move-to (rum/react *move-to)]
         (when-not
-            (or (and top? (not= move-to :top))
-                (and (not top?) (= move-to :top))
-                (and block-content? (not= move-to :nested))
-                (and (not block-content?)
-                     (seq (:block/children block))
-                     (= move-to :nested)))
+         (or (and top? (not= move-to :top))
+             (and (not top?) (= move-to :top))
+             (and block-content? (not= move-to :nested))
+             (and (not block-content?)
+                  (seq (:block/children block))
+                  (= move-to :nested)))
           (dnd-separator block move-to block-content?))))))
 
 (rum/defc block-content < rum/reactive
@@ -1758,11 +1777,11 @@
         mouse-down-key (if (util/ios?)
                          :on-click
                          :on-mouse-down ; TODO: it seems that Safari doesn't work well with on-mouse-down
-                         )
+)
         attrs (cond->
-                {:blockid       (str uuid)
-                 :data-type (name block-type)
-                 :style {:width "100%"}}
+               {:blockid       (str uuid)
+                :data-type (name block-type)
+                :style {:width "100%"}}
                 (not block-ref?)
                 (assoc mouse-down-key (fn [e]
                                         (block-content-on-mouse-down e block block-id properties content format edit-input-id))))]
@@ -1890,7 +1909,7 @@
   (if (= block :page)                   ; page
     (when label
       (let [page (db/entity [:block/name (string/lower-case label)])]
-       (page-cp config page)))
+        (page-cp config page)))
     [:a {:on-mouse-down
          (fn [e]
            (if (gobj/get e "shiftKey")
@@ -2090,16 +2109,16 @@
         edit? (state/sub [:editor/editing? edit-input-id])]
     [:div.ls-block.flex.flex-col.rounded-sm
      (cond->
-       {:id block-id
-        :data-refs data-refs
-        :data-refs-self data-refs-self
-        :style {:position "relative"}
-        :class (str uuid
-                    (when (and collapsed? has-child?) " collapsed")
-                    (when pre-block? " pre-block"))
-        :blockid (str uuid)
-        :repo repo
-        :haschild (str has-child?)}
+      {:id block-id
+       :data-refs data-refs
+       :data-refs-self data-refs-self
+       :style {:position "relative"}
+       :class (str uuid
+                   (when (and collapsed? has-child?) " collapsed")
+                   (when pre-block? " pre-block"))
+       :blockid (str uuid)
+       :repo repo
+       :haschild (str has-child?)}
 
        level
        (assoc :level level)
@@ -2199,7 +2218,7 @@
         (->elem
          :li
          (cond->
-           {:checked checked?}
+          {:checked checked?}
            number
            (assoc :value number))
          (vec-cat
@@ -2336,7 +2355,7 @@
                     transformed-query-result)
            _ (when-let [query-result (:query-result config)]
                (let [result (remove (fn [b] (some? (get-in b [:block/properties :template]))) result)]
-                     (reset! query-result result)))
+                 (reset! query-result result)))
            view-f (and view (sci/eval-string (pr-str view)))
            only-blocks? (:block/uuid (first result))
            blocks-grouped-by-page? (and (seq result)
@@ -2693,8 +2712,8 @@
   [state config blocks]
   (let [*page (get state ::page)
         segment (->> blocks
-                    (drop (* (dec @*page) max-blocks-per-page))
-                    (take max-blocks-per-page))
+                     (drop (* (dec @*page) max-blocks-per-page))
+                     (take max-blocks-per-page))
         bottom-reached (fn []
                          (when (and (= (count segment) max-blocks-per-page)
                                     (> (count blocks) (* @*page max-blocks-per-page))
@@ -2781,7 +2800,7 @@
               {})])))]
 
      (and (:group-by-page? config)
-            (vector? (first blocks)))
+          (vector? (first blocks)))
      [:div.flex.flex-col
       (let [blocks (sort-by (comp :block/journal-day first) > blocks)]
         (for [[page blocks] blocks]

+ 10 - 0
src/main/frontend/components/svg.cljs

@@ -716,5 +716,15 @@
    [:svg.icon-offline {:viewBox "0 0 1024 1024" :width size :height size}
     [:path {:d "M512 183.466667c149.333333 0 292.266667 46.933333 409.6 132.266666 19.2 12.8 23.466667 40.533333 8.533333 59.733334-12.8 19.2-40.533333 23.466667-59.733333 8.533333-102.4-74.666667-228.266667-115.2-358.4-115.2-130.133333 0-256 40.533333-358.4 115.2-19.2 12.8-44.8 8.533333-59.733333-8.533333-12.8-19.2-8.533333-44.8 8.533333-59.733334 119.466667-85.333333 260.266667-132.266667 409.6-132.266666z m0 170.666666c108.8 0 211.2 32 298.666667 91.733334 19.2 12.8 23.466667 40.533333 10.666666 59.733333-12.8 19.2-40.533333 23.466667-59.733333 10.666667-72.533333-51.2-160-78.933333-251.733333-78.933334-91.733333 0-177.066667 27.733333-249.6 76.8-19.2 12.8-44.8 8.533333-59.733334-10.666666-12.8-19.2-8.533333-44.8 10.666667-59.733334 89.6-57.6 192-89.6 300.8-89.6z m0 168.533334c23.466667 0 42.666667 19.2 42.666667 42.666666s-19.2 42.666667-42.666667 42.666667c-51.2 0-100.266667 14.933333-142.933333 40.533333-19.2 12.8-46.933333 6.4-57.6-14.933333-12.8-19.2-6.4-46.933333 14.933333-57.6 53.333333-34.133333 117.333333-53.333333 185.6-53.333333z m0 189.866666c34.133333 0 64 27.733333 64 64 0 34.133333-27.733333 64-64 64s-64-27.733333-64-64c0-34.133333 27.733333-64 64-64z m164.266667-106.666666l89.6 89.6 89.6-89.6c17.066667-17.066667 42.666667-17.066667 59.733333 0 17.066667 17.066667 17.066667 42.666667 0 59.733333l-89.6 89.6 89.6 89.6c17.066667 17.066667 17.066667 42.666667 0 59.733333-17.066667 17.066667-42.666667 17.066667-59.733333 0l-89.6-89.6-89.6 89.6c-17.066667 17.066667-42.666667 17.066667-59.733334 0-17.066667-17.066667-17.066667-42.666667 0-59.733333l89.6-89.6-89.6-89.6c-17.066667-17.066667-17.066667-42.666667 0-59.733333 14.933333-17.066667 42.666667-17.066667 59.733334 0z" :fill "currentColor"}]]))
 
+(defn maximize
+  ([] (maximize 16))
+  ([size]
+   [:svg.icon {:width size :height size :viewBox "0 0 24 24" :stroke-width "2" :stroke "currentColor" :fill "none" :stroke-linecap "round" :stroke-linejoin "round"}
+    [:path {:stroke "none" :d "M0 0h24v24H0z" :fill "none"}]
+    [:path {:d "M4 8v-2a2 2 0 0 1 2 -2h2"}]
+    [:path {:d "M4 16v2a2 2 0 0 0 2 2h2"}]
+    [:path {:d "M16 4h2a2 2 0 0 1 2 2v2"}]
+    [:path {:d "M16 20h2a2 2 0 0 0 2 -2v-2"}]]))
+
 (def arrow-expand
   (hero-icon "M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4"))

+ 30 - 0
src/main/frontend/extensions/lightbox.cljs

@@ -0,0 +1,30 @@
+(ns frontend.extensions.lightbox
+  (:require [promesa.core :as p]
+            [cljs-bean.core :as bean]
+            [frontend.loader :refer [load]]))
+
+(defn js-load$
+  [url]
+  (p/create
+    (fn [resolve]
+      (load url resolve))))
+
+(def JS_ROOT
+  (if (= js/location.protocol "file:")
+    "./js"
+    "./static/js"))
+
+(defn load-base-assets$
+  []
+  (js-load$ (str JS_ROOT "/photoswipe.js")))
+
+(defn preview-images!
+  [images]
+
+  (p/let [_ (load-base-assets$)]
+    (let [options {:dataSource images :pswpModule js/window.photoswipe.default :showHideAnimationType "fade"}
+          _ (js/console.log (bean/->js options))
+          ^js lightbox (js/window.photoswipe.PhotoSwipeLightbox. (bean/->js options))]
+      (doto lightbox
+        (.init)
+        (.loadAndOpen 0)))))

+ 1 - 0
tailwind.all.css

@@ -4,6 +4,7 @@
 @import "resources/css/inter.css";
 @import "resources/css/reveal.min.css";
 @import "resources/css/reveal_black.min.css";
+@import "resources/css/photoswipe.css";
 @import "resources/css/fonts.css";
 @import "resources/css/excalidraw.min.css";
 @import "resources/css/katex.min.css";

部分文件因文件數量過多而無法顯示