;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC Sucursal en España SL

(ns app.main.ui.workspace.libraries
  (:require-macros [app.main.style :as stl])
  (:require
   [app.common.data :as d]
   [app.common.data.macros :as dm]
   [app.common.files.variant :as cfv]
   [app.common.types.components-list :as ctkl]
   [app.common.types.file :as ctf]
   [app.common.types.library :as ctl]
   [app.common.types.tokens-lib :as ctob]
   [app.common.types.typographies-list :as ctyl]
   [app.common.uuid :as uuid]
   [app.config :as cf]
   [app.main.data.dashboard :as dd]
   [app.main.data.modal :as modal]
   [app.main.data.notifications :as ntf]
   [app.main.data.profile :as du]
   [app.main.data.team :as dtm]
   [app.main.data.workspace.colors :as mdc]
   [app.main.data.workspace.libraries :as dwl]
   [app.main.refs :as refs]
   [app.main.render :refer [component-svg]]
   [app.main.store :as st]
   [app.main.ui.components.color-bullet :as cb]
   [app.main.ui.components.link-button :as lb]
   [app.main.ui.components.search-bar :refer [search-bar*]]
   [app.main.ui.components.title-bar :refer [title-bar*]]
   [app.main.ui.context :as ctx]
   [app.main.ui.ds.buttons.button :refer [button*]]
   [app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
   [app.main.ui.ds.foundations.assets.icon :as i]
   [app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
   [app.main.ui.ds.product.empty-state :refer [empty-state*]]
   [app.main.ui.hooks :as h]
   [app.main.ui.icons :as deprecated-icon]
   [app.main.ui.workspace.tokens.import-from-library]
   [app.util.color :as uc]
   [app.util.dom :as dom]
   [app.util.i18n :refer [c tr]]
   [app.util.strings :refer [matches-search]]
   [beicon.v2.core :as rx]
   [cuerdas.core :as str]
   [rumext.v2 :as mf]))

(defn- get-library-summary
  "Given a library data return a summary representation of this library"
  [data]
  (let [colors       (count (:colors data))
        graphics     0
        typographies (count (:typographies data))
        components   (count (->> (ctkl/components-seq data)
                                 (remove #(cfv/is-secondary-variant? % data))))
        empty?       (and (zero? components)
                          (zero? graphics)
                          (zero? colors)
                          (zero? typographies))]

    {:is-empty empty?
     :colors colors
     :graphics graphics
     :typographies typographies
     :components components}))

(defn- adapt-backend-summary
  [summary]
  (let [components   (or (-> summary :components :count) 0)
        graphics     (or (-> summary :media :count) 0)
        typographies (or (-> summary :typographies :count) 0)
        colors       (or (-> summary :colors :count) 0)

        empty?       (and (zero? components)
                          (zero? graphics)
                          (zero? colors)
                          (zero? typographies))]
    {:is-empty     empty?
     :components   components
     :graphics     graphics
     :typographies typographies
     :colors       colors}))

(defn- describe-library
  [components-count graphics-count colors-count typography-count]
  (let [all-zero? (and (zero? components-count)
                       (zero? graphics-count)
                       (zero? colors-count)
                       (zero? typography-count))]
    (str
     (str/join " · "
               (cond-> []
                 (or all-zero? (pos? components-count))
                 (conj (tr "workspace.libraries.components" (c components-count)))

                 (or all-zero? (pos? graphics-count))
                 (conj (tr "workspace.libraries.graphics" (c graphics-count)))

                 (or all-zero? (pos? colors-count))
                 (conj (tr "workspace.libraries.colors" (c colors-count)))

                 (or all-zero? (pos? typography-count))
                 (conj (tr "workspace.libraries.typography" (c typography-count)))))
     "\u00A0")))

(mf/defc library-description*
  {::mf/private true}
  [{:keys [summary]}]
  (let [components-count (get summary :components)
        graphics-count   (get summary :graphics)
        typography-count (get summary :typographies)
        colors-count     (get summary :colors)]

    [:*
     (when (pos? components-count)
       [:li {:class (stl/css :element-count)}
        (tr "workspace.libraries.components" (c components-count))])

     (when (pos? graphics-count)
       [:li {:class (stl/css :element-count)}
        (tr "workspace.libraries.graphics" (c graphics-count))])

     (when (pos? colors-count)
       [:li {:class (stl/css :element-count)}
        (tr "workspace.libraries.colors" (c colors-count))])

     (when (pos? typography-count)
       [:li {:class (stl/css :element-count)}
        (tr "workspace.libraries.typography" (c typography-count))])]))

(mf/defc sample-library-entry*
  {::mf/private true}
  [{:keys [library importing]}]
  (let [id         (:id library)
        importing? (deref importing)

        team-id    (mf/use-ctx ctx/current-team-id)

        on-error
        (mf/use-fn
         (fn [_]
           (reset! importing nil)
           (rx/of (ntf/error (tr "dashboard.libraries-and-templates.import-error")))))

        on-success
        (mf/use-fn
         (mf/deps team-id)
         (fn [_]
           (st/emit! (dtm/fetch-shared-files team-id))))

        import-library
        (mf/use-fn
         (mf/deps on-success on-error)
         (fn [_]
           (reset! importing id)
           (st/emit! (dd/clone-template
                      (with-meta {:template-id id}
                        {:on-success on-success
                         :on-error on-error})))))]

    [:div {:class (stl/css :sample-library-item)
           :key (dm/str id)}
     [:div {:class (stl/css :sample-library-item-name)} (:name library)]

     [:> button* {:variant "secondary"
                  :disabled (some? importing?)
                  :on-click import-library
                  :class (stl/css :sample-library-button)}
      (if (= importing? id) (tr "labels.adding") (tr "labels.add"))]]))

(defn- empty-library?
  "Check if currentt library summary has elements or not"
  [summary]
  (boolean (:is-empty summary)))

(defn- has-tokens?
  "Check if library has tokens to be imported"
  [{:keys [data]}]
  (when-let [tokens-lib (get data :tokens-lib)]
    (not (ctob/empty-lib? tokens-lib))))

(mf/defc libraries-tab*
  {::mf/private true}
  [{:keys [is-shared linked-libraries shared-libraries]}]
  (let [file-id        (mf/use-ctx ctx/current-file-id)
        search-term*   (mf/use-state "")
        search-term    (deref search-term*)

        ;; The summary of the current/local library
        ;; NOTE: we only need a snapshot of current library
        local-library  (deref refs/workspace-data)
        summary        (get-library-summary local-library)
        empty-library? (empty-library? summary)

        selected       (h/use-shared-state mdc/colorpalette-selected-broadcast-key :recent)
        dependencies   (mf/with-memo [shared-libraries]
                         (into {} (map (juxt :id :library-file-ids) (vals shared-libraries))))

        library-names  (mf/with-memo [shared-libraries]
                         (into {} (map (fn [{:keys [id name]}]
                                         [id name])
                                       (vals shared-libraries))))

        find-connected-to
        (mf/use-fn
         (mf/deps dependencies)
         (fn [library-id]
           (->> dependencies
                (keep (fn [[k v]] (when (contains? v library-id) k))))))

        shared-libraries
        (mf/with-memo [shared-libraries linked-libraries file-id search-term]
          (when shared-libraries
            (->> (vals shared-libraries)
                 (remove #(= (:id %) file-id))
                 (remove #(contains? linked-libraries (:id %)))
                 (filter #(matches-search (:name %) search-term))
                 (map #(assoc % :connected-to (find-connected-to (:id %))))
                 (map #(assoc % :connected-to-names (->> (:connected-to %)
                                                         (keep library-names))))
                 (sort-by (comp str/lower :name)))))

        linked-libraries
        (mf/with-memo [linked-libraries find-connected-to library-names]
          (->> (vals linked-libraries)
               (map #(assoc % :connected-to (find-connected-to (:id %))))
               (map #(assoc % :connected-to-names (->> (:connected-to %)
                                                       (keep library-names))))
               (sort-by (comp str/lower :name))))

        linked-libraries-ids
        (mf/with-memo [linked-libraries]
          (into #{} d/xf:map-id linked-libraries))

        importing*
        (mf/use-state nil)

        sample-libraries
        (mf/with-memo []
          [{:id "penpot-design-system", :name "Design system example"}
           {:id "wireframing-kit", :name "Wireframe library"}
           {:id "whiteboarding-kit", :name "Whiteboarding Kit"}])


        change-search-term
        (mf/use-fn
         (fn [event]
           (reset! search-term* event)))

        link-library
        (mf/use-fn
         (mf/deps file-id)
         (fn [event]
           (let [library-id (some-> (dom/get-current-target event)
                                    (dom/get-data "library-id")
                                    (uuid/parse))]
             (reset! selected library-id)
             (st/emit! (dwl/link-file-to-library file-id library-id)))))

        unlink-library
        (mf/use-fn
         (mf/deps file-id)
         (fn [event]
           (let [library-id (some-> (dom/get-current-target event)
                                    (dom/get-data "library-id")
                                    (uuid/parse))]
             (when (= library-id @selected)
               (reset! selected :file))
             (st/emit! (dwl/unlink-file-from-library file-id library-id)
                       (dwl/sync-file file-id library-id)))))

        import-tokens
        (mf/use-fn
         (mf/deps file-id)
         (fn [event]
           (let [library-id (some-> (dom/get-current-target event)
                                    (dom/get-data "library-id")
                                    (uuid/parse))]
             (st/emit! (modal/show
                        :tokens/import-from-library {:file-id file-id
                                                     :library-id library-id})))))

        on-delete-accept
        (mf/use-fn
         (mf/deps file-id)
         #(st/emit! (dwl/set-file-shared file-id false)
                    (modal/show :libraries-dialog {:file-id file-id})))

        on-delete-cancel
        (mf/use-fn
         (mf/deps file-id)
         #(st/emit! (modal/show :libraries-dialog {:file-id file-id})))

        publish
        (mf/use-fn
         (mf/deps file-id)
         (fn [event]
           (let [input-node (dom/get-target event)
                 publish-library #(st/emit! (dwl/set-file-shared file-id true))
                 cancel-publish #(st/emit! (modal/show :libraries-dialog {:file-id file-id}))]
             (if empty-library?
               (st/emit! (modal/show
                          {:type :confirm
                           :title (tr "modals.publish-empty-library.title")
                           :message (tr "modals.publish-empty-library.message")
                           :accept-label (tr "modals.publish-empty-library.accept")
                           :on-accept publish-library
                           :on-cancel cancel-publish}))
               (publish-library))
             (dom/blur! input-node))))

        unpublish
        (mf/use-fn
         (mf/deps file-id)
         (fn [_]
           (st/emit! (modal/show
                      {:type :delete-shared-libraries
                       :ids #{file-id}
                       :origin :unpublish
                       :on-accept on-delete-accept
                       :on-cancel on-delete-cancel
                       :count-libraries 1}))))]

    [:div {:class (stl/css :libraries-content)}
     [:div {:class (stl/css :lib-section)}
      [:> title-bar* {:collapsable false
                      :title       (tr "workspace.libraries.in-this-file")
                      :class       (stl/css :title-spacing-lib)}]
      [:div {:class (stl/css :section-list)}

       [:div {:class (stl/css :section-list-publish)}
        [:div {:class (stl/css :item-content)}
         [:div {:class (stl/css :item-title)} (tr "workspace.libraries.file-library")]
         [:ul {:class (stl/css :item-contents)}
          [:> library-description* {:summary summary}]]]

        (if ^boolean is-shared
          [:> button* {:variant "secondary"
                       :type "button"
                       :on-click unpublish}
           (tr "common.unpublish")]

          [:> button* {:variant "primary"
                       :type "button"
                       :on-click publish}
           (tr "common.publish")])]

       (for [{:keys [id name data connected-to connected-to-names] :as library} linked-libraries]
         (let [disabled?   (some #(contains? linked-libraries-ids %) connected-to)
               has-tokens? (and (has-tokens? library)
                                (contains? cf/flags :token-import-from-library))]
           [:div {:class (stl/css :section-list-item)
                  :key (dm/str id)
                  :data-testid "library-item"}
            [:div {:class (stl/css :item-content)}
             [:div {:class (stl/css-case :item-name true
                                         :item-name-short has-tokens?)} name]
             [:ul {:class (stl/css :item-contents)}
              (let [summary (get-library-summary data)]
                [:*
                 [:> library-description* {:summary summary}]
                 (when (seq connected-to)
                   [:div {:class (stl/css :connected-to-wrapper)}
                    [:span "(" (tr "workspace.libraries.connected-to") " "]
                    [:span {:class (stl/css :connected-to-values)} (str/join ", " connected-to-names)]
                    [:span ")"]])])]]
            [:div {:class (stl/css :library-actions)}
             (when ^boolean has-tokens?
               [:> icon-button*
                {:type "button"
                 :aria-label (tr "workspace.tokens.import-tokens")
                 :icon i/import-export
                 :data-library-id (dm/str id)
                 :variant "secondary"
                 :on-click import-tokens}])

             [:> icon-button* {:type "button"
                               :aria-label (tr "workspace.libraries.unlink-library-btn")
                               :icon i/detach
                               :data-library-id (dm/str id)
                               :variant "secondary"
                               :disabled disabled?
                               :on-click unlink-library}]]]))]]

     [:div {:class (stl/css :shared-section)}
      [:> title-bar* {:collapsable false
                      :title       (tr "workspace.libraries.shared-libraries")
                      :class       (stl/css :title-spacing-lib)}]
      [:> search-bar* {:on-change change-search-term
                       :value search-term
                       :placeholder (tr "workspace.libraries.search-shared-libraries")
                       :icon-id i/search}]

      (if (seq shared-libraries)
        [:div {:class (stl/css :section-list-shared)}
         (for [{:keys [id name] :as library} shared-libraries]
           [:div {:class (stl/css :section-list-item)
                  :key (dm/str id)
                  :data-testid "library-item"}
            [:div {:class (stl/css :item-content)}
             [:div {:class (stl/css :item-name)} name]
             [:ul {:class (stl/css :item-contents)}
              (let [summary (-> (:library-summary library)
                                (adapt-backend-summary))]
                [:> library-description* {:summary summary}])]]

            [:> icon-button* {:class (stl/css :item-button-shared)
                              :variant "secondary"
                              :data-library-id (dm/str id)
                              :icon "add"
                              :aria-label (tr "workspace.libraries.shared-library-btn")
                              :on-click link-library}]])]

        (when (empty? shared-libraries)
          [:div {:class (stl/css :section-list-empty)}
           (cond
             (nil? shared-libraries)
             (tr "workspace.libraries.loading")

             (str/empty? search-term)
             [:*
              [:div {:class (stl/css :sample-libraries-info)}
               (tr "workspace.libraries.empty.no-libraries")
               [:a {:target "_blank"
                    :class (stl/css :sample-libraries-link)
                    :href "https://penpot.app/libraries-templates"}
                (tr "workspace.libraries.empty.some-templates")]]
              [:div {:class (stl/css :sample-libraries-container)}
               (tr "workspace.libraries.empty.add-some")
               (for [library sample-libraries]
                 [:> sample-library-entry*
                  {:library library
                   :key (dm/str (:id library))
                   :importing importing*}])]]

             :else
             (tr "workspace.libraries.no-matches-for" search-term))]))]]))

(defn- extract-assets
  [file-data library summary?]
  (let [exceeded (volatile! {:components false
                             :colors false
                             :typographies false})

        truncate (fn [asset-type items]
                   (if (and summary? (> (count items) 5))
                     (do
                       (vswap! exceeded assoc asset-type true)
                       (take 5 items))
                     items))

        assets (dwl/assets-need-sync library file-data)

        component-ids  (into #{} (->> assets
                                      (filter #(= (:asset-type %) :component))
                                      (map :asset-id)))
        color-ids      (into #{} (->> assets
                                      (filter #(= (:asset-type %) :color))
                                      (map :asset-id)))
        typography-ids (into #{} (->> assets
                                      (filter #(= (:asset-type %) :typography))
                                      (map :asset-id)))

        components   (->> component-ids
                          (map #(ctkl/get-component (:data library) %))
                          (sort-by #(str/lower (:name %)))
                          (truncate :components))
        colors       (->> color-ids
                          (map #(ctl/get-color (:data library) %))
                          (sort-by #(str/lower (:name %)))
                          (truncate :colors))
        typographies (->> typography-ids
                          (map #(ctyl/get-typography (:data library) %))
                          (sort-by #(str/lower (:name %)))
                          (truncate :typographies))]

    [library @exceeded {:components components
                        :colors colors
                        :typographies typographies}]))

(mf/defc updates-tab*
  {::mf/private true}
  [{:keys [file-id libraries]}]
  ;; FIXME: naming
  (let [summary?*  (mf/use-state true)
        summary?   (deref summary?*)
        updating?  (mf/deref refs/updating-library)

        ;; NOTE: we don't want to react on file changes, we just want
        ;; a snapshot of file on the momento of open the dialog
        file-data  (deref refs/workspace-data)

        see-all-assets
        (mf/use-fn
         (fn []
           (reset! summary?* false)))

        libs-assets (mf/with-memo [file-data libraries summary?*]
                      (->> (vals libraries)
                           (map #(extract-assets file-data % summary?))
                           (filter (fn [[_ _ {:keys [components colors typographies]}]]
                                     (or (seq components)
                                         (seq colors)
                                         (seq typographies))))))

        update         (mf/use-fn
                        (mf/deps file-id)
                        (fn [event]
                          (when-not updating?
                            (let [library-id (some-> (dom/get-current-target event)
                                                     (dom/get-data "library-id")
                                                     (uuid/parse))]
                              (when library-id
                                (st/emit!
                                 (dwl/set-updating-library true)
                                 (dwl/sync-file file-id library-id)))))))]

    [:div {:class (stl/css :updates-content)}
     [:div {:class (stl/css :update-section)}
      (if (empty? libs-assets)
        [:div {:class (stl/css :section-list-empty)}
         [:> empty-state* {:icon i/library
                           :text (tr "workspace.libraries.no-libraries-need-sync")}]]
        [:*
         [:div {:class (stl/css :section-title)} (tr "workspace.libraries.library-updates")]

         [:div {:class (stl/css :section-list)}
          (for [[{:keys [id name] :as library}
                 exceeded
                 {:keys [components colors typographies]}] libs-assets]
            [:div {:class (stl/css :section-list-item)
                   :key (dm/str id)}
             [:div {:class (stl/css :item-content)}
              [:div {:class (stl/css :item-name-long)} name]
              [:ul {:class (stl/css :item-contents)} (describe-library
                                                      (count components)
                                                      0
                                                      (count colors)
                                                      (count typographies))]]
             [:> button* {:class (stl/css :item-update)
                          :disabled updating?
                          :variant "primary"
                          :data-library-id (dm/str id)
                          :on-click update}
              (tr "workspace.libraries.update")]

             [:div {:class (stl/css :libraries-updates)}
              (when-not (empty? components)
                [:div {:class (stl/css :libraries-updates-column)}
                 (for [component components]
                   [:div {:class (stl/css :libraries-updates-item)
                          :key (dm/str (:id component))}
                    (let [component (ctf/load-component-objects (:data library) component)
                          root-shape (ctf/get-component-root (:data library) component)]
                      [:*
                       [:& component-svg {:root-shape root-shape
                                          :class (stl/css :component-svg)
                                          :objects (:objects component)}]
                       [:div {:class (stl/css :name-block)}
                        [:span {:class (stl/css :item-name)
                                :title (:name component)}
                         (:name component)]]])])
                 (when (:components exceeded)
                   [:div {:class (stl/css :libraries-updates-item)
                          :key (uuid/next)}
                    [:div {:class (stl/css :name-block :ellipsis)}
                     [:span {:class (stl/css :item-name)} "(...)"]]])])

              (when-not (empty? colors)
                [:div {:class (stl/css :libraries-updates-column)
                       :style #js {"--bullet-size" "24px"}}
                 (for [color colors]
                   (let [default-name (cond
                                        (:gradient color) (uc/gradient-type->string (get-in color [:gradient :type]))
                                        (:color color) (:color color)
                                        :else (:value color))]
                     [:div {:class (stl/css :libraries-updates-item)
                            :key (dm/str (:id color))}
                      [:*
                       [:> cb/color-bullet* {:color {:color (:color color)
                                                     :id (:id color)
                                                     :opacity (:opacity color)}}]
                       [:div {:class (stl/css :name-block)}
                        [:span {:class (stl/css :item-name)
                                :title (:name color)}
                         (:name color)]
                        (when-not (= (:name color) default-name)
                          [:span.color-value (:color color)])]]]))
                 (when (:colors exceeded)
                   [:div {:class (stl/css :libraries-updates-item)
                          :key (uuid/next)}
                    [:div {:class (stl/css :name-block.ellipsis)}
                     [:span {:class (stl/css :item-name)} "(...)"]]])])

              (when-not (empty? typographies)
                [:div {:class (stl/css :libraries-updates-column)}
                 (for [typography typographies]
                   [:div {:class (stl/css :libraries-updates-item)
                          :key (dm/str (:id typography))}
                    [:*
                     [:div {:style {:font-family (:font-family typography)
                                    :font-weight (:font-weight typography)
                                    :font-style (:font-style typography)}}
                      (tr "workspace.assets.typography.sample")]
                     [:div {:class (stl/css :name-block)}
                      [:span {:class (stl/css :item-name)
                              :title (:name typography)}
                       (:name typography)]]]])
                 (when (:typographies exceeded)
                   [:div {:class (stl/css :libraries-updates-item)
                          :key (uuid/next)}
                    [:div {:class (stl/css :name-block.ellipsis)}
                     [:span {:class (stl/css :item-name)} "(...)"]]])])]

             (when (or (pos? (:components exceeded))
                       (pos? (:colors exceeded))
                       (pos? (:typographies exceeded)))
               [:> lb/link-button*
                {:on-click see-all-assets
                 :class (stl/css :libraries-updates-see-all)
                 :value (str "(" (tr "workspace.libraries.update.see-all-changes") ")")}])])]])]]))

(mf/defc libraries-dialog
  {::mf/register modal/components
   ::mf/register-as :libraries-dialog}
  [{:keys [starting-tab file-id]}]
  (let [files   (mf/deref refs/files)
        file    (get files file-id)
        shared? (:is-shared file)

        linked-libraries
        (mf/with-memo [files file-id]
          (refs/select-libraries files file-id))

        linked-libraries
        (mf/with-memo [linked-libraries file-id]
          (d/removem (fn [[_ lib]]
                       (= (:id lib) file-id))
                     linked-libraries))

        shared-libraries
        (mf/deref refs/shared-files)

        close-dialog-outside
        (mf/use-fn
         (fn [event]
           (when (= (dom/get-target event) (dom/get-current-target event))
             (modal/hide!))))

        close-dialog
        (mf/use-fn
         (fn [_]
           (modal/hide!)))

        selected-tab*
        (mf/use-state #(d/nilv starting-tab "libraries"))

        selected-tab
        (deref selected-tab*)

        on-change-tab
        (mf/use-fn #(reset! selected-tab* %))

        tabs
        (mf/with-memo []
          [{:label (tr "workspace.libraries.libraries")
            :id "libraries"}
           {:label (tr "workspace.libraries.updates")
            :id "updates"}])]

    (mf/with-effect []
      (st/emit! (dtm/fetch-shared-files)))

    [:div {:class (stl/css :modal-overlay)
           :on-click close-dialog-outside
           :data-testid "libraries-modal"}
     [:div {:class (stl/css :modal-dialog)}
      [:> icon-button* {:class (stl/css :close-btn)
                        :on-click close-dialog
                        :aria-label (tr "labels.close")
                        :variant "ghost"
                        :icon i/close}]
      [:div {:class (stl/css :modal-title)}
       (tr "workspace.libraries.libraries")]

      [:> tab-switcher* {:tabs tabs
                         :selected selected-tab
                         :on-change on-change-tab}
       (case selected-tab
         "libraries"
         [:> libraries-tab*
          {:is-shared shared?
           :linked-libraries linked-libraries
           :shared-libraries shared-libraries}]

         "updates"
         [:> updates-tab*
          {:file-id file-id
           :libraries linked-libraries}])]]]))

(mf/defc v2-info-dialog
  {::mf/register modal/components
   ::mf/register-as :v2-info}
  []
  (let [handle-gotit-click
        (mf/use-fn
         (fn []
           (modal/hide!)
           (st/emit! (du/update-profile-props {:v2-info-shown true}))))]

    [:div {:class (stl/css :modal-overlay)}
     [:div {:class (stl/css :modal-dialog :modal-v2-info)}
      [:div {:class (stl/css :modal-v2-title)}
       "IMPORTANT INFORMATION ABOUT NEW COMPONENTS"]
      [:div  {:class (stl/css :modal-content)}
       [:div {:class (stl/css :info-content)}
        [:div {:class (stl/css :info-block)}
         [:div {:class (stl/css :info-icon)} deprecated-icon/v2-icon-1]
         [:div {:class (stl/css :info-block-title)}
          "One physical source of truth"]
         [:div {:class (stl/css :info-block-content)}
          "Main components are now found at the design space. They act as a single source "
          "of truth and can be worked on with their copies. This ensures consistency and "
          "allows better control and synchronization."]]

        [:div {:class (stl/css :info-block)}
         [:div {:class (stl/css :info-icon)} deprecated-icon/v2-icon-2]
         [:div {:class (stl/css :info-block-title)}
          "Swap components"]
         [:div {:class (stl/css :info-block-content)}
          "Now, you can replace one component copy with another within your libraries. "
          "The swap components functionality streamlines making changes, testing "
          "variations, or updating elements without extensive manual adjustments."]]

        [:div {:class (stl/css :info-block)}
         [:div {:class (stl/css :info-icon)} deprecated-icon/v2-icon-3]
         [:div {:class (stl/css :info-block-title)}
          "Graphic assets no longer exist"]
         [:div {:class (stl/css :info-block-content)}
          "Graphic assets now disappear, so that all graphic assets become components. "
          "This way, swapping between them is possible, and we avoid confusion about "
          "what should go in each typology."]]

        [:div {:class (stl/css :info-block)}
         [:div {:class (stl/css :info-icon)} deprecated-icon/v2-icon-4]
         [:div {:class (stl/css :info-block-title)}
          "Main components page"]
         [:div {:class (stl/css :info-block-content)}
          "You might find that a new page called 'Main components' has appeared in "
          "your file. On that page, you'll find all the main components that were "
          "created in your files previously to this new version."]]]

       [:div {:class (stl/css :info-bottom)}
        [:> button* {:class (stl/css :primary-button)
                     :variant "primary"
                     :on-click handle-gotit-click} "I GOT IT"]]]]]))
