Просмотр исходного кода

Merge branch 'feat/db' into perf/lazy-load-data

Tienson Qin 2 лет назад
Родитель
Сommit
7e8ab72494
96 измененных файлов с 3059 добавлено и 2187 удалено
  1. 2 2
      android/app/build.gradle
  2. 8 0
      deps/common/resources/templates/config.edn
  3. 6 0
      deps/db/src/logseq/db/frontend/property.cljs
  4. 0 1
      deps/outliner/src/logseq/outliner/core.cljs
  5. 0 2
      deps/shui/src/logseq/shui/core.cljs
  6. 5 5
      deps/shui/src/logseq/shui/list_item/v1.cljs
  7. 19 14
      deps/shui/src/logseq/shui/shortcut/v1.cljs
  8. 107 93
      packages/tldraw/apps/tldraw-logseq/src/components/ContextMenu/ContextMenu.tsx
  9. 5 5
      packages/tldraw/apps/tldraw-logseq/src/components/KeyboardShortcut/KeyboardShortcut.tsx
  10. 3 2
      packages/tldraw/apps/tldraw-logseq/src/lib/logseq-context.ts
  11. 176 68
      packages/tldraw/apps/tldraw-logseq/src/styles.css
  12. 8 8
      packages/tldraw/packages/react/src/hooks/useStylesheet.ts
  13. 26 7
      packages/ui/@/components/ui/context-menu.tsx
  14. 1 1
      packages/ui/@/components/ui/dropdown-menu.tsx
  15. 71 30
      packages/ui/src/colors.css
  16. 3 3
      packages/ui/src/index.css
  17. 171 0
      packages/ui/src/vars-classic.css
  18. 2 2
      packages/ui/tailwind.config.js
  19. 9 16
      resources/css/codemirror.lsradix.css
  20. 143 40
      resources/css/shui.css
  21. 1 1
      resources/forge.config.js
  22. 10 0
      resources/js/ui.js
  23. 1 1
      resources/package.json
  24. 1 1
      src/main/frontend/colors.cljs
  25. 12 2
      src/main/frontend/commands.cljs
  26. 26 225
      src/main/frontend/common.css
  27. 7 3
      src/main/frontend/components/block.cljs
  28. 29 23
      src/main/frontend/components/block.css
  29. 1 3
      src/main/frontend/components/cmdk.cljs
  30. 4 4
      src/main/frontend/components/command_palette.css
  31. 2 5
      src/main/frontend/components/container.cljs
  32. 24 55
      src/main/frontend/components/container.css
  33. 1 6
      src/main/frontend/components/content.css
  34. 0 2
      src/main/frontend/components/datepicker.css
  35. 1 1
      src/main/frontend/components/db_based/page.cljs
  36. 12 0
      src/main/frontend/components/editor.css
  37. 42 39
      src/main/frontend/components/file_sync.cljs
  38. 3 8
      src/main/frontend/components/file_sync.css
  39. 2 2
      src/main/frontend/components/header.cljs
  40. 3 12
      src/main/frontend/components/header.css
  41. 1 1
      src/main/frontend/components/journal.css
  42. 6 16
      src/main/frontend/components/onboarding/index.css
  43. 57 57
      src/main/frontend/components/onboarding/setups.cljs
  44. 399 312
      src/main/frontend/components/page.cljs
  45. 8 27
      src/main/frontend/components/page.css
  46. 4 3
      src/main/frontend/components/plugins.cljs
  47. 20 17
      src/main/frontend/components/plugins.css
  48. 4 2
      src/main/frontend/components/property.cljs
  49. 13 1
      src/main/frontend/components/query/builder.css
  50. 90 90
      src/main/frontend/components/right_sidebar.cljs
  51. 8 15
      src/main/frontend/components/right_sidebar.css
  52. 2 1
      src/main/frontend/components/select.cljs
  53. 44 33
      src/main/frontend/components/settings.cljs
  54. 28 1
      src/main/frontend/components/settings.css
  55. 3 2
      src/main/frontend/components/shortcut.cljs
  56. 3 3
      src/main/frontend/components/svg.cljs
  57. 3 3
      src/main/frontend/components/table.css
  58. 8 9
      src/main/frontend/components/theme.cljs
  59. 27 36
      src/main/frontend/components/theme.css
  60. 1 1
      src/main/frontend/components/user/login.cljs
  61. 24 22
      src/main/frontend/components/whiteboard.css
  62. 3 1
      src/main/frontend/dicts.cljc
  63. 2 7
      src/main/frontend/extensions/code.css
  64. 2 2
      src/main/frontend/extensions/graph.cljs
  65. 44 11
      src/main/frontend/extensions/graph/pixi.cljs
  66. 27 22
      src/main/frontend/extensions/handbooks/handbooks.css
  67. 2 2
      src/main/frontend/extensions/pdf/core.cljs
  68. 12 18
      src/main/frontend/extensions/pdf/pdf.css
  69. 9 7
      src/main/frontend/extensions/tldraw.cljs
  70. 7 3
      src/main/frontend/extensions/video/youtube.cljs
  71. 1 1
      src/main/frontend/handler/db_based/editor.cljs
  72. 4 10
      src/main/frontend/handler/editor/lifecycle.cljs
  73. 217 203
      src/main/frontend/handler/events.cljs
  74. 359 359
      src/main/frontend/modules/shortcut/config.cljs
  75. 1 0
      src/main/frontend/schema/handler/common_config.cljc
  76. 11 14
      src/main/frontend/state.cljs
  77. 11 10
      src/main/frontend/tippy-tooltip.css
  78. 29 16
      src/main/frontend/ui.cljs
  79. 32 34
      src/main/frontend/ui.css
  80. 1 1
      src/main/frontend/version.cljs
  81. 11 2
      src/main/frontend/worker/rtc/core.cljs
  82. 5 5
      src/resources/dicts/en.edn
  83. 0 2
      src/resources/dicts/es.edn
  84. 479 0
      src/resources/dicts/fa.edn
  85. 0 2
      src/resources/dicts/fr.edn
  86. 0 2
      src/resources/dicts/it.edn
  87. 0 2
      src/resources/dicts/ja.edn
  88. 0 2
      src/resources/dicts/nb-no.edn
  89. 0 2
      src/resources/dicts/pt-br.edn
  90. 0 2
      src/resources/dicts/sk.edn
  91. 1 2
      src/resources/dicts/tr.edn
  92. 0 1
      src/resources/templates/config.edn
  93. 14 0
      src/resources/tutorials/dummy-notes-fa.md
  94. 25 0
      src/resources/tutorials/tutorial-fa.md
  95. 1 0
      tailwind.all.css
  96. 49 98
      tailwind.config.js

+ 2 - 2
android/app/build.gradle

@@ -12,8 +12,8 @@ android {
         applicationId "com.logseq.app"
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
-        versionCode 79
-        versionName "0.10.5"
+        versionCode 80
+        versionName "0.10.6"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         aaptOptions {
              // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.

+ 8 - 0
deps/common/resources/templates/config.edn

@@ -290,6 +290,14 @@
  ;;  :excluded-pages? false  ; Default value: false
  ;;  :journal?        false} ; Default value: false
 
+ ;; Graph view configuration.
+ ;; Example usage:
+ ;; :graph/forcesettings
+ ;; {:link-dist       180    ; Default value: 180
+ ;;  :charge-strength -600   ; Default value: -600
+ ;;  :charge-range    600}   ; Default value: 600
+
+
  ;; Favorites to list on the left sidebar
  ;; This is _only_ for file graphs.
  :favorites []

+ 6 - 0
deps/db/src/logseq/db/frontend/property.cljs

@@ -65,6 +65,12 @@
               (mapv #(hash-map :value % :uuid (random-uuid))
                     ["Urgent" "High" "Medium" "Low"])
               :visible true}
+   :scheduled {:original-name "Scheduled"
+               :schema {:type :date}
+               :visible true}
+   :deadline {:original-name "Deadline"
+              :schema {:type :date}
+              :visible true}
 
    ;; TODO: Add more props :Assignee, :Estimate, :Cycle, :Project
 

+ 0 - 1
deps/outliner/src/logseq/outliner/core.cljs

@@ -17,7 +17,6 @@
             [logseq.db.frontend.property :as db-property]
             [logseq.db.sqlite.util :as sqlite-util]
             [cljs.pprint :as pprint]
-            [logseq.db.frontend.content :as db-content]
             [logseq.common.marker :as common-marker]))
 
 (def ^:private block-map

+ 0 - 2
deps/shui/src/logseq/shui/core.cljs

@@ -12,11 +12,9 @@
 
 ;; shortcut
 (def shortcut shui.shortcut.v1/root)
-(def shortcut-v1 shui.shortcut.v1/root)
 
 ;; icon
 (def icon shui.icon.v2/root)
-(def icon-v2 shui.icon.v2/root)
 
 ;; list-item
 (def list-item shui.list-item.v1/root)

+ 5 - 5
deps/shui/src/logseq/shui/list_item/v1.cljs

@@ -90,11 +90,11 @@
      [highlighted on-highlight-dep])
     [:div (merge
            {:style {:opacity (if highlighted 1 0.8)}
-            :class (cond-> "flex flex-col grayscale"
-                     highlighted (str " !grayscale-0 !opacity-100 bg-gray-03-alpha dark:bg-gray-04-alpha")
-                     hoverable (str " transition-all duration-50 ease-in !opacity-75 hover:!opacity-100 hover:grayscale-0 hover:cursor-pointer hover:bg-gradient-to-r hover:from-gray-03-alpha hover:to-gray-01-alpha from-0% to-100%")
+            :class (cond-> "flex flex-col transition-opacity"
+                     highlighted (str " !opacity-100 bg-gray-03-alpha dark:bg-gray-04-alpha")
+                     hoverable (str " transition-all duration-50 ease-in !opacity-75 hover:!opacity-100 hover:cursor-pointer hover:bg-gradient-to-r hover:from-gray-03-alpha hover:to-gray-01-alpha from-0% to-100%")
                      (and hoverable rounded) (str " !rounded-lg")
-                     (not compact) (str  " py-4 px-6 gap-1")
+                     (not compact) (str " py-4 px-6 gap-1")
                      compact (str " py-1.5 px-3 gap-0.5")
                      (not highlighted) (str " "))
             :ref ref
@@ -143,5 +143,5 @@
            [:span.text-gray-11 (to-string value)])])
       (when shortcut
         [:div {:class "flex gap-1"
-               :style {:opacity (if (or highlighted hover?) 1 0.5)}}
+               :style {:opacity (if (or highlighted hover?) 1 0.9)}}
          (shortcut/root shortcut)])]]))

+ 19 - 14
deps/shui/src/logseq/shui/shortcut/v1.cljs

@@ -62,31 +62,36 @@
                            %)))))))
 
 (rum/defc part
-  [ks size]
-  (let [tiles (map print-shortcut-key ks)]
-    (ui/button {:variant     :default
-                :class       "bg-gray-03 text-gray-12 px-1.5 py-0 leading-4 h-5 hover:bg-gray-04 active:bg-gray-03 hover:text-gray-11"
-                :interactive false
-                :size        size}
+  [ks size {:keys [interactive?]}]
+  (let [tiles (map print-shortcut-key ks)
+        interactive? (true? interactive?)]
+    (ui/button {:variant (if interactive? :default :text)
+                :class   (str "bg-gray-03 text-gray-10 px-1.5 py-0 leading-4 h-5 rounded font-normal "
+                           (if interactive?
+                             "hover:bg-gray-04 active:bg-gray-03 hover:text-gray-12"
+                             "bg-transparent cursor-default active:bg-gray-03 hover:text-gray-11 opacity-80"))
+                :size    size}
       (for [[index tile] (map-indexed vector tiles)]
         [:<>
          (when (< 0 index)
-           [:div.ui__button__tile-separator])
-         [:div.ui__button__tile tile]]))))
+           [:span.ui__button__tile-separator])
+         [:span.ui__button__tile tile]]))))
 
 (rum/defc root
-  [shortcut & {:keys [size theme]
-                       :or   {size  :xs
-                              theme :gray}}]
+  [shortcut & {:keys [size theme interactive?]
+               :or   {size  :xs
+                      interactive? true
+                      theme :gray}}]
   (when (seq shortcut)
     (let [shortcuts (if (coll? shortcut)
                       [shortcut]
-                      (parse-shortcuts shortcut))]
+                      (parse-shortcuts shortcut))
+          opts {:interactive? interactive?}]
       (for [[index binding] (map-indexed vector shortcuts)]
         [:<>
          (when (< 0 index)
            [:div.text-gray-11.text-sm "|"])
          (if (coll? (first binding))   ; + included
            (for [ks binding]
-             (part ks size))
-           (part binding size))]))))
+             (part ks size opts))
+           (part binding size opts))]))))

+ 107 - 93
packages/tldraw/apps/tldraw-logseq/src/components/ContextMenu/ContextMenu.tsx

@@ -1,13 +1,17 @@
 import { useApp } from '@tldraw/react'
 import { LogseqContext } from '../../lib/logseq-context'
-import { MOD_KEY, AlignType, DistributeType, isDev, EXPORT_PADDING } from '@tldraw/core'
+import {
+  MOD_KEY,
+  AlignType,
+  DistributeType,
+  isDev,
+  EXPORT_PADDING
+} from '@tldraw/core'
 import { observer } from 'mobx-react-lite'
 import { TablerIcon } from '../icons'
 import { Button } from '../Button'
 import { KeyboardShortcut } from '../KeyboardShortcut'
 import * as React from 'react'
-
-import * as ReactContextMenu from '@radix-ui/react-context-menu'
 import { toJS } from 'mobx'
 
 // @ts-ignore
@@ -37,8 +41,8 @@ export const ContextMenu = observer(function ContextMenu({
   }, [])
 
   return (
-    <ReactContextMenu.Root
-      onOpenChange={open => {
+    <LSUI.ContextMenu
+      onOpenChange={(open: boolean) => {
         if (open && !app.isIn('select.contextMenu')) {
           app.transition('select').selectedTool.transition('contextMenu')
         } else if (!open && app.isIn('select.contextMenu')) {
@@ -46,12 +50,12 @@ export const ContextMenu = observer(function ContextMenu({
         }
       }}
     >
-      <ReactContextMenu.Trigger
+      <LSUI.ContextMenuTrigger
         disabled={app.editingShape && Object.keys(app.editingShape).length !== 0}
       >
         {children}
-      </ReactContextMenu.Trigger>
-      <ReactContextMenu.Content
+      </LSUI.ContextMenuTrigger>
+      <LSUI.ContextMenuContent
         className="tl-menu tl-context-menu"
         ref={rContent}
         onEscapeKeyDown={() => app.transition('select')}
@@ -64,34 +68,35 @@ export const ContextMenu = observer(function ContextMenu({
             !app.readOnly &&
             app.selectedShapesArray?.some(s => !s.props.isLocked) && (
               <>
-                <ReactContextMenu.Item>
+                <LSUI.ContextMenuItem className={'tl-menu-button-row-wrap'}>
                   <div className="tl-menu-button-row pb-0">
                     <Button
                       tooltip={t('whiteboard/align-left')}
                       onClick={() => runAndTransition(() => app.align(AlignType.Left))}
                     >
-                      <TablerIcon name="layout-align-left" />
+                      <TablerIcon name="layout-align-left"/>
                     </Button>
                     <Button
                       tooltip={t('whiteboard/align-center-horizontally')}
                       onClick={() => runAndTransition(() => app.align(AlignType.CenterHorizontal))}
                     >
-                      <TablerIcon name="layout-align-center" />
+                      <TablerIcon name="layout-align-center"/>
                     </Button>
                     <Button
                       tooltip={t('whiteboard/align-right')}
                       onClick={() => runAndTransition(() => app.align(AlignType.Right))}
                     >
-                      <TablerIcon name="layout-align-right" />
+                      <TablerIcon name="layout-align-right"/>
                     </Button>
-                    <LSUI.Separator orientation="vertical" />
+                    <LSUI.Separator className="tl-toolbar-separator"
+                                    orientation="vertical"/>
                     <Button
                       tooltip={t('whiteboard/distribute-horizontally')}
                       onClick={() =>
                         runAndTransition(() => app.distribute(DistributeType.Horizontal))
                       }
                     >
-                      <TablerIcon name="layout-distribute-vertical" />
+                      <TablerIcon name="layout-distribute-vertical"/>
                     </Button>
                   </div>
                   <div className="tl-menu-button-row pt-0">
@@ -99,127 +104,130 @@ export const ContextMenu = observer(function ContextMenu({
                       tooltip={t('whiteboard/align-top')}
                       onClick={() => runAndTransition(() => app.align(AlignType.Top))}
                     >
-                      <TablerIcon name="layout-align-top" />
+                      <TablerIcon name="layout-align-top"/>
                     </Button>
                     <Button
                       tooltip={t('whiteboard/align-center-vertically')}
                       onClick={() => runAndTransition(() => app.align(AlignType.CenterVertical))}
                     >
-                      <TablerIcon name="layout-align-middle" />
+                      <TablerIcon name="layout-align-middle"/>
                     </Button>
                     <Button
                       tooltip={t('whiteboard/align-bottom')}
                       onClick={() => runAndTransition(() => app.align(AlignType.Bottom))}
                     >
-                      <TablerIcon name="layout-align-bottom" />
+                      <TablerIcon name="layout-align-bottom"/>
                     </Button>
-                    <LSUI.Separator orientation="vertical" />
+                    <LSUI.Separator className="tl-toolbar-separator"
+                                    orientation="vertical"/>
                     <Button
                       tooltip={t('whiteboard/distribute-vertically')}
                       onClick={() =>
                         runAndTransition(() => app.distribute(DistributeType.Vertical))
                       }
                     >
-                      <TablerIcon name="layout-distribute-horizontal" />
+                      <TablerIcon name="layout-distribute-horizontal"/>
                     </Button>
                   </div>
-                </ReactContextMenu.Item>
-                <ReactContextMenu.Separator className="menu-separator" />
-                <ReactContextMenu.Item
+                </LSUI.ContextMenuItem>
+                <LSUI.ContextMenuSeparator className="menu-separator"/>
+                <LSUI.ContextMenuItem
                   className="tl-menu-item"
                   onClick={() => runAndTransition(app.packIntoRectangle)}
                 >
-                  <TablerIcon className="tl-menu-icon" name="layout-grid" />
+                  <TablerIcon className="tl-menu-icon" name="layout-grid"/>
                   {t('whiteboard/pack-into-rectangle')}
-                </ReactContextMenu.Item>
-                <ReactContextMenu.Separator className="menu-separator" />
+                </LSUI.ContextMenuItem>
+                <LSUI.ContextMenuSeparator className="menu-separator"/>
               </>
             )}
           {app.selectedShapes?.size > 0 && (
             <>
-              <ReactContextMenu.Item
+              <LSUI.ContextMenuItem
                 className="tl-menu-item"
                 onClick={() => runAndTransition(app.api.zoomToSelection)}
               >
+                <TablerIcon className="tl-menu-icon" name="circle-dotted"/>
                 {t('whiteboard/zoom-to-fit')}
-                <KeyboardShortcut action="whiteboard/zoom-to-fit" />
-              </ReactContextMenu.Item>
-              <ReactContextMenu.Separator className="menu-separator" />
+                <KeyboardShortcut action="whiteboard/zoom-to-fit"/>
+              </LSUI.ContextMenuItem>
+              <LSUI.ContextMenuSeparator className="menu-separator"/>
             </>
           )}
           {(app.selectedShapesArray.some(s => s.type === 'group' || app.getParentGroup(s)) ||
-            app.selectedShapesArray.length > 1) &&
+              app.selectedShapesArray.length > 1) &&
             app.selectedShapesArray?.some(s => !s.props.isLocked) &&
             !app.readOnly && (
               <>
                 {app.selectedShapesArray.some(s => s.type === 'group' || app.getParentGroup(s)) && (
-                  <ReactContextMenu.Item
+                  <LSUI.ContextMenuItem
                     className="tl-menu-item"
                     onClick={() => runAndTransition(app.api.unGroup)}
                   >
-                    <TablerIcon className="tl-menu-icon" name="ungroup" />
+                    <TablerIcon className="tl-menu-icon" name="ungroup"/>
                     {t('whiteboard/ungroup')}
-                    <KeyboardShortcut action="whiteboard/ungroup" />
-                  </ReactContextMenu.Item>
+                    <KeyboardShortcut action="whiteboard/ungroup"/>
+                  </LSUI.ContextMenuItem>
                 )}
                 {app.selectedShapesArray.length > 1 &&
                   app.selectedShapesArray?.some(s => !s.props.isLocked) && (
-                    <ReactContextMenu.Item
+                    <LSUI.ContextMenuItem
                       className="tl-menu-item"
                       onClick={() => runAndTransition(app.api.doGroup)}
                     >
-                      <TablerIcon className="tl-menu-icon" name="group" />
+                      <TablerIcon className="tl-menu-icon" name="group"/>
                       {t('whiteboard/group')}
-                      <KeyboardShortcut action="whiteboard/group" />
-                    </ReactContextMenu.Item>
+                      <KeyboardShortcut action="whiteboard/group"/>
+                    </LSUI.ContextMenuItem>
                   )}
-                <ReactContextMenu.Separator className="menu-separator" />
+                <LSUI.ContextMenuSeparator className="menu-separator"/>
               </>
             )}
           {app.selectedShapes?.size > 0 && app.selectedShapesArray?.some(s => !s.props.isLocked) && (
             <>
               {!app.readOnly && (
-                <ReactContextMenu.Item
+                <LSUI.ContextMenuItem
                   className="tl-menu-item"
                   onClick={() => runAndTransition(app.cut)}
                 >
-                  <TablerIcon className="tl-menu-icon" name="cut" />
+                  <TablerIcon className="tl-menu-icon" name="cut"/>
                   {t('whiteboard/cut')}
-                </ReactContextMenu.Item>
+                </LSUI.ContextMenuItem>
               )}
-              <ReactContextMenu.Item
+              <LSUI.ContextMenuItem
                 className="tl-menu-item"
                 onClick={() => runAndTransition(app.copy)}
               >
-                <TablerIcon className="tl-menu-icon" name="copy" />
+                <TablerIcon className="tl-menu-icon" name="copy"/>
                 {t('whiteboard/copy')}
-                <KeyboardShortcut action="editor/copy" />
-              </ReactContextMenu.Item>
+                <KeyboardShortcut action="editor/copy"/>
+              </LSUI.ContextMenuItem>
             </>
           )}
           {!app.readOnly && (
-            <ReactContextMenu.Item
+            <LSUI.ContextMenuItem
               className="tl-menu-item"
               onClick={() => runAndTransition(app.paste)}
             >
-              <TablerIcon className="tl-menu-icon" name="clipboard" />
+              <TablerIcon className="tl-menu-icon" name="clipboard"/>
               {t('whiteboard/paste')}
-              <KeyboardShortcut sequence={MOD_KEY+"+v"} />
-            </ReactContextMenu.Item>
+              <KeyboardShortcut shortcut={`${MOD_KEY}+v`}/>
+            </LSUI.ContextMenuItem>
           )}
           {app.selectedShapes?.size === 1 && !app.readOnly && (
-            <ReactContextMenu.Item
+            <LSUI.ContextMenuItem
               className="tl-menu-item"
               onClick={() => runAndTransition(() => app.paste(undefined, true))}
             >
+              <TablerIcon className="tl-menu-icon" name="circle-dotted"/>
               {t('whiteboard/paste-as-link')}
-              <KeyboardShortcut sequence={MOD_KEY+"+⇧+v"} />
-            </ReactContextMenu.Item>
+              <KeyboardShortcut shortcut={`${MOD_KEY}+⇧+v`}/>
+            </LSUI.ContextMenuItem>
           )}
           {app.selectedShapes?.size > 0 && (
             <>
-              <ReactContextMenu.Separator className="menu-separator" />
-              <ReactContextMenu.Item
+              <LSUI.ContextMenuSeparator className="menu-separator"/>
+              <LSUI.ContextMenuItem
                 className="tl-menu-item"
                 onClick={() =>
                   runAndTransition(() =>
@@ -233,107 +241,113 @@ export const ContextMenu = observer(function ContextMenu({
                   )
                 }
               >
-                <TablerIcon className="tl-menu-icon" name="file-export" />
+                <TablerIcon className="tl-menu-icon" name="file-export"/>
                 {t('whiteboard/export')}
                 <div className="tl-menu-right-slot">
                   <span className="keyboard-shortcut"></span>
                 </div>
-              </ReactContextMenu.Item>
+              </LSUI.ContextMenuItem>
             </>
           )}
-          <ReactContextMenu.Separator className="menu-separator" />
-          <ReactContextMenu.Item
+          <LSUI.ContextMenuSeparator className="menu-separator"/>
+          <LSUI.ContextMenuItem
             className="tl-menu-item"
             onClick={() => runAndTransition(app.api.selectAll)}
           >
+            <TablerIcon className="tl-menu-icon" name="circle-dotted"/>
             {t('whiteboard/select-all')}
-            <KeyboardShortcut action="editor/select-parent" />
-          </ReactContextMenu.Item>
+            <KeyboardShortcut action="editor/select-parent"/>
+          </LSUI.ContextMenuItem>
           {app.selectedShapes?.size > 1 && (
-            <ReactContextMenu.Item
+            <LSUI.ContextMenuItem
               className="tl-menu-item"
               onClick={() => runAndTransition(app.api.deselectAll)}
             >
+              <TablerIcon className="tl-menu-icon" name="circle-dotted"/>
               {t('whiteboard/deselect-all')}
-            </ReactContextMenu.Item>
+            </LSUI.ContextMenuItem>
           )}
           {!app.readOnly &&
             app.selectedShapes?.size > 0 &&
             app.selectedShapesArray?.some(s => !s.props.isLocked) && (
-              <ReactContextMenu.Item
+              <LSUI.ContextMenuItem
                 className="tl-menu-item"
                 onClick={() => runAndTransition(() => app.setLocked(true))}
               >
-                <TablerIcon className="tl-menu-icon" name="lock" />
+                <TablerIcon className="tl-menu-icon" name="lock"/>
                 {t('whiteboard/lock')}
-                <KeyboardShortcut action="whiteboard/lock" />
-              </ReactContextMenu.Item>
+                <KeyboardShortcut action="whiteboard/lock"/>
+              </LSUI.ContextMenuItem>
             )}
           {!app.readOnly &&
             app.selectedShapes?.size > 0 &&
             app.selectedShapesArray?.some(s => s.props.isLocked) && (
-              <ReactContextMenu.Item
+              <LSUI.ContextMenuItem
                 className="tl-menu-item"
                 onClick={() => runAndTransition(() => app.setLocked(false))}
               >
-                <TablerIcon className="tl-menu-icon" name="lock-open" />
+                <TablerIcon className="tl-menu-icon" name="lock-open"/>
                 {t('whiteboard/unlock')}
-                <KeyboardShortcut action="whiteboard/unlock" />
-              </ReactContextMenu.Item>
+                <KeyboardShortcut action="whiteboard/unlock"/>
+              </LSUI.ContextMenuItem>
             )}
           {app.selectedShapes?.size > 0 &&
             !app.readOnly &&
             app.selectedShapesArray?.some(s => !s.props.isLocked) && (
               <>
-                <ReactContextMenu.Item
+                <LSUI.ContextMenuItem
                   className="tl-menu-item"
                   onClick={() => runAndTransition(app.api.deleteShapes)}
                 >
-                  <TablerIcon className="tl-menu-icon" name="backspace" />
+                  <TablerIcon className="tl-menu-icon" name="backspace"/>
                   {t('whiteboard/delete')}
-                  <KeyboardShortcut action="editor/delete" />
-                </ReactContextMenu.Item>
+                  <KeyboardShortcut action="editor/delete"/>
+                </LSUI.ContextMenuItem>
                 {app.selectedShapes?.size > 1 && !app.readOnly && (
                   <>
-                    <ReactContextMenu.Separator className="menu-separator" />
-                    <ReactContextMenu.Item
+                    <LSUI.ContextMenuSeparator className="menu-separator"/>
+                    <LSUI.ContextMenuItem
                       className="tl-menu-item"
                       onClick={() => runAndTransition(app.flipHorizontal)}
                     >
-                      <TablerIcon className="tl-menu-icon" name="flip-horizontal" />
+                      <TablerIcon className="tl-menu-icon"
+                                  name="flip-horizontal"/>
                       {t('whiteboard/flip-horizontally')}
-                    </ReactContextMenu.Item>
-                    <ReactContextMenu.Item
+                    </LSUI.ContextMenuItem>
+                    <LSUI.ContextMenuItem
                       className="tl-menu-item"
                       onClick={() => runAndTransition(app.flipVertical)}
                     >
-                      <TablerIcon className="tl-menu-icon" name="flip-vertical" />
+                      <TablerIcon className="tl-menu-icon"
+                                  name="flip-vertical"/>
                       {t('whiteboard/flip-vertically')}
-                    </ReactContextMenu.Item>
+                    </LSUI.ContextMenuItem>
                   </>
                 )}
                 {!app.readOnly && (
                   <>
-                    <ReactContextMenu.Separator className="menu-separator" />
-                    <ReactContextMenu.Item
+                    <LSUI.ContextMenuSeparator className="menu-separator"/>
+                    <LSUI.ContextMenuItem
                       className="tl-menu-item"
                       onClick={() => runAndTransition(app.bringToFront)}
                     >
+                      <TablerIcon className="tl-menu-icon" name="circle-dotted"/>
                       {t('whiteboard/move-to-front')}
-                      <KeyboardShortcut action="whiteboard/bring-to-front" />
-                    </ReactContextMenu.Item>
-                    <ReactContextMenu.Item
+                      <KeyboardShortcut action="whiteboard/bring-to-front"/>
+                    </LSUI.ContextMenuItem>
+                    <LSUI.ContextMenuItem
                       className="tl-menu-item"
                       onClick={() => runAndTransition(app.sendToBack)}
                     >
+                      <TablerIcon className="tl-menu-icon" name="circle-dotted"/>
                       {t('whiteboard/move-to-back')}
-                      <KeyboardShortcut action="whiteboard/send-to-back" />
-                    </ReactContextMenu.Item>
+                      <KeyboardShortcut action="whiteboard/send-to-back"/>
+                    </LSUI.ContextMenuItem>
                   </>
                 )}
 
                 {developerMode && (
-                  <ReactContextMenu.Item
+                  <LSUI.ContextMenuItem
                     className="tl-menu-item"
                     onClick={() => {
                       if (app.selectedShapesArray.length === 1) {
@@ -344,12 +358,12 @@ export const ContextMenu = observer(function ContextMenu({
                     }}
                   >
                     {t('whiteboard/dev-print-shape-props')}
-                  </ReactContextMenu.Item>
+                  </LSUI.ContextMenuItem>
                 )}
               </>
             )}
         </div>
-      </ReactContextMenu.Content>
-    </ReactContextMenu.Root>
+      </LSUI.ContextMenuContent>
+    </LSUI.ContextMenu>
   )
 })

+ 5 - 5
packages/tldraw/apps/tldraw-logseq/src/components/KeyboardShortcut/KeyboardShortcut.tsx

@@ -2,15 +2,15 @@ import { LogseqContext } from '../../lib/logseq-context'
 import * as React from 'react'
 
 export const KeyboardShortcut = ({
-  action,
-  sequence
-}: { action?: string, sequence?: string | string[] } & React.HTMLAttributes<HTMLElement>) => {
+  action, shortcut, opts,
+  ...props
+}: Partial<{ action: string, shortcut: string, opts: any }> & React.HTMLAttributes<HTMLElement>) => {
   const { renderers } = React.useContext(LogseqContext)
   const Shortcut = renderers?.KeyboardShortcut
 
   return (
-    <div className="tl-menu-right-slot">
-      <Shortcut action={action} sequence={sequence} />
+    <div className="tl-menu-right-slot" {...props}>
+      <Shortcut action={action} shortcut={shortcut} opts={opts} />
     </div>
   )
 }

+ 3 - 2
packages/tldraw/apps/tldraw-logseq/src/lib/logseq-context.ts

@@ -38,8 +38,9 @@ export interface LogseqContextValue {
       }
     }>
     KeyboardShortcut: React.FC<{
-      action?: string
-      sequence?: string | string[]
+      action?: string,
+      shortcut?: string,
+      opts?: any
     }>
   }
   handlers: {

+ 176 - 68
packages/tldraw/apps/tldraw-logseq/src/styles.css

@@ -6,19 +6,19 @@
   --ls-wb-stroke-color-blue: var(--color-blue-500, blue);
   --ls-wb-stroke-color-purple: var(--color-purple-500, purple);
   --ls-wb-stroke-color-pink: var(--color-pink-500, pink);
-  --ls-wb-stroke-color-default: var(--ls-secondary-border-color);
-  --ls-wb-text-color-default: var(--ls-primary-text-color);
-  --ls-wb-background-color-default: var(--ls-tertiary-background-color);
+  --ls-wb-stroke-color-default: var(--ls-secondary-border-color, hsl(var(--border, var(--rx-gray-05-hsl))));
+  --ls-wb-text-color-default: var(--ls-primary-text-color, hsl(var(--primary)));
+  --ls-wb-background-color-default: var(--ls-tertiary-background-color, var(--rx-gray-03));
 }
 
 .logseq-tldraw {
-  --color-panel: var(--ls-tertiary-background-color);
+  --color-panel: var(--ls-tertiary-background-color, hsl(var(--secondary)));
   --color-panel-inverted: var(--ls-secondary-text-color);
   --color-text: var(--ls-primary-text-color);
   --color-text-inverted: var(--ls-tertiary-background-color);
-  --color-hover: var(--ls-secondary-background-color);
-  --color-selectedStroke: var(--ls-button-background);
-  --color-selectedFill: hsl(var(--ls-button-background-hsl) / 0.9);
+  --color-hover: var(--ls-secondary-background-color, hsl(var(--secondary)));
+  --color-selectedStroke: var(--ls-button-background, hsl(var(--accent) / 0.9));
+  --color-selectedFill: hsl(var(--ls-button-background-hsl, var(--accent)) / 0.1);
   --color-selectedContrast: #fff;
   --shadow-small: 0 1px 2px 0 rgb(0 0 0 / 0.05);
   --shadow-medium: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
@@ -98,60 +98,50 @@ html[data-theme='light'] {
   background-color: transparent !important;
 }
 
-.tl-menu-item {
-  @apply flex items-center pl-10 pr-4 py-1 text-sm relative !important;
-
-  min-width: 220px;
-  all: unset;
-  line-height: 1;
-  height: 25px;
-  padding: 0 5px;
-  position: relative;
-  user-select: none;
-  color: var(--ls-primary-text-color);
-
-  &:hover,
-  &:focus {
-    cursor: pointer;
-    background-color: var(--ls-primary-background-color) !important;
-  }
-
-  .tl-menu-icon {
-    @apply absolute left-4 text-base opacity-50;
-  }
-
-  &[data-disabled] {
-    @apply opacity-50 pointer-events-none;
-  }
-}
-
 #tl-zoom {
   @apply w-auto !important;
 }
 
+.tl-menu-item {
+  @apply leading-[20px];
+}
+
 #zoomPopup .tl-menu-item {
   @apply pl-4 !important;
 }
 
+.tl-menu-button-row-wrap {
+  @apply flex flex-col;
+}
+
 .tl-menu-button-row {
-  @apply flex justify-between px-4 py-1;
+  @apply flex justify-between py-1 gap-[26px] opacity-80 hover:opacity-100;
+
+  .ti {
+    @apply text-lg;
+  }
 }
 
 .tl-menu {
-  @apply relative py-2 flex bottom-0 flex border-0 rounded shadow-lg;
+  @apply relative flex flex-col opacity-100 select-none;
 
-  opacity: 100%;
-  user-select: none;
-  flex-direction: column;
   z-index: 180;
   min-width: 220px;
   pointer-events: 'all';
-  background: var(--ls-secondary-background-color);
+}
+
+.tl-menu-icon {
+  @apply text-[16px] leading-none opacity-70 mr-1;
+}
+
+.tl-menu-icon.ti-circle-dotted {
+  @apply invisible;
 }
 
 .tl-menu-right-slot {
   margin-left: auto;
   padding-left: 20px;
+  line-height: 1;
 
   .keyboard-shortcut > code {
     padding: 4px !important;
@@ -177,7 +167,7 @@ html[data-theme='light'] {
 
   pointer-events: all;
   position: relative;
-  background-color: or(--logseq-whiteboard-toolbar-background, --lx-gray-03, --ls-secondary-background-color);
+  background-color: var(--lx-gray-03, var(--ls-secondary-background-color, var(--rx-gray-03)));
   border-radius: 8px;
   white-space: nowrap;
   gap: 8px;
@@ -271,32 +261,11 @@ html[data-theme='light'] {
 }
 
 .tl-button {
-  @apply relative flex items-center justify-center rounded border-0 gap-1;
-
-  height: 32px;
-  width: 32px;
-  font-family: var(--ls-font-family);
-  background: none;
-  cursor: pointer;
-  color: var(--ls-primary-text-color);
-
-  &:hover {
-    background-color: or(--ls-whiteboard-button-background-hover, --lx-gray-06, --ls-primary-background-color);
-  }
+  @apply relative flex items-center justify-center rounded border-0 gap-1 bg-none cursor-pointer;
+  @apply w-[32px] h-[32px] hover:bg-gray-06;
 
   &[data-selected='true'] {
-    background-color: or(--ls-whiteboard-button-background-selected, --lx-accent-09, --color-selectedFill);
-    color: or(--ls-whiteboard-button-text-selected, --lx-gray-12, --color-selectedContrast);
-  }
-}
-
-.tl-select-trigger {
-  @apply h-8 font-medium bg-transparent px-3;
-
-  border: 1px solid var(--ls-secondary-border-color);
-
-  &.compact {
-    @apply px-0 justify-center text-xs;
+    @apply bg-accent text-accent-foreground;
   }
 }
 
@@ -319,6 +288,59 @@ html[data-theme='light'] {
 
 .tl-tools-floating-panel {
   flex-flow: column;
+
+  .tl-select-input-trigger {
+    @apply p-0 text-xs;
+
+    height: 32px;
+    min-width: 32px;
+  }
+
+  .tl-select-input-trigger-value {
+    @apply font-semibold justify-center;
+  }
+}
+
+button.tl-select-input-trigger {
+  @apply flex items-center px-3;
+  box-shadow: 0 0 0 1px var(--ls-secondary-border-color);
+  background-color: var(--ls-secondary-background-color);
+  border-radius: 0.25rem;
+  font-size: 16px;
+  height: 100%;
+  color: var(--ls-secondary-text-color);
+}
+
+.tl-select-input-trigger-value {
+  @apply flex items-center justify-start flex-1;
+}
+
+.tl-select-input-viewport {
+  border-radius: 8px;
+  background-color: var(--ls-secondary-background-color);
+}
+
+.tl-select-input-select-item {
+  cursor: default;
+  padding: 4px 12px;
+  outline-offset: -1px;
+
+  color: var(--ls-secondary-text-color);
+
+  &[data-state='unchecked']:hover {
+    background-color: var(--ls-tertiary-background-color);
+    color: var(--ls-primary-text-color);
+  }
+
+  &[data-state='checked'] {
+    background-color: or(--ls-whiteboard-select-background-selected, --lx-accent-09, --color-indigo-500);
+    color: #fff;
+  }
+}
+
+.tl-select-input-content {
+  z-index: 100;
+  font-family: var(--ls-font-family);
 }
 
 .tl-geometry-tools-pane-anchor {
@@ -532,7 +554,7 @@ html[data-theme='light'] {
   @apply flex items-center rounded-lg text-base max-w-full;
 
   min-height: 40px;
-  background-color: var(--ls-secondary-background-color);
+  background-color: var(--ls-secondary-background-color, hsl(var(--background)));
   padding: 6px 16px;
   box-shadow: var(--shadow-small);
 }
@@ -580,6 +602,7 @@ html[data-theme='light'] {
 }
 
 .tl-quick-search .tl-text-input {
+  background-color: transparent;
   border: none;
 }
 
@@ -598,7 +621,7 @@ html[data-theme='light'] {
   @apply absolute left-0 w-full flex z-10;
 
   top: calc(100% + 12px);
-  background-color: var(--ls-primary-background-color);
+  background-color: var(--ls-primary-background-color, hsl(var(--background)));
   max-height: 300px;
   min-width: 460px;
   box-shadow: var(--shadow-large);
@@ -783,6 +806,61 @@ html[data-theme='dark'] {
   }
 }
 
+.tl-toggle-group-input {
+  @apply rounded overflow-hidden;
+  box-shadow: 0 0 0 1px var(--ls-secondary-border-color);
+}
+
+.tl-toggle-group-input-button {
+  @apply inline-flex items-center justify-center;
+  border-right: 1px solid var(--ls-secondary-border-color);
+  height: 32px;
+  width: 32px;
+  color: var(--ls-secondary-text-color);
+  opacity: 0.3;
+
+  &:last-of-type {
+    border-right: none;
+  }
+
+  &:hover {
+    background-color: var(--ls-tertiary-background-color);
+  }
+
+  &[data-state='on'] {
+    background-color: var(--ls-tertiary-background-color);
+    color: var(--ls-primary-text-color);
+    opacity: 1;
+  }
+}
+
+.tl-toggle-input {
+  @apply inline-flex items-center justify-center;
+  height: 32px;
+  min-width: 32px;
+  color: var(--ls-secondary-text-color);
+
+  &:hover {
+    background-color: var(--ls-tertiary-background-color);
+  }
+
+  &[data-state='on'] {
+    background-color: var(--ls-tertiary-background-color);
+    color: var(--ls-primary-text-color);
+  }
+}
+
+.tl-toolbar-separator {
+  background-color: var(--ls-border-color, var(--rx-gray-06));
+  width: 1px;
+  opacity: 0.9;
+
+  &[data-orientation='horizontal'] {
+    height: 1px;
+    width: auto;
+  }
+}
+
 .tl-youtube-link,
 .tl-twitter-link,
 .tl-iframe-src {
@@ -812,10 +890,22 @@ html[data-theme='dark'] {
   stroke-width: min(100px, calc(12px * var(--tl-scale)));
 }
 
+.tl-popover-content {
+  @apply rounded-lg;
+
+  background-color: var(--ls-secondary-background-color);
+  box-shadow: var(--shadow-large);
+  z-index: 100000;
+}
+
 .tl-geometry-toolbar {
   box-shadow: none;
 }
 
+.tl-popover-arrow {
+  fill: var(--ls-secondary-background-color);
+}
+
 .tl-color-palette {
   @apply grid grid-cols-4;
 }
@@ -1045,7 +1135,25 @@ button.tl-shape-links-panel-item-remove-button {
   @apply block;
 }
 
-.popper-arrow {
+.tl-tooltip-content {
+  border-radius: 4px;
+  padding: 10px 15px;
+  font-size: 15px;
+  line-height: 1;
+  color: or(--ls-whiteboard-tooltip-text, --lx-gray-12, --ls-secondary-text-color);
+  background-color: or(--ls-whiteboard-tooltip-background, --lx-gray-05, --ls-secondary-background-color);
+  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
+  user-select: none;
+  animation-duration: 700ms;
+  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
+  will-change: transform, opacity;
+
+  &[data-state='delayed-open'] {
+    animation-name: fadeIn;
+  }
+}
+
+.tl-tooltip-arrow {
   fill: var(--ls-secondary-background-color);
 }
 

+ 8 - 8
packages/tldraw/packages/react/src/hooks/useStylesheet.ts

@@ -66,15 +66,15 @@ const css = (strings: TemplateStringsArray, ...args: unknown[]) =>
   )
 
 const defaultTheme: TLTheme = {
-  accent: 'rgb(255, 0, 0)',
+  accent: 'var(--lx-accent-09, hsl(var(--primary)))',
   brushFill: 'var(--ls-scrollbar-background-color, rgba(0, 0, 0, .05))',
   brushStroke: 'var(--ls-scrollbar-thumb-hover-color, rgba(0, 0, 0, .05))',
-  selectStroke: 'var(--color-selectedFill)',
-  selectFill: 'rgba(65, 132, 244, 0.05)',
-  binding: 'rgba(65, 132, 244, 0.5)',
-  background: 'var(--ls-primary-background-color)',
-  foreground: 'var(--ls-primary-text-color)',
-  grid: 'var(--ls-quaternary-background-color)',
+  selectStroke: 'var(--color-selectedStroke)',
+  selectFill: 'var(--color-selectedFill)',
+  binding: 'var(--color-binding, rgba(65, 132, 244, 0.5))',
+  background: 'var(--ls-primary-background-color, hsl(var(--background)))',
+  foreground: 'var(--ls-primary-text-color, hsl(var(--foreground)))',
+  grid: 'var(--ls-quaternary-background-color, hsl(var(--secondary)))',
 }
 
 const tlcss = css`
@@ -234,7 +234,7 @@ const tlcss = css`
 
   .tl-clone-handle:hover {
     fill: var(--tl-selectStroke);
-    cursor: pointer; 
+    cursor: pointer;
   }
 
   .tl-clone-handle:hover line {

+ 26 - 7
packages/ui/@/components/ui/context-menu.tsx

@@ -27,7 +27,9 @@ const ContextMenuSubTrigger = React.forwardRef<
     ref={ref}
     className={cn(
       'ui__context-menu-sub-trigger',
-      'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
+      'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm ' +
+      'outline-none focus:bg-accent focus:text-accent-foreground ' +
+      'data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
       inset && 'pl-8',
       className
     )}
@@ -47,7 +49,10 @@ const ContextMenuSubContent = React.forwardRef<
     ref={ref}
     className={cn(
       'ui__context-menu-sub-content',
-      'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
+      'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in' +
+      ' data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95' +
+      ' data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2' +
+      ' data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
       className
     )}
     {...props}
@@ -64,7 +69,12 @@ const ContextMenuContent = React.forwardRef<
       ref={ref}
       className={cn(
         'ui__context-menu-content',
-        'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
+        'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 ' +
+        'text-popover-foreground shadow-md animate-in fade-in-80 ' +
+        'data-[state=open]:animate-in data-[state=closed]:animate-out ' +
+        'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 ' +
+        'data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 ' +
+        'data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
         className
       )}
       {...props}
@@ -82,7 +92,10 @@ const ContextMenuItem = React.forwardRef<
   <ContextMenuPrimitive.Item
     ref={ref}
     className={cn(
-      'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
+      'relative flex cursor-default select-none items-center rounded-sm px-2 ' +
+      'text-popover-foreground/75 hover:text-popover-foreground/100 py-1.5 text-sm ' +
+      'outline-none focus:bg-accent focus:text-accent-foreground ' +
+      'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
       inset && 'pl-8',
       className
     )}
@@ -98,7 +111,10 @@ const ContextMenuCheckboxItem = React.forwardRef<
   <ContextMenuPrimitive.CheckboxItem
     ref={ref}
     className={cn(
-      'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
+      'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm ' +
+      'text-popover-foreground/75 hover:text-popover-foreground/100 ' +
+      'outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none ' +
+      'data-[disabled]:opacity-50',
       className
     )}
     checked={checked}
@@ -122,7 +138,10 @@ const ContextMenuRadioItem = React.forwardRef<
   <ContextMenuPrimitive.RadioItem
     ref={ref}
     className={cn(
-      'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
+      'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 ' +
+      'text-popover-foreground/75 hover:text-popover-foreground/100 ' +
+      'pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground ' +
+      'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
       className
     )}
     {...props}
@@ -174,7 +193,7 @@ const ContextMenuShortcut = ({
   return (
     <span
       className={cn(
-        'ml-auto text-xs tracking-widest text-muted-foreground',
+        'ml-auto text-xs text-muted-foreground',
         className
       )}
       {...props}

+ 1 - 1
packages/ui/@/components/ui/dropdown-menu.tsx

@@ -178,7 +178,7 @@ const DropdownMenuShortcut = ({
 }: React.HTMLAttributes<HTMLSpanElement>) => {
   return (
     <span
-      className={cn('ml-auto text-xs tracking-widest opacity-60', className)}
+      className={cn('ml-auto text-xs opacity-60', className)}
       {...props}
     />
   )

+ 71 - 30
packages/ui/src/colors.css

@@ -12,6 +12,45 @@ html {
     --lx-accent-10: var(--rx-logseq-10);
     --lx-accent-11: var(--rx-logseq-11);
     --lx-accent-12: var(--rx-logseq-12);
+
+    &[data-theme=light] {
+      --primary: 200 97% 37%;
+      --primary-foreground: 255 92% 100%;
+      --accent: 200 97% 37%;
+      --accent-foreground: 255 92% 100%;
+      --ring: 200 97% 37%;
+
+      --lx-gray-01: var(--rx-gray-01);
+      --lx-gray-02: var(--rx-gray-02);
+      --lx-gray-03: var(--rx-gray-03);
+      --lx-gray-04: var(--rx-gray-04);
+      --lx-gray-05: var(--rx-gray-05);
+      --lx-gray-06: var(--rx-gray-06);
+      --lx-gray-07: var(--rx-gray-07);
+      --lx-gray-08: var(--rx-gray-08);
+      --lx-gray-09: var(--rx-gray-09);
+      --lx-gray-10: var(--rx-gray-10);
+      --lx-gray-11: var(--rx-gray-11);
+      --lx-gray-12: var(--rx-gray-12);
+    }
+
+    &[data-theme=dark] {
+      --background: 192 100% 11%;
+      --foreground: 0 0% 95%;
+      --accent: 192 80% 10%;
+      --accent-foreground: 255 92% 100%;
+      --primary: 200 97% 37%;
+      --primary-foreground: 255 92% 100%;
+      --ring: 200 97% 37%;
+      --secondary: 203 50% 20%;
+      --secondary-foreground: 0 0% 98%;
+      --muted: 192 100% 13%;
+      --border: 192 100% 14%;
+      --card: 192 100% 10%;
+      --card-foreground: 0 0% 95%;
+      --popover: 192 100% 11%;
+      --input: 203 35% 25%;
+    }
   }
 
   &[data-color=tomato] {
@@ -80,8 +119,8 @@ html {
       --ls-link-text-color: var(--rx-tomato-11);
       --ls-link-text-hover-color: var(--rx-tomato-12);
       --ls-block-ref-link-text-color: var(--rx-tomato-09);
-      --ls-secondary-text-color: var(--rx-mauve-12);
-      --ls-primary-text-color: var(--rx-mauve-11);
+      --ls-secondary-text-color: var(--rx-mauve-11);
+      --ls-primary-text-color: var(--rx-mauve-12);
       --ls-border-color: var(--rx-mauve-05);
       --ls-secondary-border-color: var(--rx-tomato-05);
       --ls-page-checkbox-color: var(--rx-mauve-07);
@@ -104,6 +143,7 @@ html {
     body, .dark-theme, .light-theme {
       --accent: 358 75.0% 59.0%;
       --primary: 358 75.0% 59.0%;
+      --primary-foreground: 190 43% 97%;
       --ring: 359 69.5% 74.3%;
       --accent-foreground: 190 43% 97%;
       --primary-accent-foreground: 190 43% 97%;
@@ -165,8 +205,8 @@ html {
       --ls-link-text-color: var(--rx-red-11);
       --ls-link-text-hover-color: var(--rx-red-12);
       --ls-block-ref-link-text-color: var(--rx-red-09);
-      --ls-secondary-text-color: var(--rx-mauve-12);
-      --ls-primary-text-color: var(--rx-mauve-11);
+      --ls-secondary-text-color: var(--rx-mauve-11);
+      --ls-primary-text-color: var(--rx-mauve-12);
       --ls-border-color: var(--rx-mauve-05);
       --ls-secondary-border-color: var(--rx-red-05);
       --ls-page-checkbox-color: var(--rx-mauve-07);
@@ -250,8 +290,8 @@ html {
       --ls-link-text-color: var(--rx-blue-11);
       --ls-link-text-hover-color: var(--rx-blue-12);
       --ls-block-ref-link-text-color: var(--rx-blue-09);
-      --ls-secondary-text-color: var(--rx-slate-12);
-      --ls-primary-text-color: var(--rx-slate-11);
+      --ls-secondary-text-color: var(--rx-slate-11);
+      --ls-primary-text-color: var(--rx-slate-12);
       --ls-border-color: var(--rx-slate-05);
       --ls-secondary-border-color: var(--rx-blue-05);
       --ls-page-checkbox-color: var(--rx-slate-07);
@@ -274,6 +314,7 @@ html {
     body, .dark-theme, .light-theme {
       --accent: 336 80.0% 57.8%;
       --primary: 336 80.0% 57.8%;
+      --primary-foreground: 190 43% 97%;
       --ring: 336 62.3% 72.9%;
       --accent-foreground: 190 43% 97%;
       --primary-accent-foreground: 190 43% 97%;
@@ -335,8 +376,8 @@ html {
       --ls-link-text-color: var(--rx-crimson-11);
       --ls-link-text-hover-color: var(--rx-crimson-12);
       --ls-block-ref-link-text-color: var(--rx-crimson-09);
-      --ls-secondary-text-color: var(--rx-mauve-12);
-      --ls-primary-text-color: var(--rx-mauve-11);
+      --ls-secondary-text-color: var(--rx-mauve-11);
+      --ls-primary-text-color: var(--rx-mauve-12);
       --ls-border-color: var(--rx-mauve-05);
       --ls-secondary-border-color: var(--rx-crimson-05);
       --ls-page-checkbox-color: var(--rx-mauve-07);
@@ -419,8 +460,8 @@ html {
       --ls-link-text-color: var(--rx-pink-11);
       --ls-link-text-hover-color: var(--rx-pink-12);
       --ls-block-ref-link-text-color: var(--rx-pink-09);
-      --ls-secondary-text-color: var(--rx-mauve-12);
-      --ls-primary-text-color: var(--rx-mauve-11);
+      --ls-secondary-text-color: var(--rx-mauve-11);
+      --ls-primary-text-color: var(--rx-mauve-12);
       --ls-border-color: var(--rx-mauve-05);
       --ls-secondary-border-color: var(--rx-pink-05);
       --ls-page-checkbox-color: var(--rx-mauve-07);
@@ -503,8 +544,8 @@ html {
       --ls-link-text-color: var(--rx-plum-11);
       --ls-link-text-hover-color: var(--rx-plum-12);
       --ls-block-ref-link-text-color: var(--rx-plum-09);
-      --ls-secondary-text-color: var(--rx-mauve-12);
-      --ls-primary-text-color: var(--rx-mauve-11);
+      --ls-secondary-text-color: var(--rx-mauve-11);
+      --ls-primary-text-color: var(--rx-mauve-12);
       --ls-border-color: var(--rx-mauve-05);
       --ls-secondary-border-color: var(--rx-plum-05);
       --ls-page-checkbox-color: var(--rx-mauve-07);
@@ -587,8 +628,8 @@ html {
       --ls-link-text-color: var(--rx-purple-11);
       --ls-link-text-hover-color: var(--rx-purple-12);
       --ls-block-ref-link-text-color: var(--rx-purple-09);
-      --ls-secondary-text-color: var(--rx-mauve-12);
-      --ls-primary-text-color: var(--rx-mauve-11);
+      --ls-secondary-text-color: var(--rx-mauve-11);
+      --ls-primary-text-color: var(--rx-mauve-12);
       --ls-border-color: var(--rx-mauve-05);
       --ls-secondary-border-color: var(--rx-purple-05);
       --ls-page-checkbox-color: var(--rx-mauve-07);
@@ -671,8 +712,8 @@ html {
       --ls-link-text-color: var(--rx-violet-11);
       --ls-link-text-hover-color: var(--rx-violet-12);
       --ls-block-ref-link-text-color: var(--rx-violet-09);
-      --ls-secondary-text-color: var(--rx-mauve-12);
-      --ls-primary-text-color: var(--rx-mauve-11);
+      --ls-secondary-text-color: var(--rx-mauve-11);
+      --ls-primary-text-color: var(--rx-mauve-12);
       --ls-border-color: var(--rx-mauve-05);
       --ls-secondary-border-color: var(--rx-violet-05);
       --ls-page-checkbox-color: var(--rx-mauve-07);
@@ -755,8 +796,8 @@ html {
       --ls-link-text-color: var(--rx-indigo-11);
       --ls-link-text-hover-color: var(--rx-indigo-12);
       --ls-block-ref-link-text-color: var(--rx-indigo-09);
-      --ls-secondary-text-color: var(--rx-slate-12);
-      --ls-primary-text-color: var(--rx-slate-11);
+      --ls-secondary-text-color: var(--rx-slate-11);
+      --ls-primary-text-color: var(--rx-slate-12);
       --ls-border-color: var(--rx-slate-05);
       --ls-secondary-border-color: var(--rx-indigo-05);
       --ls-page-checkbox-color: var(--rx-slate-07);
@@ -841,8 +882,8 @@ html {
       --ls-link-text-color: var(--rx-cyan-11);
       --ls-link-text-hover-color: var(--rx-cyan-12);
       --ls-block-ref-link-text-color: var(--rx-cyan-09);
-      --ls-secondary-text-color: var(--rx-slate-12);
-      --ls-primary-text-color: var(--rx-slate-11);
+      --ls-secondary-text-color: var(--rx-slate-11);
+      --ls-primary-text-color: var(--rx-slate-12);
       --ls-border-color: var(--rx-slate-05);
       --ls-secondary-border-color: var(--rx-cyan-05);
       --ls-page-checkbox-color: var(--rx-slate-07);
@@ -925,8 +966,8 @@ html {
       --ls-link-text-color: var(--rx-teal-11);
       --ls-link-text-hover-color: var(--rx-teal-12);
       --ls-block-ref-link-text-color: var(--rx-teal-09);
-      --ls-secondary-text-color: var(--rx-sage-12);
-      --ls-primary-text-color: var(--rx-sage-11);
+      --ls-secondary-text-color: var(--rx-sage-11);
+      --ls-primary-text-color: var(--rx-sage-12);
       --ls-border-color: var(--rx-sage-05);
       --ls-secondary-border-color: var(--rx-teal-05);
       --ls-page-checkbox-color: var(--rx-sage-07);
@@ -1010,8 +1051,8 @@ html {
       --ls-link-text-color: var(--rx-green-11);
       --ls-link-text-hover-color: var(--rx-green-12);
       --ls-block-ref-link-text-color: var(--rx-green-09);
-      --ls-secondary-text-color: var(--rx-sage-12);
-      --ls-primary-text-color: var(--rx-sage-11);
+      --ls-secondary-text-color: var(--rx-sage-11);
+      --ls-primary-text-color: var(--rx-sage-12);
       --ls-border-color: var(--rx-sage-05);
       --ls-secondary-border-color: var(--rx-green-05);
       --ls-page-checkbox-color: var(--rx-sage-07);
@@ -1094,8 +1135,8 @@ html {
       --ls-link-text-color: var(--rx-grass-11);
       --ls-link-text-hover-color: var(--rx-grass-12);
       --ls-block-ref-link-text-color: var(--rx-grass-09);
-      --ls-secondary-text-color: var(--rx-olive-12);
-      --ls-primary-text-color: var(--rx-olive-11);
+      --ls-secondary-text-color: var(--rx-olive-11);
+      --ls-primary-text-color: var(--rx-olive-12);
       --ls-border-color: var(--rx-olive-05);
       --ls-secondary-border-color: var(--rx-grass-05);
       --ls-page-checkbox-color: var(--rx-olive-07);
@@ -1178,8 +1219,8 @@ html {
       --ls-link-text-color: var(--rx-orange-11);
       --ls-link-text-hover-color: var(--rx-orange-12);
       --ls-block-ref-link-text-color: var(--rx-orange-09);
-      --ls-secondary-text-color: var(--rx-sand-12);
-      --ls-primary-text-color: var(--rx-sand-11);
+      --ls-secondary-text-color: var(--rx-sand-11);
+      --ls-primary-text-color: var(--rx-sand-12);
       --ls-border-color: var(--rx-sand-05);
       --ls-secondary-border-color: var(--rx-orange-05);
       --ls-page-checkbox-color: var(--rx-sand-07);
@@ -1263,8 +1304,8 @@ html {
       --ls-link-text-color: var(--rx-brown-11);
       --ls-link-text-hover-color: var(--rx-brown-12);
       --ls-block-ref-link-text-color: var(--rx-brown-09);
-      --ls-secondary-text-color: var(--rx-sand-12);
-      --ls-primary-text-color: var(--rx-sand-11);
+      --ls-secondary-text-color: var(--rx-sand-11);
+      --ls-primary-text-color: var(--rx-sand-12);
       --ls-border-color: var(--rx-sand-05);
       --ls-secondary-border-color: var(--rx-brown-05);
       --ls-page-checkbox-color: var(--rx-sand-07);

+ 3 - 3
packages/ui/src/index.css

@@ -20,7 +20,7 @@
     --secondary-foreground: 222.2 47.4% 11.2%;
 
     --muted: 210 40% 96.1%;
-    --muted-foreground: 215.4 16.3% 46.9%;
+    --muted-foreground: 0 0% 52.3%;
 
     --accent: 210 40% 96.1%;
     --accent-foreground: 222.2 47.4% 11.2%;
@@ -28,7 +28,7 @@
     --destructive: 0 84.2% 60.2%;
     --destructive-foreground: 210 40% 98%;
 
-    --border: 214.3 31.8% 91.4%;
+    --border: 300 1% 92%;
     --input: 214.3 31.8% 91.4%;
     --ring: 222.2 84% 4.9%;
 
@@ -52,7 +52,7 @@
     --secondary-foreground: 210 40% 98%;
 
     --muted: 217.2 32.6% 17.5%;
-    --muted-foreground: 215 20.2% 65.1%;
+    --muted-foreground: 0 0% 49.4%;
 
     --accent: 217.2 32.6% 17.5%;
     --accent-foreground: 210 40% 98%;

+ 171 - 0
packages/ui/src/vars-classic.css

@@ -0,0 +1,171 @@
+:root {
+  --ls-tag-text-opacity: 0.8;
+  --ls-tag-text-hover-opacity: 1;
+  --ls-page-text-size: 1em;
+  --ls-page-title-size: 36px;
+  --ls-main-content-max-width: 810px;
+  --ls-main-content-max-width-wide: 1280px;
+  --ls-font-family: Inter;
+  --ls-scrollbar-width: 6px;
+  --ls-border-radius-low: 4px;
+  --ls-border-radius-medium: 8px;
+  --ls-headbar-height: 3rem;
+  --ls-headbar-inner-top-padding: 0px;
+  --ls-left-sidebar-width: 246px;
+  --ls-left-sidebar-sm-width: 74vw;
+  --ls-left-sidebar-nav-btn-size: 38px;
+  --ls-native-kb-height: 0px;
+
+  --ls-highlight-color-gray: var(--rx-gray-05);
+  --ls-highlight-color-red: var(--rx-red-05);
+  --ls-highlight-color-yellow: var(--rx-yellow-05);
+  --ls-highlight-color-green: var(--rx-green-05);
+  --ls-highlight-color-blue: var(--rx-blue-05);
+  --ls-highlight-color-purple: var(--rx-purple-05);
+  --ls-highlight-color-pink: var(--rx-pink-05);
+}
+
+.white-theme,
+.light-theme,
+html[data-theme='light'] {
+  --color-level-1: var(--rx-gray-02);
+  --color-level-2: var(--rx-gray-03);
+  --color-level-3: var(--rx-gray-04);
+  --color-level-4: var(--rx-gray-05);
+  --color-level-5: var(--rx-gray-06);
+  --color-level-6: var(--rx-gray-07);
+}
+
+html[data-theme=light][data-color=logseq] {
+  --ls-primary-background-color: #ffffff;
+  --ls-secondary-background-color: #f7f7f7;
+  --ls-tertiary-background-color: #eaeaea;
+  --ls-quaternary-background-color: #dcdcdc;
+  --ls-table-tr-even-background-color: var(--ls-secondary-background-color);
+  --ls-active-primary-color: rgb(0, 105, 182);
+  --ls-active-secondary-color: #00477c;
+  --ls-block-properties-background-color: var(--ls-secondary-background-color);
+  --ls-page-properties-background-color: var(--ls-secondary-background-color);
+  --ls-block-ref-link-text-color: #d8e1e8;
+  --ls-border-color: #ccc;
+  --ls-secondary-border-color: #e2e2e2;
+  --ls-tertiary-border-color: rgba(200, 200, 200, 0.3);
+  --ls-guideline-color: rgba(46, 27, 5, 0.08);
+  --ls-menu-hover-color: var(--ls-a-chosen-bg);
+  --ls-primary-text-color: #433f38;
+  --ls-secondary-text-color: #161e2e;
+  --ls-title-text-color: var(--ls-header-button-background);
+  --ls-link-text-color: #106ba3;
+  --ls-link-text-hover-color: #1a537c;
+  --ls-link-ref-text-color: var(--ls-link-text-color);
+  --ls-link-ref-text-hover-color: var(--ls-link-text-hover-color);
+  --ls-tag-text-color: var(--ls-link-ref-text-color);
+  --ls-tag-text-hover-color: var(--ls-link-ref-text-hover-color);
+  --ls-slide-background-color: #fff;
+  --ls-block-bullet-border-color: #dedede;
+  --ls-block-bullet-color: rgba(67, 63, 56, 0.25);
+  --ls-block-highlight-color: #c0e6fd;
+  --ls-selection-background-color: #e4f2ff;
+  --ls-selection-text-color: var(--ls-secondary-text-color);
+  --ls-page-checkbox-color: #9dbbd8;
+  --ls-page-checkbox-border-color: var(--ls-page-checkbox-color);
+  --ls-page-blockquote-color: var(--ls-primary-text-color);
+  --ls-page-blockquote-bg-color: var(--lx-gray-03, #fbfaf8);
+  --ls-page-blockquote-border-color: var(--lx-gray-08, #799bbc);
+  --ls-page-mark-color: #262626;
+  --ls-page-mark-bg-color: #fef3ac;
+  --ls-page-inline-code-bg-color: var(--ls-secondary-background-color);
+  --ls-page-inline-code-color: var(--ls-primary-text-color);
+  --ls-scrollbar-foreground-color: rgba(0, 0, 0, 0.1);
+  --ls-scrollbar-background-color: rgba(0, 0, 0, 0.05);
+  --ls-scrollbar-thumb-hover-color: rgba(0, 0, 0, 0.2);
+  --ls-cloze-text-color: #0000cd;
+  --ls-icon-color: #646464;
+  --ls-search-icon-color: var(--ls-primary-text-color);
+  --ls-search-icon-hover-color: var(--ls-secondary-text-color);
+  --ls-a-chosen-bg: var(--ls-quaternary-background-color);
+  --ls-pie-bg-color: #e1e1e1;
+  --ls-pie-fg-color: #0a4a5d;
+
+  --ls-error-text-color: var(--color-red-700);
+  --ls-error-background-color: var(--color-red-100);
+  --ls-warning-text-color: var(--color-yellow-700);
+  --ls-warning-background-color: var(--color-yellow-100);
+  --ls-success-text-color: var(--color-green-800);
+  --ls-success-background-color: var(--color-green-100);
+  --ls-focus-ring-color: rgba(66, 133, 244, 0.5);
+  --ls-header-button-background: rgba(15, 20, 25, 1);
+  --ls-left-sidebar-text-color: var(--lx-gray-12);
+  --ls-button-background-hsl: 200 98% 35%;
+  --ls-button-background: hsl(var(--ls-button-background-hsl));
+}
+
+html[data-theme=dark][data-color=logseq] {
+  --ls-primary-background-color: #002b36;
+  --ls-secondary-background-color: #023643;
+  --ls-tertiary-background-color: #08404f;
+  --ls-quaternary-background-color: #094b5a;
+  --ls-table-tr-even-background-color: #03333f;
+  --ls-active-primary-color: #8ec2c2;
+  --ls-active-secondary-color: #d0e8e8;
+  --ls-block-properties-background-color: #06323e;
+  --ls-page-properties-background-color: #06323e;
+  --ls-block-ref-link-text-color: #1a6376;
+  --ls-border-color: #0e5263;
+  --ls-secondary-border-color: #126277;
+  --ls-tertiary-border-color: rgba(0, 2, 0, 0.1);
+  --ls-guideline-color: #0b4a5a;
+  --ls-menu-hover-color: var(--ls-secondary-background-color);
+  --ls-primary-text-color: #a4b5b6;
+  --ls-secondary-text-color: #dfdfdf;
+  --ls-title-text-color: #93a1a1;
+  --ls-link-text-color: rgb(138, 187, 187);
+  --ls-link-text-hover-color: var(--ls-active-secondary-color);
+  --ls-link-ref-text-color: var(--ls-link-text-color);
+  --ls-link-ref-text-hover-color: var(--ls-link-text-hover-color);
+  --ls-tag-text-color: var(--ls-link-text-color);
+  --ls-tag-text-hover-color: var(--ls-link-text-hover-color);
+  --ls-slide-background-color: var(--ls-primary-background-color);
+  --ls-block-bullet-border-color: #0f4958;
+  --ls-block-bullet-color: #608e91;
+  --ls-block-highlight-color: #0a3d4b;
+  --ls-selection-background-color: #338fff;
+  --ls-selection-text-color: #fff;
+  --ls-page-checkbox-color: #6093a0;
+  --ls-page-checkbox-border-color: var(--ls-primary-background-color);
+  --ls-page-blockquote-color: var(--ls-primary-text-color);
+  --ls-page-blockquote-bg-color: var(--ls-secondary-background-color);
+  --ls-page-blockquote-border-color: var(--ls-border-color);
+  --ls-page-mark-color: #262626;
+  --ls-page-mark-bg-color: #fef3ac;
+  --ls-page-inline-code-color: var(--ls-primary-text-color);
+  --ls-page-inline-code-bg-color: #01222a;
+  --ls-scrollbar-foreground-color: #11505f;
+  --ls-scrollbar-background-color: rgba(30, 60, 67, 0.1);
+  --ls-scrollbar-thumb-hover-color: rgba(255, 255, 255, 0.2);
+  --ls-cloze-text-color: #8fbc8f;
+  --ls-icon-color: var(--ls-link-text-color);
+  --ls-search-icon-color: var(--ls-primary-text-color);
+  --ls-search-icon-hover-color: var(--ls-secondary-text-color);
+  --ls-a-chosen-bg: var(--ls-quaternary-background-color);
+  --ls-pie-bg-color: #01303b;
+  --ls-pie-fg-color: #0b5869;
+
+  --ls-error-text-color: var(--color-red-400);
+  --ls-error-background-color: var(--color-red-900);
+  --ls-warning-text-color: var(--color-yellow-400);
+  --ls-warning-background-color: var(--color-yellow-900);
+  --ls-success-text-color: var(--color-green-100);
+  --ls-success-background-color: var(--color-green-900);
+  --ls-focus-ring-color: rgba(18, 98, 119, 0.5);
+  --ls-header-button-background: #dee4ea;
+  --ls-left-sidebar-text-color: var(--lx-gray-11);
+  --ls-button-background-hsl: 200 98% 35%;
+  --ls-button-background: hsl(var(--ls-button-background-hsl));
+  --color-level-1: var(--ls-secondary-background-color);
+  --color-level-2: var(--ls-tertiary-background-color);
+  --color-level-3: var(--ls-quaternary-background-color);
+  --color-level-4: #195d6c;
+  --color-level-5: #266c7d;
+  --color-level-6: #3a7e8e;
+}

+ 2 - 2
packages/ui/tailwind.config.js

@@ -65,11 +65,11 @@ module.exports = {
           foreground: 'hsl(var(--muted-foreground))',
         },
         accent: {
-          DEFAULT: 'hsl(var(--accent))',
+          DEFAULT: 'var(--lx-gray-04, hsl(var(--accent)))',
           foreground: 'hsl(var(--accent-foreground))',
         },
         popover: {
-          DEFAULT: 'hsl(var(--popover))',
+          DEFAULT: 'var(--lx-gray-03, hsl(var(--popover)))',
           foreground: 'hsl(var(--popover-foreground))',
         },
         card: {

+ 9 - 16
resources/css/codemirror.lsradix.css

@@ -35,21 +35,17 @@ http://ethanschoonover.com/lsradix/img/lsradix-palette.png
   rendering-intent: auto;
 }
 .cm-s-lsradix.cm-s-dark {
-  /* color: or(--lx-gray-09, #839496); */
-  color: or(--lx-gray-11, #839496);
-  background-color: or(--lx-gray-01, #002b36);
-  text-shadow: #002b36 0 1px;
+  background-color: var(--lx-gray-01, hsl(var(--secondary)/.7));
+  color: var(--lx-gray-10, hsl(var(--secondary-foreground)));
 }
 
 .dark .cm-s-lsradix.cm-s-dark {
-  background-color: or(--lx-gray-02, #002b36);
+  background-color: var(--lx-gray-02, hsl(var(--secondary)/.7));
 }
 
 .cm-s-lsradix.cm-s-light {
-  /* background-color: or(--lx-gray-12, #fdf6e3); */
-  background-color: or(--lx-gray-02, #fdf6e3);
-  color: or(--lx-gray-10, #657b83);
-  text-shadow: #eee8d5 0 1px;
+  background-color: var(--lx-gray-02, hsl(var(--secondary)/.7));
+  color: var(--lx-gray-10, hsl(var(--secondary-foreground)));
 }
 
 .cm-s-lsradix .CodeMirror-widget {
@@ -124,23 +120,20 @@ http://ethanschoonover.com/lsradix/img/lsradix-palette.png
 
 /* Dark */
 .cm-s-lsradix.cm-s-dark .CodeMirror-gutters {
-  background-color: or(--lx-gray-01, #073642);
+  background-color: var(--lx-gray-03, hsl(var(--secondary)));
 }
 
 .cm-s-lsradix.cm-s-dark .CodeMirror-linenumber {
-  color: or(--lx-gray-09, #586e75);
-  /* color: or(--lx-gray-03, #586e75); */
-  text-shadow: #021014 0 -1px;
+  color: var(--lx-gray-09, #586e75);
 }
 
 /* Light */
 .cm-s-lsradix.cm-s-light .CodeMirror-gutters {
-  background-color: or(--lx-gray-03, #eee8d5);
-  /* background-color: or(--lx-gray-11, #eee8d5); */
+  background-color: var(--lx-gray-03, hsl(var(--secondary)));
 }
 
 .cm-s-lsradix.cm-s-light .CodeMirror-linenumber {
-  color: or(--lx-gray-09, #839496);
+  color: var(--lx-gray-09, #839496);
 }
 
 /* Common */

+ 143 - 40
resources/css/shui.css

@@ -2,15 +2,60 @@ html * {
   border-color: hsl(var(--border));
 }
 
+html[data-theme=light] {
+  --accent: var(--rx-gray-12-hsl);
+  --accent-foreground: var(--rx-gray-02-hsl);
+  --input: var(--rx-gray-03-hsl);
+  --secondary: 240 4.8% 95.9%;
+}
+
+html[data-theme=dark] {
+  --accent: var(--rx-gray-12-hsl);
+  --accent-foreground: var(--rx-gray-02-hsl);
+  --primary-foreground: 0 0% 22%;
+  --background: 0 0% 11%;
+  --foreground: 0 0% 95%;
+  --card: 0 0% 11%;
+  --card-foreground: 0 0% 95%;
+  --secondary: 0 0% 20%;
+  --secondary-foreground: 0 0% 98%;
+  --border: 0 0% 16%;
+  --muted: 0 0% 15%;
+  --popover: 0 0% 7%;
+  --popover-foreground: 0 0 95%;
+  --input: 0 0% 25%;
+}
+
 html {
   .ui__dropdown-menu-content,
   .ui__context-menu-content,
   .ui__select-content {
     --accent: var(--rx-gray-04-hsl);
     --accent-foreground: var(--rx-gray-12-hsl);
+
+    --muted: var(--rx-gray-05-hsl);
+  }
+
+  .ui__calendar {
+    --accent: var(--rx-gray-04-hsl);
+    --accent-foreground: var(--rx-gray-12-hsl);
   }
 
   &:not([data-color=logseq]) {
+    .ui__dropdown-menu-item,
+    div[data-radix-popper-content-wrapper] div[role=menuitem] {
+      &:focus, &:hover {
+        background-color: var(--lx-gray-04, hsl(var(--accent)));
+      }
+    }
+
+
+    div[data-radix-popper-content-wrapper] div[role=menu],
+    .menu-links-wrapper,
+    .menu-links-outer,
+    .absolute-modal[data-modal-name] {
+      background-color: var(--lx-popover-bg, var(--lx-gray-01, hsl(var(--popover))));
+    }
   }
 
   &[data-color=logseq] {
@@ -23,24 +68,48 @@ html {
     }
   }
 
-  .ui__calendar {
-    --accent: var(--rx-gray-04-hsl);
-    --accent-foreground: var(--rx-gray-12-hsl);
+  &[data-color=none] {
+    --ls-block-bullet-color: var(--rx-gray-08);
+    --ls-block-bullet-active-color: var(--rx-gray-12);
+
+    ::selection {
+      @apply bg-primary/20;
+    }
+
+    #ui__ac-inner {
+    }
+
+    .cp__cmdk {
+      --lx-gray-07: var(--rx-gray-07);
+    }
+
+    .ui__toggle {
+      &-background-off {
+        @apply bg-gray-08;
+
+        .switcher {
+          @apply bg-gray-10;
+        }
+      }
+
+      &-background-on {
+        .switcher {
+          @apply bg-gray-03;
+        }
+      }
+    }
+
+    .tl-container {
+      --ls-primary-background-color: hsl(var(--background));
+      --ls-secondary-background-color: var(--rx-gray-01);
+      --ls-tertiary-background-color: var(--rx-gray-03);
+      --ls-quaternary-background-color: var(--rx-gray-05);
+    }
   }
 }
 
 html[data-theme=light] {
-  --accent: var(--rx-gray-04-hsl);
-  --accent-foreground: var(--rx-gray-12-hsl);
-  --input: var(--rx-gray-03-hsl);
-
   &[data-color=logseq] {
-    --primary: 200 97% 37%;
-    --primary-foreground: 255 92% 100%;
-    --accent: 200 97% 37%;
-    --accent-foreground: 255 92% 100%;
-    --ring: 200 97% 37%;
-
     .references-blocks-item {
       --lx-bg-override: var(--rx-gray-03-alpha);
     }
@@ -52,35 +121,34 @@ html[data-theme=light] {
 }
 
 html[data-theme=dark] {
-  --primary-foreground: 255 92% 100%;
-  --background: 0 0% 11%;
-  --foreground: 0 0% 95%;
-  --card: 0 0% 11%;
-  --card-foreground: 0 0% 95%;
-  --secondary: 0 0% 20%;
-  --secondary-foreground: 0 0% 98%;
-  --border: 0 0% 16%;
-  --muted: 0 0% 15%;
-  --popover: 0 0% 7%;
-  --popover-foreground: 0 0 95%;
-  --input: 0 0% 25%;
+  background-color: #161616;
 
   &[data-color=logseq] {
-    --background: 192 100% 11%;
-    --foreground: 0 0% 95%;
-    --accent: 192 80% 10%;
-    --accent-foreground: 255 92% 100%;
-    --primary: 200 97% 37%;
-    --primary-foreground: 255 92% 100%;
-    --ring: 200 97% 37%;
-    --secondary: 203 50% 20%;
-    --secondary-foreground: 0 0% 98%;
-    --muted: 192 100% 13%;
-    --border: 192 100% 16%;
-    --card: 192 100% 10%;
-    --card-foreground: 0 0% 95%;
-    --popover: 192 100% 11%;
-    --input: 203 35% 25%;
+    @apply bg-[#002b36];
+
+    .ui__modal-panel {
+      @apply border-accent-01;
+    }
+
+    .tippy-tooltip {
+      @apply border-accent-02;
+    }
+
+    .references-blocks-item {
+      background-color: var(--lx-gray-03, var(--ls-secondary-background-color));
+    }
+
+    .cp__right-sidebar-inner {
+      .references-blocks-item {
+        background-color: var(--lx-gray-04, var(--ls-tertiary-background-color));
+      }
+    }
+
+    .cp__themes-installed {
+      .it.is-active, .it:hover {
+        @apply bg-accent-01;
+      }
+    }
 
     .ui__button {
       &.as-outline {
@@ -92,6 +160,17 @@ html[data-theme=dark] {
     .ui__context-menu-content,
     .ui__select-content {
       --accent: 190 100% 15%;
+      --muted: 192 100% 13%;
+    }
+
+    .ui__button {
+      &.as-ghost {
+        @apply hover:bg-accent-01;
+      }
+    }
+
+    .menu-separator {
+      @apply opacity-20;
     }
 
     .ui__calendar {
@@ -101,6 +180,30 @@ html[data-theme=dark] {
     .rc-datepicker {
       --accent: 200 97% 37%;
     }
+
+    .cp__cmdk {
+      .border-gray-06,
+      .border-gray-07 {
+        border-color: var(--ls-border-color, var(--lx-gray-06));
+        opacity: .6;
+      }
+
+      > .hints {
+        @apply border-accent-01 bg-gray-02;
+      }
+    }
+
+    .tl-button {
+      &:hover {
+        @apply bg-accent-02;
+      }
+    }
+
+    .cp__header {
+      > .r > div:not(.ui__dropdown-trigger) a.button, button.button {
+        @apply opacity-60 hover:opacity-90;
+      }
+    }
   }
 }
 

+ 1 - 1
resources/forge.config.js

@@ -4,7 +4,7 @@ module.exports = {
   packagerConfig: {
     name: 'Logseq',
     icon: './icons/logseq_big_sur.icns',
-    buildVersion: 79,
+    buildVersion: 80,
     protocols: [
       {
         "protocol": "logseq",

Разница между файлами не показана из-за своего большого размера
+ 10 - 0
resources/js/ui.js


+ 1 - 1
resources/package.json

@@ -1,7 +1,7 @@
 {
   "name": "Logseq",
   "productName": "Logseq",
-  "version": "0.10.5",
+  "version": "0.10.6",
   "main": "electron.js",
   "author": "Logseq",
   "license": "AGPL-3.0",

+ 1 - 1
src/main/frontend/colors.cljs

@@ -3,7 +3,7 @@
   (:require [clojure.string :as string]
             [frontend.util :as util]))
 
-(def color-list [:tomato :red :crimson :pink :plum :purple :violet :indigo :blue :cyan :teal :green :grass :orange :brown])
+(def color-list [:tomato :red :crimson :pink :plum :purple :violet :indigo :blue :cyan :teal :green :grass :orange])
 ;(def color-list [:tomato :red :blue])
 
 (defn variable

+ 12 - 2
src/main/frontend/commands.cljs

@@ -308,9 +308,9 @@
     ;; task management
       (get-statuses)
       [["Deadline" [[:editor/clear-current-slash]
-                    [:editor/show-date-picker :deadline]]]
+                    [:editor/set-deadline]]]
        ["Scheduled" [[:editor/clear-current-slash]
-                     [:editor/show-date-picker :scheduled]]]]
+                     [:editor/set-scheduled]]]]
 
     ;; priority
       (get-priorities)
@@ -676,6 +676,16 @@
     (db-based-set-priority priority)
     (file-based-set-priority priority)))
 
+(defmethod handle-step :editor/set-scheduled [[_]]
+  (if (config/db-based-graph? (state/get-current-repo))
+    (state/pub-event! [:editor/new-property "Scheduled"])
+    (handle-step :editor/show-date-picker :scheduled)))
+
+(defmethod handle-step :editor/set-deadline [[_]]
+  (if (config/db-based-graph? (state/get-current-repo))
+    (state/pub-event! [:editor/new-property "Deadline"])
+    (handle-step :editor/show-date-picker :deadline)))
+
 (defmethod handle-step :editor/insert-properties [[_ _] _format]
   (when-let [input-id (state/get-edit-input-id)]
     (when-let [current-input (gdom/getElement input-id)]

+ 26 - 225
src/main/frontend/common.css

@@ -1,26 +1,3 @@
-:root {
-  --ls-tag-text-opacity: 0.8;
-  --ls-tag-text-hover-opacity: 1;
-  --ls-page-text-size: 1em;
-  --ls-page-title-size: 36px;
-  --ls-main-content-max-width: 810px;
-  --ls-main-content-max-width-wide: 1280px;
-  --ls-font-family: Inter;
-  --ls-scrollbar-width: 6px;
-  --ls-border-radius-low: 4px;
-  --ls-border-radius-medium: 8px;
-  --ls-headbar-height: 3rem;
-  --ls-headbar-inner-top-padding: 0px;
-  --ls-left-sidebar-width: 246px;
-  --ls-left-sidebar-sm-width: 74vw;
-  --ls-left-sidebar-nav-btn-size: 38px;
-  --ls-native-kb-height: 0px;
-  --ls-error-color: var(--color-red-500);
-  --ls-warning-color: var(--color-orange-500);
-  --ls-success-color: var(--color-green-500);
-  --ls-highlight-color-default: var(--ls-secondary-background-color);
-}
-
 @media (prefers-color-scheme: dark) {
   html {
     background-color: #002b36;
@@ -37,164 +14,6 @@
   }
 }
 
-.dark-theme,
-html[data-theme='dark'] {
-  --ls-primary-background-color: #002b36;
-  --ls-secondary-background-color: #023643;
-  --ls-tertiary-background-color: #08404f;
-  --ls-quaternary-background-color: #094b5a;
-  --ls-table-tr-even-background-color: #03333f;
-  --ls-active-primary-color: #8ec2c2;
-  --ls-active-secondary-color: #d0e8e8;
-  --ls-block-properties-background-color: #06323e;
-  --ls-page-properties-background-color: #06323e;
-  --ls-block-ref-link-text-color: #1a6376;
-  --ls-border-color: #0e5263;
-  --ls-secondary-border-color: #126277;
-  --ls-tertiary-border-color: rgba(0, 2, 0, 0.1);
-  --ls-guideline-color: #0b4a5a;
-  --ls-menu-hover-color: var(--ls-secondary-background-color);
-  --ls-primary-text-color: #a4b5b6;
-  --ls-secondary-text-color: #dfdfdf;
-  --ls-title-text-color: #93a1a1;
-  --ls-link-text-color: rgb(138, 187, 187);
-  --ls-link-text-hover-color: var(--ls-active-secondary-color);
-  --ls-link-ref-text-color: var(--ls-link-text-color);
-  --ls-link-ref-text-hover-color: var(--ls-link-text-hover-color);
-  --ls-tag-text-color: var(--ls-link-text-color);
-  --ls-tag-text-hover-color: var(--ls-link-text-hover-color);
-  --ls-slide-background-color: var(--ls-primary-background-color);
-  --ls-block-bullet-border-color: #0f4958;
-  --ls-block-bullet-color: #608e91;
-  --ls-block-highlight-color: #0a3d4b;
-  --ls-selection-background-color: #338fff;
-  --ls-selection-text-color: #fff;
-  --ls-page-checkbox-color: #6093a0;
-  --ls-page-checkbox-border-color: var(--ls-primary-background-color);
-  --ls-page-blockquote-color: var(--ls-primary-text-color);
-  --ls-page-blockquote-bg-color: var(--ls-secondary-background-color);
-  --ls-page-blockquote-border-color: var(--ls-border-color);
-  --ls-page-mark-color: #262626;
-  --ls-page-mark-bg-color: #fef3ac;
-  --ls-page-inline-code-color: var(--ls-primary-text-color);
-  --ls-page-inline-code-bg-color: #01222a;
-  --ls-scrollbar-foreground-color: #11505f;
-  --ls-scrollbar-background-color: rgba(30, 60, 67, 0.1);
-  --ls-scrollbar-thumb-hover-color: rgba(255, 255, 255, 0.2);
-  --ls-cloze-text-color: #8fbc8f;
-  --ls-icon-color: var(--ls-link-text-color);
-  --ls-search-icon-color: var(--ls-primary-text-color);
-  --ls-search-icon-hover-color: var(--ls-secondary-text-color);
-  --ls-a-chosen-bg: var(--ls-quaternary-background-color);
-  --ls-pie-bg-color: #01303b;
-  --ls-pie-fg-color: #0b5869;
-  --ls-highlight-color-gray: var(--color-gray-900);
-  --ls-highlight-color-red: var(--color-red-900);
-  --ls-highlight-color-yellow: var(--color-yellow-900);
-  --ls-highlight-color-green: var(--color-green-900);
-  --ls-highlight-color-blue: var(--color-blue-900);
-  --ls-highlight-color-purple: var(--color-purple-900);
-  --ls-highlight-color-pink: var(--color-pink-900);
-  --ls-error-text-color: var(--color-red-400);
-  --ls-error-background-color: var(--color-red-900);
-  --ls-warning-text-color: var(--color-yellow-400);
-  --ls-warning-background-color: var(--color-yellow-900);
-  --ls-success-text-color: var(--color-green-100);
-  --ls-success-background-color: var(--color-green-900);
-  --ls-focus-ring-color: rgba(18, 98, 119, 0.5);
-  --ls-header-button-background: #dee4ea;
-  --ls-left-sidebar-text-color: var(--lx-gray-11);
-  --ls-button-background-hsl: 200 98% 35%;
-  --ls-button-background: hsl(var(--ls-button-background-hsl));
-  --color-level-1: var(--ls-secondary-background-color);
-  --color-level-2: var(--ls-tertiary-background-color);
-  --color-level-3: var(--ls-quaternary-background-color);
-  --color-level-4: #195d6c;
-  --color-level-5: #266c7d;
-  --color-level-6: #3a7e8e;
-}
-
-/* You should always use .light-theme for light mode, the .white-theme is just for backward compatibility.
-
-See: https://github.com/logseq/logseq/pull/4652. */
-.white-theme,
-.light-theme,
-html[data-theme='light'] {
-  --ls-primary-background-color: #ffffff;
-  --ls-secondary-background-color: #f7f7f7;
-  --ls-tertiary-background-color: #eaeaea;
-  --ls-quaternary-background-color: #dcdcdc;
-  --ls-table-tr-even-background-color: var(--ls-secondary-background-color);
-  --ls-active-primary-color: rgb(0, 105, 182);
-  --ls-active-secondary-color: #00477c;
-  --ls-block-properties-background-color: var(--ls-secondary-background-color);
-  --ls-page-properties-background-color: var(--ls-secondary-background-color);
-  --ls-block-ref-link-text-color: #d8e1e8;
-  --ls-border-color: #ccc;
-  --ls-secondary-border-color: #e2e2e2;
-  --ls-tertiary-border-color: rgba(200, 200, 200, 0.3);
-  --ls-guideline-color: rgba(46, 27, 5, 0.08);
-  --ls-menu-hover-color: var(--ls-a-chosen-bg);
-  --ls-primary-text-color: #433f38;
-  --ls-secondary-text-color: #161e2e;
-  --ls-title-text-color: var(--ls-header-button-background);
-  --ls-link-text-color: #106ba3;
-  --ls-link-text-hover-color: #1a537c;
-  --ls-link-ref-text-color: var(--ls-link-text-color);
-  --ls-link-ref-text-hover-color: var(--ls-link-text-hover-color);
-  --ls-tag-text-color: var(--ls-link-ref-text-color);
-  --ls-tag-text-hover-color: var(--ls-link-ref-text-hover-color);
-  --ls-slide-background-color: #fff;
-  --ls-block-bullet-border-color: #dedede;
-  --ls-block-bullet-color: rgba(67, 63, 56, 0.25);
-  --ls-block-highlight-color: #c0e6fd;
-  --ls-selection-background-color: #e4f2ff;
-  --ls-selection-text-color: var(--ls-secondary-text-color);
-  --ls-page-checkbox-color: #9dbbd8;
-  --ls-page-checkbox-border-color: var(--ls-page-checkbox-color);
-  --ls-page-blockquote-color: var(--ls-primary-text-color);
-  --ls-page-blockquote-bg-color: var(--lx-gray-03, #fbfaf8);
-  --ls-page-blockquote-border-color: var(--lx-gray-08, #799bbc);
-  --ls-page-mark-color: #262626;
-  --ls-page-mark-bg-color: #fef3ac;
-  --ls-page-inline-code-bg-color: var(--ls-secondary-background-color);
-  --ls-page-inline-code-color: var(--ls-primary-text-color);
-  --ls-scrollbar-foreground-color: rgba(0, 0, 0, 0.1);
-  --ls-scrollbar-background-color: rgba(0, 0, 0, 0.05);
-  --ls-scrollbar-thumb-hover-color: rgba(0, 0, 0, 0.2);
-  --ls-cloze-text-color: #0000cd;
-  --ls-icon-color: #646464;
-  --ls-search-icon-color: var(--ls-primary-text-color);
-  --ls-search-icon-hover-color: var(--ls-secondary-text-color);
-  --ls-a-chosen-bg: var(--ls-quaternary-background-color);
-  --ls-pie-bg-color: #e1e1e1;
-  --ls-pie-fg-color: #0a4a5d;
-  --ls-highlight-color-gray: var(--color-gray-100);
-  --ls-highlight-color-red: var(--color-red-100);
-  --ls-highlight-color-yellow: var(--color-yellow-100);
-  --ls-highlight-color-green: var(--color-green-100);
-  --ls-highlight-color-blue: var(--color-blue-100);
-  --ls-highlight-color-purple: var(--color-purple-100);
-  --ls-highlight-color-pink: var(--color-pink-100);
-  --ls-error-text-color: var(--color-red-600);
-  --ls-error-background-color: var(--color-red-100);
-  --ls-warning-text-color: var(--color-yellow-700);
-  --ls-warning-background-color: var(--color-yellow-100);
-  --ls-success-text-color: var(--color-green-800);
-  --ls-success-background-color: var(--color-green-100);
-  --ls-focus-ring-color: rgba(66, 133, 244, 0.5);
-  --ls-header-button-background: rgba(15, 20, 25, 1);
-  --ls-left-sidebar-text-color: var(--lx-gray-12);
-  --ls-button-background-hsl: 200 98% 35%;
-  --ls-button-background: hsl(var(--ls-button-background-hsl));
-  --color-level-1: var(--ls-secondary-background-color);
-  --color-level-2: var(--ls-tertiary-background-color);
-  --color-level-3: var(--ls-quaternary-background-color);
-  --color-level-4: #d0e6fa;
-  --color-level-5: #bbdaf6;
-  --color-level-6: #a7cef1;
-}
-
 html:not(.is-native-android) {
   font-family: var(--ls-font-family), sans-serif, system-ui, -apple-system,
   BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans',
@@ -207,9 +26,9 @@ html {
 }
 
 body {
-  color: or(--ls-default-text-color, --lx-gray-12, --ls-primary-text-color);
+  color: var(--lx-gray-12, var(--ls-primary-text-color, hsl(var(--foreground))));
+  background-color: var(--lx-gray-01, var(--ls-primary-background-color, hsl(var(--background))));
   line-height: 1.5;
-  background-color: transparent;
   min-height: 100%;
   word-break: break-word; /* compatible for overflow-wrap: anywhere */
 }
@@ -264,12 +83,12 @@ body {
 
   a {
     cursor: pointer;
-    color: or(--ls-anchor-link-text-color, --lx-accent-11, --ls-link-text-color, #045591);
+    color: var(--lx-accent-11, var(--ls-link-text-color, hsl(var(--primary)/.8)));
     text-decoration: none;
   }
 
   a:hover {
-    color: or(--ls-anchor-link-text-color-hover, --lx-accent-12, --ls-link-text-hover-color, #000);
+    color: var(--lx-accent-12, var(--ls-link-text-hover-color, hsl(var(--primary))));
   }
 
   code {
@@ -296,21 +115,13 @@ body {
     text-indent: 0;
     padding: 8px 20px;
     border-left: 4px solid;
-    border-left-color: var(--ls-page-blockquote-border-color, #d3d3d3);
-    background-color: var(--ls-page-blockquote-bg-color, #f7f7f7);
+    border-left-color: var(--ls-page-blockquote-border-color, hsl(var(--primary)/.4));
+    background-color: var(--ls-page-blockquote-bg-color, hsl(var(--secondary)));
+    color: var(--ls-page-blockquote-color, hsl(var(--secondary-foreground)));
     margin: 1rem 0;
-    color: var(--ls-page-blockquote-color, #24292e);
     font-size: 1rem;
   }
 
-
-  input[type='text'],
-  input[type='password'] {
-    color: var(--ls-primary-text-color);
-    background: transparent;
-    font-size: inherit;
-  }
-
   summary {
     outline: none;
   }
@@ -454,8 +265,7 @@ li p:last-child,
 }
 
 .admonition-icon {
-  border-right: 1px solid;
-  border-right-color: var(--ls-border-color, #ccc);
+  @apply border-r;
 }
 
 i.ti {
@@ -526,10 +336,10 @@ i.ti {
 
 /* region FIXME: override elements (?) */
 h1.title, h1.title input {
-  margin-bottom: 1.5rem;
-  color: or(--ls-journal-title-color, --lx-gray-12, --ls-title-text-color, #222);
-  font-size: var(--ls-page-title-size, 36px);
-  font-weight: 500;
+  @apply mb-4 font-medium;
+
+  color: var(--lx-gray-12, var(--ls-title-text-color, hsl(var(--foreground))));
+  font-size: var(--ls-page-title-size, 32px);
 }
 
 .title .page-icon {
@@ -539,7 +349,7 @@ h1.title, h1.title input {
 .block-highlight,
 .content .selected {
   transition: background-color 0.2s cubic-bezier(0, 1, 0, 1);
-  background-color: var(--ls-block-highlight-color);
+  background-color: var(--ls-block-highlight-color, var(--rx-gray-04));
   padding: -1px;
 }
 
@@ -573,16 +383,14 @@ button.menu {
 .menu-link:hover,
 button.pull:hover,
 button.menu:focus {
-  background-color: or(--ls-settings-list-item-hover-background-color, --lx-gray-05, --ls-menu-hover-color, #f4f5f7);
+  background-color: or(--lx-gray-05, --ls-menu-hover-color, --rx-gray-05);
 }
 
 .menu-links-wrapper,
 .menu-links-outer {
-  @apply py-2 rounded-md shadow-lg overflow-y-auto;
+  @apply py-2 rounded-md shadow-lg overflow-y-auto border bg-popover min-w-[12rem];
 
   max-height: calc(100vh - 100px) !important;
-  background-color: or(--ls-settings-dropdown-background, --lx-gray-03, --ls-primary-background-color, #fff);
-  min-width: 12rem;
 }
 
 .menu-backdrop {
@@ -592,17 +400,12 @@ button.menu:focus {
 }
 
 .menu-link {
-  background-color: or(--ls-settings-dropdown-link-item-background, --lx-gray-03, --ls-primary-background-color, #fff);
-  color: or(--ls-settings-dropdown-link-text-color, --lx-gray-11, --ls-primary-text-color);
-  user-select: none;
+  @apply text-popover-foreground/75 select-none hover:text-popover-foreground/100;
+  @apply text-sm px-2 py-1.5 mx-1 hover:rounded transition-opacity duration-150;
 }
 
 .menu-separator {
-  @apply my-1;
-
-  opacity: 0.5;
-  border-top-width: 1px;
-  border-color: var(--ls-border-color, #ccc);
+  @apply my-1 opacity-50 border-t;
 }
 
 a.login {
@@ -685,7 +488,7 @@ a.tag {
   display: inline-block;
   cursor: pointer;
   border-radius: 4px;
-  color: or(--ls-tag-text, --lx-accent-11, --ls-tag-text-color, #045591);
+  color: var(--lx-accent-11, var(--ls-tag-text-color, hsl(var(--primary))));
   opacity: var(--ls-tag-text-opacity, 0.7);
 }
 
@@ -695,11 +498,11 @@ a.tag:hover {
 }
 
 svg.note {
-  color: var(--ls-primary-text-color, #19407c);
+  color: var(--rx-yellow-08);
 }
 
 svg.tip {
-  color: var(--ls-active-primary-color);
+  color: var(--lx-accent-08, var(--rx-blue-08));
 }
 
 /* endregion */
@@ -718,7 +521,7 @@ svg.tip {
 
 hr {
   margin: 2rem 0;
-  border-color: var(--ls-border-color, #ccc);
+  border-color: var(--lx-gray-05, var(--ls-border-color, var(--rx-gray-05)));
 }
 
 .resize {
@@ -797,10 +600,8 @@ mark {
   font-family: MonoLisa, 'Fira Code', Monaco, Menlo, Consolas, 'COURIER NEW',
   monospace;
   letter-spacing: 0;
-  background-color: or(--ls-inline-code-background, --lx-gray-06, --ls-page-inline-code-bg-color, #eee);
-  color: or(--ls-inline-code-text, --lx-gray-11, --ls-page-inline-code-color);
-  background-color: var(--ls-page-inline-code-bg-color, #eee);
-  color: var(--ls-page-inline-code-color);
+  background-color: var(--lx-gray-06, var(--ls-page-inline-code-bg-color, var(--rx-gray-05)));
+  color: var(--lx-gray-11, var(--ls-page-inline-code-color, var(--rx-gray-11)));
   text-rendering: optimizeSpeed;
 }
 
@@ -835,11 +636,11 @@ a.tooltip-priority {
 }
 
 .page-reference:hover {
-  background: or(--ls-page-reference-hover-background, --lx-accent-04-alpha, --ls-secondary-background-color);
+  background: var(--lx-accent-04-alpha, var(--ls-secondary-background-color, hsl(var(--primary)/.4)));
 }
 
 .references-blocks .page-reference:hover {
-  background: or(--ls-page-reference-block-hover-background, --lx-accent-04-alpha, --ls-tertiary-background-color);
+  background: var(--lx-accent-04-alpha, var(--ls-tertiary-background-color, hsl(var(--primary)/.4)));
 }
 
 #head .fade-link {

+ 7 - 3
src/main/frontend/components/block.cljs

@@ -1390,7 +1390,10 @@
                   url)]
         (if (and (coll? src)
                  (= (first src) "youtube-player"))
-          (youtube/youtube-video (last src) nil)
+          (let [t (re-find #"&t=(\d+)" url)
+                opts (when (seq t)
+                       {:start (nth t 1)})]
+            (youtube/youtube-video (last src) opts))
           (when src
             (let [width (min (- (util/get-width) 96) 560)
                   height (int (* width (/ (if (string/includes? src "player.bilibili.com")
@@ -2536,8 +2539,9 @@
                                       :on-hide (fn [value event]
                                                  (let [select? (and (= event :esc)
                                                                     (not (string/includes? value "```")))]
-                                                   (p/let [_ (editor-handler/save-block! (editor-handler/get-state) value)]
-                                                     (editor-handler/escape-editing select?))))}
+                                                   (p/do!
+                                                    (editor-handler/save-block! (editor-handler/get-state) value)
+                                                    (editor-handler/escape-editing select?))))}
                                      edit-input-id
                                      config))]
           (if (and named? (seq (:block/tags block)) db-based?)

+ 29 - 23
src/main/frontend/components/block.css

@@ -177,15 +177,21 @@
   position: absolute;
   border-radius: 2px;
   opacity: 0.6;
-}
+  border-left-color: var(--lx-gray-09, var(--ls-border-color, var(--rx-gray-09)));
+
+  &:hover {
+    background-color: var(--lx-gray-10, var(--ls-primary-text-color, var(--rx-gray-10)));
+    opacity: .7;
+  }
 
-.block-children-left-border:hover {
-  background-color: or(--ls-block-left-color, --lx-gray-11, --ls-primary-text-color);
+  &:active {
+    opacity: 1;
+  }
 }
 
 .block-children {
   border-left: 1px solid;
-  border-left-color: or(--lx-gray-04-alpha, --ls-guideline-color, #ddd) !important;
+  border-left-color: var(--lx-gray-04-alpha, var(--ls-guideline-color, var(--rx-gray-04-alpha))) !important;
 
   padding-top: 2px;
   padding-bottom: 3px;
@@ -297,12 +303,10 @@
 }
 
 .page-ref {
-  --lx-text-override: var(--ls-link-ref-text-color);
-  @apply text-accent-11;
+  color: var(--lx-accent-11, var(--ls-link-text-color, hsl(var(--primary)/.8)));
 
   &:hover {
-    --lx-text-override: var(--ls-link-ref-text-hover-color);
-    @apply text-accent-12;
+    color: var(--lx-accent-11, var(--ls-link-text-color, hsl(var(--primary))));
   }
 }
 
@@ -340,14 +344,10 @@
   }
 }
 
-.block-properties {
+.block-properties, .page-properties {
   margin: 4px 0;
   padding: 4px 8px;
-  background-color: var(--ls-block-properties-background-color, #f0f8ff);
-}
-
-.page-properties {
-  background-color: var(--ls-page-properties-background-color);
+  background-color: var(--lx-gray-03, var(--ls-block-properties-background-color, var(--rx-gray-03)));
 }
 
 .block-marker {
@@ -377,9 +377,9 @@
     border-radius: 2px;
   }
 
-  /* .bullet-container .selected { */
-  /*   border: 3px solid; */
-  /* } */
+  span.bullet-container:not(.as-order-list) .selected {
+    border: 3px solid;
+  }
 }
 
 .ls-block {
@@ -479,10 +479,10 @@
 }
 
 .color-level {
-  background-color: or(--ls-right-sidebar-content-background, --lx-gray-02, --color-level-1);
+  background-color: var(--lx-gray-02, var(--color-level-1, var(--rx-gray-02)));
 
   .dark & {
-    background-color: or(--ls-right-sidebar-content-background, --lx-gray-01, --color-level-1);
+    background-color: var(--lx-gray-01, var(--color-level-1, var(--rx-gray-01)));
   }
 
   & .color-level {
@@ -576,11 +576,11 @@
 
   &:not(.typed-list) {
     &.bullet-closed {
-      background-color: or(--ls-bullet-closed-background, --lx-gray-04-alpha, --ls-block-bullet-border-color, #ced9e0);
+      background-color: var(--lx-gray-04-alpha, var(--ls-block-bullet-border-color, var(--rx-gray-04-alpha)));
     }
 
     .bullet {
-      background-color: or(--lx-gray-08, --ls-block-bullet-color, #394b59);
+      background-color: var(--lx-gray-08, var(--ls-block-bullet-color, var(--rx-gray-08)));
       transition: transform 0.2s;
     }
   }
@@ -599,11 +599,11 @@
   color: var(--ls-primary-text-color);
 
   &:hover > .bullet-container:not(.typed-list) {
-    background-color: or(--lx-gray-04-alpha, --ls-block-bullet-border-color, #ced9e0);
+    background-color: var(--lx-gray-04-alpha, var(--ls-block-bullet-border-color, var(--rx-gray-04-alpha)));
 
     .bullet {
       transform: scale(1.2);
-      background-color: or(--lx-gray-08, --ls-block-bullet-color, inherit) !important;
+      background-color: var(--lx-gray-08, var(--ls-block-bullet-color, var(--rx-gray-08))) !important;
     }
   }
 }
@@ -758,3 +758,9 @@ html.is-mac {
     @apply bg-gray-03 rounded p-4;
   }
 }
+
+.cp__right-sidebar-inner {
+  .references-blocks-item {
+    @apply bg-gray-04;
+  }
+}

+ 1 - 3
src/main/frontend/components/cmdk.cljs

@@ -826,9 +826,7 @@
                       {:on-click #(handle-action action (assoc state :opts opts) %)
                        :muted    true}))]
     (when action
-      [:div {:class "flex w-full px-3 py-2 gap-2 justify-between"
-             :style {:background "var(--lx-gray-03)"
-                     :border-top "1px solid var(--lx-gray-07)"}}
+      [:div.hints
        [:div.text-sm.leading-6
         [:div.flex.flex-row.gap-1.items-center
          [:div.font-medium.text-gray-12 "Tip:"]

+ 4 - 4
src/main/frontend/components/command_palette.css

@@ -16,7 +16,6 @@
     .menu-link {
       transition: none;
       border: none;
-      border-radius: unset !important;
       background: none;
 
       .type-icon {
@@ -40,13 +39,13 @@
 
       &.chosen,
       &.chosen p {
-        background-color: or(--ls-cp-chosen, --lx-gray-03, --ls-a-chosen-bg);
+        background-color: var(--lx-gray-03, var(--ls-a-chosen-bg, var(--rx-gray-03)));
         color: var(--ls-secondary-text-color);
       }
 
       .dark &.chosen,
       .dark &.chosen p {
-        background-color: or(--ls-cp-chosen, --lx-gray-02, --ls-a-chosen-bg);
+        background-color: var(--lx-gray-02, var(--ls-a-chosen-bg, var(--rx-gray-02)));
       }
 
       &:hover p {
@@ -86,8 +85,9 @@
 
   &-input {
     padding: 16px;
-    font-size: 20px;
+    font-size: 16px;
     outline: none;
+    background-color: transparent;
   }
 
   &-results {

+ 2 - 5
src/main/frontend/components/container.cljs

@@ -85,6 +85,7 @@
                              (state/get-current-repo)
                              (:db/id page-entity)
                              :page))]
+    ;; TODO: move to standalone component
     (shui/context-menu
       (shui/context-menu-trigger
         [:a.flex.items-center
@@ -708,11 +709,7 @@
         links (state/sub :custom-context-menu/links)
         position (state/sub :custom-context-menu/position)]
     (when (and show? links position)
-      (ui/css-transition
-       {:class-names "fade"
-        :timeout {:enter 500
-                  :exit 300}}
-       (render-custom-context-menu links position)))))
+      (render-custom-context-menu links position))))
 
 (rum/defc new-block-mode < rum/reactive
   []

+ 24 - 55
src/main/frontend/components/container.css

@@ -5,25 +5,12 @@
   }
 }
 
-#app-container {
-  background-color: or(--ls-top-bar-background, --lx-gray-01, --ls-primary-background-color, #fff);
-  position: relative;
-}
-
-.dark #app-container {
-  background-color: or(--ls-top-bar-background, --lx-gray-02, --ls-primary-background-color, #fff);
-}
-
 #root {
-  > div {
-    color: or(--ls-document-text-color, --lx-gray-12, --ls-primary-text-color, #24292e);
-    font-size: var(--ls-page-text-size);
-  }
+  font-size: var(--ls-page-text-size);
 }
 
 #app-container {
-  display: flex;
-  flex: 0 0 100%;
+  @apply flex basis-full;
 }
 
 #skip-to-main {
@@ -79,13 +66,7 @@
   overflow: auto;
 }
 
-.dark .left-sidebar-inner {
-  --left-sidebar-bg-color: or(--ls-left-sidebar-background, --lx-gray-02, --ls-secondary-background-color);
-}
-
 .left-sidebar-inner {
-  --left-sidebar-bg-color: or(--ls-left-sidebar-background-color, --lx-gray-02, --ls-primary-background-color);
-
   position: relative;
   height: 100%;
   padding-top: 12px;
@@ -182,8 +163,8 @@
     }
 
     &:hover, &.active {
-      background-color: or(--ls-left-sidebar-active-background, --lx-gray-04, --color-level-3);
-      color: or(--ls-left-sidebar-active-text-color, --lx-gray-12);
+      background-color: var(--lx-gray-04, var(--color-level-3, var(--rx-gray-04)));
+      color: var(--lx-gray-12, var(--rx-gray-12));
 
       .ui__icon {
         opacity: .9;
@@ -216,7 +197,6 @@
       @apply pl-6 pr-4 py-1 flex justify-between items-center select-none sticky top-[-4px];
       @apply cursor-pointer z-[2] active:opacity-80;
 
-      background-color: var(--left-sidebar-bg-color);
 
       .ui__icon {
         @apply flex justify-center;
@@ -229,7 +209,7 @@
       }
 
       &:hover {
-        background-color: or(--ls-nav-item-hover, --lx-gray-04, --ls-tertiary-background-color);
+        background-color: var(--lx-gray-04, var(--ls-tertiary-background-color, var(--rx-gray-04)));
 
         * {
           opacity: 1 !important;
@@ -287,9 +267,8 @@
           }
 
           &:hover {
-            background-color: or(--ls-recessed-nav-item-hover, --lx-gray-04, --ls-quaternary-background-color);
+            background-color: var(--lx-gray-04, var(--ls-quaternary-background-color, var(--rx-gray-04)));
             opacity: 1;
-            background-color: var(--ls-quaternary-background-color);
           }
         }
       }
@@ -367,16 +346,14 @@
     }
   }
 
-  @screen sm {
-    --left-sidebar-bg-color: or(--ls-left-sidebar-background, --lx-gray-02, --ls-secondary-background-color);
+  .dark & {
+    --left-sidebar-bg-color: var(--lx-gray-02, var(--ls-secondary-background-color, hsl(var(--secondary, var(--rx-gray-03-hsl)))));
+  }
 
+  @screen sm {
     padding-top: 0;
     width: var(--ls-left-sidebar-width);
 
-    .dark & {
-      --left-sidebar-bg-color: or(--ls-left-sidebar-background, --lx-gray-02, --ls-secondary-background-color);
-    }
-
     > .wrap {
       margin-top: 52px;
     }
@@ -390,18 +367,15 @@
 }
 
 .cp__sidebar-left-layout {
-  position: fixed;
-  top: 0;
+  @apply fixed top-0 left-0 w-[10px];
 
-  left: 0;
   z-index: var(--ls-z-index-level-5);
-  width: 10px;
 
   a {
     @apply opacity-90 hover:opacity-100;
     transition: all 120ms ease-out;
 
-    color: or(--ls-left-sidebar-text-color, --ls-header-button-background);
+    color: var(--ls-left-sidebar-text-color, var(--ls-header-button-background));
   }
 
   > .left-sidebar-inner {
@@ -560,14 +534,6 @@
   /* box-shadow: inset 0 0 0 1px var(--ls-border-color); */
 }
 
-.cp__sidebar-main-layout {
-  background-color: or(--ls-main-content-background, --lx-gray-01, --ls-primary-background-color);
-}
-
-.dark .cp__sidebar-main-layout {
-  background-color: or(--ls-main-content-background, --lx-gray-02, --ls-primary-background-color);
-}
-
 .cp__sidebar-main-content {
   width: 100%;
   max-width: var(--ls-main-content-max-width);
@@ -594,16 +560,14 @@
       @apply rounded-full h-8 w-8 flex items-center justify-center
       font-bold select-none cursor-pointer;
 
-      background-color: or(--ls-left-sidebar-help-background, --lx-gray-01, --ls-secondary-background-color);
+      background-color: var(--lx-gray-02, var(--ls-secondary-background-color, var(--rx-gray-02)));
     }
   }
 
   &-menu-popup {
-    @apply fixed bottom-14 right-8 z-10 border
-    rounded-lg min-w-[260px] shadow;
+    @apply fixed bottom-14 right-8 z-10 border rounded-lg min-w-[260px] shadow;
 
-    background-color: var(--ls-secondary-background-color);
-    border-color: var(--ls-border-color);
+    background-color: var(--ls-secondary-background-color, var(--rx-gray-03));
 
     > .list-wrap {
       @apply flex flex-col pt-3;
@@ -612,7 +576,7 @@
         color: var(--ls-primary-text-color);
 
         &:active, &:hover {
-          background-color: var(--ls-tertiary-background-color);
+          background-color: var(--ls-tertiary-background-color, var(--rx-gray-05));
         }
       }
     }
@@ -664,6 +628,7 @@
 
   &-inner {
     padding-top: 0;
+    background-color: var(--lx-gray-02, var(--ls-secondary-background-color));
   }
 
   &-settings {
@@ -734,9 +699,7 @@
   }
 
   .sidebar-item {
-    @apply relative;
-    flex: 1 1;
-    min-height: 100px;
+    @apply relative flex-1 min-h-[100px];
 
     .sidebar-item-header {
       .breadcrumb {
@@ -851,4 +814,10 @@ html[data-theme='dark'] {
       background-color: rgba(0, 0, 0, .15);
     }
   }
+
+  .cp__right-sidebar {
+    .sidebar-item {
+      background-color: var(--lx-gray-03, var(--ls-secondary-background-color));
+    }
+  }
 }

+ 1 - 6
src/main/frontend/components/content.css

@@ -12,13 +12,8 @@
 }
 
 #custom-context-menu {
-  @apply transition ease-out duration-100 transform
-  opacity-100 scale-100 absolute;
+  @apply absolute animate-in zoom-in-95;
 
   z-index: calc(var(--ls-z-index-level-1) + 1);
   width: 270px;
-
-  a:hover {
-    color: var(--ls-primary-text-color);
-  }
 }

+ 0 - 2
src/main/frontend/components/datepicker.css

@@ -49,10 +49,8 @@
   top: 100px;
   left: 20px;
   padding: 10px;
-  margin-top: 1px;
   line-height: 16px;
   border-radius: 4px;
-  background: #efefef;
 }
 
 .datepicker table {

+ 1 - 1
src/main/frontend/components/db_based/page.cljs

@@ -171,7 +171,7 @@
       [:div.page-info {:on-mouse-over #(reset! *hover? true)
                        :on-mouse-leave #(reset! *hover? false)}
        (when (or hover-or-expanded? has-tags? has-properties? class?)
-         [:div.fade-in.p-2 {:class (if (or @*hover? (not collapsed?))
+         [:div.p-2 {:class (if (or @*hover? (not collapsed?))
                                      "border rounded"
                                      "border rounded border-transparent")}
           [:div.info-title.cursor {:on-click

+ 12 - 0
src/main/frontend/components/editor.css

@@ -36,6 +36,10 @@
     transform: translateY(calc(-100% - 2rem));
   }
 
+  &[data-modal-name] {
+    @apply bg-popover border overflow-x-hidden overflow-y-auto rounded-lg py-1;
+  }
+
   &[data-modal-name="commands"],
   &[data-modal-name="select-code-block-mode"] {
     @screen sm {
@@ -43,6 +47,14 @@
       max-width: 90vw !important;
     }
   }
+
+  &[data-modal-name="date-picker"] {
+    @apply py-0;
+
+    .rc-datepicker {
+      @apply my-0;
+    }
+  }
 }
 
 .is-mobile {

+ 42 - 39
src/main/frontend/components/file_sync.cljs

@@ -305,9 +305,10 @@
               (calc-time-left))]]])
 
        [:div.c
+        {:class (when waiting? "pt-2")}
         (second tip-b&p)
         (when (or history-files? (not no-active-files?))
-          [:span.inline-flex.ml-1.active:opacity-50
+          [:span.inline-flex.pl-2.active:opacity-50
            {:on-click #(set-list-active? (not list-active?))}
            (if list-active?
              (ui/icon "chevron-up" {:style {:font-size 24}})
@@ -518,47 +519,49 @@
 
 (rum/defc pick-local-graph-for-sync [graph]
   [:div.cp__file-sync-related-normal-modal
-   [:div.flex.justify-center.pb-4 [:span.icon-wrap (ui/icon "cloud-download")]]
+   [:div.flex.justify-center.pb-4
+    [:span.icon-wrap (ui/icon "cloud-download" {:size 22})]]
 
-   [:h1.mb-5.text-2xl.text-center.font-bold (util/format "Sync graph \"%s\" to local"
-                                                         (:GraphName graph))]
+   [:h1.mb-5.text-2xl.text-center.font-bold
+    (util/format "Sync graph \"%s\" to local" (:GraphName graph))]
 
    (ui/button
-    "Open a local directory"
-    :class "block w-full py-4 mt-4"
-    :on-click #(do
-                 (state/close-modal!)
-                 (fs-sync/<sync-stop)
-                 (->
-                  (page-handler/ls-dir-files!
-                   (fn [{:keys [url]}]
-                     (file-sync-handler/init-remote-graph url graph)
-                     (js/setTimeout (fn [] (repo-handler/refresh-repos!)) 200))
-
-                   {:on-open-dir
-                    (fn [result]
-                      (prn ::on-open-dir result)
-                      (let [empty-dir? (not (seq (:files result)))
-                            root (:path result)]
-                        (cond
-                          (string/blank? root)
-                          (p/rejected (js/Error. nil))  ;; cancel pick a directory
-
-                          empty-dir?
-                          (p/resolved nil)
-
-                          :else ; dir is not empty
-                          (-> (if (util/electron?)
-                                (ipc/ipc :readGraphTxIdInfo root)
-                                (fs-util/read-graphs-txid-info root))
-                              (p/then (fn [^js info]
-                                        (when (or (nil? info)
-                                                  (nil? (second info))
-                                                  (not= (second info) (:GraphUUID graph)))
-                                          (if (js/confirm "This directory is not empty, are you sure to sync the remote graph to it? Make sure to back up the directory first.")
-                                            (p/resolved nil)
-                                            (p/rejected (js/Error. nil))))))))))}) ;; cancel pick a non-empty directory
-                  (p/catch (fn [])))))
+     "Open a local directory"
+     :class "block w-full mt-4"
+     :size :lg
+     :on-click #(do
+                  (state/close-modal!)
+                  (fs-sync/<sync-stop)
+                  (->
+                    (page-handler/ls-dir-files!
+                      (fn [{:keys [url]}]
+                        (file-sync-handler/init-remote-graph url graph)
+                        (js/setTimeout (fn [] (repo-handler/refresh-repos!)) 200))
+
+                      {:on-open-dir
+                       (fn [result]
+                         (prn ::on-open-dir result)
+                         (let [empty-dir? (not (seq (:files result)))
+                               root (:path result)]
+                           (cond
+                             (string/blank? root)
+                             (p/rejected (js/Error. nil))   ;; cancel pick a directory
+
+                             empty-dir?
+                             (p/resolved nil)
+
+                             :else                          ; dir is not empty
+                             (-> (if (util/electron?)
+                                   (ipc/ipc :readGraphTxIdInfo root)
+                                   (fs-util/read-graphs-txid-info root))
+                               (p/then (fn [^js info]
+                                         (when (or (nil? info)
+                                                 (nil? (second info))
+                                                 (not= (second info) (:GraphUUID graph)))
+                                           (if (js/confirm "This directory is not empty, are you sure to sync the remote graph to it? Make sure to back up the directory first.")
+                                             (p/resolved nil)
+                                             (p/rejected (js/Error. nil))))))))))}) ;; cancel pick a non-empty directory
+                    (p/catch (fn [])))))
 
    [:div.text-xs.opacity-50.px-1.flex-row.flex.items-center.p-2
     (ui/icon "alert-circle")

+ 3 - 8
src/main/frontend/components/file_sync.css

@@ -1,7 +1,7 @@
 :root {
-  --ls-color-file-sync-error: var(--ls-error-color);
-  --ls-color-file-sync-pending: var(--color-yellow-500);
-  --ls-color-file-sync-idle: var(--ls-success-color);
+  --ls-color-file-sync-error: var(--color-red-600);
+  --ls-color-file-sync-pending: var(--color-yellow-600);
+  --ls-color-file-sync-idle: var(--color-green-600);
 }
 
 .cp__file-sync {
@@ -96,11 +96,6 @@
         font-size: 13px;
         padding: 6px 20px;
 
-        > div.flex > div {
-          margin: 0 !important;
-          flex: 1;
-        }
-
         &.is-first-placeholder {
           padding: 0 !important;
           user-select: none;

+ 2 - 2
src/main/frontend/components/header.cljs

@@ -28,7 +28,7 @@
   < {:key-fn #(identity "home-button")}
   []
   (ui/with-shortcut :go/home "left"
-    [:button.button.icon.inline
+    [:button.button.icon.inline.mx-1
      {:title (t :home)
       :on-click #(do
                    (when (mobile-util/native-iphone?)
@@ -47,7 +47,7 @@
                   logged?
                   (not sync-enabled?))
       [:span.flex.space-x-2
-       [:a.button.text-sm.font-medium.block
+       [:a.button.text-sm.font-medium.block.text-gray-11
         {:on-click #(state/pub-event! [:user/login])}
         [:span (t :login)]
         (when loading?

+ 3 - 12
src/main/frontend/components/header.css

@@ -178,22 +178,13 @@
 }
 
 .button {
-  @apply h-8 px-2.5 py-1 rounded-md opacity-60;
-  display: block;
-  user-select: none;
-
-  &:hover, &.active {
-    opacity: 1;
-    background: none;
+  @apply h-8 px-2.5 py-1 rounded-md opacity-90 block select-none hover:opacity-100 active:opacity-80;
 
+  &:hover {
     @screen md {
-      background: or(--ls-header-button-hover, --lx-gray-04, --ls-tertiary-background-color);
+      background: var(--lx-gray-04, var(--ls-tertiary-background-color, var(--rx-gray-04)));
     }
   }
-
-  &:active {
-    opacity: .7;
-  }
 }
 
 .button.icon {

+ 1 - 1
src/main/frontend/components/journal.css

@@ -7,7 +7,7 @@
 
   .journal-item {
     border-top: 1px solid;
-    border-top-color: or(--ls-journal-page-rule, --lx-gray-07, --ls-border-color, #738694);
+    border-top-color: var(--lx-gray-07, var(--ls-border-color, var(--rx-gray-06)));
     margin: 24px 0;
     padding: 24px 0;
     min-height: 250px;

+ 6 - 16
src/main/frontend/components/onboarding/index.css

@@ -32,7 +32,6 @@ body[data-page=import] {
           &:first-child {
             display: block;
             text-align: center;
-            padding-bottom: 15px;
           }
         }
       }
@@ -53,7 +52,7 @@ body[data-page=import] {
           flex: 1;
 
           &.a {
-            background-color: var(--ls-tertiary-background-color);
+            background-color: var(--ls-tertiary-background-color, var(--rx-gray-03));
             display: flex;
             flex-direction: column;
             align-items: center;
@@ -172,8 +171,7 @@ body[data-page=import] {
         }
 
         &.importer {
-          background-color: var(--ls-tertiary-background-color);
-          position: relative;
+          @apply relative bg-gray-03;
 
           > section {
             flex: unset;
@@ -298,16 +296,8 @@ body[data-page=import] {
     }
 
     label.action-input {
-      transition: none;
-      color: var(--ls-active-primary-color);
-      background-color: var(--ls-quaternary-background-color);
-      height: 68px;
-      width: 100%;
-      opacity: .8;
-      user-select: none;
-      border-radius: 12px;
-      overflow: hidden;
-      cursor: pointer;
+      @apply transition-none bg-gray-06 h-[68px] w-full opacity-80 select-none;
+      @apply rounded-xl overflow-hidden cursor-pointer;
 
       small {
         font-size: 11px;
@@ -413,7 +403,7 @@ body[data-page=import] {
 
     .shepherd-footer {
       button {
-        background-color: var(--lx-bg-override, var(--lx-accent-09, var(--ls-button-background)));
+        background-color: var(--lx-accent-09, var(--ls-button-background));
         padding: 4px 8px;
         border-radius: 6px;
         overflow: hidden;
@@ -431,7 +421,7 @@ body[data-page=import] {
       }
 
       button:hover {
-          background-color: var(--lx-bg-override, var(--lx-accent-10, var(--ls-button-background)));
+          background-color: var(--lx-accent-10, var(--ls-button-background));
       }
     }
   }

+ 57 - 57
src/main/frontend/components/onboarding/setups.cljs

@@ -63,65 +63,65 @@
         logged?        (user-handler/logged-in?)]
 
     (setups-container
-     :picker
-     [:article.flex.w-full
-      [:section.a.
-       (when (and (mobile-util/native-platform?) (not native-ios?))
-         (mobile-intro))
+      :picker
+      [:article.flex.w-full
+       [:section.a.
+        (when (and (mobile-util/native-platform?) (not native-ios?))
+          (mobile-intro))
 
-       (if native-ios?
-         ;; TODO: open for all native mobile platforms
-         (graph-picker/graph-picker-cp {:onboarding-and-home? onboarding-and-home?
-                                        :logged? logged?
-                                        :native-icloud? native-icloud?})
+        (if native-ios?
+          ;; TODO: open for all native mobile platforms
+          (graph-picker/graph-picker-cp {:onboarding-and-home? onboarding-and-home?
+                                         :logged? logged?
+                                         :native-icloud? native-icloud?})
 
-         (if (or (nfs/supported?) (mobile-util/native-platform?))
-           [:div.choose.flex.flex-col.items-center
-            {:on-click #(page-handler/ls-dir-files!
-                         (fn []
-                           (shortcut/refresh!)))}
-            [:i]
-            [:div.control
-             [:label.action-input.flex.items-center.justify-center.flex-col
-              {:disabled parsing?}
-
-              (if parsing?
-                (ui/loading "")
-                [[:strong (t :on-boarding/section-btn-title)]
-                 [:small (t :on-boarding/section-btn-desc)]])]]]
-           [:div.px-5
-            (ui/admonition :warning
-                           (widgets/native-fs-api-alert))
+          (if (or (nfs/supported?) (mobile-util/native-platform?))
             [:div.choose.flex.flex-col.items-center
-             (ui/button "Open a DB-based Graph"
-                        :on-click #(state/pub-event! [:graph/new-db-graph]))]]))]
-      [:section.b.flex.items-center.flex-col
-       [:p.flex
-        [:i.as-flex-center (ui/icon "zoom-question" {:style {:fontSize "22px"}})]
-        [:span.flex-1.flex.flex-col
-         [:strong (t :on-boarding/section-title)]
-         [:small.opacity-60 (t :on-boarding/section-desc)]]]
+             {:on-click #(page-handler/ls-dir-files!
+                           (fn []
+                             (shortcut/refresh!)))}
+             [:i]
+             [:div.control
+              [:label.action-input.flex.items-center.justify-center.flex-col
+               {:disabled parsing?}
+
+               (if parsing?
+                 (ui/loading "")
+                 [[:strong (t :on-boarding/section-btn-title)]
+                  [:small (t :on-boarding/section-btn-desc)]])]]]
+            [:div.px-5
+             (ui/admonition :warning
+               (widgets/native-fs-api-alert))
+             [:div.choose.flex.flex-col.items-center
+              (ui/button "Open a DB-based Graph"
+                :on-click #(state/pub-event! [:graph/new-db-graph]))]]))]
+       [:section.b.flex.items-center.flex-col
+        [:p.flex
+         [:i.as-flex-center (ui/icon "zoom-question" {:style {:fontSize "22px"}})]
+         [:span.flex-1.flex.flex-col
+          [:strong (t :on-boarding/section-title)]
+          [:small.opacity-60 (t :on-boarding/section-desc)]]]
 
-       [:p.text-sm.pt-5.tracking-wide
-        [:span (str (t :on-boarding/section-tip-1 DEVICE))]
-        [:br]
-        [:span (t :on-boarding/section-tip-2)]]
+        [:p.text-sm.pt-5.tracking-wide
+         [:span (str (t :on-boarding/section-tip-1 DEVICE))]
+         [:br]
+         [:span (t :on-boarding/section-tip-2)]]
 
-       [:ul
-        (for [[title label icon]
-              [[(t :on-boarding/section-assets) "/assets" "whiteboard"]
-               [(t :on-boarding/section-journals) "/journals" "calendar-plus"]
-               [(t :on-boarding/section-pages) "/pages" "page"]
-               []
-               [(t :on-boarding/section-app) "/logseq" "tool"]
-               [(t :on-boarding/section-config) "/logseq/config.edn"]]]
-          (if-not title
-            [:li.hr]
-            [:li
-             {:key title}
-             [:i.as-flex-center
-              {:class (when (string/ends-with? label ".edn") "is-file")}
-              (when icon (ui/icon icon))]
-             [:span
-              [:strong.uppercase title]
-              [:small.opacity-50 label]]]))]]])))
+        [:ul
+         (for [[title label icon]
+               [[(t :on-boarding/section-assets) "/assets" "whiteboard"]
+                [(t :on-boarding/section-journals) "/journals" "calendar-plus"]
+                [(t :on-boarding/section-pages) "/pages" "page"]
+                []
+                [(t :on-boarding/section-app) "/logseq" "tool"]
+                [(t :on-boarding/section-config) "/logseq/config.edn"]]]
+           (if-not title
+             [:li.hr]
+             [:li
+              {:key title}
+              [:i.as-flex-center
+               {:class (when (string/ends-with? label ".edn") "is-file")}
+               (when icon (ui/icon icon))]
+              [:span
+               [:strong.uppercase title]
+               [:small.opacity-50 label]]]))]]])))

Разница между файлами не показана из-за своего большого размера
+ 399 - 312
src/main/frontend/components/page.cljs


+ 8 - 27
src/main/frontend/components/page.css

@@ -1,7 +1,3 @@
-.page-references h2 {
-  color: var(--ls-title-text-color);
-}
-
 .cp__page {
   &-publish-actions {
     background-color: var(--ls-primary-background-color);
@@ -97,14 +93,14 @@
 
   .actions {
     position: sticky;
-    background-color: or(--ls-all-pages-table, --lx-gray-01, --ls-primary-background-color);
+    background-color: var(--lx-gray-01, var(--ls-primary-background-color, var(--rx-gray-01)));
     white-space: nowrap;
     top: -18px;
     padding-bottom: 10px;
     z-index: 1;
 
     .dark & {
-        background-color: or(--ls-all-pages-table, --lx-gray-02, --ls-primary-background-color);
+        background-color: var(--lx-gray-02, var(--ls-primary-background-color, var(--rx-gray-02)));
     }
 
     @screen md {
@@ -137,7 +133,6 @@
       @apply text-base space-x-2;
 
       a.button {
-        color: var(--ls-primary-text-color);
         margin-top: 1px;
         height: unset;
         padding: 4px;
@@ -146,7 +141,6 @@
 
         &.active {
           opacity: 1;
-          color: var(--ls-link-ref-text-color);
         }
       }
 
@@ -248,20 +242,12 @@
 
   h1.page-title {
     margin-bottom: 0;
-    font-size: var(--ls-page-title-size, 36px);
-  }
-
-  .page-icon {
-    font-size: 48px;
   }
 
   .edit-input {
-    width: 100%;
-    height: 32px;
-    border: none;
+    @apply w-full border-0 p-0 pr-1 bg-transparent outline-0;
+
     box-shadow: none;
-    padding: 0;
-    padding-right: 4px;
 
     &-wrapper {
       @apply rounded;
@@ -271,6 +257,10 @@
       }
     }
   }
+
+  .page-icon {
+      font-size: 48px;
+  }
 }
 
 a.page-title {
@@ -279,7 +269,6 @@ a.page-title {
   transition: none;
   display: block;
   color: inherit;
-  margin-bottom: 0;
 }
 
 .page-title-sizer-wrapper {
@@ -400,14 +389,6 @@ html.is-native-ios {
   user-select: none;
 }
 
-.class-parent .form-select {
-  line-height: 1rem;
-}
-
-.ring-none {
-    @apply focus:ring-0 focus:ring-offset-0;
-}
-
 .page-info {
     min-height: 46px;
     margin-left: -21px;

+ 4 - 3
src/main/frontend/components/plugins.cljs

@@ -606,7 +606,8 @@
                    :options {:on-click
                              #(p/let [root (plugin-handler/get-ls-dotdir-root)]
                                 (js/apis.openPath (str root "/preferences.json")))}}
-                  {:title   [:span.flex.items-center.whitespace-nowrap.space-x-1 (ui/icon "bug") (t :plugin/open-logseq-dir) [:code "~/.logseq"]]
+                  {:title   [:span.flex.items-center.whitespace-nowrap.gap-1
+                             (ui/icon "bug") (t :plugin/open-logseq-dir) [:code "~/.logseq"]]
                    :options {:on-click
                              #(p/let [root (plugin-handler/get-ls-dotdir-root)]
                                 (js/apis.openPath root))}}])
@@ -1043,7 +1044,7 @@
           {:title   key
            :item    [:div.flex.items-center.item-wrap
                      (ui-item-renderer pid :toolbar (assoc opts :prefix "pl-" :key (str "pl-" key)))
-                     [:span.opacity-80 {:style {:padding-left "2px"}} key]
+                     [:span {:style {:padding-left "2px"}} key]
                      [:span.pin.flex.items-center.opacity-60
                       {:class (util/classnames [{:pinned pinned?}])}
                       (ui/icon (if pinned? "pinned" "pin"))]]
@@ -1065,7 +1066,7 @@
 
          (when badge-updates?
            {:title   [:div.flex.items-center.space-x-5.leading-none
-                      [:span (t :plugin/found-updates)] (ui/point "bg-red-600" 5 {:style {:margin-top 2}})]
+                      [:span (t :plugin/found-updates)] (ui/point "bg-red-700" 5 {:style {:margin-top 2}})]
             :options {:on-click #(open-waiting-updates-modal!)
                       :class    "extra-item"}
             :icon    (ui/icon "download")})]

+ 20 - 17
src/main/frontend/components/plugins.css

@@ -42,7 +42,8 @@
           }
         }
 
-        &.active {}
+        &.active {
+        }
       }
     }
 
@@ -196,7 +197,7 @@
   &-item-card {
     @apply flex py-3 px-1 rounded-md;
 
-    background-color: var(--ls-tertiary-background-color);
+    background-color: var(--ls-tertiary-background-color, hsl(var(--muted)));
     height: 150px;
 
     li {
@@ -648,11 +649,10 @@
   &-installed {
     margin: -2rem;
     outline: none;
-    padding: 1rem;
+    padding: .5rem;
 
     .it {
       user-select: none;
-      background-color: var(--ls-secondary-background-color);
       border: 1px solid transparent;
       margin-bottom: 4px;
       cursor: pointer;
@@ -662,18 +662,12 @@
         font-weight: 600;
       }
 
-      &.is-active {
-        background-color: var(--ls-tertiary-background-color);
-        border: 1px solid var(--ls-quaternary-background-color);
-        opacity: 1;
+      &:hover, &.is-active {
+        @apply opacity-100 bg-gray-06;
       }
 
       &.is-selected {
-        opacity: 1;
-      }
-
-      &:hover {
-        opacity: 1;
+        @apply opacity-100;
       }
     }
   }
@@ -861,11 +855,10 @@
       }
 
       .menu-link {
-        padding: 3px 5px;
+        @apply px-[5px] py-1.5;
 
         &.extra-item {
-          padding: 4px 15px;
-          opacity: .8;
+          @apply opacity-80 px-4 py-1.5;
 
           .title-wrap {
             margin-left: 8px !important;
@@ -879,7 +872,7 @@
 
       .item-wrap {
         padding-right: 28px;
-        font-size: 13px;
+        font-size: 14px;
         position: relative;
 
         div[data-injected-ui] :is(.ti, .tie) {
@@ -900,6 +893,16 @@
           opacity: 90;
         }
       }
+
+      .menu-links-wrapper {
+        a {
+          @apply !text-popover-foreground/80;
+
+          &.button {
+            @apply h-auto hover:bg-transparent scale-95;
+          }
+        }
+      }
     }
   }
 }

+ 4 - 2
src/main/frontend/components/property.cljs

@@ -441,8 +441,10 @@
 
 (rum/defcs new-property < rum/reactive
   (rum/local false ::new-property?)
-  (rum/local nil ::property-key)
   (rum/local nil ::property-value)
+  {:will-unmount (fn [state]
+                   (state/set-state! :editor/new-property-key nil)
+                   state)}
   [state block id keyboard-triggered? opts]
   (let [*new-property? (::new-property? state)
         container-id (state/sub :editor/properties-container)
@@ -450,7 +452,7 @@
 
     (when-not (and (:in-block-container? opts) (not keyboard-triggered?))
       [:div.ls-new-property
-       (let [*property-key (::property-key state)
+       (let [*property-key (:editor/new-property-key @state/state)
              *property-value (::property-value state)]
          (cond
            new-property?

+ 13 - 1
src/main/frontend/components/query/builder.css

@@ -21,7 +21,13 @@
     }
 
     .cp__select .input-wrap input {
-        border: none;
+        @apply border-0 outline-0 text-popover-foreground/90;
+
+        box-shadow: none;
+    }
+
+    .item-results-wrap {
+        @apply py-1;
     }
 
     .cp__select-input {
@@ -52,4 +58,10 @@
     .query-clause-btn {
         border-color: var(--ls-border-color);
     }
+
+    .query-builder-picker {
+       .form-input {
+           @apply focus:border-0;
+       }
+    }
 }

+ 90 - 90
src/main/frontend/components/right_sidebar.cljs

@@ -16,15 +16,14 @@
             [frontend.handler.ui :as ui-handler]
             [frontend.state :as state]
             [frontend.ui :as ui]
+            [logseq.shui.ui :as shui]
             [frontend.util :as util]
             [frontend.config :as config]
             [frontend.modules.editor.undo-redo :as undo-redo]
             [medley.core :as medley]
             [reitit.frontend.easy :as rfe]
             [rum.core :as rum]
-            [frontend.handler.common :as common-handler]
-            [frontend.db.rtc.debug-ui :as rtc-debug-ui]
-            [frontend.handler.property.util :as pu]))
+            [frontend.db.rtc.debug-ui :as rtc-debug-ui]))
 
 (rum/defc toggle
   []
@@ -73,8 +72,11 @@
 (rum/defc history-action-info
   [[k v]]
   (when v [:.ml-4 (ui/foldable
-                   [:div (str k v)]
+                   [:div (str k)]
                    [:.ml-4 (case k
+                             :tx-id
+                             [:.my-1 [:pre.code.pre-wrap-white-space.bg-base-4 (str v)]]
+
                              :blocks
                              (map (fn [block]
                                     [:.my-1 [:pre.code.pre-wrap-white-space.bg-base-4 (str block)]]) v)
@@ -85,14 +87,10 @@
                                       [:pre.code.pre-wrap-white-space.bg-base-4
                                        [:span.font-bold (str key) " "] (str val)])) v)
 
-                             (if (coll? v)
-                               (map (fn [[key val]]
-                                      (when val
-                                        [:pre.code.pre-wrap-white-space.bg-base-4
-                                         [:span.font-bold (str key) " "] (str val)])) v)
-                               (when v
-                                 [:pre.code.pre-wrap-white-space.bg-base-4
-                                  [:span.font-bold (str key) " "] (str v)])))]
+                             (map (fn [[key val]]
+                                    (when val
+                                      [:pre.code.pre-wrap-white-space.bg-base-4
+                                       [:span.font-bold (str key) " "] (str val)])) v))]
                    {:default-collapsed? true})]))
 
 (rum/defc history-stack
@@ -151,9 +149,9 @@
           page (db/entity repo lookup)
           page-name (:block/name page)]
       [[:.flex.items-center.page-title
-        (if-let [icon (pu/lookup (:block/properties page) :icon)]
+        (if-let [icon (get-in page [:block/properties :icon])]
           [:.text-md.mr-2 icon]
-          (ui/icon (if (contains? (set (:block/type page)) "whiteboard") "whiteboard" "page") {:class "text-md mr-2"}))
+          (ui/icon (if (= "whiteboard" (:block/type page)) "whiteboard" "page") {:class "text-md mr-2"}))
         [:span.overflow-hidden.text-ellipsis (db-model/get-page-original-name page-name)]]
        (page-cp repo page-name)])
 
@@ -183,7 +181,6 @@
     :shortcut-settings
     [[:.flex.items-center (ui/icon "command" {:class "text-md mr-2"}) (t :help/shortcuts)]
      (shortcut-settings)]
-
     :rtc
     [[:.flex.items-center (ui/icon "cloud" {:class "text-md mr-2"}) "(Dev) RTC"]
      (rtc-debug-ui/rtc-debug-ui)]
@@ -196,28 +193,33 @@
 (defonce *drag-from
   (atom nil))
 
-(rum/defc context-menu-content
-  [db-id idx type collapsed? block-count toggle-fn]
-  [:.menu-links-wrapper.text-left
-   {:on-click toggle-fn}
-   (ui/menu-link {:on-click #(state/sidebar-remove-block! idx)} (t :right-side-bar/pane-close))
-   (when (> block-count 1) (ui/menu-link {:on-click #(state/sidebar-remove-rest! db-id)} (t :right-side-bar/pane-close-others)))
-   (when (> block-count 1) (ui/menu-link {:on-click (fn []
-                                                      (state/clear-sidebar-blocks!)
-                                                      (state/hide-right-sidebar!))} (t :right-side-bar/pane-close-all)))
-   (when (or (not collapsed?) (> block-count 1)) [:hr.menu-separator])
-   (when-not collapsed? (ui/menu-link {:on-click #(state/sidebar-block-toggle-collapse! db-id)} (t :right-side-bar/pane-collapse)))
-   (when (> block-count 1) (ui/menu-link {:on-click #(state/sidebar-block-collapse-rest! db-id)} (t :right-side-bar/pane-collapse-others)))
-   (when (> block-count 1) (ui/menu-link {:on-click #(state/sidebar-block-set-collapsed-all! true)} (t :right-side-bar/pane-collapse-all)))
-   (when (or collapsed? (> block-count 1)) [:hr.menu-separator])
-   (when collapsed? (ui/menu-link {:on-click #(state/sidebar-block-toggle-collapse! db-id)} (t :right-side-bar/pane-expand)))
-   (when (> block-count 1) (ui/menu-link {:on-click #(state/sidebar-block-set-collapsed-all! false)}  (t :right-side-bar/pane-expand-all)))
-   (when (= type :page) [:hr.menu-separator])
-   (when (= type :page)
-     (let [name (:block/name (db/entity db-id))]
-       (ui/menu-link {:href (if (db-model/whiteboard-page? name)
+(rum/defc x-menu-content
+  [db-id idx type collapsed? block-count toggle-fn as-dropdown?]
+  (let [menu-content (if as-dropdown? shui/dropdown-menu-content shui/context-menu-content)
+        menu-item (if as-dropdown? shui/dropdown-menu-item shui/context-menu-content)
+        multi-items? (> block-count 1)]
+
+    (menu-content
+      {:on-click toggle-fn :class "w-48" :align "end"}
+
+      (menu-item {:on-click #(state/sidebar-remove-block! idx)} (t :right-side-bar/pane-close))
+      (when multi-items? (menu-item {:on-click #(state/sidebar-remove-rest! db-id)} (t :right-side-bar/pane-close-others)))
+      (when multi-items? (menu-item {:on-click (fn []
+                                                 (state/clear-sidebar-blocks!)
+                                                 (state/hide-right-sidebar!))} (t :right-side-bar/pane-close-all)))
+      (when (and (not collapsed?) multi-items?) [:hr.menu-separator])
+      (when-not collapsed? (menu-item {:on-click #(state/sidebar-block-toggle-collapse! db-id)} (t :right-side-bar/pane-collapse)))
+      (when multi-items? (menu-item {:on-click #(state/sidebar-block-collapse-rest! db-id)} (t :right-side-bar/pane-collapse-others)))
+      (when multi-items? (menu-item {:on-click #(state/sidebar-block-set-collapsed-all! true)} (t :right-side-bar/pane-collapse-all)))
+      (when (and collapsed? multi-items?) [:hr.menu-separator])
+      (when collapsed? (menu-item {:on-click #(state/sidebar-block-toggle-collapse! db-id)} (t :right-side-bar/pane-expand)))
+      (when multi-items? (menu-item {:on-click #(state/sidebar-block-set-collapsed-all! false)} (t :right-side-bar/pane-expand-all)))
+      (when (= type :page) [:hr.menu-separator])
+      (when (= type :page)
+        (let [name (:block/name (db/entity db-id))]
+          (menu-item {:href (if (db-model/whiteboard-page? name)
                               (rfe/href :whiteboard {:name name})
-                              (rfe/href :page {:name name}))} (t :right-side-bar/pane-open-as-page))))])
+                              (rfe/href :page {:name name}))} (t :right-side-bar/pane-open-as-page)))))))
 
 (rum/defc drop-indicator
   [idx drag-to]
@@ -253,59 +255,63 @@
       (let [collapsed? (state/sub [:ui/sidebar-collapsed-blocks db-id])]
         [:<>
          (when (zero? idx) (drop-indicator (dec idx) drag-to))
-         [:div.flex.sidebar-item.content.color-level.shadow-md.rounded-md
+         [:div.flex.sidebar-item.content.color-level.rounded-md.shadow-lg
           {:class [(str "item-type-" (name block-type))
                    (when collapsed? "collapsed")]}
           (let [[title component] item]
             [:div.flex.flex-col.w-full.relative
              [:.flex.flex-row.justify-between.pr-2.sidebar-item-header.color-level.rounded-t-md
-              {:class (when collapsed? "rounded-b-md")
-               :draggable true
+              {:class         (when collapsed? "rounded-b-md")
+               :draggable     true
                :on-drag-start (fn [event]
                                 (editor-handler/block->data-transfer! (:block/name (db/entity db-id)) event)
                                 (reset! *drag-from idx))
-               :on-drag-end (fn [_event]
-                              (when drag-to (state/sidebar-move-block! idx drag-to))
-                              (reset! *drag-to nil)
-                              (reset! *drag-from nil))
-               :on-mouse-up (fn [event]
-                              (when (= (.-which (.-nativeEvent event)) 2)
-                                (state/sidebar-remove-block! idx)))
-               :on-context-menu (fn [e]
-                                  (util/stop e)
-                                  (common-handler/show-custom-context-menu! e (context-menu-content db-id idx block-type collapsed? block-count #())))}
+               :on-drag-end   (fn [_event]
+                                (when drag-to (state/sidebar-move-block! idx drag-to))
+                                (reset! *drag-to nil)
+                                (reset! *drag-from nil))
+               :on-mouse-up   (fn [event]
+                                (when (= (.-which (.-nativeEvent event)) 2)
+                                  (state/sidebar-remove-block! idx)))}
+
               [:button.flex.flex-row.p-2.items-center.w-full.overflow-hidden
                {:aria-expanded (str (not collapsed?))
-                :id (str "sidebar-panel-header-" idx)
+                :id            (str "sidebar-panel-header-" idx)
                 :aria-controls (str "sidebar-panel-content-" idx)
-                :on-click (fn [event]
-                            (util/stop event)
-                            (state/sidebar-block-toggle-collapse! db-id))}
+                :on-click      (fn [event]
+                                 (util/stop event)
+                                 (state/sidebar-block-toggle-collapse! db-id))}
                [:span.opacity-50.hover:opacity-100.flex.items-center.pr-1
                 (ui/rotating-arrow collapsed?)]
-               [:div.ml-1.font-medium.overflow-hidden
+               [:div.ml-1.font-medium.overflow-hidden.whitespace-nowrap
                 title]]
               [:.item-actions.flex.items-center
-               (ui/dropdown (fn [{:keys [toggle-fn]}]
-                              [:button.button {:title (t :right-side-bar/pane-more)
-                                               :on-click (fn [e]
-                                                           (util/stop e)
-                                                           (toggle-fn))} (ui/icon "dots")])
-                            (fn [{:keys [close-fn]}]
-                              (context-menu-content db-id idx block-type collapsed? block-count close-fn)))
-               [:button.button.close {:title (t :right-side-bar/pane-close)
-                                      :on-click #(state/sidebar-remove-block! idx)} (ui/icon "x")]]]
-             [:div {:role "region"
-                    :id (str "sidebar-panel-content-" idx)
+               (shui/dropdown-menu
+                 (shui/dropdown-menu-trigger
+                   {:as-child true}
+                   (shui/button
+                     {:title   (t :right-side-bar/pane-more)
+                      :class   "px-3"
+                      :variant :text}
+                     (ui/icon "dots")))
+                 (x-menu-content db-id idx block-type collapsed? block-count #() true))
+
+               (shui/button
+                 {:title    (t :right-side-bar/pane-close)
+                  :variant  :text
+                  :class "px-3"
+                  :on-click #(state/sidebar-remove-block! idx)}
+                 (ui/icon "x"))]]
+
+             [:div {:role            "region"
+                    :id              (str "sidebar-panel-content-" idx)
                     :aria-labelledby (str "sidebar-panel-header-" idx)
-                    :class (util/classnames [{:hidden collapsed?
-                                              :initial (not collapsed?)
-                                              :p-4 (not (contains? #{:page :block :contents :search :shortcut-settings} block-type))
-                                              :pt-4 (not (contains? #{:search :shortcut-settings} block-type))
-                                              :p-1 (not (contains? #{:search :shortcut-settings} block-type))}])}
-              (ui/catch-error
-               [:span.warning "Something wrong happens"]
-               (inner-component component (not drag-from)))]
+                    :class           (util/classnames [{:hidden  collapsed?
+                                                        :initial (not collapsed?)
+                                                        :p-4     (not (contains? #{:page :block :contents :search :shortcut-settings} block-type))
+                                                        :pt-4    (not (contains? #{:search :shortcut-settings} block-type))
+                                                        :p-1     (not (contains? #{:search :shortcut-settings} block-type))}])}
+              (inner-component component (not drag-from))]
              (when drag-from (drop-area idx))])]
          (drop-indicator idx drag-to)]))))
 
@@ -338,9 +344,7 @@
         add-resizing-class #(.. js/document.documentElement -classList (add "is-resizing-buf"))
         remove-resizing-class (fn []
                                 (.. js/document.documentElement -classList (remove "is-resizing-buf"))
-                                (reset! ui-handler/*right-sidebar-resized-at (js/Date.now))
-                                (when-let [element js/document.activeElement]
-                                  (.blur element)))
+                                (reset! ui-handler/*right-sidebar-resized-at (js/Date.now)))
         set-width! (fn [ratio]
                      (when el-ref
                        (let [value (* ratio 100)
@@ -400,11 +404,11 @@
      [])
 
     (rum/use-effect!
-     (fn []
+      (fn []
         ;; sidebar animation duration
-       (js/setTimeout
-        #(reset! ui-handler/*right-sidebar-resized-at (js/Date.now)) 300))
-     [sidebar-open?])
+        (js/setTimeout
+          #(reset! ui-handler/*right-sidebar-resized-at (js/Date.now)) 300))
+      [sidebar-open?])
 
     [:.resizer
      {:ref              el-ref
@@ -460,24 +464,20 @@
           [:div.text-sm
            [:button.button.cp__right-sidebar-settings-btn {:on-click (fn [_e]
                                                                        (state/sidebar-add-block! repo "history" :history))}
-            (t :right-side-bar/history)]])
-        ]]
+            (t :right-side-bar/history)]])]]
 
-      [:.sidebar-item-list.flex-1.scrollbar-spacing
+      [:.sidebar-item-list.flex-1.scrollbar-spacing.px-2
        (if @*anim-finished?
          (for [[idx [repo db-id block-type]] (medley/indexed blocks)]
-            (rum/with-key
-              (sidebar-item repo idx db-id block-type block-count)
-              (str "sidebar-block-" db-id)))
+           (rum/with-key
+             (sidebar-item repo idx db-id block-type block-count)
+             (str "sidebar-block-" db-id)))
          [:div.p-4
           [:span.font-medium.opacity-50 "Loading ..."]])]]]))
 
 (rum/defcs sidebar < rum/reactive
   [state]
-  (let [blocks (->> (state/sub-right-sidebar-blocks)
-                    (remove (fn [item]
-                              (and (contains? #{:page :block} (last item))
-                                   (nil? (db/entity (second item)))))))
+  (let [blocks (state/sub-right-sidebar-blocks)
         blocks (if (empty? blocks)
                  [[(state/get-current-repo) "contents" :contents nil]]
                  blocks)

+ 8 - 15
src/main/frontend/components/right_sidebar.css

@@ -19,33 +19,26 @@ html[data-theme=light] {
   @apply ml-1 mt-[-8px] pb-[150px];
 
   height: calc(100vh - 48px);
-  background-color: or(--ls-right-ridebar-color, --lx-gray-01, --ls-secondary-background-color, #d8e1e8);
 }
 
 html[data-theme=light] a.toggle:hover {
   color: var(--ls-primary-text-color);
 }
 
-.cp__header a, .cp__header button {
-    opacity: 1;
-    color: or(--ls-header-button-text-color, --lx-gray-11, --ls-header-button-background);
-}
+.cp__header {
+  > .r > div:not(.ui__dropdown-trigger) a, button {
+    color: var(--lx-gray-11, var(--ls-header-button-background, var(--rx-gray-11)));
 
-.cp__header a:hover, .cp__header button:hover, .cp__right-sidebar-topbar button:hover {
-    color: or(--ls-header-button-text-color-hover, --lx-gray-12, --ls-header-button-background);
+    &:hover {
+      color: var(--lx-gray-12, var(--ls-header-button-background, var(--rx-gray-12)));
+    }
+  }
 }
 
 .cp__right-sidebar-topbar {
-  @apply px-1 h-12;
-  background-color: var(--ls-primary-background-color);
+  @apply px-1 h-12 bg-transparent;
 
   button {
     @apply opacity-100;
   }
 }
-
-html[data-theme=dark] {
-    .cp__header a, .cp__header button {
-        opacity: 0.7;
-    }
-}

+ 2 - 1
src/main/frontend/components/select.cljs

@@ -106,6 +106,7 @@
         input-container (or
                          input-container
                          [:div.input-wrap
+                          {:style {:margin-bottom "-2px"}}
                           [:input.cp__select-input.w-full
                            (merge {:type        "text"
                                    :placeholder (or input-default-placeholder (t prompt-key))
@@ -116,7 +117,7 @@
                                                     (reset! input v)
                                                     (and (fn? on-input) (on-input v))))}
                                   input-opts')]])
-        results-container [:div
+        results-container [:div.py-1
                            [:div.item-results-wrap
                             (ui/auto-complete
                              search-result

+ 44 - 33
src/main/frontend/components/settings.cljs

@@ -12,7 +12,6 @@
             [frontend.date :as date]
             [frontend.db :as db]
             [frontend.dicts :as dicts]
-            [frontend.handler :as handler]
             [frontend.handler.config :as config-handler]
             [frontend.handler.file-sync :as file-sync-handler]
             [frontend.handler.global-config :as global-config-handler]
@@ -332,40 +331,52 @@
                              :action     pick-theme
                              :desc       (ui/render-keyboard-shortcut (shortcut-helper/gen-shortcut-seq :ui/toggle-theme))})))
 
-(defn accent-color-row []
+(defn accent-color-row [_in-modal?]
   (let [color-accent (state/sub :ui/radix-color)
-        pick-theme [:div.grid {:style {:grid-template-columns "repeat(5, 1fr)"
-                                       :gap "0.75rem"
-                                       :width "100%"
-                                       :max-width "16rem"}}
-                    (for [color colors/color-list
-                          :let [active? (= color color-accent)]]
+        pick-theme [:div.cp__accent-colors-list-wrap
+                    {:class (if _in-modal? "as-modal-picker" "")}
+                    (for [color (concat [:none :logseq] colors/color-list)
+                          :let [active? (= color color-accent)
+                                none? (= color :none)]]
                       [:div.flex.items-center {:style {:height 28}}
-                       [:div {:class "w-5 h-5 rounded-full flex justify-center items-center transition ease-in duration-100 hover:cursor-pointer hover:opacity-100"
-                              :title color
-                              :style {:background-color (colors/variable color :09)
-                                      :outline-color (colors/variable color (if active? :07 :06))
-                                      :outline-width (if active? "4px" "1px")
-                                      :outline-style :solid
-                                      :opacity (if active? 1 0.5)}
-                              :on-click (fn [_e] (state/set-color-accent! color))}
-                        [:div {:class "w-2 h-2 rounded-full transition ease-in duration-100"
-                               :style {:background-color (str "var(--rx-" (name color) "-07)")
-                                       :opacity (if active? 1 0)}}]]])
-                    (when color-accent
-                      [:div.col-span-5
-                       (shui-ui/button
-                         {:variant  :secondary
-                          :size :xs
-                          :on-click (fn [_e] (state/unset-color-accent!))}
-                         "Back to default color")])]]
+                       (ui/tippy
+                         {:html (case color
+                                  :none [:p {:style {:max-width "300px"}}
+                                         "Cancel accent color. This is currently in beta stage and mainly used for compatibility with custom themes."]
+                                  :logseq "Logseq classical color"
+                                  (str (name color) " color") )
+                          :delay [1000, 100]}
+                         (shui-ui/button
+                           {:class      "w-5 h-5 px-1 rounded-full flex justify-center items-center transition ease-in duration-100 hover:cursor-pointer hover:opacity-100"
+                            :auto-focus (and _in-modal? active?)
+                            :style      {:background-color (colors/variable color :09)
+                                         :outline-color    (colors/variable color (if active? :07 :06))
+                                         :outline-width    (if active? "4px" "1px")
+                                         :outline-style    :solid
+                                         :opacity          (if active? 1 0.5)}
+                            :variant    :text
+                            :on-click   (fn [_e] (state/set-color-accent! color))}
+                           [:strong
+                            {:class (if none? "h-0.5 w-full bg-red-700"
+                                              "w-2 h-2 rounded-full transition ease-in duration-100")
+                             :style {:background-color (if-not none? (str "var(--rx-" (name color) "-07)") "")
+                                     :opacity          (if (or none? active?) 1 0)}}]))
+                       ])]]
 
     [:<>
-     (row-with-button-action {:left-label "Accent color"
-                              :description "Choosing an accent color will override any theme you have selected."
-                              :-for       "toggle_radix_theme"
-                              :stretch    true
-                              :action     pick-theme})]))
+     (row-with-button-action {:left-label  "Accent color"
+                              :description "Choosing an accent color may override any theme you have selected."
+                              :-for        "toggle_radix_theme"
+                              :desc        (when-not _in-modal?
+                                             [:span.pl-6 (ui/render-keyboard-shortcut
+                                                           (shortcut-helper/gen-shortcut-seq :ui/accent-colors-picker))])
+                              :stretch     (boolean _in-modal?)
+                              :action      pick-theme})]))
+
+(rum/defc modal-accent-colors-inner
+  []
+  [:div.cp__settings-accent-colors-modal-inner
+   (accent-color-row true)])
 
 (defn date-format-row [t preferred-date-format]
   [:div.it.sm:grid.sm:grid-cols-3.sm:gap-4.sm:items-:div.it.sm:grid.sm:grid-cols-3.sm:gap-4.sm:items-center
@@ -543,7 +554,7 @@
 (defn clear-cache-row [t]
   (row-with-button-action {:left-label   (t :settings-page/clear-cache)
                            :button-label (t :settings-page/clear)
-                           :on-click     handler/clear-cache!
+                           :on-click     #(state/pub-event! [:graph/clear-cache!])
                            :-for         "clear_cache"}))
 
 (defn version-row [t version]
@@ -670,7 +681,7 @@
      (language-row t preferred-language)
      (theme-modes-row t switch-theme system-theme? dark?)
      (when (and (util/electron?) (not util/mac?)) (native-titlebar-row t))
-     (when show-radix-themes? (accent-color-row))
+     (when show-radix-themes? (accent-color-row false))
      (when (config/global-config-enabled?) (edit-global-config-edn))
      (when current-repo (edit-config-edn))
      (when current-repo (edit-custom-css))

+ 28 - 1
src/main/frontend/components/settings.css

@@ -14,7 +14,7 @@
     }
 
     aside {
-      @apply bg-gray-400/5 p-4;
+      @apply bg-gray-03-alpha p-4;
 
       > ul > li {
         > a {
@@ -316,6 +316,17 @@
       pointer-events: none;
     }
   }
+
+  &-accent-colors-modal-inner {
+    & > .it {
+      grid-template-columns: auto;
+      margin: -8px;
+    }
+
+    label[for=toggle_radix_theme] {
+      @apply text-xl font-semibold opacity-90;
+    }
+  }
 }
 
 .cp__assets {
@@ -489,3 +500,19 @@ body[data-settings-tab=keymap] {
     }
   }
 }
+
+.ui__modal[label=accent-colors-picker] {
+  .panel-content {
+    @apply sm:min-w-[520px];
+  }
+}
+
+.cp__accent-colors {
+  &-list-wrap {
+    @apply grid grid-cols-8 gap-2 max-w-[250px];
+
+    &.as-modal-picker {
+      @apply grid-cols-8 gap-3 pt-1 pb-2 ml-8 max-w-none;
+    }
+  }
+}

+ 3 - 2
src/main/frontend/components/shortcut.cljs

@@ -475,5 +475,6 @@
 
                         (not unset?)
                         [:code.flex.items-center.bg-transparent
-                         (shui/shortcut-v1 (string/join " | " (map #(dh/binding-for-display id %) binding))
-                           nil {:size :md})])]]))))])])]]))
+                         (shui/shortcut
+                           (string/join " | " (map #(dh/binding-for-display id %) binding))
+                           {:size :md :interactive? true})])]]))))])])]]))

+ 3 - 3
src/main/frontend/components/svg.cljs

@@ -82,7 +82,7 @@
   []
   [:svg.h-8.w-8.important
    {:view-box "0 0 512 512"
-    :fill     "var(--ls-error-color)"}
+    :fill     "var(--color-red-600)"}
    [:path
     {:d
      "M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"}]])
@@ -91,7 +91,7 @@
   []
   [:svg.h-8.w-8.caution
    {:view-box "0 0 384 512"
-    :fill     "var(--ls-warning-color)"}
+    :fill     "var(--color-orange-600)"}
    [:path
     {:d
      "M216 23.86c0-23.8-30.65-32.77-44.15-13.04C48 191.85 224 200 224 288c0 35.63-29.11 64.46-64.85 63.99-35.17-.45-63.15-29.77-63.15-64.94v-85.51c0-21.7-26.47-32.23-41.43-16.5C27.8 213.16 0 261.33 0 320c0 105.87 86.13 192 192 192s192-86.13 192-192c0-170.29-168-193-168-296.14z"}]])
@@ -103,7 +103,7 @@
    [:svg.h-8.w-8.warning
     (merge
       {:view-box "0 0 576 512"
-       :fill     "var(--ls-warning-color)"}
+       :fill     "var(--color-orange-600)"}
       opts)
     [:path
      {:d

+ 3 - 3
src/main/frontend/components/table.css

@@ -14,7 +14,7 @@
     font-size: 14px;
     font-weight: 400;
     color: var(--ls-primary-text-color);
-    border-bottom: 2px solid var(--ls-border-color);
+    border-bottom: 2px solid var(--ls-border-color, var(--rx-gray-05));
     padding: 10px 8px;
   }
 
@@ -24,11 +24,11 @@
   }
 
   tr:nth-child(even) {
-    background: var(--ls-table-tr-even-background-color);
+    background: var(--ls-table-tr-even-background-color, var(--rx-gray-03));
   }
 
   tr:nth-child(odd) {
-    background: var(--ls-primary-background-color);
+    background: var(--ls-primary-background-color, var(--rx-gray-01));
   }
 
   caption {

+ 8 - 9
src/main/frontend/components/theme.cljs

@@ -22,12 +22,14 @@
         [restored-sidebar? set-restored-sidebar?] (rum/use-state false)]
 
     (rum/use-effect!
-     #(let [doc js/document.documentElement
-            cls (.-classList doc)]
+     #(let [^js doc js/document.documentElement
+            ^js cls (.-classList doc)
+            ^js cls-body (.-classList js/document.body)]
         (.setAttribute doc "data-theme" theme)
         (if (= theme "dark") ;; for tailwind dark mode
-          (.add cls "dark")
-          (.remove cls "dark"))
+          ; The white-theme is for backward compatibility. See: https://github.com/logseq/logseq/pull/4652.
+          (do (.add cls "dark") (doto cls-body (.remove "white-theme" "light-theme") (.add "dark-theme")))
+          (do (.remove cls "dark") (doto cls-body (.remove "dark-theme") (.add "white-theme" "light-theme"))))
         (ui/apply-custom-theme-effect! theme)
         (plugin-handler/hook-plugin-app :theme-mode-changed {:mode theme}))
      [theme])
@@ -111,11 +113,8 @@
      #(storage/set :file-sync/onboarding-state onboarding-state)
      [onboarding-state])
 
-    [:div
-     {:class    (util/classnames
-                 [(str theme "-theme")
-                  {:white-theme (= "light" theme)}]) ; The white-theme is for backward compatibility. See: https://github.com/logseq/logseq/pull/4652.
-      :on-click on-click}
+    [:div.theme-container
+     {:on-click on-click}
      child
 
      (pdf/default-embed-playground)]))

+ 27 - 36
src/main/frontend/components/theme.css

@@ -1,6 +1,6 @@
 :root {
   scrollbar-width: thin;
-  scrollbar-color: or(--lx-gray-05, --ls-scrollbar-foreground-color) or(--lx-gray-02, --ls-scrollbar-background-color);
+  scrollbar-color: var(--lx-gray-05, var(--ls-scrollbar-foreground-color)) var(--lx-gray-02, var(--ls-scrollbar-background-color));
 
   --ls-z-index-level-0: 0;
   --ls-z-index-level-1: 9;
@@ -10,19 +10,25 @@
   --ls-z-index-level-5: 99999;
 }
 
-html {
+@media (prefers-color-scheme: dark) {
+  .preboot-loading {
+    color: lightgray;
+  }
+}
+
+.visible-scrollbar, html:not(.is-mac) {
   ::-webkit-scrollbar-thumb {
-    background-color: or(--ls-scrollbar-thumb-color, --lx-gray-05, --ls-scrollbar-foreground-color);
+    background-color: var(--lx-gray-05, var(--ls-scrollbar-foreground-color, var(--rx-gray-05)));
   }
 
   ::-webkit-scrollbar {
-    background-color: or(--ls-scrollbar-color, --lx-gray-02, --ls-scrollbar-background-color);
-    width: var(--ls-scrollbar-width);
+    background-color: var(--lx-gray-02, var(--ls-scrollbar-background-color, var(--rx-gray-02)));
+    width: var(--ls-scrollbar-width, 6px);
     height: 8px;
   }
 
   ::-webkit-scrollbar-thumb:active {
-    background-color: or(--ls-scrollbar-thumb-color-active, --lx-gray-06, --ls-scrollbar-thumb-hover-color);
+    background-color: var(--lx-gray-06, var(--ls-scrollbar-thumb-hover-color, var(--rx-gray-06)));
   }
 
   ::-webkit-scrollbar-corner {
@@ -30,46 +36,34 @@ html {
   }
 }
 
-@media (prefers-color-scheme: dark) {
-  .preboot-loading {
-    color: lightgray;
+.hide-scrollbar {
+  -ms-overflow-style: none; /* IE and Edge */
+  scrollbar-width: none !important; /* Firefox */
+
+  &::-webkit-scrollbar {
+    display: none;
   }
 }
 
 .form-checkbox, .form-radio {
-  color: var(--ls-page-checkbox-color, #6093a0);
-  background-color: var(--ls-page-checkbox-color, #6093a0);
-  border-color: var(--ls-page-checkbox-border-color, #6093a0);
+  color: var(--ls-page-checkbox-color, hsl(var(--primary)/.4));
+  background-color: var(--ls-page-checkbox-color, var(--rx-gray-06));
+  border-color: var(--ls-page-checkbox-border-color, hsl(var(--border)));
   border: none;
   position: relative;
-  margin-right: 2px;
 }
 
 .form-checkbox:hover {
   transform: scale(1.1);
 }
 
-html[data-theme='dark'] {
-  background-color: var(--ls-primary-background-color);
-
-  input.form-input {
-    background: none;
-  }
-}
-
-html[data-theme='light'] {
+html[data-theme='light'] .theme-container {
   .form-checkbox {
     &:focus {
       border-color: var(--ls-page-checkbox-border-color);
     }
   }
 
-  .cp__header {
-    a {
-      color: var(--ls-primary-text-color);
-    }
-  }
-
   a.right-sidebar-button {
     color: var(--ls-primary-text-color);
   }
@@ -79,14 +73,7 @@ html[data-theme='light'] {
   }
 }
 
-.hide-scrollbar {
-  -ms-overflow-style: none; /* IE and Edge */
-  scrollbar-width: none !important; /* Firefox */
-
-  &::-webkit-scrollbar {
-    display: none;
-  }
-}
+html[data-theme='dark'] .theme-container {}
 
 html.locked-scroll {
   overflow: hidden !important;
@@ -163,3 +150,7 @@ main.ls-fold-button-on-right {
     }
   }
 }
+
+main.theme-inner {
+  --left-sidebar-bg-color: var(--lx-gray-02, hsl(var(--secondary, var(--rx-gray-03-hsl))));
+}

+ 1 - 1
src/main/frontend/components/user/login.cljs

@@ -84,4 +84,4 @@
     {:close-btn?      true
      :label           "user-login"
      :close-backdrop? false
-     :center?         true}))
+     :center?         false}))

+ 24 - 22
src/main/frontend/components/whiteboard.css

@@ -44,19 +44,30 @@ h1.title.whiteboard-dashboard-title {
 }
 
 .dashboard-preview-card {
-  @apply transition;
-  border: 1px solid var(--ls-border-color);
+  @apply transition border;
 }
 
 .dashboard-create-card {
-  @apply items-center justify-center relative;
-  background-color: or(--ls-create-whiteboard-background, --lx-gray-02, --ls-secondary-background-color);
+  @apply items-center justify-center relative border opacity-90 hover:shadow-lg;
+
+  background-color: var(--lx-gray-02, var(--ls-secondary-background-color, var(--rx-gray-02)));
   box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.06);
-  border: 1px solid transparent;
+
+  .ls-icon-plus, .dashboard-create-card-caption {
+    @apply opacity-60;
+  }
+
+  &:hover {
+    @apply opacity-100;
+
+    .ls-icon-plus, .dashboard-create-card-caption {
+      @apply opacity-90;
+    }
+  }
 }
 
 .dark .dashboard-create-card {
-  background-color: or(--ls-create-whiteboard-background, --lx-gray-03, --ls-secondary-background-color);
+  background-color: var(--lx-gray-03, var(--ls-secondary-background-color, var(--rx-gray-03)));
 }
 
 .dashboard-create-card i {
@@ -72,23 +83,14 @@ h1.title.whiteboard-dashboard-title {
   font-size: 14px;
 }
 
-.dashboard-create-card:hover {
-  background-color: var(--ls-selection-background-color);
-  box-shadow: 0 4px 8px -2px rgba(16, 24, 40, 0.1),
-  0 2px 4px -2px rgba(16, 24, 40, 0.06);
-  border: 1px solid var(--ls-page-blockquote-border-color);
-}
-
 .dashboard-card-title {
-  @apply px-4 py-3 flex flex-col;
-  gap: 4px;
-  border-bottom: 1px solid var(--ls-border-color);
-  background-color: or(--ls-whiteboard-card-title-background, --lx-gray-02, --ls-secondary-background-color);
-  font-size: 16px;
+  @apply px-4 py-3 flex flex-col gap-1 border-b;
+
+  background-color: var(--lx-gray-02, var(--ls-secondary-background-color, var(--rx-gray-02)));
 }
 
 .dark .dashboard-card-title {
-  background-color: or(--ls-whiteboard-card-title-background, --lx-gray-03, --ls-secondary-background-color);
+  background-color: var(--lx-gray-03, var(--ls-secondary-background-color, var(--rx-gray-03)));
 }
 
 .dashboard-card-title-name {
@@ -151,11 +153,11 @@ input.tl-text-input {
   z-index: 2000;
   gap: 4px;
   line-height: 1.4;
-  background: or(--ls-whiteboard-title-background, --lx-gray-01, --ls-primary-background-color);
+  background: var(--lx-gray-01, var(--ls-primary-background-color, hsl(var(--background))));
 }
 
 .dark .whiteboard-page-title-root {
-  background: or(--ls-whiteboard-title-background, --lx-gray-02, --ls-primary-background-color);
+  background: var(--lx-gray-02, var(--ls-primary-background-color, hsl(var(--background))));
 }
 
 .whiteboard-page-title {
@@ -180,7 +182,7 @@ input.tl-text-input {
   }
 
   .edit-input {
-    @apply h-full w-full p-0 border-none shadow-none;
+    @apply h-full w-full p-0 border-none shadow-none bg-transparent;
   }
 }
 

+ 3 - 1
src/main/frontend/dicts.cljc

@@ -59,6 +59,7 @@
    :pl      (edn-resource "dicts/pl.edn")
    :sk      (edn-resource "dicts/sk.edn")
    :uk      (edn-resource "dicts/uk.edn")
+   :fa      (edn-resource "dicts/fa.edn")
    :id      (edn-resource "dicts/id.edn")})
 
 (def languages
@@ -82,7 +83,8 @@
    {:label "Українська" :value :uk}
    {:label "한국어" :value :ko}
    {:label "Slovenčina" :value :sk}
+   {:label "فارسی" :value :fa}
    {:label "Bahasa Indonesia" :value :id}])
 
 (assert (= (set (keys dicts)) (set (map :value languages)))
-        "List of user-facing languages must match list of dictionaries")
+        "List of user-facing languages must match list of dictionaries")

+ 2 - 7
src/main/frontend/extensions/code.css

@@ -1,10 +1,5 @@
 .extensions__code {
-  @apply relative;
-  z-index: 0;
-  display: flex;
-  flex-direction: row;
-  flex-wrap: nowrap;
-  justify-content: space-between;
+  @apply relative z-0 flex flex-row flex-nowrap justify-between;
 
   &-lang {
     @apply p-1 text-sm;
@@ -51,7 +46,7 @@
   line-height: 1.45em;
 
   &-scroll {
-    padding-top: 18px;
+    padding-top: 14px;
     padding-bottom: 62px;
   }
 

+ 2 - 2
src/main/frontend/extensions/graph.cljs

@@ -51,9 +51,9 @@
   {:did-update pixi/render!
    :should-update (fn [old-state new-state]
                     (not= (select-keys (first (:rum/args old-state))
-                                       [:nodes :links :dark?])
+                                       [:nodes :links :dark? :link-dist :charge-strength :charge-range])
                           (select-keys (first (:rum/args new-state))
-                                       [:nodes :links :dark?])))
+                                       [:nodes :links :dark? :link-dist :charge-strength :charge-range])))
    :will-unmount (fn [state]
                    (reset! pixi/*graph-instance nil)
                    state)}

+ 44 - 11
src/main/frontend/extensions/graph/pixi.cljs

@@ -10,6 +10,8 @@
 
 (defonce *graph-instance (atom nil))
 (defonce *simulation (atom nil))
+(defonce *simulation-paused?
+  (atom false))
 
 (def Graph (gobj/get graphology "Graph"))
 
@@ -54,20 +56,34 @@
    :edge {:color "#A5B4FC"}})
 
 (defn layout!
-  [nodes links]
-  (let [nodes-count (count nodes)
-        simulation (forceSimulation nodes)]
+  "Node forces documentation can be read in more detail here https://d3js.org/d3-force"
+  [nodes links link-dist charge-strength charge-range]
+  (let [simulation (forceSimulation nodes)]
     (-> simulation
         (.force "link"
+                ;; The link force pushes linked nodes together or apart according to the desired link distance.
+                ;; The strength of the force is proportional to the difference between the linked nodes distance
+                ;; and the target distance, similar to a spring force.
                 (-> (forceLink)
                     (.id (fn [d] (.-id d)))
-                    (.distance 180)
+                    (.distance link-dist)
                     (.links links)))
         (.force "charge"
+                ;; The many-body (or n-body) force applies mutually amongst all nodes.
+                ;; It can be used to simulate gravity or electrostatic charge.
                 (-> (forceManyBody)
-                    (.distanceMax (if (> nodes-count 500) 4000 600))
+                    ;; The minimum distance between nodes over which this force is considered.
+                    ;; A minimum distance establishes an upper bound on the strength of the force between two nearby nodes, avoiding instability.
+                    (.distanceMin 1)
+                    ;; The maximum distance between nodes over which this force is considered.
+                    ;; Specifying a finite maximum distance improves performance and produces a more localized layout.
+                    (.distanceMax charge-range)
+                    ;; For a cluster of nodes that is far away, the charge force can be approximated by treating the cluster as a single, larger node.
+                    ;; The theta parameter determines the accuracy of the approximation
                     (.theta 0.5)
-                    (.strength -600)))
+                    ;; A positive value causes nodes to attract each other, similar to gravity,
+                    ;; while a negative value causes nodes to repel each other, similar to electrostatic charge.
+                    (.strength charge-strength)))
         (.force "collision"
                 (-> (forceCollide)
                     (.radius (+ 8 18))
@@ -75,7 +91,10 @@
         (.force "x" (-> (forceX 0) (.strength 0.02)))
         (.force "y" (-> (forceY 0) (.strength 0.02)))
         (.force "center" (forceCenter))
-        (.velocityDecay 0.8))
+        ;; The decay factor is akin to atmospheric friction; after the application of any forces during a tick,
+        ;; each node’s velocity is multiplied by 1 - decay. As with lowering the alpha decay rate,
+        ;; less velocity decay may converge on a better solution, but risks numerical instabilities and oscillation.
+        (.velocityDecay 0.5))
     (reset! *simulation simulation)
     simulation))
 
@@ -96,7 +115,20 @@
   (when-let [instance (:pixi @*graph-instance)]
     (.destroy instance)
     (reset! *graph-instance nil)
-    (reset! *simulation nil)))
+    (reset! *simulation nil))
+  (reset! *simulation-paused? false))
+
+(defn stop-simulation!
+  []
+  (when-let [^js simulation @*simulation]
+    (.stop simulation)
+    (reset! *simulation-paused? true)))
+
+(defn resume-simulation!
+  []
+  (when-let [^js simulation @*simulation]
+    (.restart simulation))
+  (reset! *simulation-paused? false))
 
 (defn- update-position!
   [node obj]
@@ -144,7 +176,8 @@
              #_:clj-kondo/ignore
              (when-let [node (.get nodes node-key)]
                (when-let [s @*simulation]
-                 (when-not (.-active event)
+                 (when-not (or (.-active event)
+                               @*simulation-paused?)
                    (-> (.alphaTarget s 0.3)
                        (.restart))
                    (js/setTimeout #(.alphaTarget s 0) 2000))
@@ -167,7 +200,7 @@
     (when @*graph-instance
       (clear-nodes! (:graph @*graph-instance))
       (destroy-instance!))
-    (let [{:keys [nodes links style hover-style height register-handlers-fn dark?]} (first (:rum/args state))
+    (let [{:keys [nodes links style hover-style height register-handlers-fn dark? link-dist charge-strength charge-range]} (first (:rum/args state))
           style                                                                     (or style (default-style dark?))
           hover-style                                                               (or hover-style (default-hover-style dark?))
           graph                                                                     (Graph.)
@@ -182,7 +215,7 @@
           links                                                                     (remove (fn [{:keys [source target]}] (or (nil? source) (nil? target))) links)
           nodes-js                                                                  (bean/->js nodes)
           links-js                                                                  (bean/->js links)
-          simulation                                                                (layout! nodes-js links-js)]
+          simulation                                                                (layout! nodes-js links-js link-dist charge-strength charge-range)]
       (doseq [node nodes-js]
         (try (.addNode graph (.-id node) node)
           (catch :default e

+ 27 - 22
src/main/frontend/extensions/handbooks/handbooks.css

@@ -13,7 +13,7 @@
       @apply dark:text-white px-3 pt-3 pb-2 sticky top-0 left-0 z-[4]
       transition-shadow duration-200;
 
-      background-color: var(--ls-tertiary-background-color);
+      background-color: var(--ls-tertiary-background-color1);
 
       .title {
         text-align: left;
@@ -33,11 +33,11 @@
       > .input-wrap {
         @apply mx-4 mb-2 flex rounded-lg mt-1.5;
 
-        border: 3px solid var(--ls-primary-background-color);
-        background-color: var(--ls-primary-background-color);
+        border: 3px solid var(--ls-primary-background-color1);
+        background-color: var(--ls-primary-background-color1);
 
         &:focus-within {
-          border: 3px solid var(--ls-secondary-border-color);
+          border: 3px solid var(--ls-secondary-border-color, var(--rx-gray-06));
         }
 
         > input {
@@ -76,7 +76,7 @@
       @apply text-sm px-3 py-2.5 rounded-lg cursor-pointer
       mb-2 active:opacity-90 select-none items-center;
 
-      background-color: var(--ls-secondary-background-color);
+      background-color: var(--ls-secondary-background-color1);
       border: 1px solid var(--ls-border-color);
       transition: background-color .3s;
 
@@ -104,7 +104,7 @@
       }
 
       &:hover, &.active {
-        background-color: var(--ls-primary-background-color);
+        background-color: var(--ls-primary-background-color1);
         border-color: var(--ls-secondary-border-color);
 
         > .l {
@@ -133,15 +133,15 @@
     .category-card {
       @apply flex rounded px-2 py-3 active:opacity-90 cursor-pointer transition-colors items-end;
 
-      border-left: 4px solid var(--ls-secondary-background-color);
-      background-color: var(--ls-secondary-background-color);
+      border-left: 4px solid var(--ls-secondary-background-color1);
+      background-color: var(--ls-secondary-background-color1);
 
       &[data-total="0"] {
         @apply hidden;
       }
 
       &:hover, &:active {
-        background-color: var(--ls-primary-background-color);
+        background-color: var(--ls-primary-background-color1);
       }
 
       > .icon-wrap {
@@ -282,7 +282,7 @@
           @apply relative flex flex-col rounded py-2 px-3 leading-5 select-none z-[1];
 
           color: var(--ls-primary-text-color);
-          background-color: var(--ls-secondary-background-color);
+          background-color: var(--ls-secondary-background-color1);
 
           small {
             @apply text-[11px] opacity-50 pl-0.5;
@@ -305,7 +305,7 @@
           ul {
             @apply absolute top-[58px] left-0 w-full list-none m-0 rounded-b py-2;
 
-            background-color: var(--ls-secondary-background-color);
+            background-color: var(--ls-secondary-background-color1);
             transform: translateY(-5px);
             max-height: 300px;
             overflow: auto;
@@ -314,7 +314,7 @@
               @apply list-none px-3 py-1 transition-colors text-sm;
 
               &:hover {
-                background-color: var(--ls-tertiary-background-color);
+                background-color: var(--ls-tertiary-background-color1);
               }
             }
           }
@@ -336,11 +336,16 @@
   }
 
   &-popup {
-    @apply fixed rounded-lg overflow-hidden
+    --ls-primary-background-color1: var(--ls-primary-background-color, var(--lx-gray-01, var(--rx-gray-02)));
+    --ls-secondary-background-color1: var(--ls-secondary-background-color, var(--lx-gray-03, var(--rx-gray-03)));
+    --ls-tertiary-background-color1: var(--ls-tertiary-background-color, var(--lx-gray-05, var(--rx-gray-05)));
+    --ls-quaternary-background-color1: var(--ls-quaternary-background-color, var(--lx-gray-08, var(--rx-gray-08)));
+
+    @apply fixed rounded-lg overflow-hidden border
     z-[19] shadow-lg flex justify-center flex-col;
 
-    background-color: var(--ls-tertiary-background-color);
-    border: 1px solid var(--ls-tertiary-background-color);
+    background-color: var(--ls-tertiary-background-color1);
+    border: 1px solid var(--ls-tertiary-background-color1);
     touch-action: none;
     height: 686px;
     max-height: 86vh;
@@ -352,7 +357,7 @@
 
 html[data-theme="light"] {
   .cp__handbooks-popup {
-    background-color: var(--ls-primary-background-color);
+    background-color: var(--ls-primary-background-color1);
 
     .input-wrap {
       background-color: #f1f1f1;
@@ -364,7 +369,7 @@ html[data-theme="light"] {
 
     .topic-card, :not(.as-primary).link-card {
       &:hover, &.active {
-        background-color: var(--ls-tertiary-background-color);
+        background-color: var(--ls-tertiary-background-color1);
         border-color: var(--ls-secondary-border-color);
       }
     }
@@ -372,27 +377,27 @@ html[data-theme="light"] {
 
   .cp__handbooks-content {
     .hd {
-      background-color: var(--ls-primary-background-color);
+      background-color: var(--ls-primary-background-color1);
     }
 
     .ft {
-      background-color: var(--ls-primary-background-color);
+      background-color: var(--ls-primary-background-color1);
     }
 
     .search {
-      background-color: var(--ls-primary-background-color);
+      background-color: var(--ls-primary-background-color1);
     }
 
     .chapters-select {
       .select-trigger {
-        background-color: var(--ls-tertiary-background-color);
+        background-color: var(--ls-tertiary-background-color1);
       }
     }
 
     .categories-list {
       .category-card {
         &:hover, &:active {
-          background-color: var(--ls-tertiary-background-color);
+          background-color: var(--ls-tertiary-background-color1);
         }
       }
     }

+ 2 - 2
src/main/frontend/extensions/pdf/core.cljs

@@ -808,8 +808,8 @@
 
     (let [^js viewer        (:viewer state)
           in-system-window? (some-> viewer (.-$inSystemWindow))]
-      [:div.extensions__pdf-viewer-cnt
-       [:div.extensions__pdf-viewer
+      [:div.extensions__pdf-viewer-cnt.visible-scrollbar
+       [:div.extensions__pdf-viewer.overflow-x-auto
         {:ref *el-ref :class (util/classnames [{:is-area-dashed area-dashed?}])}
         [:div.pdfViewer "viewer pdf"]
         [:div.pp-holder]

+ 12 - 18
src/main/frontend/extensions/pdf/pdf.css

@@ -425,15 +425,16 @@ input::-webkit-inner-spin-button {
   }
 
   &-resizer {
-    position: absolute;
-    width: 3px;
-    height: 88vh;
-    background-color: rgba(0, 0, 0, 0);
-    overflow: hidden;
-    z-index: 4;
-    top: 10vh;
-    cursor: col-resize;
-    right: 0;
+    @apply absolute w-[3px] h-screen overflow-hidden;
+    @apply z-10 right-0 cursor-col-resize;
+
+    transition: background-color 300ms;
+    transition-delay: 300ms;
+
+    &.is-active, &:hover,
+    &:focus, &:active {
+      @apply bg-primary/90;
+    }
   }
 
   &-hls-text-region {
@@ -841,14 +842,7 @@ input::-webkit-inner-spin-button {
     }
 
     .hl-area {
-      @apply relative;
-
-      display: inline-block;
-      cursor: text;
-      border: 1px solid #eee;
-      border-radius: 4px;
-      overflow: hidden;
-      margin-top: 4px;
+      @apply relative inline-block cursor-text border rounded-md overflow-hidden mt-1;
 
       .actions {
         @apply absolute right-1 top-1 flex opacity-0 transition-opacity;
@@ -936,7 +930,7 @@ body[data-page] {
     }
 
     &-viewer-cnt {
-      display: flex;
+      @apply flex overflow-x-hidden;
     }
 
     &-highlights {

+ 9 - 7
src/main/frontend/extensions/tldraw.cljs

@@ -23,6 +23,7 @@
             [rum.core :as rum]
             [frontend.ui :as ui]
             [frontend.components.whiteboard :as whiteboard]
+            [cljs-bean.core :as bean]
             [frontend.db.async :as db-async]))
 
 (def tldraw (r/adapt-class (gobj/get TldrawLogseq "App")))
@@ -82,13 +83,14 @@
          (map (fn [k] (js->clj (gobj/get props k) {:keywordize-keys true})) ["id" "className" "options"])))
 
 (rum/defc keyboard-shortcut
-  [props]
-  (let [action (gobj/get props "action")
-        sequence (or (gobj/get props "sequence")
-                     (ui/keyboard-shortcut-from-config (keyword action)))]
-    (cond
-      (string? sequence) (ui/render-keyboard-shortcut sequence)
-      :else (interpose " | " (map ui/render-keyboard-shortcut sequence)))))
+  [^js props]
+  (when-let [props (bean/->clj props)]
+    (let [{:keys [action shortcut opts]} props
+          shortcut (if (string? action) (ui/keyboard-shortcut-from-config (keyword action)) shortcut)
+          opts (merge {:interactive? false} opts)]
+      (cond
+        (string? shortcut) (ui/render-keyboard-shortcut shortcut opts)
+        :else (interpose " | " (map #(ui/render-keyboard-shortcut % opts) shortcut))))))
 
 (def tldraw-renderers {:Page page-cp
                        :Block block-cp

+ 7 - 3
src/main/frontend/extensions/video/youtube.cljs

@@ -51,16 +51,20 @@
        (<! (load-youtube-api))
        (register-player state))
      state)}
-  [state id {:keys [width height] :as _opts}]
+  [state id {:keys [width height start] :as _opts}]
   (let [width  (or width (min (- (util/get-width) 96)
                               560))
-        height (or height (int (* width (/ 315 560))))]
+        height (or height (int (* width (/ 315 560))))
+        url (str "https://www.youtube.com/embed/" id "?enablejsapi=1")
+        url (if start
+              (str url "&start=" start)
+              url)]
     [:iframe
      {:id                (str "youtube-player-" id)
       :allow-full-screen "allowfullscreen"
       :allow             "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope"
       :frame-border      "0"
-      :src               (str "https://www.youtube.com/embed/" id "?enablejsapi=1")
+      :src               url
       :height            height
       :width             width}]))
 

+ 1 - 1
src/main/frontend/handler/db_based/editor.cljs

@@ -73,7 +73,7 @@
 (defn wrap-parse-block
   [{:block/keys [content left level tags] :as block}]
   (let [block (or (and (:db/id block) (db/pull (:db/id block))) block)
-        block (if (string/blank? content)
+        block (if (nil? content)
                 block
                 (let [ast (mldoc/->edn (string/trim content) :markdown)
                       first-elem-type (first (ffirst ast))

+ 4 - 10
src/main/frontend/handler/editor/lifecycle.cljs

@@ -30,24 +30,18 @@
   state)
 
 (defn will-remount!
-  [old-state state]
+  [_old-state state]
   (keyboards-handler/esc-save! state)
-  (let [old-content (:block/content (:block (first (:rum/args old-state))))
-        new-content (:block/content (:block (first (:rum/args state))))
-        input (state/get-input)]
-    (when (and input (not= old-content new-content))
-      (set! (.-new-value input) new-content))
-    state))
+  state)
 
 (defn will-unmount
   [state]
-  (let [{:keys [value block node] :as state} (editor-handler/get-state)
-        new-value (or (and node (.-new-value node)) value)]
+  (let [{:keys [value block] :as state} (editor-handler/get-state)]
     (editor-handler/clear-when-saved!)
     (when (db/entity [:block/uuid (:block/uuid block)]) ; block still exists
       (when-not (or (contains? #{:undo :redo} (state/get-editor-op))
                     (state/editor-in-composition?))
-        (editor-handler/save-block! state new-value))))
+        (editor-handler/save-block! state value))))
   state)
 
 (def lifecycle

+ 217 - 203
src/main/frontend/handler/events.cljs

@@ -13,6 +13,7 @@
             [frontend.commands :as commands]
             [frontend.components.class :as class-component]
             [frontend.components.cmdk :as cmdk]
+            [frontend.components.settings :as settings]
             [frontend.components.diff :as diff]
             [frontend.components.encryption :as encryption]
             [frontend.components.file-sync :as file-sync]
@@ -88,12 +89,12 @@
 
 (defn file-sync-restart! []
   (async/go (async/<! (p->c (persist-var/load-vars)))
-            (async/<! (sync/<sync-stop))
-            (some-> (sync/<sync-start) async/<!)))
+    (async/<! (sync/<sync-stop))
+    (some-> (sync/<sync-start) async/<!)))
 
 (defn- file-sync-stop! []
   (async/go (async/<! (p->c (persist-var/load-vars)))
-            (async/<! (sync/<sync-stop))))
+    (async/<! (sync/<sync-stop))))
 
 (defn- enable-beta-features!
   []
@@ -119,9 +120,9 @@
               (p/let [repos (repo-handler/refresh-repos!)]
                 (when-let [repo (state/get-current-repo)]
                   (when (some #(and (= (:url %) repo)
-                                    (vector? (:sync-meta %))
-                                    (util/uuid-string? (first (:sync-meta %)))
-                                    (util/uuid-string? (second (:sync-meta %)))) repos)
+                                 (vector? (:sync-meta %))
+                                 (util/uuid-string? (first (:sync-meta %)))
+                                 (util/uuid-string? (second (:sync-meta %)))) repos)
                     (sync/<sync-start)))))
             (ui-handler/re-render-root!)
             (file-sync/maybe-onboarding-show status)))))))
@@ -168,7 +169,7 @@
        (do
          (state/set-current-repo! graph)
          (page-handler/init-commands!)
-       ;; load config
+         ;; load config
          (repo-config-handler/restore-repo-config! graph)
          (when-not (= :draw (state/get-current-route))
            (route-handler/redirect-to-home!))
@@ -184,9 +185,9 @@
   "graph: the target graph to switch to"
   [graph _opts]
   (p/do!
-   (repo-handler/restore-and-setup-repo! graph)
-   (graph-switch graph)
-   (state/set-state! :sync-graph/init? false)))
+    (repo-handler/restore-and-setup-repo! graph)
+    (graph-switch graph)
+    (state/set-state! :sync-graph/init? false)))
 
 (defmethod handle :graph/switch [[_ graph opts]]
   (state/set-state! :db/async-queries #{})
@@ -198,13 +199,13 @@
       (if (or (not request-finished?) (not writes-finished?)) ; TODO: test (:sync-graph/init? @state/state)
         (do
           (log/info :graph/switch (cond->
-                                   {:request-finished? request-finished?
-                                    :file-writes-finished? writes-finished?}
+                                    {:request-finished? request-finished?
+                                     :file-writes-finished? writes-finished?}
                                     (false? request-finished?)
                                     (assoc :unfinished-requests? @ldb/*request-id->response)))
           (notification/show!
-           "Please wait seconds until all changes are saved for the current graph."
-           :warning))
+            "Please wait seconds until all changes are saved for the current graph."
+            :warning))
         (graph-switch-on-persisted graph opts)))))
 
 (defmethod handle :graph/pull-down-remote-graph [[_ graph dir-name]]
@@ -218,33 +219,33 @@
           (when-let [root (state/get-local-container-root-url)]
             (let [graph-path (graph-picker/validate-graph-dirname root graph-name)]
               (->
-               (p/let [exists? (fs/dir-exists? graph-path)]
-                 (let [overwrite? (if exists?
-                                    (js/confirm (str "There's already a directory with the name \"" graph-name "\", do you want to overwrite it? Make sure to backup it first if you're not sure about it."))
-                                    true)]
-                   (if overwrite?
-                     (p/let [_ (fs/mkdir-if-not-exists graph-path)]
-                       (nfs-handler/ls-dir-files-with-path!
-                        graph-path
-                        {:ok-handler (fn []
-                                       (file-sync-handler/init-remote-graph graph-path graph)
-                                       (js/setTimeout (fn [] (repo-handler/refresh-repos!)) 200))}))
-                     (let [graph-name (-> (js/prompt "Please specify a new directory name to download the graph:")
-                                          str
-                                          string/trim)]
-                       (when-not (string/blank? graph-name)
-                         (state/pub-event! [:graph/pull-down-remote-graph graph graph-name]))))))
-               (p/catch (fn [^js e]
-                          (notification/show! (str e) :error)
-                          (js/console.error e)))))))))
+                (p/let [exists? (fs/dir-exists? graph-path)]
+                  (let [overwrite? (if exists?
+                                     (js/confirm (str "There's already a directory with the name \"" graph-name "\", do you want to overwrite it? Make sure to backup it first if you're not sure about it."))
+                                     true)]
+                    (if overwrite?
+                      (p/let [_ (fs/mkdir-if-not-exists graph-path)]
+                        (nfs-handler/ls-dir-files-with-path!
+                          graph-path
+                          {:ok-handler (fn []
+                                         (file-sync-handler/init-remote-graph graph-path graph)
+                                         (js/setTimeout (fn [] (repo-handler/refresh-repos!)) 200))}))
+                      (let [graph-name (-> (js/prompt "Please specify a new directory name to download the graph:")
+                                         str
+                                         string/trim)]
+                        (when-not (string/blank? graph-name)
+                          (state/pub-event! [:graph/pull-down-remote-graph graph graph-name]))))))
+                (p/catch (fn [^js e]
+                           (notification/show! (str e) :error)
+                           (js/console.error e)))))))))
     (state/set-modal!
-     (file-sync/pick-dest-to-sync-panel graph)
-     {:center? true})))
+      (file-sync/pick-dest-to-sync-panel graph)
+      {:center? true})))
 
 (defmethod handle :graph/pick-page-histories [[_ graph-uuid page-name]]
   (state/set-modal!
-   (file-sync/pick-page-histories-panel graph-uuid page-name)
-   {:id :page-histories :label "modal-page-histories"}))
+    (file-sync/pick-page-histories-panel graph-uuid page-name)
+    {:id :page-histories :label "modal-page-histories"}))
 
 (defmethod handle :graph/open-new-window [[_ev target-repo]]
   (p/let [current-repo (state/get-current-repo)]
@@ -263,19 +264,19 @@
   [repo]
   (when
    (and (not (util/electron?))
-        (not (mobile-util/native-platform?)))
+     (not (mobile-util/native-platform?)))
     (fn [close-fn]
       [:div
-      ;; TODO: fn translation with args
+       ;; TODO: fn translation with args
        [:p
         "Grant native filesystem permission for directory: "
         [:b (config/get-local-dir repo)]]
        (ui/button
-        (t :settings-permission/start-granting)
-        :class "ui__modal-enter"
-        :on-click (fn []
-                    (nfs/check-directory-permission! repo)
-                    (close-fn)))])))
+         (t :settings-permission/start-granting)
+         :class "ui__modal-enter"
+         :on-click (fn []
+                     (nfs/check-directory-permission! repo)
+                     (close-fn)))])))
 
 (defmethod handle :modal/nfs-ask-permission []
   (when-let [repo (get-local-repo)]
@@ -283,9 +284,9 @@
 
 (defonce *query-properties (atom {}))
 (rum/defc query-properties-settings-inner < rum/reactive
-  {:will-unmount (fn [state]
-                   (reset! *query-properties {})
-                   state)}
+                                            {:will-unmount (fn [state]
+                                                             (reset! *query-properties {})
+                                                             state)}
   [block shown-properties all-properties]
   (let [query-properties (rum/react *query-properties)]
     [:div.p-4
@@ -305,15 +306,15 @@
          [:div.flex.flex-row.m-2.justify-between.align-items
           [:div (if (uuid? property) (db-pu/get-property-name property) (name property))]
           [:div.mt-1 (ui/toggle shown?
-                                (fn []
-                                  (let [value (not shown?)]
-                                    (swap! *query-properties assoc property value)
-                                    (editor-handler/set-block-query-properties!
-                                     (:block/uuid block)
-                                     all-properties
-                                     property
-                                     value)))
-                                true)]]))]))
+                       (fn []
+                         (let [value (not shown?)]
+                           (swap! *query-properties assoc property value)
+                           (editor-handler/set-block-query-properties!
+                             (:block/uuid block)
+                             all-properties
+                             property
+                             value)))
+                       true)]]))]))
 
 (defn query-properties-settings
   [block shown-properties all-properties]
@@ -326,13 +327,13 @@
         block-properties (if (config/db-based-graph? (state/get-current-repo))
                            query-properties
                            (some-> query-properties
-                                   (common-handler/safe-read-string "Parsing query properties failed")))
+                             (common-handler/safe-read-string "Parsing query properties failed")))
         shown-properties (if (seq block-properties)
                            (set block-properties)
                            (set all-properties))
         shown-properties (set/intersection (set all-properties) shown-properties)]
     (state/set-modal! (query-properties-settings block shown-properties all-properties)
-                      {:center? true})))
+      {:center? true})))
 
 (defmethod handle :modal/show-cards [_]
   (state/set-modal! srs/global-cards {:id :srs
@@ -345,6 +346,17 @@
 (defmethod handle :modal/show-themes-modal [_]
   (plugin/open-select-theme!))
 
+(defmethod handle :modal/toggle-accent-colors-modal [_]
+  (let [label "accent-colors-picker"]
+    (if (or (= label (state/get-modal-id))
+          (= label (some-> (state/get-sub-modals) (first) :modal/id)))
+      (state/close-sub-modal! label)
+      (state/set-sub-modal!
+        #(settings/modal-accent-colors-inner)
+        {:center? true
+         :id      label
+         :label   label}))))
+
 (rum/defc modal-output
   [content]
   content)
@@ -376,11 +388,11 @@
       (p/let [writes-finished? (when sqlite (.file-writes-finished? sqlite (state/get-current-repo)))
               request-finished? (ldb/request-finished?)]
         (prn :debug :writes-finished? writes-finished?
-             :request-finished? request-finished?)
+          :request-finished? request-finished?)
         (when (and request-finished? writes-finished? disk-content db-content
-                   (not= (util/trim-safe disk-content) (util/trim-safe db-content)))
+                (not= (util/trim-safe disk-content) (util/trim-safe db-content)))
           (state/set-modal! #(diff/local-file repo path disk-content db-content)
-                            {:label "diff__cp"}))))))
+            {:label "diff__cp"}))))))
 
 
 (defmethod handle :modal/display-file-version-selector  [[_ versions path  get-content]]
@@ -395,7 +407,7 @@
     (p/let [dir               (config/get-repo-dir repo)
             dir-exists?       (fs/dir-exists? dir)]
       (when (and (not dir-exists?)
-                 (not util/nfs?))
+              (not util/nfs?))
         (state/pub-event! [:graph/dir-gone dir]))))
   (p/let [;; re-render-root is async and delegated to rum, so we need to wait for main ui to refresh
           _ (js/setTimeout #(mobile/mobile-postinit) 1000)
@@ -413,10 +425,10 @@
 
 (defmethod handle :go/search [_]
   (state/set-modal! cmdk/cmdk-modal
-                    {:fullscreen? true
-                     :close-btn?  false
-                     :panel?      false
-                     :label "ls-modal-search"}))
+    {:fullscreen? true
+     :close-btn?  false
+     :panel?      false
+     :label "ls-modal-search"}))
 
 (defmethod handle :go/plugins [_]
   (plugin/open-plugins-modal!))
@@ -437,8 +449,8 @@
 
 (defmethod handle :go/proxy-settings [[_ agent-opts]]
   (state/set-sub-modal!
-   (fn [_] (plugin/user-proxy-settings-panel agent-opts))
-   {:id :https-proxy-panel :center? true}))
+    (fn [_] (plugin/user-proxy-settings-panel agent-opts))
+    {:id :https-proxy-panel :center? true}))
 
 
 (defmethod handle :redirect-to-home [_]
@@ -452,11 +464,11 @@
 (defmethod handle :capture-error [[_ {:keys [error payload]}]]
   (let [[user-uuid graph-uuid tx-id] @sync/graphs-txid
         payload (assoc payload
-                       :user-id user-uuid
-                       :graph-id graph-uuid
-                       :tx-id tx-id)]
+                  :user-id user-uuid
+                  :graph-id graph-uuid
+                  :tx-id tx-id)]
     (Sentry/captureException error
-                             (bean/->js {:tags payload}))))
+      (bean/->js {:tags payload}))))
 
 (defmethod handle :exec-plugin-cmd [[_ {:keys [pid cmd action]}]]
   (commands/exec-plugin-simple-command! pid cmd action))
@@ -490,7 +502,7 @@
       (js/setTimeout (fn []
                        (when-let [toolbar (.querySelector main-node "#mobile-editor-toolbar")]
                          (set! (.. toolbar -style -bottom) (str keyboard-height "px"))))
-                     100))))
+        100))))
 
 (defmethod handle :mobile/keyboard-will-hide [[_]]
   (let [main-node (util/app-scroll-container-node)]
@@ -518,8 +530,8 @@
   [repo-url]
   (when repo-url
     (let [app-id (-> (first (string/split repo-url "/Documents"))
-                     (string/split "/")
-                     last)]
+                   (string/split "/")
+                   last)]
       app-id)))
 
 (defmethod handle :validate-appId [[_ graph-switch-f graph]]
@@ -534,13 +546,13 @@
               current-document-url (.getUri Filesystem #js {:path ""
                                                             :directory (.-Documents Directory)})
               current-app-id (-> (js->clj current-document-url :keywordize-keys true)
-                                 get-ios-app-id)]
+                               get-ios-app-id)]
         (if (= deprecated-app-id current-app-id)
           (when graph-switch-f (graph-switch-f graph true))
           (do
             (notification/show! [:div "Migrating from previous App installation..."]
-                                :warning
-                                true)
+              :warning
+              true)
             (prn ::migrate-app-id :from deprecated-app-id :to current-app-id)
             (file-sync-stop!)
             (.unwatch mobile-util/fs-watcher)
@@ -549,11 +561,11 @@
               (try
                 ;; replace app-id part of repo url
                 (reset! conn/conns
-                        (update-keys @conn/conns
-                                     (fn [key]
-                                       (if (string/includes? key deprecated-app-id)
-                                         (string/replace key deprecated-app-id current-app-id)
-                                         key))))
+                  (update-keys @conn/conns
+                    (fn [key]
+                      (if (string/includes? key deprecated-app-id)
+                        (string/replace key deprecated-app-id current-app-id)
+                        key))))
                 (db-persist/rename-graph! deprecated-repo current-repo)
                 (search/remove-db! deprecated-repo)
                 (state/add-repo! {:url current-repo :nfs? true})
@@ -571,7 +583,7 @@
   (let [downloading?   (:plugin/updates-downloading? @state/state)
         auto-checking? (plugin-handler/get-auto-checking?)]
     (when-let [coming (and (not downloading?)
-                           (get-in @state/state [:plugin/updates-coming id]))]
+                        (get-in @state/state [:plugin/updates-coming id]))]
       (let [error-code (:error-code coming)
             error-code (if (= error-code (str :no-new-version)) nil error-code)
             title      (:title coming)]
@@ -579,14 +591,14 @@
           (if-not error-code
             (plugin/set-updates-sub-content! (str title "...") 0)
             (notification/show!
-             (str "[Checked]<" title "> " error-code) :error)))))
+              (str "[Checked]<" title "> " error-code) :error)))))
 
     (if (and updated? downloading?)
       ;; try to start consume downloading item
       (if-let [next-coming (state/get-next-selected-coming-update)]
         (plugin-handler/check-or-update-marketplace-plugin!
-         (assoc next-coming :only-check false :error-code nil)
-         (fn [^js e] (js/console.error "[Download Err]" next-coming e)))
+          (assoc next-coming :only-check false :error-code nil)
+          (fn [^js e] (js/console.error "[Download Err]" next-coming e)))
         (plugin-handler/close-updates-downloading))
 
       ;; try to start consume pending item
@@ -594,29 +606,29 @@
         (do
           (println "Updates: take next pending - " (:id next-pending))
           (js/setTimeout
-           #(plugin-handler/check-or-update-marketplace-plugin!
-             (assoc next-pending :only-check true :auto-check auto-checking? :error-code nil)
-             (fn [^js e]
-               (notification/show! (.toString e) :error)
-               (js/console.error "[Check Err]" next-pending e))) 500))
+            #(plugin-handler/check-or-update-marketplace-plugin!
+               (assoc next-pending :only-check true :auto-check auto-checking? :error-code nil)
+               (fn [^js e]
+                 (notification/show! (.toString e) :error)
+                 (js/console.error "[Check Err]" next-pending e))) 500))
 
         ;; try to open waiting updates list
         (do (when (and prev-pending? (not auto-checking?)
-                       (seq (state/all-available-coming-updates)))
+                    (seq (state/all-available-coming-updates)))
               (plugin/open-waiting-updates-modal!))
             (plugin-handler/set-auto-checking! false))))))
 
 (defmethod handle :plugin/hook-db-tx [[_ {:keys [blocks tx-data] :as payload}]]
   (when-let [payload (and (seq blocks)
-                          (merge payload {:tx-data (map #(into [] %) tx-data)}))]
+                       (merge payload {:tx-data (map #(into [] %) tx-data)}))]
     (plugin-handler/hook-plugin-db :changed payload)
     (plugin-handler/hook-plugin-block-changes payload)))
 
 (defmethod handle :plugin/loader-perf-tip [[_ {:keys [^js o _s _e]}]]
   (when-let [opts (.-options o)]
     (notification/show!
-     (plugin/perf-tip-content (.-id o) (.-name opts) (.-url opts))
-     :warning false (.-id o))))
+      (plugin/perf-tip-content (.-id o) (.-name opts) (.-url opts))
+      :warning false (.-id o))))
 
 (defmethod handle :mobile-file-watcher/changed [[_ ^js event]]
   (let [type (.-event event)
@@ -637,16 +649,16 @@
 
 (defmethod handle :graph/ask-for-re-fresh [_]
   (handle
-   [:modal/show
-    [:div {:style {:max-width 700}}
-     [:p (t :sync-from-local-changes-detected)]
-     (ui/button
-      (t :yes)
-      :autoFocus "on"
-      :class "ui__modal-enter"
-      :on-click (fn []
-                  (state/close-modal!)
-                  (nfs-handler/refresh! (state/get-current-repo) refresh-cb)))]]))
+    [:modal/show
+     [:div {:style {:max-width 700}}
+      [:p (t :sync-from-local-changes-detected)]
+      (ui/button
+        (t :yes)
+        :autoFocus "on"
+        :class "ui__modal-enter"
+        :on-click (fn []
+                    (state/close-modal!)
+                    (nfs-handler/refresh! (state/get-current-repo) refresh-cb)))]]))
 
 (defmethod handle :sync/create-remote-graph [[_ current-repo]]
   (let [graph-name (js/decodeURI (util/node-path.basename current-repo))]
@@ -660,21 +672,21 @@
         (state/set-repos! (map (fn [r]
                                  (if (= (:url r) current-repo)
                                    (assoc r
-                                          :GraphUUID GraphUUID
-                                          :GraphName graph-name
-                                          :remote? true)
+                                     :GraphUUID GraphUUID
+                                     :GraphName graph-name
+                                     :remote? true)
                                    r))
-                               (state/get-repos)))))))
+                            (state/get-repos)))))))
 
 (defmethod handle :modal/remote-encryption-input-pw-dialog [[_ repo-url remote-graph-info type opts]]
   (state/set-modal!
-   (encryption/input-password
-    repo-url nil (merge
-                  (assoc remote-graph-info
-                         :type (or type :create-pwd-remote)
-                         :repo repo-url)
-                  opts))
-   {:center? true :close-btn? false :close-backdrop? false}))
+    (encryption/input-password
+      repo-url nil (merge
+                     (assoc remote-graph-info
+                       :type (or type :create-pwd-remote)
+                       :repo repo-url)
+                     opts))
+    {:center? true :close-btn? false :close-backdrop? false}))
 
 (defmethod handle :journal/insert-template [[_ page-name]]
   (let [page-name (util/page-name-sanity-lc page-name)]
@@ -682,9 +694,9 @@
       (when (db/page-empty? (state/get-current-repo) page-name)
         (when-let [template (state/get-default-journal-template)]
           (editor-handler/insert-template!
-           nil
-           template
-           {:target page}))))))
+            nil
+            template
+            {:target page}))))))
 
 (defmethod handle :editor/set-org-mode-heading [[_ block heading]]
   (when-let [id (:block/uuid block)]
@@ -695,31 +707,31 @@
     (let [file (:block/file page-entity)]
       (when-let [path (:file/path file)]
         (when (and (not= content (:file/content file))
-                   (:file/content file))
+                (:file/content file))
           (sync/add-new-version-file graph path (:file/content file)))
         (p/let [_ (file-handler/alter-file graph
-                                           path
-                                           content
-                                           {:re-render-root? true
-                                            :skip-compare? true})]
+                    path
+                    content
+                    {:re-render-root? true
+                     :skip-compare? true})]
           (state/close-modal!)
           (route-handler/redirect! {:to :page
                                     :path-params {:name (:block/name page-entity)}}))))))
 
 (defmethod handle :whiteboard/onboarding [[_ opts]]
   (state/set-modal!
-   (fn [close-fn] (whiteboard/onboarding-welcome close-fn))
-   (merge {:close-btn?      false
-           :center?         true
-           :close-backdrop? false} opts)))
+    (fn [close-fn] (whiteboard/onboarding-welcome close-fn))
+    (merge {:close-btn?      false
+            :center?         true
+            :close-backdrop? false} opts)))
 
 (defmethod handle :file-sync/onboarding-tip [[_ type opts]]
   (let [type (keyword type)]
     (state/set-modal!
-     (file-sync/make-onboarding-panel type)
-     (merge {:close-btn?      false
-             :center?         true
-             :close-backdrop? (not= type :welcome)} opts))))
+      (file-sync/make-onboarding-panel type)
+      (merge {:close-btn?      false
+              :center?         true
+              :close-backdrop? (not= type :welcome)} opts))))
 
 (defmethod handle :file-sync/maybe-onboarding-show [[_ type]]
   (file-sync/maybe-onboarding-show type))
@@ -765,24 +777,24 @@
 
 (defmethod handle :ui/notify-skipped-downloading-files [[_ paths]]
   (notification/show!
-   [:div
-    [:div.mb-4
-     [:div.font-semibold.mb-4.text-xl "It seems that some of your filenames are in the outdated format."]
-     [:p
-      "The files below that have reserved characters can't be saved on this device."]
-     [:div.overflow-y-auto.max-h-96
-      [:ol.my-2
-       (for [path paths]
-         [:li path])]]
-
-     [:div
+    [:div
+     [:div.mb-4
+      [:div.font-semibold.mb-4.text-xl "It seems that some of your filenames are in the outdated format."]
       [:p
-       "Check " [:a {:href "https://docs.logseq.com/#/page/logseq%20file%20and%20folder%20naming%20rules"
-                     :target "_blank"}
-                 "Logseq file and folder naming rules"]
-       " for more details."]]]]
-   :warning
-   false))
+       "The files below that have reserved characters can't be saved on this device."]
+      [:div.overflow-y-auto.max-h-96
+       [:ol.my-2
+        (for [path paths]
+          [:li path])]]
+
+      [:div
+       [:p
+        "Check " [:a {:href "https://docs.logseq.com/#/page/logseq%20file%20and%20folder%20naming%20rules"
+                      :target "_blank"}
+                  "Logseq file and folder naming rules"]
+        " for more details."]]]]
+    :warning
+    false))
 
 (defmethod handle :graph/setup-a-repo [[_ opts]]
   (let [opts' (merge {:picked-root-fn #(state/close-modal!)
@@ -790,37 +802,37 @@
                       :logged?        (user-handler/logged-in?)} opts)]
     (if (mobile-util/native-ios?)
       (state/set-modal!
-       #(graph-picker/graph-picker-cp opts')
-       {:label "graph-setup"})
+        #(graph-picker/graph-picker-cp opts')
+        {:label "graph-setup"})
       (page-handler/ls-dir-files! st/refresh! opts'))))
 
 (defmethod handle :graph/new-db-graph [[_ _opts]]
   (state/set-modal!
-   repo/new-db-graph
-   {:id :new-db-graph
-    :label "graph-setup"}))
+    repo/new-db-graph
+    {:id :new-db-graph
+     :label "graph-setup"}))
 
 (defmethod handle :search/transact-data [[_ repo data]]
   (let [file-based? (config/local-file-based-graph? repo)
         data' (cond-> data
                 file-based?
-                        ;; remove built-in properties from content
+                ;; remove built-in properties from content
                 (update :blocks-to-add
-                        (fn [blocks]
-                          (map #(update % :content
-                                        (fn [content]
-                                          (property-util/remove-built-in-properties (get % :format :markdown) content)))
-                               blocks))))]
+                  (fn [blocks]
+                    (map #(update % :content
+                            (fn [content]
+                              (property-util/remove-built-in-properties (get % :format :markdown) content)))
+                      blocks))))]
     (search/transact-blocks! repo data')))
 
 (defmethod handle :class/configure [[_ page]]
   (state/set-modal!
-   #(vector :<>
-            (class-component/configure page {})
-            (db-page/page-properties page {:configure? true}))
-   {:id :page-configure
-    :label "page-configure"
-    :container-overflow-visible? true}))
+    #(vector :<>
+       (class-component/configure page {})
+       (db-page/page-properties page {:configure? true}))
+    {:id :page-configure
+     :label "page-configure"
+     :container-overflow-visible? true}))
 
 (defmethod handle :file/alter [[_ repo path content]]
   (p/let [_ (file-handler/alter-file repo path content {:from-disk? true})]
@@ -844,21 +856,21 @@
         [:div
          [:p
           (str "It seems that another whiteboard file already has the ID \"" id
-               "\". You can fix it by changing the ID in this file with another UUID.")]
+            "\". You can fix it by changing the ID in this file with another UUID.")]
          [:p
           "Or, let me"
           (ui/button "Fix"
-                     :on-click (fn []
-                                 (let [dir (config/get-repo-dir repo)]
-                                   (p/let [content (fs/read-file dir file)]
-                                     (let [new-content (string/replace content (str id) (str (random-uuid)))]
-                                       (p/let [_ (fs/write-file! repo
-                                                                 dir
-                                                                 file
-                                                                 new-content
-                                                                 {})]
-                                         (reset! resolved? true))))))
-                     :class "inline mx-1")
+            :on-click (fn []
+                        (let [dir (config/get-repo-dir repo)]
+                          (p/let [content (fs/read-file dir file)]
+                            (let [new-content (string/replace content (str id) (str (random-uuid)))]
+                              (p/let [_ (fs/write-file! repo
+                                          dir
+                                          file
+                                          new-content
+                                          {})]
+                                (reset! resolved? true))))))
+            :class "inline mx-1")
           "it."]])]]))
 
 (defmethod handle :file/parse-and-load-error [[_ repo parse-errors]]
@@ -870,10 +882,10 @@
                         (for [[file error] parse-errors]
                           (let [data (ex-data error)]
                             (cond
-                             (and (common-config/whiteboard? file)
-                                  (= :transact/upsert (:error data))
-                                  (uuid? (last (:assertion data))))
-                             (rum/with-key (file-id-conflict-item repo file data) file)
+                              (and (common-config/whiteboard? file)
+                                (= :transact/upsert (:error data))
+                                (uuid? (last (:assertion data))))
+                              (rum/with-key (file-id-conflict-item repo file data) file)
 
                               :else
                               (do
@@ -918,16 +930,18 @@
   (when-let [blocks (and block (db-model/get-block-immediate-children (state/get-current-repo) (:block/uuid block)))]
     (editor-handler/toggle-blocks-as-own-order-list! blocks)))
 
-(defmethod handle :editor/new-property [[_]]
+(defmethod handle :editor/new-property [[_ property-key]]
   (p/do!
     (when-let [edit-block (state/get-edit-block)]
-     (when-let [block-id (:block/uuid edit-block)]
-       (let [block (db/entity [:block/uuid block-id])
-             collapsed? (or (get-in @state/state [:ui/collapsed-blocks (state/get-current-repo) block-id])
-                            (:block/collapsed? block))]
-         (when collapsed?
-           (editor-handler/set-blocks-collapsed! [block-id] false)))))
+      (when-let [block-id (:block/uuid edit-block)]
+        (let [block (db/entity [:block/uuid block-id])
+              collapsed? (or (get-in @state/state [:ui/collapsed-blocks (state/get-current-repo) block-id])
+                           (:block/collapsed? block))]
+          (when collapsed?
+            (editor-handler/set-blocks-collapsed! [block-id] false)))))
     (editor-handler/save-current-block!)
+    (when property-key
+      (state/set-state! :editor/new-property-key property-key))
     (property-handler/editing-new-property!)))
 
 (rum/defc multi-tabs-dialog
@@ -936,7 +950,7 @@
     [:div.flex.p-4.flex-col.gap-4.h-64
      [:span.warning.text-lg
       (util/format "Logseq doesn't support multiple %ss access to the same graph yet, please close this %s or switch to another graph."
-                   word word)]
+        word word)]
      [:div.text-lg
       [:p "Switch to another repo: "]
       (repo/repos-dropdown {:on-click (fn [e]
@@ -967,18 +981,18 @@
     (async/go-loop []
       (let [[payload d] (async/<! chan)]
         (->
-         (try
-           (p/resolved (handle payload))
-           (catch :default error
-             (p/rejected error)))
-         (p/then (fn [result]
-                   (p/resolve! d result)))
-         (p/catch (fn [error]
-                    (let [type :handle-system-events/failed]
-                      (state/pub-event! [:capture-error {:error error
-                                                         :payload {:type type
-                                                                   :payload payload}}])
-                      (p/reject! d error))))))
+          (try
+            (p/resolved (handle payload))
+            (catch :default error
+              (p/rejected error)))
+          (p/then (fn [result]
+                    (p/resolve! d result)))
+          (p/catch (fn [error]
+                     (let [type :handle-system-events/failed]
+                       (state/pub-event! [:capture-error {:error error
+                                                          :payload {:type type
+                                                                    :payload payload}}])
+                       (p/reject! d error))))))
       (recur))
     chan))
 

+ 359 - 359
src/main/frontend/modules/shortcut/config.cljs

@@ -416,7 +416,7 @@
                                              :fn      (fn [] (js/document.execCommand "copy"))}
 
    :graph/export-as-html                    {:fn      #(export-handler/download-repo-as-html!
-                                                        (state/get-current-repo))
+                                                         (state/get-current-repo))
                                              :binding []}
 
    :graph/open                              {:fn      #(do
@@ -547,11 +547,11 @@
    :editor/toggle-open-blocks               {:binding "t o"
                                              :fn      editor-handler/toggle-open!}
 
-   :ui/cycle-color-off                      {:binding "c o"
+   :ui/accent-color-reset                   {:binding "c o"
                                              :fn      state/unset-color-accent!}
 
-   :ui/cycle-color                          {:binding "c c"
-                                             :fn      state/cycle-color!}
+   :ui/accent-colors-picker                 {:binding "c c"
+                                             :fn      #(state/pub-event! [:modal/toggle-accent-colors-modal])}
 
    :git/commit                              {:binding  "mod+g c"
                                              :inactive (not (util/electron?))
@@ -582,8 +582,8 @@
       {::commands       (set (keys all-built-in-keyboard-shortcuts))
        ::dicts/commands dicts/abbreviated-commands}]
   (assert (= (::commands keyboard-commands) (::dicts/commands keyboard-commands))
-          (str "Keyboard commands must have an english label"
-               (data/diff (::commands keyboard-commands) (::commands keyboard-commands)))))
+    (str "Keyboard commands must have an english label"
+      (data/diff (::commands keyboard-commands) (::commands keyboard-commands)))))
 
 (defn- resolve-fn
   "Converts a keyword fn to the actual fn. The fn to be resolved needs to be
@@ -591,7 +591,7 @@
   [keyword-fn]
   (fn []
     (if-let [resolved-fn (some-> (find-ns-obj (namespace keyword-fn))
-                                 (aget (munge (name keyword-fn))))]
+                           (aget (munge (name keyword-fn))))]
       (resolved-fn)
       (throw (ex-info (str "Unable to resolve " keyword-fn " to a fn") {})))))
 
@@ -608,369 +608,369 @@
   (->> (if (sequential? ks)
          ks (let [{:keys [ns includes excludes]} ks]
               (->> (keys all-built-in-keyboard-shortcuts)
-                   (filter (fn [k]
-                             (and (or (and ns (keyword? k)
-                                           (contains? (->> (if (seqable? ns) (seq ns) [ns]) (map #(name %)) (set))
-                                                      (namespace k)))
-                                      (and includes (contains? (set includes) k)))
-                                  (if (not (seq excludes)) true (not (contains? (set excludes) k)))))))))
-       (select-keys all-built-in-keyboard-shortcuts)
-       (remove (comp :inactive val))
-       ;; Convert keyword fns to real fns
-       (map (fn [[k v]]
-              [k (if (keyword? (:fn v))
-                   (assoc v :fn (resolve-fn (:fn v)))
-                   v)]))
-       (map (fn [[k v]]
-              [k (if (:file-graph? v)
-                   (update v :fn wrap-fn-with-file-graph-only-warning)
-                   v)]))
-       (into {})))
+                (filter (fn [k]
+                          (and (or (and ns (keyword? k)
+                                     (contains? (->> (if (seqable? ns) (seq ns) [ns]) (map #(name %)) (set))
+                                       (namespace k)))
+                                 (and includes (contains? (set includes) k)))
+                            (if (not (seq excludes)) true (not (contains? (set excludes) k)))))))))
+    (select-keys all-built-in-keyboard-shortcuts)
+    (remove (comp :inactive val))
+    ;; Convert keyword fns to real fns
+    (map (fn [[k v]]
+           [k (if (keyword? (:fn v))
+                (assoc v :fn (resolve-fn (:fn v)))
+                v)]))
+    (map (fn [[k v]]
+           [k (if (:file-graph? v)
+                (update v :fn wrap-fn-with-file-graph-only-warning)
+                v)]))
+    (into {})))
 
 ;; This is the only var that should be publicly expose :fn functionality
 (defonce ^:large-vars/data-var *config
   (atom
-   {:shortcut.handler/date-picker
-    (build-category-map {:ns :date-picker})
-
-    :shortcut.handler/pdf
-    (-> (build-category-map {:ns :pdf})
-        (with-meta {:before m/enable-when-not-editing-mode!}))
-
-    :shortcut.handler/whiteboard
-    (-> (build-category-map {:ns :whiteboard})
-        (with-meta {:before m/enable-when-not-editing-mode!}))
-
-    :shortcut.handler/auto-complete
-    (build-category-map {:ns :auto-complete})
-
-    :shortcut.handler/cards
-    (-> (build-category-map {:ns :cards})
-        (with-meta {:before m/enable-when-not-editing-mode!}))
-
-    :shortcut.handler/block-editing-only
-    (-> (build-category-map
-         [:editor/escape-editing
-          :editor/backspace
-          :editor/delete
-          :editor/zoom-in
-          :editor/zoom-out
-          :editor/new-block
-          :editor/new-line
-          :editor/follow-link
-          :editor/open-link-in-sidebar
-          :editor/bold
-          :editor/italics
-          :editor/highlight
-          :editor/strike-through
-          :editor/clear-block
-          :editor/kill-line-before
-          :editor/kill-line-after
-          :editor/beginning-of-block
-          :editor/end-of-block
-          :editor/forward-word
-          :editor/backward-word
-          :editor/forward-kill-word
-          :editor/backward-kill-word
-          :editor/replace-block-reference-at-point
-          :editor/copy-embed
-          :editor/paste-text-in-one-block-at-point
-          :editor/insert-youtube-timestamp])
-        (with-meta {:before m/enable-when-editing-mode!}))
-
-    :shortcut.handler/editor-global
-    (-> (build-category-map
-         [:graph/export-as-html
-          :graph/open
-          :graph/remove
-          :graph/add
-          :graph/db-add
-          :graph/re-index
-          :editor/cycle-todo
-          :editor/up
-          :editor/down
-          :editor/left
-          :editor/right
-          :editor/select-up
-          :editor/select-down
-          :editor/move-block-up
-          :editor/move-block-down
-          :editor/open-edit
-          :editor/select-block-up
-          :editor/select-block-down
-          :editor/select-parent
-          :editor/delete-selection
-          :editor/expand-block-children
-          :editor/collapse-block-children
-          :editor/indent
-          :editor/outdent
-          :editor/copy
-          :editor/copy-text
-          :editor/cut
-          :command/toggle-favorite])
-        (with-meta {:before m/enable-when-not-component-editing!}))
-
-    :shortcut.handler/global-prevent-default
-    (-> (build-category-map
-         [:editor/insert-link
-          :editor/select-all-blocks
-          :editor/toggle-undo-redo-mode
-          :editor/toggle-number-list
-          :editor/undo
-          :editor/redo
-          :ui/toggle-brackets
-          :go/search-in-page
-          :go/search
-          :go/electron-find-in-page
-          :go/electron-jump-to-the-next
-          :go/electron-jump-to-the-previous
-          :go/backward
-          :go/forward
-          :search/re-index
-          :sidebar/open-today-page
-          :sidebar/clear
-          :command/run
-          :command-palette/toggle
-          :editor/add-property
-          :window/close])
-        (with-meta {:before m/prevent-default-behavior}))
-
-    :shortcut.handler/global-non-editing-only
-    (-> (build-category-map
-         [:go/home
-          :go/journals
-          :go/all-pages
-          :go/flashcards
-          :go/graph-view
-          :go/all-graphs
-          :go/whiteboards
-          :go/keyboard-shortcuts
-          :go/tomorrow
-          :go/next-journal
-          :go/prev-journal
-          :ui/toggle-document-mode
-          :ui/toggle-settings
-          :ui/toggle-right-sidebar
-          :ui/toggle-left-sidebar
-          :ui/toggle-help
-          :ui/toggle-theme
-          :ui/toggle-contents
-          :editor/open-file-in-default-app
-          :editor/open-file-in-directory
-          :editor/copy-current-file
-          :editor/copy-page-url
-          :editor/new-whiteboard
-          :ui/toggle-wide-mode
-          :ui/select-theme-color
-          :ui/goto-plugins
-          :ui/install-plugins-from-file
-          :editor/toggle-open-blocks
-          :ui/clear-all-notifications
-          :git/commit
-          :sidebar/close-top
-          :dev/show-block-data
-          :dev/show-block-ast
-          :dev/show-page-data
-          :dev/show-page-ast
-          :dev/replace-graph-with-db-file
-          :ui/cycle-color
-          :ui/cycle-color-off])
-        (with-meta {:before m/enable-when-not-editing-mode!}))
-
-    :shortcut.handler/misc
-            ;; always overrides the copy due to "mod+c mod+s"
-    {:misc/copy (:misc/copy all-built-in-keyboard-shortcuts)}}))
+    {:shortcut.handler/date-picker
+     (build-category-map {:ns :date-picker})
+
+     :shortcut.handler/pdf
+     (-> (build-category-map {:ns :pdf})
+       (with-meta {:before m/enable-when-not-editing-mode!}))
+
+     :shortcut.handler/whiteboard
+     (-> (build-category-map {:ns :whiteboard})
+       (with-meta {:before m/enable-when-not-editing-mode!}))
+
+     :shortcut.handler/auto-complete
+     (build-category-map {:ns :auto-complete})
+
+     :shortcut.handler/cards
+     (-> (build-category-map {:ns :cards})
+       (with-meta {:before m/enable-when-not-editing-mode!}))
+
+     :shortcut.handler/block-editing-only
+     (-> (build-category-map
+           [:editor/escape-editing
+            :editor/backspace
+            :editor/delete
+            :editor/zoom-in
+            :editor/zoom-out
+            :editor/new-block
+            :editor/new-line
+            :editor/follow-link
+            :editor/open-link-in-sidebar
+            :editor/bold
+            :editor/italics
+            :editor/highlight
+            :editor/strike-through
+            :editor/clear-block
+            :editor/kill-line-before
+            :editor/kill-line-after
+            :editor/beginning-of-block
+            :editor/end-of-block
+            :editor/forward-word
+            :editor/backward-word
+            :editor/forward-kill-word
+            :editor/backward-kill-word
+            :editor/replace-block-reference-at-point
+            :editor/copy-embed
+            :editor/paste-text-in-one-block-at-point
+            :editor/insert-youtube-timestamp])
+       (with-meta {:before m/enable-when-editing-mode!}))
+
+     :shortcut.handler/editor-global
+     (-> (build-category-map
+           [:graph/export-as-html
+            :graph/open
+            :graph/remove
+            :graph/add
+            :graph/db-add
+            :graph/re-index
+            :editor/cycle-todo
+            :editor/up
+            :editor/down
+            :editor/left
+            :editor/right
+            :editor/select-up
+            :editor/select-down
+            :editor/move-block-up
+            :editor/move-block-down
+            :editor/open-edit
+            :editor/select-block-up
+            :editor/select-block-down
+            :editor/select-parent
+            :editor/delete-selection
+            :editor/expand-block-children
+            :editor/collapse-block-children
+            :editor/indent
+            :editor/outdent
+            :editor/copy
+            :editor/copy-text
+            :editor/cut
+            :command/toggle-favorite])
+       (with-meta {:before m/enable-when-not-component-editing!}))
+
+     :shortcut.handler/global-prevent-default
+     (-> (build-category-map
+           [:editor/insert-link
+            :editor/select-all-blocks
+            :editor/toggle-undo-redo-mode
+            :editor/toggle-number-list
+            :editor/undo
+            :editor/redo
+            :ui/toggle-brackets
+            :go/search-in-page
+            :go/search
+            :go/electron-find-in-page
+            :go/electron-jump-to-the-next
+            :go/electron-jump-to-the-previous
+            :go/backward
+            :go/forward
+            :search/re-index
+            :sidebar/open-today-page
+            :sidebar/clear
+            :command/run
+            :command-palette/toggle
+            :editor/add-property
+            :window/close])
+       (with-meta {:before m/prevent-default-behavior}))
+
+     :shortcut.handler/global-non-editing-only
+     (-> (build-category-map
+           [:go/home
+            :go/journals
+            :go/all-pages
+            :go/flashcards
+            :go/graph-view
+            :go/all-graphs
+            :go/whiteboards
+            :go/keyboard-shortcuts
+            :go/tomorrow
+            :go/next-journal
+            :go/prev-journal
+            :ui/toggle-document-mode
+            :ui/toggle-settings
+            :ui/toggle-right-sidebar
+            :ui/toggle-left-sidebar
+            :ui/toggle-help
+            :ui/toggle-theme
+            :ui/toggle-contents
+            :editor/open-file-in-default-app
+            :editor/open-file-in-directory
+            :editor/copy-current-file
+            :editor/copy-page-url
+            :editor/new-whiteboard
+            :ui/toggle-wide-mode
+            :ui/select-theme-color
+            :ui/goto-plugins
+            :ui/install-plugins-from-file
+            :editor/toggle-open-blocks
+            :ui/clear-all-notifications
+            :git/commit
+            :sidebar/close-top
+            :dev/show-block-data
+            :dev/show-block-ast
+            :dev/show-page-data
+            :dev/show-page-ast
+            :dev/replace-graph-with-db-file
+            :ui/accent-colors-picker
+            :ui/accent-color-reset])
+       (with-meta {:before m/enable-when-not-editing-mode!}))
+
+     :shortcut.handler/misc
+     ;; always overrides the copy due to "mod+c mod+s"
+     {:misc/copy (:misc/copy all-built-in-keyboard-shortcuts)}}))
 
 ;; To add a new entry to this map, first add it here and then
 ;; a description for it in frontend.dicts.en/dicts
 ;; Full list of categories for docs purpose
 (defonce ^:large-vars/data-var *category
   (atom
-   {:shortcut.category/basics
-    [:go/search
-     :editor/new-block
-     :editor/new-line
-     :editor/indent
-     :editor/outdent
-     :editor/select-all-blocks
-     :editor/select-parent
-     :go/search-in-page
-     :command-palette/toggle
-     :go/electron-find-in-page
-     :go/electron-jump-to-the-next
-     :go/electron-jump-to-the-previous
-     :editor/undo
-     :editor/redo
-     :editor/copy
-     :editor/copy-text
-     :editor/cut]
-
-    :shortcut.category/formatting
-    [:editor/bold
-     :editor/insert-link
-     :editor/italics
-     :editor/strike-through
-     :editor/highlight]
-
-    :shortcut.category/navigating
-    [:editor/up
-     :editor/down
-     :editor/left
-     :editor/right
-     :editor/collapse-block-children
-     :editor/expand-block-children
-     :editor/toggle-open-blocks
-     :go/backward
-     :go/forward
-     :go/home
-     :go/journals
-     :go/all-pages
-     :go/graph-view
-     :go/all-graphs
-     :go/whiteboards
-     :go/flashcards
-     :go/tomorrow
-     :go/next-journal
-     :go/prev-journal
-     :go/keyboard-shortcuts]
-
-    :shortcut.category/block-editing
-    [:editor/backspace
-     :editor/delete
-     :editor/indent
-     :editor/outdent
-     :editor/new-block
-     :editor/new-line
-     :editor/zoom-in
-     :editor/zoom-out
-     :editor/cycle-todo
-     :editor/follow-link
-     :editor/open-link-in-sidebar
-     :editor/move-block-up
-     :editor/move-block-down
-     :editor/escape-editing
-     :editor/add-property]
-
-    :shortcut.category/block-command-editing
-    [:editor/backspace
-     :editor/clear-block
-     :editor/kill-line-before
-     :editor/kill-line-after
-     :editor/beginning-of-block
-     :editor/end-of-block
-     :editor/forward-word
-     :editor/backward-word
-     :editor/forward-kill-word
-     :editor/backward-kill-word
-     :editor/replace-block-reference-at-point
-     :editor/copy-embed
-     :editor/paste-text-in-one-block-at-point
-     :editor/select-up
-     :editor/select-down]
-
-    :shortcut.category/block-selection
-    [:editor/open-edit
-     :editor/select-all-blocks
-     :editor/select-parent
-     :editor/select-block-up
-     :editor/select-block-down
-     :editor/delete-selection]
-
-    :shortcut.category/toggle
-    [:ui/toggle-help
-     :editor/toggle-open-blocks
-     :editor/toggle-undo-redo-mode
-     :editor/toggle-number-list
-     :ui/toggle-wide-mode
-     :ui/toggle-document-mode
-     :ui/toggle-brackets
-     :ui/toggle-theme
-     :ui/toggle-left-sidebar
-     :ui/toggle-right-sidebar
-     :ui/toggle-settings
-     :ui/toggle-contents
-     :ui/cycle-color-off
-     :ui/cycle-color]
-
-    :shortcut.category/whiteboard
-    [:editor/new-whiteboard
-     :whiteboard/select
-     :whiteboard/pan
-     :whiteboard/portal
-     :whiteboard/pencil
-     :whiteboard/highlighter
-     :whiteboard/eraser
-     :whiteboard/connector
-     :whiteboard/text
-     :whiteboard/rectangle
-     :whiteboard/ellipse
-     :whiteboard/reset-zoom
-     :whiteboard/zoom-to-fit
-     :whiteboard/zoom-to-selection
-     :whiteboard/zoom-out
-     :whiteboard/zoom-in
-     :whiteboard/send-backward
-     :whiteboard/send-to-back
-     :whiteboard/bring-forward
-     :whiteboard/bring-to-front
-     :whiteboard/lock
-     :whiteboard/unlock
-     :whiteboard/group
-     :whiteboard/ungroup
-     :whiteboard/toggle-grid
-     :whiteboard/clone-left
-     :whiteboard/clone-right
-     :whiteboard/clone-top
-     :whiteboard/clone-bottom]
-
-    :shortcut.category/others
-    [:pdf/previous-page
-     :pdf/next-page
-     :pdf/close
-     :pdf/find
-     :command/toggle-favorite
-     :command/run
-     :graph/export-as-html
-     :graph/open
-     :graph/remove
-     :graph/add
-     :graph/re-index
-     :sidebar/close-top
-     :sidebar/clear
-     :sidebar/open-today-page
-     :search/re-index
-     :editor/insert-youtube-timestamp
-     :editor/open-file-in-default-app
-     :editor/open-file-in-directory
-     :editor/copy-page-url
-     :window/close
-     :auto-complete/prev
-     :auto-complete/next
-     :auto-complete/complete
-     :auto-complete/shift-complete
-     :auto-complete/meta-complete
-     :auto-complete/open-link
-     :date-picker/prev-day
-     :date-picker/next-day
-     :date-picker/prev-week
-     :date-picker/next-week
-     :date-picker/complete
-     :git/commit
-     :dev/show-block-data
-     :dev/show-block-ast
-     :dev/show-page-data
-     :dev/show-page-ast
-     :dev/replace-graph-with-db-file
-     :ui/clear-all-notifications]
-
-    :shortcut.category/plugins
-    []}))
+    {:shortcut.category/basics
+     [:go/search
+      :editor/new-block
+      :editor/new-line
+      :editor/indent
+      :editor/outdent
+      :editor/select-all-blocks
+      :editor/select-parent
+      :go/search-in-page
+      :command-palette/toggle
+      :go/electron-find-in-page
+      :go/electron-jump-to-the-next
+      :go/electron-jump-to-the-previous
+      :editor/undo
+      :editor/redo
+      :editor/copy
+      :editor/copy-text
+      :editor/cut]
+
+     :shortcut.category/formatting
+     [:editor/bold
+      :editor/insert-link
+      :editor/italics
+      :editor/strike-through
+      :editor/highlight]
+
+     :shortcut.category/navigating
+     [:editor/up
+      :editor/down
+      :editor/left
+      :editor/right
+      :editor/collapse-block-children
+      :editor/expand-block-children
+      :editor/toggle-open-blocks
+      :go/backward
+      :go/forward
+      :go/home
+      :go/journals
+      :go/all-pages
+      :go/graph-view
+      :go/all-graphs
+      :go/whiteboards
+      :go/flashcards
+      :go/tomorrow
+      :go/next-journal
+      :go/prev-journal
+      :go/keyboard-shortcuts]
+
+     :shortcut.category/block-editing
+     [:editor/backspace
+      :editor/delete
+      :editor/indent
+      :editor/outdent
+      :editor/new-block
+      :editor/new-line
+      :editor/zoom-in
+      :editor/zoom-out
+      :editor/cycle-todo
+      :editor/follow-link
+      :editor/open-link-in-sidebar
+      :editor/move-block-up
+      :editor/move-block-down
+      :editor/escape-editing
+      :editor/add-property]
+
+     :shortcut.category/block-command-editing
+     [:editor/backspace
+      :editor/clear-block
+      :editor/kill-line-before
+      :editor/kill-line-after
+      :editor/beginning-of-block
+      :editor/end-of-block
+      :editor/forward-word
+      :editor/backward-word
+      :editor/forward-kill-word
+      :editor/backward-kill-word
+      :editor/replace-block-reference-at-point
+      :editor/copy-embed
+      :editor/paste-text-in-one-block-at-point
+      :editor/select-up
+      :editor/select-down]
+
+     :shortcut.category/block-selection
+     [:editor/open-edit
+      :editor/select-all-blocks
+      :editor/select-parent
+      :editor/select-block-up
+      :editor/select-block-down
+      :editor/delete-selection]
+
+     :shortcut.category/toggle
+     [:ui/toggle-help
+      :editor/toggle-open-blocks
+      :editor/toggle-undo-redo-mode
+      :editor/toggle-number-list
+      :ui/toggle-wide-mode
+      :ui/toggle-document-mode
+      :ui/toggle-brackets
+      :ui/toggle-theme
+      :ui/toggle-left-sidebar
+      :ui/toggle-right-sidebar
+      :ui/toggle-settings
+      :ui/toggle-contents
+      :ui/accent-colors-picker
+      :ui/accent-color-reset]
+
+     :shortcut.category/whiteboard
+     [:editor/new-whiteboard
+      :whiteboard/select
+      :whiteboard/pan
+      :whiteboard/portal
+      :whiteboard/pencil
+      :whiteboard/highlighter
+      :whiteboard/eraser
+      :whiteboard/connector
+      :whiteboard/text
+      :whiteboard/rectangle
+      :whiteboard/ellipse
+      :whiteboard/reset-zoom
+      :whiteboard/zoom-to-fit
+      :whiteboard/zoom-to-selection
+      :whiteboard/zoom-out
+      :whiteboard/zoom-in
+      :whiteboard/send-backward
+      :whiteboard/send-to-back
+      :whiteboard/bring-forward
+      :whiteboard/bring-to-front
+      :whiteboard/lock
+      :whiteboard/unlock
+      :whiteboard/group
+      :whiteboard/ungroup
+      :whiteboard/toggle-grid
+      :whiteboard/clone-left
+      :whiteboard/clone-right
+      :whiteboard/clone-top
+      :whiteboard/clone-bottom]
+
+     :shortcut.category/others
+     [:pdf/previous-page
+      :pdf/next-page
+      :pdf/close
+      :pdf/find
+      :command/toggle-favorite
+      :command/run
+      :graph/export-as-html
+      :graph/open
+      :graph/remove
+      :graph/add
+      :graph/re-index
+      :sidebar/close-top
+      :sidebar/clear
+      :sidebar/open-today-page
+      :search/re-index
+      :editor/insert-youtube-timestamp
+      :editor/open-file-in-default-app
+      :editor/open-file-in-directory
+      :editor/copy-page-url
+      :window/close
+      :auto-complete/prev
+      :auto-complete/next
+      :auto-complete/complete
+      :auto-complete/shift-complete
+      :auto-complete/meta-complete
+      :auto-complete/open-link
+      :date-picker/prev-day
+      :date-picker/next-day
+      :date-picker/prev-week
+      :date-picker/next-week
+      :date-picker/complete
+      :git/commit
+      :dev/show-block-data
+      :dev/show-block-ast
+      :dev/show-page-data
+      :dev/show-page-ast
+      :dev/replace-graph-with-db-file
+      :ui/clear-all-notifications]
+
+     :shortcut.category/plugins
+     []}))
 
 (let [category-maps {::category       (set (keys @*category))
                      ::dicts/category dicts/categories}]
   (assert (= (::category category-maps) (::dicts/category category-maps))
-          (str "Keys for category maps must have an english label "
-               (data/diff (::category category-maps) (::dicts/category category-maps)))))
+    (str "Keys for category maps must have an english label "
+      (data/diff (::category category-maps) (::dicts/category category-maps)))))
 
 (defn get-category-shortcuts
   "Active list of categories for docs purpose"
@@ -987,9 +987,9 @@
      (swap! *shortcut-cmds assoc id (:cmd shortcut-map))
      (let [plugin? (str/starts-with? (str id) ":plugin.")
            category (or (:category shortcut-map)
-                        (if plugin?
-                          :shortcut.category/plugins
-                          :shortcut.category/others))]
+                      (if plugin?
+                        :shortcut.category/plugins
+                        :shortcut.category/others))]
        (swap! *category update category #(conj % id))))))
 
 (defn remove-shortcut!

+ 1 - 0
src/main/frontend/schema/handler/common_config.cljc

@@ -62,6 +62,7 @@
     [:ref/default-open-blocks-level :int]
     [:ref/linked-references-collapsed-threshold :int]
     [:graph/settings [:map-of :keyword [:or :boolean :int :nil]]]
+    [:graph/forcesettings [:map-of :keyword :int]]
     [:favorites [:vector :string]]
     ;; There isn't a :float yet
     [:srs/learning-fraction float?]

+ 11 - 14
src/main/frontend/state.cljs

@@ -7,7 +7,6 @@
             [clojure.string :as string]
             [dommy.core :as dom]
             [electron.ipc :as ipc]
-            [frontend.colors :as colors]
             [frontend.mobile.util :as mobile-util]
             [frontend.spec.storage :as storage-spec]
             [frontend.storage :as storage]
@@ -135,6 +134,7 @@
       :editor/content                        (atom {})
       :editor/block                          (atom nil)
       :editor/new-property-input-id          (atom nil)
+      :editor/new-property-key               (atom nil)
       :editor/properties-container           (atom nil)
       :editor/block-dom-id                   (atom nil)
       :editor/set-timestamp-block            (atom nil) ;; click rendered block timestamp-cp to set timestamp
@@ -672,6 +672,10 @@ Similar to re-frame subscriptions"
   []
   (:graph/settings (sub-config)))
 
+(defn graph-forcesettings
+  []
+  (:graph/forcesettings (sub-config)))
+
 ;; Enable by default
 (defn show-brackets?
   []
@@ -1480,14 +1484,15 @@ Similar to re-frame subscriptions"
            input (medley/filter-vals
                    #(not (nil? %1))
                    {:modal/id            id
-                    :modal/label         (or label (if center? "ls-modal-align-center" ""))
+                    :modal/label         (if label (name label) "")
+                    :modal/class         (if center? "as-center" "")
                     :modal/payload       payload
                     :modal/show?         (if (boolean? show?) show? true)
                     :modal/panel-content panel-content
                     :modal/close-btn?    close-btn?
                     :modal/close-backdrop? (if (boolean? close-backdrop?) close-backdrop? true)})]
        (swap! state update-in
-              [:modal/subsets (or idx (count modals))]
+         [:modal/subsets (or idx (count modals))]
               merge input)
        (:modal/subsets @state)))))
 
@@ -1527,7 +1532,8 @@ Similar to re-frame subscriptions"
          (<! (async/timeout 100)))
        (swap! state assoc
               :modal/id id
-              :modal/label (or label (if center? "ls-modal-align-center" ""))
+              :modal/label (if label (name label) "")
+              :modal/class (if center? "as-center" "")
               :modal/show? (boolean modal-panel-content)
               :modal/panel-content modal-panel-content
               :modal/payload payload
@@ -2323,19 +2329,10 @@ Similar to re-frame subscriptions"
   (util/set-android-theme))
 
 (defn unset-color-accent! []
-  (swap! state assoc :ui/radix-color nil)
+  (swap! state assoc :ui/radix-color :logseq)
   (storage/remove :ui/radix-color)
   (util/set-android-theme))
 
-(defn cycle-color! []
-  (let [current-color (get-color-accent)
-        next-color (->> (cons nil colors/color-list)
-                        (drop-while #(not= % current-color))
-                        (second))]
-    (if next-color
-      (set-color-accent! next-color)
-      (unset-color-accent!))))
-
 (defn handbook-open?
   []
   (:ui/handbooks-open? @state))

+ 11 - 10
src/main/frontend/tippy-tooltip.css

@@ -5,7 +5,7 @@
 .tippy-popper[x-placement^=top] [x-arrow],
 .tippy-popper[x-placement^=top] [x-arrow].arrow-small,
 .tippy-popper[x-placement^=top] [x-arrow].arrow-big {
-  border-top-color: var(--ls-quaternary-background-color);
+  border-top-color: var(--ls-tertiary-background-color);
 }
 
 .tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-circle],
@@ -25,7 +25,7 @@
 .tippy-popper[x-placement^=bottom] [x-arrow],
 .tippy-popper[x-placement^=bottom] [x-arrow].arrow-small,
 .tippy-popper[x-placement^=bottom] [x-arrow].arrow-big {
-  border-bottom-color: var(--ls-quaternary-background-color);
+  border-bottom-color: var(--ls-tertiary-background-color);
 }
 
 .tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-arrow],
@@ -37,7 +37,7 @@
 .tippy-popper[x-placement^=left] [x-arrow],
 .tippy-popper[x-placement^=left] [x-arrow].arrow-small,
 .tippy-popper[x-placement^=left] [x-arrow].arrow-big {
-  border-left-color: var(--ls-quaternary-background-color);
+  border-left-color: var(--ls-tertiary-background-color);
 }
 
 .tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-arrow],
@@ -49,21 +49,21 @@
 .tippy-popper[x-placement^=right] [x-arrow],
 .tippy-popper[x-placement^=right] [x-arrow].arrow-small,
 .tippy-popper[x-placement^=right] [x-arrow].arrow-big {
-  border-right-color: var(--ls-quaternary-background-color);
+  border-right-color: var(--ls-tertiary-background-color);
 }
 
 .tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow],
 .tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow].arrow-small,
 .tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow].arrow-big {
-  border-right-color: var(--ls-secondary-background-color);
+  border-right-color: var(--ls-tertiary-background-color);
 }
 
 .tippy-tooltip {
-  color: var(--ls-primary-text-color);
-  font-size: inherit;
-  padding: 0;
+  @apply shadow border border-gray-07 dark:border-gray-05 px-2 py-1;
+
   will-change: auto;
-  background-color: var(--ls-quaternary-background-color);
+  color: var(--ls-primary-text-color, hsl(var(--foreground)));
+  background-color: var(--lx-gray-03, var(--ls-tertiary-background-color, var(--rx-gray-03)));
 }
 
 .tippy-tooltip [x-circle] {
@@ -75,7 +75,8 @@
 }
 
 .tippy-wrapper {
-  background-color: var(--ls-quaternary-background-color);
+  border-radius: 8px;
+  margin: 0 -6px;
 }
 
 .tippy-hover {

+ 29 - 16
src/main/frontend/ui.cljs

@@ -196,14 +196,14 @@
                        (string/split #" "))
                    sequence)]
     [:span.keyboard-shortcut
-     (shui/shortcut-v1 sequence opts)]))
+     (shui/shortcut sequence opts)]))
 
 (rum/defc menu-link
   [{:keys [only-child? no-padding? class shortcut] :as options} child]
   (if only-child?
     [:div.menu-link
      (dissoc options :only-child?) child]
-    [:a.flex.justify-between.px-4.py-2.text-sm.transition.ease-in-out.duration-150.cursor.menu-link
+    [:a.flex.justify-between.menu-link
      (cond-> options
              (true? no-padding?)
              (assoc :class (str class " no-padding"))
@@ -213,7 +213,7 @@
 
      [:span.flex-1 child]
      (when shortcut
-       [:span.ml-1 (render-keyboard-shortcut shortcut)])]))
+       [:span.ml-1 (render-keyboard-shortcut shortcut {:interactive? false})])]))
 
 (rum/defc dropdown-with-links
   [content-fn links
@@ -670,13 +670,16 @@
         show? (state/sub :modal/show?)
         label (state/sub :modal/label)
         style (state/sub :modal/style)
+        class (state/sub :modal/class)
         close-fn (fn []
                    (state/close-modal!)
                    (state/close-settings!))
         modal-panel-content (or modal-panel-content (fn [_close] [:div]))]
     [:div.ui__modal
-     {:style {:z-index (if show? 999 -1)}
-      :label label}
+     {:style {:z-index (if show? 999 -1)
+              :display (if show? "flex" "none")}
+      :label label
+      :class class}
      (css-transition
       {:in show? :timeout 0}
       (fn [state]
@@ -742,12 +745,14 @@
             show? (:modal/show? modal)
             label (:modal/label modal)
             style (:modal/style modal)
+            class (:modal/class modal)
             close-fn (fn []
                        (state/close-sub-modal! id))
             modal-panel-content (or modal-panel-content (fn [_close] [:div]))]
         [:div.ui__modal.is-sub-modal
          {:style {:z-index (if show? (+ 999 idx) -1)}
-          :label label}
+          :label label
+          :class class}
          (css-transition
           {:in show? :timeout 0}
           (fn [state]
@@ -992,16 +997,24 @@
                           [:div {:key "tippy"} ""])))
            (rum/fragment {:key "tippy-children"} child))))
 
-(rum/defc slider
-  [default-value {:keys [min max on-change]}]
-  [:input.cursor-pointer
-   {:type      "range"
-    :value     (int default-value)
-    :min       min
-    :max       max
-    :style     {:width "100%"}
-    :on-change #(let [value (util/evalue %)]
-                  (on-change value))}])
+(rum/defcs slider < rum/reactive
+  {:init (fn [state]
+           (assoc state ::value (atom (first (:rum/args state)))))}
+  [state _default-value {:keys [min max on-change]}]
+  (let [*value (::value state)
+        value (rum/react *value)
+        value' (int value)]
+    (assert (int? value'))
+    [:input.cursor-pointer
+     {:type      "range"
+      :value     value'
+      :min       min
+      :max       max
+      :style     {:width "100%"}
+      :on-change #(let [value (util/evalue %)]
+                    (reset! *value value))
+      :on-mouse-up #(let [value (util/evalue %)]
+                      (on-change value))}]))
 
 (rum/defcs tweet-embed < (rum/local true :loading?)
   [state id]

+ 32 - 34
src/main/frontend/ui.css

@@ -6,7 +6,7 @@
     -webkit-overflow-scrolling: touch;
 
     .menu-link {
-      word-break: break-all;
+      @apply break-all rounded;
 
       .has-help {
         display: flex;
@@ -14,20 +14,17 @@
         justify-content: space-between;
 
         small {
-          visibility: visible;
-          cursor: help;
+          @apply cursor-help visible flex;
 
           svg {
-            opacity: .3;
-          }
-
-          &:hover svg {
-            opacity: .9;
+            @apply opacity-30 hover:opacity-90;
           }
         }
       }
 
       &:hover, &.chosen {
+        background-color: var(--lx-gray-05, var(--ls-menu-hover-color, hsl(var(--secondary))));
+
         .has-help small {
           visibility: visible;
         }
@@ -35,7 +32,7 @@
 
       &:not(.chosen):hover {
         background-color: unset !important;
-        color: or(--ls-autocomplete-color-hover, --lx-gray-12, --ls-primary-text-color);
+        color: var(--lx-gray-12, var(--ls-primary-text-color, hsl(var(--secondary))));
       }
     }
   }
@@ -48,9 +45,7 @@
 }
 
 .ui__ac-group-name {
-  @apply p-2 text-xs;
-  color: or(--ls-dropdown-title-color, --lx-gray-11-alpha, --ls-block-ref-link-text-color);
-  background-color: or(--ls-dropdown-title-background, --lx-gray-03);
+  @apply p-2 text-xs text-popover-foreground/20 font-medium;
 }
 
 .search-all #ui__ac-inner {
@@ -71,8 +66,10 @@
   }
 
   .notification-area {
-    background-color: or(--logseq-of-notification-background, --lx-gray-04, --ls-tertiary-background-color, #fff);
-    color: or(--ls-notification-text-color, --lx-gray-11, --ls-primary-text-color);
+    @apply border;
+
+    background-color: or(--ls-notification-background, --lx-gray-03, --ls-tertiary-background-color, --rx-gray-03);
+    color: or(--ls-notification-text-color, --lx-gray-11, --ls-primary-text-color, --rx-gray-11);
   }
 }
 
@@ -103,7 +100,7 @@
   top-12 sm:top-[calc(3vh+50px)];
 
   &-overlay {
-    @apply fixed inset-0 transition-opacity;
+    @apply fixed inset-0;
   }
 
   &-overlay div {
@@ -113,10 +110,9 @@
   }
 
   &-panel {
-    @apply relative rounded-md shadow-xl border-none;
+    @apply relative rounded-md shadow-lg border border-gray-06 overflow-hidden;
 
-    overflow: hidden;
-    background: or(--ls-modal-panel-color, --lx-gray-04, --ls-secondary-background-color);
+    background: var(--lx-gray-02, var(--ls-secondary-background-color, hsl(var(--popover))));
 
     .panel-content {
       overflow-y: auto;
@@ -163,7 +159,8 @@
     }
   }
 
-  &[label="ls-modal-align-center"] {
+  &[label="ls-modal-align-center"],
+  &.as-center{
     top: 0;
 
     .ui__modal-panel {
@@ -283,10 +280,11 @@ html.is-mobile {
 }
 
 .dropdown-wrapper {
-  background-color: or(--ls-dropdown-background, --lx-gray-03, --ls-primary-background-color, #fff);
-  border: 1px solid or(--ls-dropdown-border-color, --lx-gray-05, --ls-tertiary-background-color);
-  min-width: 12rem;
-  border-radius: 6px;
+  @apply border min-w-[12rem] rounded-md bg-popover overflow-hidden;
+
+  .menu-links-wrapper {
+    @apply border-0;
+  }
 }
 
 .dropdown-caret {
@@ -306,10 +304,10 @@ html.is-mobile {
   @apply block w-full pl-3 pr-10 py-2 text-base leading-6 rounded
   border-gray-300 focus:outline-none sm:text-sm sm:leading-5;
 
-  background-color: or(--ls-form-select-background-color, --lx-gray-03, --ls-primary-background-color, transparent);
+  background-color: var(--lx-gray-03, var(--ls-primary-background-color, transparent));
   background-repeat: no-repeat;
   border-width: 1px;
-  border-color: or(--ls-form-select-border-color, --lx-gray-07, --ls-border-color);
+  border-color: var(--lx-gray-07, var(--ls-border-color));
 
   &.is-small {
     @apply pl-2 py-1.5 sm:leading-4 sm:text-xs;
@@ -317,11 +315,7 @@ html.is-mobile {
 }
 
 .form-input {
-  @apply block w-full pl-2
-  sm:text-sm sm:leading-5 rounded;
-
-  border-width: 1px;
-  border-color: or(--ls-form-input-border-color, --lx-gray-07, --ls-border-color);
+  @apply block w-full pl-2 sm:text-sm sm:leading-5 rounded bg-background border border-gray-07;
 
   &:focus {
     box-shadow: 0 0 0 2px rgba(164, 202, 254, 0.45);
@@ -354,9 +348,9 @@ html.is-mobile {
   width: 24px;
   height: 24px;
   flex-shrink: 0;
-  border-color: or(--ls-type-icon-border-color, --lx-gray-03, --ls-primary-background-color);
+  border-color: var(--lx-gray-03, var(--ls-primary-background-color));
   overflow: hidden;
-  color: or(--ls-type-icon-text-color, --lx-gray-12, --ls-primary-text-color);
+  color: var(--lx-gray-12, var(--ls-primary-text-color));
 
   .ti,
   .tie {
@@ -365,7 +359,7 @@ html.is-mobile {
 
   &:before {
     @apply block absolute inset-0 ;
-    background: or(--ls-type-icon-before-color, --lx-gray-03, --ls-primary-background-color);
+    background: var(--lx-gray-03, var(--ls-primary-background-color));
     content: " ";
   }
 }
@@ -379,5 +373,9 @@ html.is-mobile {
 }
 
 .ui__toggle-background-off {
-  background: or(--ls-toggle-off-background, --lx-gray-08, rgb(212, 212, 212));
+  background: var(--lx-gray-08, rgb(212, 212, 212));
 }
+
+input[type='range'] {
+  accent-color: var(--lx-accent-10, var(--rx-blue-10));
+}

+ 1 - 1
src/main/frontend/version.cljs

@@ -1,3 +1,3 @@
 (ns ^:no-doc frontend.version)
 
-(defonce version "0.10.5")
+(defonce version "0.10.6")

+ 11 - 2
src/main/frontend/worker/rtc/core.cljs

@@ -284,6 +284,7 @@
 
           :else
           (let [b-ent (d/entity @conn [:block/uuid block-uuid])
+                db-id (:db/id b-ent)
                 new-block
                 (cond-> b-ent
                   (and (contains? key-set :content)
@@ -300,13 +301,21 @@
                   (contains? key-set :tags)           (assoc :block/tags (some->> (seq (:tags op-value))
                                                                                   (map (partial vector :block/uuid))
                                                                                   (d/pull-many @conn [:db/id])
-                                                                                  (filter :db/id)))
+                                                                                  (keep :db/id)))
                   (contains? key-set :properties)     (assoc :block/properties
                                                              (transit/read transit-r (:properties op-value)))
                   (contains? key-set :link)           (assoc :block/link (some->> (:link op-value)
                                                                                   (vector :block/uuid)
                                                                                   (d/pull @conn [:db/id])
-                                                                                  :db/id)))]
+                                                                                  :db/id)))
+                *other-tx-data (atom [])]
+            ;; 'save-block' dont handle card-many attrs well?
+            (when (contains? key-set :alias)
+              (swap! *other-tx-data conj [:db/retract db-id :block/alias]))
+            (when (contains? key-set :tags)
+              (swap! *other-tx-data conj [:db/retract db-id :block/tags]))
+            (when (seq @*other-tx-data)
+              (ldb/transact! conn @*other-tx-data {:persist-op? false}))
             (transact-db! :save-block repo conn date-formatter new-block)))))))
 
 (defn apply-remote-move-ops

+ 5 - 5
src/resources/dicts/en.edn

@@ -236,7 +236,7 @@
  :editor/expand-block-children "Expand all"
  :editor/collapse-block-children "Collapse all"
  :editor/delete-selection "Delete selected blocks"
- :editor/cycle-todo "Rotate the TODO state of the current item"
+ :editor/cycle-todo "Rotate the TODO state"
  :dev/show-page-data "(Dev) Show page data"
  :dev/show-block-data "(Dev) Show block data"
  :dev/show-block-ast "(Dev) Show block AST"
@@ -697,8 +697,8 @@
   :editor/backward-kill-word    "Delete a word backwards"
   :editor/replace-block-reference-at-point "Replace block reference with its content at point"
   :editor/paste-text-in-one-block-at-point "Paste text into one block at point"
-  :editor/insert-youtube-timestamp         "Insert youtube timestamp"
-  :editor/cycle-todo              "Rotate the TODO state of the current item"
+  :editor/insert-youtube-timestamp "Insert youtube timestamp"
+  :editor/cycle-todo              "Rotate the TODO state"
   :editor/up                      "Move cursor up / Select up"
   :editor/down                    "Move cursor down / Select down"
   :editor/left                    "Move cursor left / Open selected block at beginning"
@@ -795,8 +795,8 @@
   :ui/toggle-help                 "Toggle help"
   :ui/toggle-theme                "Toggle between dark/light theme"
   :ui/toggle-contents             "Toggle Contents in sidebar"
-  :ui/cycle-color-off             "Cycle color off"
-  :ui/cycle-color                 "Cycle color"
+  :ui/accent-color-reset          "Reset accent color"
+  :ui/accent-colors-picker        "Pick  accent color"
    ;;  :ui/open-new-window             "Open another window"
   :command/toggle-favorite        "Add to/remove from favorites"
   :editor/open-file-in-default-app "Open file in default app"

+ 0 - 2
src/resources/dicts/es.edn

@@ -224,8 +224,6 @@
  :command.sidebar/close-top                         "Cierra el elemento superior en la barra lateral derecha"
  :command.sidebar/open-today-page                   "Abrir la página de hoy en barra lateral derecha"
  :command.ui/clear-all-notifications                "Borrar todas las notificaciones"
- :command.ui/cycle-color                            "Ciclo de color"
- :command.ui/cycle-color-off                        "Ciclo de color desactivado"
  :command.ui/goto-plugins                           "Ir al panel de extensiones"
  :command.ui/install-plugins-from-file              "Instalar extensiones de plugins.edn"
  :command.ui/select-theme-color                     "Seleccionar temas de colores disponibles"

+ 479 - 0
src/resources/dicts/fa.edn

@@ -0,0 +1,479 @@
+{:accessibility/skip-to-main-content "برو به محتوای اصلی"
+ :tutorial/text #resource "tutorials/tutorial-fa.md"
+ :tutorial/dummy-notes #resource "tutorials/dummy-notes-fa.md"
+ :on-boarding/demo-graph "این یک گراف نمایشی است و تا زمانی که یک پوشه محلی را باز نکنید، تغییرات آن ذخیره نخواهند شد."
+ :on-boarding/add-graph "افزودن یک گراف"
+ :on-boarding/open-local-dir "باز کردن یک پوشه محلی"
+ :on-boarding/new-graph-desc-1 "لاگ‌سیک هم از مارک‌داون و هم از حالت Org پیشتیبانی می‌کند. می‌توانید یک پوشه موجود را باز کرده و یا یکی روی دستگاه‌تان بسازید. داده‌های شما صرفا روی دستگاه شما ذخیره می‌شوند."
+ :on-boarding/new-graph-desc-2 "بعد از این که پوشه‌ای را باز کنید, سه پوشه در آن ساخته می‌شود:"
+ :on-boarding/new-graph-desc-3 "/journals - محل ذخیره برگه‌های روزنگارها"
+ :on-boarding/new-graph-desc-4 "/pages - محل ذخیره بقیه برگه‌ها"
+ :on-boarding/new-graph-desc-5 "/logseq - محل ذخیره تنظیمات، custom.css و برخی فراداده‌ها."
+ :on-boarding/welcome-whiteboard-modal-title "یک بوم جدید برای ایده‌های شما."
+ :on-boarding/welcome-whiteboard-modal-description "نخته‌سفید‌ها ابزار قوی برای طوفان فکری و سازمان‌دهی هستند. اکنون می‌توانید افکارتان را از پایگاه دانش و یا مستقیما در کنار هم قرار دهید تا بتوانید آن‌ها را به روشی جدید به هم وصل کرده، ارتباط دهید و بفهمید. "
+ :on-boarding/welcome-whiteboard-modal-skip "پرش"
+ :on-boarding/welcome-whiteboard-modal-start "شروع کار با تخته‌سفید"
+ :on-boarding/tour-whiteboard-home "{1} خانه‌ای برای تخته‌سفیدهای شما"
+ :on-boarding/tour-whiteboard-home-description "تخته‌سفیدها، بخش مختص به خود را در برنامه دارند؛ جایی که شما می‌توانید همه‌شان را در یک نگاه ببینید، تخته‌های جدیدی بسازید و یا به راحتی پاک‌شان کنید."
+ :on-boarding/tour-whiteboard-new "{1} ساختن تخته‌سفید جدید"
+ :on-boarding/tour-whiteboard-new-description "راه‌های متعددی برای ساخت یک نخته‌سفید جدید وجود دارد. یکی از آن‌ها همیشه درست در همین مکان روی پیشخوان است."
+ :handbook/title           "راهنما"
+ :handbook/topics          "موضوعات"
+ :handbook/popular-topics  "موضوعات محبوب"
+ :handbook/help-categories "دسته‌بندی‌های راهنما"
+ :handbook/search          "جستجو"
+ :handbook/home            "خانه"
+ :handbook/settings        "تنظیمات"
+ :handbook/close           "بستن"
+ :on-boarding/tour-whiteboard-btn-next "بعدی"
+ :on-boarding/tour-whiteboard-btn-back "قبلی"
+ :on-boarding/tour-whiteboard-btn-finish "پایان"
+ :on-boarding/quick-tour-btn-next "بعدی"
+ :on-boarding/quick-tour-btn-back "قبلی"
+ :on-boarding/quick-tour-btn-finish "پایان"
+ :on-boarding/quick-tour-btn-skip "پرش از گشت و گذار سریع"
+ :on-boarding/quick-tour-steps "گام "
+ :on-boarding/quick-tour-help-title "❓ راهنما"
+ :on-boarding/quick-tour-help-desc "همواره می‌توانید با کلیک روی اینجا، به راهنما و ساید اطلاعات درباره لاگ‌سیک دسترسی پیدا کنید."
+ :on-boarding/quick-tour-journal-page-title "📆 برگه روزنگار"
+ :on-boarding/quick-tour-journal-page-desc-1 "این، برگه روزنگار امروز است. می‌توانید افکار، ایده‌ها و چیزهایی را که یاد می‌گیرید را اینجا وارد کنید.نگران سازمان‌دهی نباشید. فقط بنویسید و"
+ :on-boarding/quick-tour-journal-page-desc-3 "افکار شما."
+ :on-boarding/quick-tour-left-sidebar-title "👀 نوار کناری چپ"
+ :on-boarding/quick-tour-left-sidebar-desc "نوار کنار چپ را باز کنید تا موارد مهم فهرست در لاگ‌سیک را ببینید."
+ :on-boarding/quick-tour-favorites-title "⭐️ برگزیده‌ها"
+ :on-boarding/quick-tour-favorites-desc-1 "با کمک فهرست `...` در هر برگه می‌توانید برگه‌های برگزیده را سنجاق کنید."
+ :on-boarding/quick-tour-favorites-desc-2 "ما همچنین تعدادی برگه قالب را برای کمک به شما برای شروع اضافه کرده‌ایم. هر زمان که شروع به ایجاد یادداشت‌های خود کردید، می‌توانید این‌ها را حذف کنید."
+ :on-boarding/command-palette-quick-tour "گشت و گذار سریع برای آماده‌سازی"
+ :on-boarding/importing-main-title "درون‌ریزی یادداشت‌های موجود"
+ :on-boarding/importing-main-desc "این کار را می‌توانید بعدا هم انجام دهید."
+ :on-boarding/importing-title "آیا یادداشت‌هایی از پیش دارید که بخواهد وارد برنامه کنید؟"
+ :on-boarding/importing-desc "اگر در قالب‌های JSON، EDN یا مارک‌داون هستند، لاگ‌سیک می‌تواند با آن‌ها کار کند."
+ :on-boarding/importing-roam-desc "درون‌ریزی یک خروجی JSON از گراف Roam."
+ :on-boarding/importing-lsq-desc "درون‌ریزی یک خروجی JSON یا END از گراف لاگ‌سیک."
+ :on-boarding/importing-opml-desc " درون‌ریزی پرونده‌های OPML"
+ :on-boarding/main-title (fn [] ["به " [:strong "لاگ‌سیک"] "خوش‌آمدید!"])
+ :on-boarding/main-desc "در ابتدا نیاز به انتخاب پوشه‌ای دارید که لاگ‌سیک، افکار، ایده‌ها و یادداشت‌های شما را در آن‌جا ذخیره کند."
+ :on-boarding/section-btn-title "انتخاب یک پوشه"
+ :on-boarding/section-btn-desc  "یک پوشه از پیش موجود را باز کرده و یا یکی بسازید"
+ :on-boarding/section-title     "چگونه لاگ‌سیک کار شما را ذخیره می‌کند"
+ :on-boarding/section-desc      "داخل پوشه‌ای که انتخاب می‌کنید، لاگ‌سیک چهار پوشه خواهد ساخت."
+ :on-boarding/section-tip-1     "هر برگه  یک پرونده است که تنها روی {1} شما ذخیره می‌شود."
+ :on-boarding/section-tip-2     "بعدا می‌توانید انتخاب کنید که آن را هم‌گام کنید."
+ :on-boarding/section-assets    "گ‍رافیک‌ها و اسناد"
+ :on-boarding/section-computer  "رایانه"
+ :on-boarding/section-journals  "یادداشت‌های روزانه"
+ :on-boarding/section-pages     "برگه‌ها"
+ :on-boarding/section-phone     "گوشی"
+ :on-boarding/section-app       "فرایندهای داخلی برنامه"
+ :on-boarding/section-config    "پرونده پیکربندی"
+ :help/title-usage            "استفاده"
+ :help/title-community        "اجتماع"
+ :help/title-development      "توسعه"
+ :help/title-about            "درباره"
+ :help/title-terms            "قوانین"
+ :help/start                  "شروع"
+ :help/about                  "درباره لاگ‌سیک"
+ :help/roadmap                "مسیر توسعه"
+ :help/bug                    "گزارش مشکل"
+ :help/feature                "درخواست ویژگی"
+ :help/changelog              "فهرست تغییرات"
+ :help/blog                   "بلاگ لاگ‌سیک"
+ :help/docs                   "مستندات"
+ :help/privacy                "سیاست حریم شخصی"
+ :help/terms                  "قوانین"
+ :help/forum-community        "تالار گفتگو"
+ :help/shortcuts              "کلیدهای میان‌بر"
+ :help/shortcuts-triggers     "محرک‌ها"
+ :help/shortcut               "میان‌بر"
+ :help/search                 "جستجو در برگه‌ها/بلوک‌ها/نظرات"
+ :help/block-reference        "ارجاع بلوک"
+ :help/open-link-in-sidebar   "باز کردن پیوند در نوار کناری"
+ :search/page-names      "جستجو در نام برگه‌ها"
+ :search-item/whiteboard "تخته‌سفید"
+ :search-item/page       "برگه"
+ :search-item/no-result  "نتایجی یافت نشد"
+ :help/context-menu    "فهرست زمینه‌ای بلوک"
+ :help/markdown-syntax "نحو مارک‌داون"
+ :help/org-mode-syntax "نحو حالت Org"
+ :bold "ضخیم"
+ :italics "کج"
+ :strikethrough "خط‌زده"
+ :code "کد"
+ :untitled "بدون عنوان"
+ :right-side-bar/help                 "راهنما"
+ :right-side-bar/switch-theme         "پوسته"
+ :right-side-bar/contents             "محتوا"
+ :right-side-bar/page-graph           "گراف برگه"
+ :right-side-bar/history-global       "سراسری"
+ :right-side-bar/history-pageonly     "فقط برگه"
+ :right-side-bar/block-ref            "ارجاعات بلوک"
+ :right-side-bar/graph-view           "نمای گراف"
+ :right-side-bar/all-pages            "همه برگه‌ها"
+ :right-side-bar/whiteboards          "تخته‌سفیدها"
+ :right-side-bar/flashcards           "فلش کارت‌ها"
+ :right-side-bar/new-page             "برگه جدید"
+ :right-side-bar/show-journals        "نمایش روزنگارها"
+ :right-side-bar/separator            "دستگیره تغییر اندازه نوار سمت راست"
+ :right-side-bar/toggle-right-sidebar "باز و بسته کردن نوار سمت راست"
+ :right-side-bar/pane-close           "بستن"
+ :right-side-bar/pane-close-others    "بسته بقیه"
+ :right-side-bar/pane-close-all       "بستن همه"
+ :right-side-bar/pane-collapse        "جمع کردن"
+ :right-side-bar/pane-collapse-others "جمع کردن بقیه"
+ :right-side-bar/pane-collapse-all    "جمع کردن همه"
+ :right-side-bar/pane-expand          "گسترش"
+ :right-side-bar/pane-expand-all      "گسترش همه"
+ :right-side-bar/pane-open-as-page    "باز کردن به عنوان صفحه"
+ :right-side-bar/pane-more            "بیشتر"
+ :left-side-bar/switch           "تغییر به:"
+ :left-side-bar/journals         "روزنگارها"
+ :left-side-bar/create           "ساخت"
+ :left-side-bar/new-page         "برگه جدید"
+ :left-side-bar/new-whiteboard   "تخته‌سفید جدید"
+ :left-side-bar/nav-favorites    "برگزیده‌ها"
+ :left-side-bar/nav-recent-pages "اخیر"
+ :page/something-went-wrong "اشتباهی رخ داد"
+ :page/logseq-is-having-a-problem "لاگ‌سیک دچار مشکلی شده است. برای بازگرداندن آن به حالت قابل استفاده لطفا گام‌های زیر را به ترتیب انجام دهید:"
+ :page/step "گام {1}"
+ :page/try "امتحان کنید"
+ :page/slide-view "نمایش به صورت اسلاید"
+ :page/slide-view-tip-go-fullscreen (fn [] [[:span.opacity-70 "نکته: دکمه "] [:code "f"] [:span.opacity-70 " را برای رفتن به حالت تمام صفحه بفشارید"]])
+ :page/delete-confirmation "مطمئنید که می‌خواید این برگه به همراه پرونده‌اش را پاک کنید؟"
+ :page/open-in-finder "باز کردن در پوشه"
+ :page/open-with-default-app "باز کردن با برنامه پیش‌فرض"
+ :page/make-public "عمومی ساختن برای انتشار"
+ :page/version-history "نمایش تاریخچهٔ برگه"
+ :page/open-backup-directory "باز کردن پوشه نسخه پشتیبان برگه"
+ :page/make-private "تبدیل به خصوصی"
+ :page/delete "حذف برگه"
+ :page/add-to-favorites "افزودن به برگزیده‌ها"
+ :page/unfavorite "برداشتن از برگزیده‌ها"
+ :page/show-journals "نمایش روزنگارها"
+ :block/name "نام برگه"
+ :page/earlier "پیش‌تر"
+ :page/copy-page-url "رونوشت از نشانی برگه"
+ :page/illegal-page-name "نام برگه غیرمجاز!"
+ :page/page-already-exists "برگه «{1}» از پیش موجود است!"
+ :page/whiteboard-to-journal-error "برگه‌های تخته‌سفید را نمی‌توان به عناوین روزنگار تغییر نام داد!"
+ :file/name "نام پرونده"
+ :file/last-modified-at "آخرین تغییر در"
+ :file/no-data "بدون داده"
+ :file/format-not-supported "قالب .{1} پشتیبانی نمی‌شود."
+ :file/validate-existing-file-error "این برگه از پیش در پروندهٔ دیگری موجود است: {1}, پرونده جاری: {2}. لطفا یکی از آن‌ها را نگه داشته و سپس گراف خود را بازفهرست‌بندی کنید."
+ :page/created-at "ساخته شده در"
+ :page/updated-at "به‌روز شده در"
+ :linked-references/filter-search "جستجو در برگه‌های پیوند شده"
+ :linked-references/filter-heading "پالایه"
+ :linked-references/filter-directions "برای شمول کلیک و برای استثناء کردن، شیفت کلیک کنید. دوباره کلیک کنید تا پاک شود."
+ :linked-references/filter-includes "شامل شده‌ها: "
+ :linked-references/filter-excludes "استثناء شده‌ها: "
+ :linked-references/reference-count (fn [filtered-count total]
+                                      ;; 1 Linked Reference
+                                      ;; 1 of 1 Linked Reference
+                                      ;; 2 of 5 Linked References
+                                      (str
+                                       (when filtered-count
+                                         (str filtered-count " از "))
+                                       total
+                                       (if (= total 1) " ارجاع پیوندی" " ارجاع پیوندی")))
+ :unlinked-references/reference-count (fn [total]
+                                        ;; 1 Unlinked Reference
+                                        ;; 5 Unlinked References
+                                        (str total
+                                         (if (= total 1) " ارجاع غیر پیوندی" " ارجاع غیر پیوندی")))
+ :editor/block-search "جستجو برای بلوک"
+ :text/image "تصویر"
+ :asset/show-in-folder "نمایش تصویر در پوشه"
+ :asset/open-in-browser "باز کردن تصویر در مرورگر"
+ :asset/delete "حذف تصویر"
+ :asset/copy "رونوشت تصویر"
+ :asset/maximize "بیشینه کردن تصویر"
+ :asset/confirm-delete "آیا مطمئنید که می‌خواید این {1} را پاک کنید؟"
+ :asset/physical-delete "به همراه حذف پرونده (توجه داشته باشید که این کار بازگشت‌پذیر نیست)"
+ :color/gray "خاکستری"
+ :color/red "قرمز"
+ :color/yellow "زرد"
+ :color/green "سبز"
+ :color/blue "آبی"
+ :color/purple "بنفش"
+ :color/pink "صورتی"
+ :editor/copy "رونوشت"
+ :editor/cut "برش"
+ :editor/expand-block-children "گسترش همه"
+ :editor/collapse-block-children "جمع کردن همه"
+ :editor/delete-selection "حذف بلوک‌های انتخاب شده"
+ :editor/cycle-todo "چرخش وضعیت TODO مورد جاری"
+ :content/copy-export-as "رونوشت / برون‌ریزی به صورت.."
+ :content/copy-block-url "رونوشت نشانی بلوک"
+ :content/copy-block-ref "رونوشت ارجاع بلوک"
+ :content/copy-block-emebed "رونوشت جاساز بلوک"
+ :content/copy-ref "رونوشت از این ارجاع"
+ :content/delete-ref "حذف این ارجاع"
+ :content/replace-with-text "جایگزینی با متن"
+ :content/replace-with-embed "جایگزینی با جاساز"
+ :content/open-in-sidebar "باز کردن در نوار کناری"
+ :content/click-to-edit "برای ویرایش، کلیک کنید"
+ :context-menu/make-a-flashcard "ساخت یک فلش کارت"
+ :context-menu/toggle-number-list "تغییر فهرست شمارشی"
+ :context-menu/preview-flashcard "پیش‌نمایش فلش کارت"
+ :context-menu/make-a-template "ساخت یک قالب"
+ :context-menu/input-template-name "نام قالب چیست؟"
+ :context-menu/template-include-parent-block "بلوک والد نیز در قالب شامل شود؟"
+ :context-menu/template-exists-warning "این قالب از پیش وجود دارد!"
+:settings-page/alpha-features "ویژگی‌های آلفا"
+:settings-page/app-updated "برنامه شما به روز است 🎉"
+:settings-page/auto-chmod "تغییر خودکار سطوح دسترسی پرونده"
+:settings-page/auto-chmod-desc "غیر فعال کنید تا اجازه ویرایش توسط چند کاربر با دسترسی‌هایی که از طریق عضویت گروه اعطا شده است را بدهید."
+:settings-page/auto-expand-block-refs "گسترش خودکار ارجاعات بلوک در زمان بزرگ‌نمایی"
+:settings-page/auto-expand-block-refs-tip "این گزینه تعیین می‌کند که آیا ارجاعات بلوک در زمان بزرگ‌نمایی به طور خودکار گسترش یابد یا خیر."
+:settings-page/auto-updater "به‌روزرسان خودکار"
+:settings-page/beta-features "ویژگی‌های بتا"
+:settings-page/changelog "چه خبر؟"
+:settings-page/check-for-updates "بررسی برای به‌روزرسانی"
+:settings-page/checking "در حال بررسی ..."
+:settings-page/clear "پاک کردن"
+:settings-page/clear-cache "پاک کردن حافظه نهان"
+:settings-page/clear-cache-warning "عملیات پاک کردن حافظه نهان، گراف‌های باز را نادیده می‌گیرد. تغییرات ذخیره نشده را از دست خواهید داد."
+:settings-page/current-version "نسخه جاری"
+:settings-page/custom-configuration "پیکربندی سفارشی"
+:settings-page/custom-date-format "قالب تاریخ ترجیحی"
+:settings-page/custom-date-format-notification "برای این که این تغییر اعمال شود لازم است که گراف‌تان را بازفهرست‌بندی کنید"
+:settings-page/custom-date-format-warning "بازفهرست‌بندی ضروری است! پیوند ارجاعات روزنگار قطع خواهند شد!"
+:settings-page/custom-global-configuration "پیکربندی سراسری سفارشی"
+:settings-page/custom-theme "پوسته سفارشی"
+:settings-page/developer-mode "حالت توسعه‌دهنده"
+:settings-page/developer-mode-desc "حالت توسعه‌دهنده به مشارکت‌کنندگان و توسعه‌دهندگان افزونه‌ها امکان می‌دهد تا به شکل مؤثرتری بتوانند یکپارچگی کارشان با لاگ‌سیک را به آزمون بگذارند."
+:settings-page/disable-sentry "فرستادن داده‌های استفاده و ارزیابی به لاگ‌سیک"
+:settings-page/disable-sentry-desc "لاگ‌سیک هرگز پایگاه داده گراف محلی شما را گردآوری نکرده و داده‌های شما را نمی‌فروشد."
+:settings-page/edit-config-edn "ویرایش config.edn"
+:settings-page/edit-custom-css "ویرایش custom.css"
+:settings-page/edit-export-css "ویرایش export.css"
+:settings-page/edit-global-config-edn "ویرایش سراسری config.edn"
+:settings-page/enable-all-pages-public "عمومی کردن همه صفحه‌ها در زمانی انتشار"
+:settings-page/enable-flashcards "فلش‌کارت‌ها"
+:settings-page/enable-journals "روزنگارها"
+:settings-page/enable-whiteboards "تخته‌سفیدها"
+:settings-page/export-theme "برون‌ریزی پوسته"
+:settings-page/git-commit-delay "فواصل ذخیره خودکار گیت به ثانیه"
+:settings-page/git-commit-on-close "ذخیره گیت در زمان خروج"
+:settings-page/git-desc-1 "برای مشاهده تاریخچهٔ ویرایش برگه، روی سه نقطه افقی گوشهٔ بالا سمت راست کلیک کرده و «نمایش تاریخچهٔ برگه» را انتخاب کنید."
+:settings-page/git-desc-2 "همچنین برای کاربران حرفه‌ای، لاگ‌سیک از "
+:settings-page/git-desc-3 " برای مدیریت نسخه پیشتیبانی می‌کند. به مسئولیت خودتان از گیت استفاده کنید زیرا مسائل عمومی گیت توسط تیم لاگ‌سیک پشتیبانی نمی‌شود."
+:settings-page/git-switcher-label "فعال‌سازی ذخیره خودکار گیت"
+:settings-page/git-tip "اگر هم‌گام‌سازی لاگ‌سیک را فعال کرده باشید می‌توانید مستقیما تاریخچهٔ ویرایش‌های برگه را مشاهده کنید. این بخش فقط برای خوره‌های فناوری است."
+:settings-page/home-default-page "تنظیم صفحه خانگی پیش‌فرض"
+:settings-page/login-prompt "برای آن که پیش از دیگران به ویژگی‌های جدید دسترسی پیدا کنید لازم است حامی لاگ‌سیک روی اوپن کالکتیو باشید و بنابراین لازم است که ابتدا وارد حساب‌تان بشوید."
+:settings-page/native-titlebar "نوار عنوان بومی"
+:settings-page/native-titlebar-desc "نوار عنوان پنجره بومی را روی گنولینوکس و ویندوز فعال می‌کند."
+:settings-page/network-proxy "پروکسی شبکه"
+:settings-page/plugin-system "افزونه‌ها"
+:settings-page/preferred-file-format "قالب پرونده ترجیحی"
+:settings-page/preferred-outdenting "برون‌رفتگی منطقی"
+:settings-page/preferred-outdenting-tip "سمت چپ، فرون‌رفتگی با تنظیمات پیش‌فرض را نمایش می‌دهد و سمت راست، برون‌رفتگی در حالت فعال بودن برون‌رفتگی منطقی را "
+:settings-page/preferred-outdenting-tip-more "← بیشتر بدانید"
+:settings-page/preferred-pasting-file "شیوه ترجیحی چسباندن پرونده"
+:settings-page/preferred-pasting-file-hint "وقتی فعال باشد، چسباندن یک تصویر از اینترنت باعث بارگیری و درج تصویر می‌شود. وقتی غیر فعال باشد، تنها پیوند به تصویر چسبانده خواهد شد."
+:settings-page/preferred-workflow "گردش کار ترجیحی"
+:settings-page/revision "بازبینی: "
+:settings-page/show-brackets "نمایش براکت"
+:settings-page/show-full-blocks "نمایش تمام خطوط یک ارجاع بلوکی"
+:settings-page/spell-checker "بررسی کننده نگارش"
+:settings-page/sync "هم‌گام‌سازی"
+:settings-page/sync-desc-1 "برای دستورالعمل شیوه تنظیمات و استفاده از هم‌گام‌سازی"
+:settings-page/sync-desc-2 "اینجا"
+:settings-page/sync-desc-3 "کلیک کنید."
+:settings-page/sync-diff-merge "فعال‌سازی ادغام هوشمند در زمان هم‌گام‌سازی"
+:settings-page/sync-diff-merge-desc "در صورت بروز تعارض، به جای نوشتن روی پرونده راه‌دور، تغییرات محلی با پرونده راه‌دو به صورت خودکار ادغام شود"
+:settings-page/tab-account "حساب"
+:settings-page/tab-advanced "پیشرفته"
+:settings-page/tab-assets "دارایی‌ها"
+:settings-page/tab-editor "ویرایش‌گر"
+:settings-page/tab-features "ویژگی‌ها"
+:settings-page/tab-general "عمومی"
+:settings-page/tab-keymap "نگاشت کلید"
+:settings-page/tab-version-control "کنترل نسخه"
+:settings-page/theme-dark "تیره"
+:settings-page/theme-light "روشن"
+:settings-page/theme-system "سامانه"
+:settings-page/update-available "انتشار جدید پیدا شد "
+:settings-page/update-error-1 "⚠️ اوه، مشکلی پیش آمد!"
+
+ :yes "بله"
+
+ :submit "ارسال"
+ :cancel "لغو"
+ :close "بستن"
+ :delete "پاک کردن"
+ :save "ذخیره"
+ :type "نوع"
+ :host "میزبان"
+ :port "درگاه"
+ :re-index "بازفهرست‌بندی"
+ :re-index-detail "ساخت دوباره گراف"
+ :re-index-multiple-windows-warning "پیش از بازفهرست‌بندی این گراف لازم است این پنجره را ببندید."
+ :re-index-discard-unsaved-changes-warning "بازفهرست‌بندی، گراف جاری را نادیده گرفته و سپس همهٔ پرونده‌ها را مجددا به همان شکلی که در حال حاضر روی دستگاه ذخیره شده‌اند پردازش می‌کند. شما تغییرات ذخیره نشده را از دست خواهید دید و این فرایند می‌تواند قدری طول بکشد. ادامه می‌دهید؟"
+ :sync-from-local-files "تازه‌سازی"
+ :sync-from-local-files-detail "وارد کردن تغییرات از پرونده‌های محلی"
+ :sync-from-local-changes-detected "تازه‌سازی پرونده‌های تغییر یافته روی دستگاه را که نسبت به محتوای برگهٔ لاگ‌سیک جاری انحراف دارند را شناسایی و پردازش می‌کند. ادامه می‌دهید؟"
+
+ :home "خانه"
+ :new-page "برگه جدید:"
+ :whiteboard "تخته‌سفید"
+ :whiteboards "تخته‌سفیدها"
+ :new-graph "افزودن گراف جدید"
+ :graph "گراف"
+ :graph/all-graphs "همه گراف‌ها"
+ :graph/local-graphs "گراف‌های محلی:"
+ :graph/remote-graphs "گراف‌های راه‌دور:"
+ :export "برون‌ریزی"
+ :export-graph "برون‌ریزی گراف"
+ :export-page "برون‌ریزی برگه"
+ :export-markdown "برون‌ریزی به صورت مارک‌داون معیاری (بدون خصوصیات بلوک‌ها)"
+ :export-opml "برون‌ریزی به صورت OPML"
+ :export-public-pages "برون‌ریزی برگه‌های عمومی"
+ :export-json "برون‌ریزی به صورت JSON"
+ :export-roam-json "برون‌ریزی به صورت Roam JSON"
+ :export-edn "برون‌ریزی به صورت EDN"
+ :export-transparent-background "پس‌زمینه شفاف"
+ :export-copy-to-clipboard "رونوشت در بریده‌دان"
+ :export-copied-to-clipboard "در بریده‌دان رونوشت شد!"
+ :export-save-to-file "ذخیره در پرونده"
+ :all-graphs "همهٔ گراف‌ها"
+ :all-pages "همهٔ برگه‌ها"
+ :all-whiteboards "همه تخته‌سفیدها"
+ :all-files "همهٔ پرونده‌ها"
+ :all-journals "همهٔ روزنگارها"
+ :settings "تنظیمات"
+ :settings-of-plugins "افزونه‌ها"
+ :plugins "افزونه‌ها"
+ :themes "پوسته‌ها"
+ :relaunch-confirm-to-work "برای آن که کار کند لازم است که برنامه از نو راه‌اندازی شود. می‌خواید هم‌اکنون بازراه‌اندازی کنید؟"
+ :import "درون‌ریزی"
+ :importing "در حال درون‌ریزی"
+ :join-community "به اجتماع بپیوندید"
+ :discourse-title "تالار گفتگوی ما!"
+ :help-shortcut-title "برای بررسی میان‌برها و دیگر نکات کلیک کنید"
+ :loading "در حال بار شدن..."
+ :parsing-files "تجزیه پرونده‌ها"
+ :loading-files "بار کردن پرونده‌ها"
+ :login "ورود"
+ :logout "خروج"
+ :logout-user "خروج ({1})"
+ :download "بارگیری"
+ :language "زبان"
+ :remove-background "حذف پس‌زمینه"
+ :open-a-directory "باز کردن یک پوشه محلی"
+ :toggle-theme      "تغییر پوسته"
+
+ :help/shortcut-page-title "کلیدهای میان‌بر"
+
+ :plugin/installed "نصب شده"
+ :plugin/installed-plugin "افزونه نصب شده: {1}"
+ :plugin/not-installed "نصب نشده"
+ :plugin/installing "در حال نصب"
+ :plugin/install "نصب"
+ :plugin/reload "بار کردن مجدد"
+ :plugin/update "به‌روزرسانی"
+ :plugin/update-plugin "به‌روزرسانی افزونه: {1} - {2}"
+ :plugin/check-update "بررسی به‌روزرسانی"
+ :plugin/check-all-updates "بررسی همه به‌روزرسانی‌ها"
+ :plugin/found-updates "به‌روزرسانی‌های جدید"
+ :plugin/found-n-updates "{1} به‌روزرسانی پیدا شد"
+ :plugin/update-all-selected "به‌روزرسانی همه انتخاب شده‌ها"
+ :plugin/all-updated "همگی به‌روز شدند!"
+ :plugin/updates-downloading "بارگیری به‌روزرسانی‌ها"
+ :plugin/refresh-lists "تازه‌سازی فهرست‌ها"
+ :plugin/enabled "فعال"
+ :plugin/disabled "غیرفعال"
+ :plugin/update-available "به‌روزرسانی موجود است"
+ :plugin/updating "در حال به‌روزرسانی"
+ :plugin/uninstall "حذف نصب"
+ :plugin/marketplace "بازارچه"
+ :plugin/downloads "بارگیری‌ها"
+ :plugin/stars "ستاره‌ها"
+ :plugin/title "عنوان ({1})"
+ :plugin/all "همه"
+ :plugin/unpacked "بسته‌بندی نشده"
+ :plugin/delete-alert "برای حذف افزونهٔ [{1}] اطمینان دارید؟"
+ :plugin/open-settings "باز کردن تنظیمات"
+ :plugin/open-package "باز کردن بسته"
+ :plugin/load-unpacked "بار کردن افزونه بسته‌بندی نشده"
+ :plugin/restart "بازراه‌اندازی برنامه"
+ :plugin/unpacked-tips "انتخاب پوشهٔ افزونه"
+ :plugin/contribute "✨ افزونهٔ جدید نوشته و بفرستید"
+ :plugin/up-to-date "به روز است {1}"
+ :plugin/custom-js-alert "پرونده‌ای به نام custom.js پیدا کردم. مجازم که اجرایش کنم؟ (اگر از محتوای این پرونده سر در نمی‌آورید، پیشنهاد می‌شود که اجازه اجرا را ندهید چون می‌تواند مخاطرات امنیتی داشته باشد.)"
+ :plugin/security-warning "افزونه‌ها می‌توانند به گراف و پرونده‌های محلی شما دسترسی داشته و درخواست‌هایی روی شبکه بفرستند.
+       آن‌ها همجنین می‌توانند باعت تخریب و یا از دست رفتن داده‌ها شوند. ما مشغول کار روی قوانین دسترسی مناسب برای گراف شما هستیم.
+       در این بین، اطمینان حاصل کنید که به طور منظم از گراف‌های خود نسخه پشتیبان تهیه کرده و تنها زمانی از افزونه‌ها استفاده کنید
+       که می‌توانید کد منبع آن‌ها مطالعه و درک کنید."
+ :plugin/search-plugin "جستجوی افزونه‌ها"
+ :plugin/open-preferences "باز کردن ترجیحات"
+ :plugin/open-logseq-dir "باز کردن"
+ :plugin/remote-error "خطای راه دور: "
+ :plugin/checking-for-updates "در حال بررسی به‌روزرسانی افزونه‌ها..."
+ :plugin/list-of-updates "افزونه‌های دارای به‌روزرسانی: "
+ :plugin/auto-check-for-updates "بررسی خودکار برای به‌روزرسانی"
+ :plugin.install-from-file/menu-title "نصب از plugins.edn"
+ :plugin.install-from-file/title "نصب افزونه‌ها از plugins.edn"
+ :plugin.install-from-file/notice "این افزونه‌ها جایگزین افزونه‌های شما می‌‌شوند:"
+ :plugin.install-from-file/success "همه افزونه‌ها نصب شدند!"
+
+ :updater/new-version-install "نسخه‌ای جدید بارگیری شده است."
+ :updater/quit-and-install "بازراه‌اندازی برای نصب"
+
+ :paginates/pages "مجموعا {1} برگه"
+ :paginates/prev "قبلی"
+ :paginates/next "بعدی"
+
+ :tips/all-done "همه انجام شدند!"
+
+ :select/default-prompt "یکی را انتخاب کنید"
+ :select/default-select-multiple "یک یا چند مورد را انتخاب کنید"
+ :select.graph/prompt "یک گراف را انتخاب کنید"
+ :select.graph/empty-placeholder-description "گرافی یافت نشد. می‌خواهید مورد دیگری را اضافه کنید؟"
+ :select.graph/add-graph "بله، گراف دیگری را اضافه کن"
+
+ :file-sync/other-user-graph "گراف محلی جاری به گراف راه‌دور کاربر دیگری متصل است. به همین دلیل شروع هم‌گام‌سازی ممکن نیست."
+ :file-sync/graph-deleted "گراف راه‌دور جاری پاک شده است"
+ :file-sync/rsapi-cannot-upload-err "شروع هم‌گام‌سازی ممکن نیست. لطفا از درستی زمان محلی‌تان اطمینان حاصل کنید."
+ :file-sync/connectivity-testing-failed "بررسی اتصال شبکه به شکست انجامید. لطفا تنظیمات شبکه خود را بررسی کنید. نشانی‌های بررسی: "
+
+ :notification/clear-all "پاک کردن همه"
+
+ :shortcut.category/basics "مقدماتی"
+ :shortcut.category/formatting "قالب‌بندی"
+ :shortcut.category/navigating "ناوبری"
+ :shortcut.category/block-editing "تنظیمات عمومی ویرایش بلوک"
+ :shortcut.category/block-command-editing "ویرایش دستوری بلوک"
+ :shortcut.category/block-selection "انتخاب بلوک (با دکمه Esc از حالت انتخاب خارج می‌شوید)"
+ :shortcut.category/toggle "تغییر حالت"
+ :shortcut.category/others "سایر"
+ :shortcut.category/plugins "افزونه‌ها"
+ :shortcut.category/whiteboard "تخته‌سفید"
+
+ :keymap/all "همه"
+ :keymap/disabled "غیر فعال"
+ :keymap/unset "تنظیم نشده"
+ :keymap/custom "سفارشی"
+ :keymap/search "جستجو"
+ :keymap/total "تعداد کل میان‌برها"
+ :keymap/keystroke-filter "پالایهٔ تاج‌مهره"
+ :keymap/keystroke-record-desc "سلسله‌ای از کلیدها را برای پالایش میان‌برها بفشارید"
+ :keymap/keystroke-record-setup-label "سلسله‌ای از دکمه‌ها را برای تنظیم میان‌بر بفشارید"
+ :keymap/restore-to-default "بازگردانی به پیش‌فرض سامانه"
+ :keymap/customize-for-label "سفارشی‌سازی میان‌برها"
+ :keymap/conflicts-for-label "تعارض میان‌بر برای"
+
+ :window/minimize "کمینه‌سازی"
+ :window/maximize "بیشینه‌سازی"
+ :window/restore "بازگردانی"
+ :window/close "بستن"
+ :window/exit-fullscreen "خروج از حالت تمام صفحه"
+
+ :header/toggle-left-sidebar         "تغییر وضعیت نوار چپ"
+ :header/search                      "جستجو"
+ :header/more                        "بیشتر"
+ :header/go-back                     "برو عقب"
+ :header/go-forward                  "برو جلو"
+}

+ 0 - 2
src/resources/dicts/fr.edn

@@ -372,8 +372,6 @@
     :command.search/re-index  "Reconstruire l'index de recherche"
     :command.sidebar/clear  "Vider intégralement la barre latérale droite"
     :command.sidebar/open-today-page  "Ouvrir la page du jour dans la barre latérale droite"
-    :command.ui/cycle-color "Bascule de la couleur"
-    :command.ui/cycle-color-off "Bascule de la couleur désactivée"
     :command.ui/goto-plugins  "Aller vers le panneau des extensions"
     :command.ui/install-plugins-from-file  "Installer les extensions depuis plugins.edn"
     :command.ui/select-theme-color  "Sélectionner les couleurs disponibles du thème"

+ 0 - 2
src/resources/dicts/it.edn

@@ -388,8 +388,6 @@
  :command.pdf/find "PDF: cerca testo nel documento"
  :command.sidebar/close-top "Chiudi l'elemento in alto nel pannello laterale destra"
  :command.ui/clear-all-notifications "Cancella tutte le notifiche"
- :command.ui/cycle-color "Cicla colore"
- :command.ui/cycle-color-off "Disattiva cicla colore"
  :command.ui/install-plugins-from-file "Installa plugin da plugins.edn"
  :command.whiteboard/bring-forward "Sposta in avanti"
  :command.whiteboard/bring-to-front "Sposta in fronte"

+ 0 - 2
src/resources/dicts/ja.edn

@@ -762,8 +762,6 @@
  :command.ui/toggle-help "ヘルプの表示/非表示"
  :command.ui/toggle-theme "テーマの切り替え"
  :command.ui/toggle-contents "目次の開閉"
- :command.ui/cycle-color-off "循環させた色を元に戻す"
- :command.ui/cycle-color "色を循環させる"
 
  :command.command/toggle-favorite "お気に入りへ追加/削除"
  :command.editor/open-file-in-default-app "ファイルを既定のアプリで開く"

+ 0 - 2
src/resources/dicts/nb-no.edn

@@ -756,8 +756,6 @@
 
  :command.command-palette/toggle "Søk kommandoer"
  :command.go/search-in-page "Søk blokker på side"
- :command.ui/cycle-color "Veksle farge"
- :command.ui/cycle-color-off "Veksle farge av"
  :command.whiteboard/clone-down "Klon ned"
  :command.whiteboard/clone-left "Klon venstre"
  :command.whiteboard/clone-right "Klon høyre"

+ 0 - 2
src/resources/dicts/pt-br.edn

@@ -727,8 +727,6 @@
  :command.sidebar/close-top "Fechar o item superior na barra lateral direita"
  :command.sidebar/open-today-page "Abrir a página de hoje na barra lateral direita"
  :command.ui/clear-all-notifications "Limpar todas as notificações"
- :command.ui/cycle-color "Mudar cor"
- :command.ui/cycle-color-off "Desativar mudança de cor"
  :command.ui/goto-plugins "Ir para o painel de plugins"
  :command.ui/install-plugins-from-file "Instalar plugins do arquivo plugins.edn"
  :command.ui/select-theme-color "Selecionar cores de tema disponíveis"

+ 0 - 2
src/resources/dicts/sk.edn

@@ -747,8 +747,6 @@
  :command.ui/toggle-help                           "Zobraziť/Skryť pomocníka"
  :command.ui/toggle-theme                          "Prepínať medzi tmavým/svetlým motívom"
  :command.ui/toggle-contents                       "Zobraziť/Skryť obsah na bočnom paneli"
- :command.ui/cycle-color-off                       "Vypnúť zmenu farieb"
- :command.ui/cycle-color                           "Zmeniť farbu"
  :command.command/toggle-favorite                  "Pridať/Odstrániť z obľúbených"
  :command.editor/open-file-in-default-app          "Otvoriť súbor v predvolenej aplikácii"
  :command.editor/open-file-in-directory            "Otvoriť súbor v nadradenom adresári"

+ 1 - 2
src/resources/dicts/tr.edn

@@ -260,6 +260,7 @@
  :settings-page/git-desc-1 "Sayfanın düzenleme geçmişini görüntülemek için sağ üst köşedeki üç yatay noktaya basın ve \"Sayfa geçmişini görüntüle\" ögesini seçin."
  :settings-page/git-desc-2 "Profesyonel kullanıcılar için Logseq, sürüm kontrolü için "
  :settings-page/git-desc-3 " kullanımını da destekler. Genel Git sorunları Logseq ekibi tarafından desteklenmediğinden Git'i kullanmanın riski size aittir."
+ :settings-page/git-commit-on-close "Pencere kapatıldığında git commit'i çalıştır"
  :settings-page/git-switcher-label "Otomatik git commit'i etkinleştir"
  :settings-page/git-commit-delay "Otomatik git commit saniyesi"
  :settings-page/edit-config-edn "config.edn dosyasını düzenle"
@@ -780,8 +781,6 @@
  :command.ui/toggle-help                 "Yardımı aç/kapat"
  :command.ui/toggle-theme                "Koyu ve açık tema arasında geçiş yap"
  :command.ui/toggle-contents             "Kenar çubuğundaki içeriği aç/kapat"
- :command.ui/cycle-color-off             "Renk değiştirmeyi kapat"
- :command.ui/cycle-color                 "Renk değiştir"
  :command.command/toggle-favorite        "Sık kullanılanlara ekle/çıkar"
  :command.editor/open-file-in-default-app "Dosyayı varsayılan uygulamada aç"
  :command.editor/open-file-in-directory   "Dosyayı üst dizinde aç"

+ 0 - 1
src/resources/templates/config.edn

@@ -1 +0,0 @@
-../../../deps/common/resources/templates/config.edn

+ 14 - 0
src/resources/tutorials/dummy-notes-fa.md

@@ -0,0 +1,14 @@
+---
+title: چگونه یادداشت‌برداری کنیم؟
+---
+
+- درود. من یک بلوک هستم!
+:PROPERTIES:
+:id: 5f713e91-8a3c-4b04-a33a-c39482428e2d
+:END:
+    - من یک زیربلوک هستم!
+    - من هم یک زیر بلوک دیگه هستم!
+- آهای! من هم یک بلوک هستم!
+:PROPERTIES:
+:id: 5f713ea8-8cba-403d-ac00-9964b1ec7190
+:END:

+ 25 - 0
src/resources/tutorials/tutorial-fa.md

@@ -0,0 +1,25 @@
+## درود. به لاگ‌سیک خوش آمدید!
+- لاگ‌سیک یک سکوی [آزاد](https://github.com/logseq/logseq) برای مدیریت _دانش_ و همکاری است که _حریم شخصی_ را در اولویت اول قرار می‌دهد.
+- این مطلب، یک آموزش ۳ دقیقه‌ای برای شروع کار با لاگ‌سیک است. بگذارید شروع کنیم!
+- بگذارید سه نکته که می‌توانند مفید باشند را ببینیم.
+#+BEGIN_TIP
+برای ویرایش هر بلوک، روی آن کلید کنید.
+با فشردن دکمه `Enter‍` یک بلوک جدید بسازید.
+با فشردن `Shift+Enter` یک خط جدید بسازید.
+با فشردن `/` همه دستورات را ببینید.
+#+END_TIP
+- 1. بیایید برگه‌ای به نام [[چگونه یادداشت‌برداری کنیم؟]] بسازیم. می‌توانید روی آن کلید کنید تا به برگه مربوطه بروید و یا می‌توانید با فشردن `Shift+Click`، آن را در نوار کناری باز کنید! حالا باید بتوانید هم _ارجاعات پیوندی_ و هم _ارجاعات غیر پیوندی_ را ببینید.
+- 2. بیایید به چند بلوک در [[چگونه یادداشت‌برداری کنیم؟]] ارجاع دهیم. می‌توانید با `Shift-Click` روی هر ارجاع، آن را در نوار کناری باز کنید. سعی کنید تغییراتی در نوار کناری بدهید. می‌بینید که تغییرات در بلوک‌های ارجاع داده شده نیز تغییر مي‌کنند!
+    - ((5f713e91-8a3c-4b04-a33a-c39482428e2d)) : این یک ارجاع بوک است.
+    - ((5f713ea8-8cba-403d-ac00-9964b1ec7190)) : این یک ارجاع بلوک دیگر است.
+- 3. آیا از برچسب‌ها پشتیبانی مي‌کنید؟
+    - قطعا! این یک برچسب #dummy است.
+- 4. آیا از کلمات کلیدی تعریف وظایف مثل todo/doing/done و اولویت‌بندی‌ها پیشتیبانی می‌کنید؟
+    - بله. `/` را بنویسید و کلیدواژه وظایف یا اولویت‌بندی (A/B/C) مورد نظرتان را انتخاب کنید.
+    - NOW [#A] آموزشی درباره «چگونه یادداشت برداری کنیم؟» بسازم.
+    - LATER [#A] این ویدئوی فوق‌العاده، ساختهٔ [:a {:href "https://twitter.com/shuomi3" :target "_blank"} "@shuomi3"] درباره این که چگونه از لاگ‌سیک برای یادداشت برداری و سازمان‌دهی زندگی را ببینم.
+    {{youtube https://www.youtube.com/watch?v=BhHfF0P9A80&ab_channel=ShuOmi}}
+    - DONE ساخت یک برگه
+    - CANCELED [#C] نوشتن یک برگه با بیش از هزار بلوک
+- همین و بس! می‌توانید مواردی دیگری را اضافه کنید و یا پوشه محلی را برای وارد کردن تعدادی یادداشت جدید باز کنید!
+- همچنین می‌توانید برنامهٔ میزکار را از این نشانی دریافت کنید: https://github.com/logseq/logseq/releases

+ 1 - 0
tailwind.all.css

@@ -5,6 +5,7 @@
 
 @import "packages/ui/src/radix.css";
 @import "packages/ui/src/radix-hsl.css";
+@import "packages/ui/src/vars-classic.css";
 @import "packages/ui/src/colors.css";
 @import "packages/ui/src/index.css";
 @import "resources/css/shui.css";

+ 49 - 98
tailwind.config.js

@@ -2,73 +2,22 @@ const colors = require('tailwindcss/colors')
 const plugin = require('tailwindcss/plugin')
 const radix = require('@radix-ui/colors')
 
-const lx = override => ({
-  'accent-01': 'or(' + override + ', --lx-accent-01, --ls-page-properties-background-color)',
-  'accent-02': 'or(' + override + ', --lx-accent-02, --ls-page-properties-background-color)',
-  'accent-03': 'or(' + override + ', --lx-accent-03, --ls-page-properties-background-color)',
-  'accent-04': 'or(' + override + ', --lx-accent-04, --ls-page-properties-background-color)',
-  'accent-05': 'or(' + override + ', --lx-accent-05, --color-blue-900)',
-  'accent-06': 'or(' + override + ', --lx-accent-06, --color-blue-800)',
-  'accent-07': 'or(' + override + ', --lx-accent-07, --color-blue-700)',
-  'accent-08': 'or(' + override + ', --lx-accent-08, --color-blue-600)',
-  'accent-09': 'or(' + override + ', --lx-accent-09, --color-blue-500)',
-  'accent-10': 'or(' + override + ', --lx-accent-10, --color-blue-400)',
-  'accent-11': 'or(' + override + ', --lx-accent-11, --color-blue-200)',
-  'accent-12': 'or(' + override + ', --lx-accent-12, --color-blue-50)',
-  'accent-01-alpha': 'or(' + override + ', --lx-accent-01-alpha, --ls-page-properties-background-color)',
-  'accent-02-alpha': 'or(' + override + ', --lx-accent-02-alpha, --ls-page-properties-background-color)',
-  'accent-03-alpha': 'or(' + override + ', --lx-accent-03-alpha, --ls-page-properties-background-color)',
-  'accent-04-alpha': 'or(' + override + ', --lx-accent-04-alpha, --ls-page-properties-background-color)',
-  'accent-05-alpha': 'or(' + override + ', --lx-accent-05-alpha, --color-blue-900)',
-  'accent-06-alpha': 'or(' + override + ', --lx-accent-06-alpha, --color-blue-800)',
-  'accent-07-alpha': 'or(' + override + ', --lx-accent-07-alpha, --color-blue-700)',
-  'accent-08-alpha': 'or(' + override + ', --lx-accent-08-alpha, --color-blue-600)',
-  'accent-09-alpha': 'or(' + override + ', --lx-accent-09-alpha, --color-blue-500)',
-  'accent-10-alpha': 'or(' + override + ', --lx-accent-10-alpha, --color-blue-400)',
-  'accent-11-alpha': 'or(' + override + ', --lx-accent-11-alpha, --color-blue-200)',
-  'accent-12-alpha': 'or(' + override + ', --lx-accent-12-alpha, --color-blue-50)',
-  'gray-01': 'or(' + override + ', --lx-gray-01, --ls-primary-background-color)',
-  'gray-02': 'or(' + override + ', --lx-gray-02, --ls-secondary-background-color)',
-  'gray-03': 'or(' + override + ', --lx-gray-03, --ls-tertiary-background-color)',
-  'gray-04': 'or(' + override + ', --lx-gray-04, --ls-quaternary-background-color)',
-  'gray-05': 'or(' + override + ', --lx-gray-05, --color-level-4)',
-  'gray-06': 'or(' + override + ', --lx-gray-06, --ls-block-bullet-border-color)',
-  'gray-07': 'or(' + override + ', --lx-gray-07, --ls-border-color)',
-  'gray-08': 'or(' + override + ', --lx-gray-08, --ls-secondary-border-color)',
-  'gray-09': 'or(' + override + ', --lx-gray-09, --color-level-5)',
-  'gray-10': 'or(' + override + ', --lx-gray-10, --ls-title-text-color)',
-  'gray-11': 'or(' + override + ', --lx-gray-11, --ls-primary-text-color)',
-  'gray-12': 'or(' + override + ', --lx-gray-12, --ls-secondary-text-color)',
-  'gray-01-alpha': 'or(' + override + ', --lx-gray-01-alpha, --ls-primary-background-color)',
-  'gray-02-alpha': 'or(' + override + ', --lx-gray-02-alpha, --ls-secondary-background-color)',
-  'gray-03-alpha': 'or(' + override + ', --lx-gray-03-alpha, --ls-tertiary-background-color)',
-  'gray-04-alpha': 'or(' + override + ', --lx-gray-04-alpha, --ls-quaternary-background-color)',
-  'gray-05-alpha': 'or(' + override + ', --lx-gray-05-alpha, --color-level-4)',
-  'gray-06-alpha': 'or(' + override + ', --lx-gray-06-alpha, --ls-block-bullet-color)',
-  'gray-07-alpha': 'or(' + override + ', --lx-gray-07-alpha, --ls-border-color)',
-  'gray-08-alpha': 'or(' + override + ', --lx-gray-08-alpha, --ls-secondary-border-color)',
-  'gray-09-alpha': 'or(' + override + ', --lx-gray-09-alpha, --color-level-5)',
-  'gray-10-alpha': 'or(' + override + ', --lx-gray-10-alpha, --color-level-6)',
-  'gray-11-alpha': 'or(' + override + ', --lx-gray-11-alpha, --ls-primary-text-color)',
-  'gray-12-alpha': 'or(' + override + ', --lx-gray-12-alpha, --ls-secondary-text-color)',
-})
-
 const accent = {
   'DEFAULT': 'hsl(var(--accent))',
   'base': 'hsl(var(--accent))',
   'foreground': 'hsl(var(--accent-foreground))',
-  '01': 'var(--lx-accent-01)',
-  '02': 'var(--lx-accent-02)',
-  '03': 'var(--lx-accent-03)',
-  '04': 'var(--lx-accent-04)',
-  '05': 'var(--lx-accent-05)',
-  '06': 'var(--lx-accent-06)',
-  '07': 'var(--lx-accent-07)',
-  '08': 'var(--lx-accent-08)',
-  '09': 'var(--lx-accent-09)',
-  '10': 'var(--lx-accent-10)',
-  '11': 'var(--lx-accent-11)',
-  '12': 'var(--lx-accent-12)',
+  '01': 'var(--lx-accent-01, --rx-gray-01)',
+  '02': 'var(--lx-accent-02, hsl(var(--accent)/.1))',
+  '03': 'var(--lx-accent-03, hsl(var(--accent)/.15))',
+  '04': 'var(--lx-accent-04, hsl(var(--accent)/.2))',
+  '05': 'var(--lx-accent-05, hsl(var(--accent)/.3))',
+  '06': 'var(--lx-accent-06, hsl(var(--accent)/.4))',
+  '07': 'var(--lx-accent-07, hsl(var(--accent)/.5))',
+  '08': 'var(--lx-accent-08, hsl(var(--accent)/.6))',
+  '09': 'var(--lx-accent-09, hsl(var(--accent)/.7))',
+  '10': 'var(--lx-accent-10, hsl(var(--accent)/.8))',
+  '11': 'var(--lx-accent-11, hsl(var(--accent)/.9))',
+  '12': 'var(--lx-accent-12, --rx-gray-12)',
   '01-alpha': 'var(--lx-accent-01-alpha)',
   '02-alpha': 'var(--lx-accent-02-alpha)',
   '03-alpha': 'var(--lx-accent-03-alpha)',
@@ -85,30 +34,30 @@ const accent = {
 
 const gray = {
   ...colors.gray,
-  '01': 'var(--lx-gray-01)',
-  '02': 'var(--lx-gray-02)',
-  '03': 'var(--lx-gray-03)',
-  '04': 'var(--lx-gray-04)',
-  '05': 'var(--lx-gray-05)',
-  '06': 'var(--lx-gray-06)',
-  '07': 'var(--lx-gray-07)',
-  '08': 'var(--lx-gray-08)',
-  '09': 'var(--lx-gray-09)',
-  '10': 'var(--lx-gray-10)',
-  '11': 'var(--lx-gray-11)',
-  '12': 'var(--lx-gray-12)',
-  '01-alpha': 'var(--lx-gray-01-alpha)',
-  '02-alpha': 'var(--lx-gray-02-alpha)',
-  '03-alpha': 'var(--lx-gray-03-alpha)',
-  '04-alpha': 'var(--lx-gray-04-alpha)',
-  '05-alpha': 'var(--lx-gray-05-alpha)',
-  '06-alpha': 'var(--lx-gray-06-alpha)',
-  '07-alpha': 'var(--lx-gray-07-alpha)',
-  '08-alpha': 'var(--lx-gray-08-alpha)',
-  '09-alpha': 'var(--lx-gray-09-alpha)',
-  '10-alpha': 'var(--lx-gray-10-alpha)',
-  '11-alpha': 'var(--lx-gray-11-alpha)',
-  '12-alpha': 'var(--lx-gray-12-alpha)',
+  '01': 'var(--lx-gray-01, var(--ls-primary-background-color, var(--rx-gray-01)))',
+  '02': 'var(--lx-gray-02, var(--ls-secondary-background-color, var(--rx-gray-02)))',
+  '03': 'var(--lx-gray-03, var(--ls-tertiary-background-color, var(--rx-gray-03)))',
+  '04': 'var(--lx-gray-04, var(--ls-quaternary-background-color, var(--rx-gray-04)))',
+  '05': 'var(--lx-gray-05, var(--rx-gray-05))',
+  '06': 'var(--lx-gray-06, var(--rx-gray-06))',
+  '07': 'var(--lx-gray-07, var(--rx-gray-07))',
+  '08': 'var(--lx-gray-08, var(--rx-gray-08))',
+  '09': 'var(--lx-gray-09, var(--rx-gray-09))',
+  '10': 'var(--lx-gray-10, var(--rx-gray-10))',
+  '11': 'var(--lx-gray-11, var(--rx-gray-11))',
+  '12': 'var(--lx-gray-12, var(--rx-gray-12))',
+  '01-alpha': 'var(--lx-gray-01-alpha, var(--rx-gray-01-alpha))',
+  '02-alpha': 'var(--lx-gray-02-alpha, var(--rx-gray-02-alpha))',
+  '03-alpha': 'var(--lx-gray-03-alpha, var(--rx-gray-03-alpha))',
+  '04-alpha': 'var(--lx-gray-04-alpha, var(--rx-gray-04-alpha))',
+  '05-alpha': 'var(--lx-gray-05-alpha, var(--rx-gray-05-alpha))',
+  '06-alpha': 'var(--lx-gray-06-alpha, var(--rx-gray-06-alpha))',
+  '07-alpha': 'var(--lx-gray-07-alpha, var(--rx-gray-07-alpha))',
+  '08-alpha': 'var(--lx-gray-08-alpha, var(--rx-gray-08-alpha))',
+  '09-alpha': 'var(--lx-gray-09-alpha, var(--rx-gray-09-alpha))',
+  '10-alpha': 'var(--lx-gray-10-alpha, var(--rx-gray-10-alpha))',
+  '11-alpha': 'var(--lx-gray-11-alpha, var(--rx-gray-11-alpha))',
+  '12-alpha': 'var(--lx-gray-12-alpha, var(--rx-gray-12-alpha))',
 }
 
 function exposeColorsToCssVars ({ addBase, theme }) {
@@ -193,8 +142,7 @@ module.exports = {
     require('@tailwindcss/aspect-ratio'),
     require('tailwind-capitalize-first-letter'),
     require('tailwindcss-animate'),
-    exposeColorsToCssVars,
-    withOverride,
+    exposeColorsToCssVars
   ],
   theme: {
     extend: {
@@ -226,15 +174,15 @@ module.exports = {
         'lmd': '728px',
         'llg': '960px'
       },
-      backgroundColor: {
-        ...lx('--lx-bg-override'),
-      },
-      textColor: {
-        ...lx('--lx-text-override'),
-      },
-      borderColor: {
-        ...lx('--lx-border-override'),
-      },
+      // backgroundColor: {
+      //   ...lx('--lx-bg-override'),
+      // },
+      // textColor: {
+      //   ...lx('--lx-text-override'),
+      // },
+      // borderColor: {
+      //   ...lx('--lx-border-override'),
+      // },
       borderRadius: {
         lg: 'var(--radius)',
         md: 'calc(var(--radius) - 2px)',
@@ -278,6 +226,9 @@ module.exports = {
         DEFAULT: 'hsl(var(--popover))',
         foreground: 'hsl(var(--popover-foreground))',
       },
+      popovelx: {
+        DEFAULT: 'var(--lx-gray-03, hsl(var(--popover)))',
+      },
       card: {
         DEFAULT: 'hsl(var(--card))',
         foreground: 'hsl(var(--card-foreground))',

Некоторые файлы не были показаны из-за большого количества измененных файлов