Browse Source

refactor: separate og and db version (#12276)

separate og and new version apps

remove file sync, tldraw, excalidraw and zotero
Tienson Qin 2 weeks ago
parent
commit
bcc478b5f7
100 changed files with 105 additions and 6290 deletions
  1. 1 15
      .carve/ignore
  2. 1 2
      clj-e2e/test/logseq/e2e/plugins_basic_test.clj
  3. 3 4
      deps/cli/src/logseq/cli/common/graph.cljs
  4. 0 18
      deps/common/resources/templates/config.edn
  5. 1 1
      deps/common/src/logseq/common/config.cljs
  6. 1 1
      deps/common/src/logseq/common/graph.cljs
  7. 6 14
      deps/db/src/logseq/db/common/view.cljs
  8. 73 93
      deps/outliner/src/logseq/outliner/core.cljs
  9. 10 15
      deps/outliner/src/logseq/outliner/op.cljs
  10. 3 3
      deps/outliner/src/logseq/outliner/page.cljs
  11. 1 1
      deps/outliner/src/logseq/outliner/tree.cljs
  12. 2 2
      deps/outliner/test/logseq/outliner/core_test.cljs
  13. 1 1
      deps/publishing/src/logseq/publishing/export.cljs
  14. 0 4
      gulpfile.js
  15. 1 1
      ios/App/App/FsWatcher.swift
  16. 0 2
      libs/src/LSPlugin.ts
  17. 1 6
      package.json
  18. 0 19
      packages/tldraw/.editorconfig
  19. 0 3
      packages/tldraw/.eslintignore
  20. 0 19
      packages/tldraw/.eslintrc
  21. 0 2
      packages/tldraw/.gitattributes
  22. 0 17
      packages/tldraw/.gitignore
  23. 0 17
      packages/tldraw/.npmignore
  24. 0 11
      packages/tldraw/.prettierrc
  25. 0 21
      packages/tldraw/LICENSE.md
  26. 0 29
      packages/tldraw/README.md
  27. 0 3
      packages/tldraw/apps/tldraw-logseq/README.md
  28. 0 29
      packages/tldraw/apps/tldraw-logseq/build.mjs
  29. 0 42
      packages/tldraw/apps/tldraw-logseq/package.json
  30. 0 3
      packages/tldraw/apps/tldraw-logseq/postcss.config.js
  31. 0 148
      packages/tldraw/apps/tldraw-logseq/src/app.tsx
  32. 0 113
      packages/tldraw/apps/tldraw-logseq/src/components/ActionBar/ActionBar.tsx
  33. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/ActionBar/index.ts
  34. 0 20
      packages/tldraw/apps/tldraw-logseq/src/components/AppUI.tsx
  35. 0 71
      packages/tldraw/apps/tldraw-logseq/src/components/BlockLink/BlockLink.tsx
  36. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/BlockLink/index.ts
  37. 0 15
      packages/tldraw/apps/tldraw-logseq/src/components/Button/Button.tsx
  38. 0 26
      packages/tldraw/apps/tldraw-logseq/src/components/Button/CircleButton.tsx
  39. 0 2
      packages/tldraw/apps/tldraw-logseq/src/components/Button/index.ts
  40. 0 67
      packages/tldraw/apps/tldraw-logseq/src/components/ContextBar/ContextBar.tsx
  41. 0 560
      packages/tldraw/apps/tldraw-logseq/src/components/ContextBar/contextBarActionFactory.tsx
  42. 0 2
      packages/tldraw/apps/tldraw-logseq/src/components/ContextBar/index.ts
  43. 0 369
      packages/tldraw/apps/tldraw-logseq/src/components/ContextMenu/ContextMenu.tsx
  44. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/ContextMenu/index.ts
  45. 0 56
      packages/tldraw/apps/tldraw-logseq/src/components/Devtools/Devtools.tsx
  46. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/Devtools/index.ts
  47. 0 93
      packages/tldraw/apps/tldraw-logseq/src/components/GeometryTools/GeometryTools.tsx
  48. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/GeometryTools/index.ts
  49. 0 16
      packages/tldraw/apps/tldraw-logseq/src/components/KeyboardShortcut/KeyboardShortcut.tsx
  50. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/KeyboardShortcut/index.ts
  51. 0 55
      packages/tldraw/apps/tldraw-logseq/src/components/Minimap/Minimap.tsx
  52. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/Minimap/index.ts
  53. 0 39
      packages/tldraw/apps/tldraw-logseq/src/components/PopoverButton/PopoverButton.tsx
  54. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/PopoverButton/index.ts
  55. 0 103
      packages/tldraw/apps/tldraw-logseq/src/components/PrimaryTools/PrimaryTools.tsx
  56. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/PrimaryTools/index.ts
  57. 0 44
      packages/tldraw/apps/tldraw-logseq/src/components/QuickLinks/QuickLinks.tsx
  58. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/QuickLinks/index.ts
  59. 0 437
      packages/tldraw/apps/tldraw-logseq/src/components/QuickSearch/QuickSearch.tsx
  60. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/QuickSearch/index.ts
  61. 0 16
      packages/tldraw/apps/tldraw-logseq/src/components/StatusBar/StatusBar.tsx
  62. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/StatusBar/index.ts
  63. 0 50
      packages/tldraw/apps/tldraw-logseq/src/components/ToolButton/ToolButton.tsx
  64. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/ToolButton/index.ts
  65. 0 31
      packages/tldraw/apps/tldraw-logseq/src/components/Tooltip/Tooltip.tsx
  66. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/Tooltip/index.ts
  67. 0 65
      packages/tldraw/apps/tldraw-logseq/src/components/ZoomMenu/ZoomMenu.tsx
  68. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/ZoomMenu/index.ts
  69. 0 35
      packages/tldraw/apps/tldraw-logseq/src/components/icons/TablerIcon.tsx
  70. 0 1
      packages/tldraw/apps/tldraw-logseq/src/components/icons/index.ts
  71. 0 122
      packages/tldraw/apps/tldraw-logseq/src/components/inputs/ColorInput.tsx
  72. 0 12
      packages/tldraw/apps/tldraw-logseq/src/components/inputs/NumberInput.tsx
  73. 0 59
      packages/tldraw/apps/tldraw-logseq/src/components/inputs/ScaleInput.tsx
  74. 0 75
      packages/tldraw/apps/tldraw-logseq/src/components/inputs/SelectInput.tsx
  75. 0 162
      packages/tldraw/apps/tldraw-logseq/src/components/inputs/ShapeLinksInput.tsx
  76. 0 18
      packages/tldraw/apps/tldraw-logseq/src/components/inputs/TextInput.tsx
  77. 0 76
      packages/tldraw/apps/tldraw-logseq/src/components/inputs/ToggleGroupInput.tsx
  78. 0 34
      packages/tldraw/apps/tldraw-logseq/src/components/inputs/ToggleInput.tsx
  79. 0 6
      packages/tldraw/apps/tldraw-logseq/src/hooks/useCameraMoving.ts
  80. 0 11
      packages/tldraw/apps/tldraw-logseq/src/hooks/useCopy.ts
  81. 0 14
      packages/tldraw/apps/tldraw-logseq/src/hooks/useDrop.ts
  82. 0 515
      packages/tldraw/apps/tldraw-logseq/src/hooks/usePaste.ts
  83. 0 12
      packages/tldraw/apps/tldraw-logseq/src/hooks/useQuickAdd.ts
  84. 0 18
      packages/tldraw/apps/tldraw-logseq/src/index.ts
  85. 0 3
      packages/tldraw/apps/tldraw-logseq/src/lib/index.ts
  86. 0 70
      packages/tldraw/apps/tldraw-logseq/src/lib/logseq-context.ts
  87. 0 148
      packages/tldraw/apps/tldraw-logseq/src/lib/preview-manager.tsx
  88. 0 32
      packages/tldraw/apps/tldraw-logseq/src/lib/shapes/BindingIndicator.tsx
  89. 0 195
      packages/tldraw/apps/tldraw-logseq/src/lib/shapes/BoxShape.tsx
  90. 0 62
      packages/tldraw/apps/tldraw-logseq/src/lib/shapes/DotShape.tsx
  91. 0 223
      packages/tldraw/apps/tldraw-logseq/src/lib/shapes/EllipseShape.tsx
  92. 0 65
      packages/tldraw/apps/tldraw-logseq/src/lib/shapes/GroupShape.tsx
  93. 0 159
      packages/tldraw/apps/tldraw-logseq/src/lib/shapes/HTMLShape.tsx
  94. 0 116
      packages/tldraw/apps/tldraw-logseq/src/lib/shapes/HighlighterShape.tsx
  95. 0 100
      packages/tldraw/apps/tldraw-logseq/src/lib/shapes/IFrameShape.tsx
  96. 0 119
      packages/tldraw/apps/tldraw-logseq/src/lib/shapes/ImageShape.tsx
  97. 0 252
      packages/tldraw/apps/tldraw-logseq/src/lib/shapes/LineShape.tsx
  98. 0 605
      packages/tldraw/apps/tldraw-logseq/src/lib/shapes/LogseqPortalShape.tsx
  99. 0 83
      packages/tldraw/apps/tldraw-logseq/src/lib/shapes/PdfShape.tsx
  100. 0 77
      packages/tldraw/apps/tldraw-logseq/src/lib/shapes/PenShape.tsx

+ 1 - 15
.carve/ignore

@@ -11,29 +11,15 @@ frontend.debug/defn
 frontend.debug/print
 frontend.debug/print
 ;; Lazily loaded
 ;; Lazily loaded
 frontend.extensions.code/editor
 frontend.extensions.code/editor
-;; Lazily loaded
-frontend.extensions.age-encryption/keygen
-frontend.extensions.age-encryption/encrypt-with-x25519
-frontend.extensions.age-encryption/decrypt-with-x25519
-frontend.extensions.age-encryption/encrypt-with-user-passphrase
-frontend.extensions.age-encryption/decrypt-with-user-passphrase
-;; Lazily loaded
-frontend.extensions.excalidraw/draw
-;; Lazily loaded
-frontend.extensions.tldraw/tldraw-app
-frontend.extensions.tldraw/generate-preview
 ;; Referenced in commented TODO
 ;; Referenced in commented TODO
 frontend.extensions.pdf.utils/get-page-bounding
 frontend.extensions.pdf.utils/get-page-bounding
 ;; For repl
 ;; For repl
-frontend.extensions.zotero.api/item
-;; For repl
-frontend.external.roam/reset-state!
-;; For repl
 logseq.graph-parser.mldoc/ast-export-markdown
 logseq.graph-parser.mldoc/ast-export-markdown
 ;; Protocol fn wrapper that could be used
 ;; Protocol fn wrapper that could be used
 frontend.fs/readdir
 frontend.fs/readdir
 ;; Referenced in TODO
 ;; Referenced in TODO
 frontend.handler.metadata/update-properties!
 frontend.handler.metadata/update-properties!
+frontend.handler.user/<ensure-id&access-token
 ;; Referenced in comment
 ;; Referenced in comment
 frontend.image/get-orientation
 frontend.image/get-orientation
 ;; For debugging
 ;; For debugging

+ 1 - 2
clj-e2e/test/logseq/e2e/plugins_basic_test.clj

@@ -361,8 +361,7 @@
       (is (= (get tag1 ":logseq.property.class/extends") [id2]) "tag1 extends tag2 with db id")
       (is (= (get tag1 ":logseq.property.class/extends") [id2]) "tag1 extends tag2 with db id")
       (let [_ (ls-api-call! :editor.addTagExtends id1 id3)
       (let [_ (ls-api-call! :editor.addTagExtends id1 id3)
             tag1 (ls-api-call! :editor.getTag id1)]
             tag1 (ls-api-call! :editor.getTag id1)]
-        (is (= (get tag1 ":logseq.property.class/extends") [id2 id3]) "tag1 extends tag2,tag3 with db ids"))
-      )))
+        (is (= (get tag1 ":logseq.property.class/extends") [id2 id3]) "tag1 extends tag2,tag3 with db ids")))))
 
 
 (deftest get-tags-by-name-test
 (deftest get-tags-by-name-test
   (testing "get tags by exact name"
   (testing "get tags by exact name"

+ 3 - 4
deps/cli/src/logseq/cli/common/graph.cljs

@@ -26,7 +26,6 @@
     (->> (common-graph/read-directories dir)
     (->> (common-graph/read-directories dir)
          (remove (fn [s] (= s common-config/unlinked-graphs-dir)))
          (remove (fn [s] (= s common-config/unlinked-graphs-dir)))
          (map graph-name->path)
          (map graph-name->path)
-         (map (fn [s]
-                (if (string/starts-with? s common-config/file-version-prefix)
-                  s
-                  (str common-config/db-version-prefix s)))))))
+         (keep (fn [s]
+                 (when-not (string/starts-with? s common-config/file-version-prefix)
+                   (str common-config/db-version-prefix s)))))))

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

@@ -116,11 +116,6 @@
  ;;  :enabled-in-timestamped-blocks false ;don't display logbook at all
  ;;  :enabled-in-timestamped-blocks false ;don't display logbook at all
  ;; }
  ;; }
 
 
- ;; File sync options
- ;; Ignore these files when syncing, regexp is supported.
- ;; This is _only_ for file graphs.
- ;; :file-sync/ignore-files []
-
  ;; Configure the escaping method for special characters in page titles.
  ;; Configure the escaping method for special characters in page titles.
  ;; This is _only_ for file graphs.
  ;; This is _only_ for file graphs.
  ;; Warning:
  ;; Warning:
@@ -391,17 +386,4 @@
  ;;  :redirect-page? false          ;; Default value: false
  ;;  :redirect-page? false          ;; Default value: false
  ;;  :default-page "quick capture"} ;; Default page: "quick capture"
  ;;  :default-page "quick capture"} ;; Default page: "quick capture"
 
 
- ;; Configure the Enter key behavior for
- ;; context-aware editing with DWIM (Do What I Mean).
- ;; context-aware Enter key behavior implies that pressing Enter will
- ;; have different outcomes based on the context.
- ;; For instance, pressing Enter within a list generates a new list item,
- ;; whereas pressing Enter in a block reference opens the referenced block.
- ;; :dwim/settings
- ;; {:admonition&src?  true        ;; Default value: true
- ;;  :markup?          false       ;; Default value: false
- ;;  :block-ref?       true        ;; Default value: true
- ;;  :page-ref?        true        ;; Default value: true
- ;;  :properties?      true        ;; Default value: true
- ;;  :list?            false}      ;; Default value: false
  }
  }

+ 1 - 1
deps/common/src/logseq/common/config.cljs

@@ -91,7 +91,7 @@
 (defn text-formats
 (defn text-formats
   []
   []
   #{:json :org :md :yml :dat :asciidoc :rst :txt :markdown :adoc :html :js :ts :edn :clj :ml :rb :ex :erl :java :php :c :css
   #{:json :org :md :yml :dat :asciidoc :rst :txt :markdown :adoc :html :js :ts :edn :clj :ml :rb :ex :erl :java :php :c :css
-    :excalidraw :tldr :sh})
+    :tldr :sh})
 
 
 (defn img-formats
 (defn img-formats
   []
   []

+ 1 - 1
deps/common/src/logseq/common/graph.cljs

@@ -82,7 +82,7 @@ Rules:
            (re-find #"^\.[^.]+" rpath))))))
            (re-find #"^\.[^.]+" rpath))))))
 
 
 (def ^:private allowed-formats
 (def ^:private allowed-formats
-  #{:org :markdown :md :edn :json :js :css :excalidraw :tldr})
+  #{:org :markdown :md :edn :json :js :css})
 
 
 (defn- get-ext
 (defn- get-ext
   [p]
   [p]

+ 6 - 14
deps/db/src/logseq/db/common/view.cljs

@@ -290,16 +290,12 @@
    (map :e)
    (map :e)
    set))
    set))
 
 
-(defn- get-entities-for-all-pages [db sorting property-ident {:keys [db-based?]}]
+(defn- get-entities-for-all-pages [db sorting property-ident]
   (let [refs-count? (and (coll? sorting) (some (fn [m] (= (:id m) :block.temp/refs-count)) sorting))
   (let [refs-count? (and (coll? sorting) (some (fn [m] (= (:id m) :block.temp/refs-count)) sorting))
-        exclude-ids (when db-based? (get-exclude-page-ids db))]
+        exclude-ids (get-exclude-page-ids db)]
     (keep (fn [d]
     (keep (fn [d]
             (let [e (entity-plus/unsafe->Entity db (:e d))]
             (let [e (entity-plus/unsafe->Entity db (:e d))]
-              (when-not (if db-based?
-                          (exclude-ids (:db/id e))
-                          (or (ldb/hidden-or-internal-tag? e)
-                              (entity-util/property? e)
-                              (entity-util/built-in? e)))
+              (when-not (exclude-ids (:db/id e))
                 (cond-> e
                 (cond-> e
                   refs-count?
                   refs-count?
                   (assoc :block.temp/refs-count (common-initial-data/get-block-refs-count db (:e d)))))))
                   (assoc :block.temp/refs-count (common-initial-data/get-block-refs-count db (:e d)))))))
@@ -311,11 +307,10 @@
         view-for-id (or (:db/id view-for) view-for-id*)
         view-for-id (or (:db/id view-for) view-for-id*)
         non-hidden-e (fn [id] (let [e (d/entity db id)]
         non-hidden-e (fn [id] (let [e (d/entity db id)]
                                 (when-not (entity-util/hidden? e)
                                 (when-not (entity-util/hidden? e)
-                                  e)))
-        db-based? (entity-plus/db-based-graph? db)]
+                                  e)))]
     (case feat-type
     (case feat-type
       :all-pages
       :all-pages
-      (get-entities-for-all-pages db sorting property-ident {:db-based? db-based?})
+      (get-entities-for-all-pages db sorting property-ident)
 
 
       :class-objects
       :class-objects
       (db-class/get-class-objects db view-for-id)
       (db-class/get-class-objects db view-for-id)
@@ -443,10 +438,7 @@
     :else
     :else
     (let [view (d/entity db view-id)
     (let [view (d/entity db view-id)
           group-by-property (:logseq.property.view/group-by-property view)
           group-by-property (:logseq.property.view/group-by-property view)
-          db-based? (entity-plus/db-based-graph? db)
-          list-view? (or (= :logseq.property.view/type.list (:db/ident (:logseq.property.view/type view)))
-                         (and (not db-based?)
-                              (contains? #{:linked-references :unlinked-references} view-feature-type)))
+          list-view? (= :logseq.property.view/type.list (:db/ident (:logseq.property.view/type view)))
           group-by-property-ident (or (:db/ident group-by-property) group-by-property-ident)
           group-by-property-ident (or (:db/ident group-by-property) group-by-property-ident)
           group-by-closed-values? (some? (:property/closed-values group-by-property))
           group-by-closed-values? (some? (:property/closed-values group-by-property))
           ref-property? (= (:db/valueType group-by-property) :db.type/ref)
           ref-property? (= (:db/valueType group-by-property) :db.type/ref)

+ 73 - 93
deps/outliner/src/logseq/outliner/core.cljs

@@ -12,14 +12,12 @@
             [logseq.db :as ldb]
             [logseq.db :as ldb]
             [logseq.db.common.entity-plus :as entity-plus]
             [logseq.db.common.entity-plus :as entity-plus]
             [logseq.db.common.order :as db-order]
             [logseq.db.common.order :as db-order]
-            [logseq.db.file-based.schema :as file-schema]
             [logseq.db.frontend.class :as db-class]
             [logseq.db.frontend.class :as db-class]
             [logseq.db.frontend.schema :as db-schema]
             [logseq.db.frontend.schema :as db-schema]
             [logseq.db.sqlite.create-graph :as sqlite-create-graph]
             [logseq.db.sqlite.create-graph :as sqlite-create-graph]
             [logseq.db.sqlite.util :as sqlite-util]
             [logseq.db.sqlite.util :as sqlite-util]
             [logseq.graph-parser.block :as gp-block]
             [logseq.graph-parser.block :as gp-block]
             [logseq.graph-parser.db :as gp-db]
             [logseq.graph-parser.db :as gp-db]
-            [logseq.graph-parser.property :as gp-property]
             [logseq.outliner.batch-tx :include-macros true :as batch-tx]
             [logseq.outliner.batch-tx :include-macros true :as batch-tx]
             [logseq.outliner.datascript :as ds]
             [logseq.outliner.datascript :as ds]
             [logseq.outliner.pipeline :as outliner-pipeline]
             [logseq.outliner.pipeline :as outliner-pipeline]
@@ -28,8 +26,6 @@
             [malli.core :as m]
             [malli.core :as m]
             [malli.util :as mu]))
             [malli.util :as mu]))
 
 
-;; TODO: remove `repo` usage, use db to check `entity-plus/db-based-graph?`
-
 (def ^:private block-map
 (def ^:private block-map
   (mu/optional-keys
   (mu/optional-keys
    [:map
    [:map
@@ -299,25 +295,23 @@
 
 
 (extend-type Entity
 (extend-type Entity
   otree/INode
   otree/INode
-  (-save [this *txs-state db repo _date-formatter {:keys [retract-attributes? retract-attributes outliner-op]
-                                                   :or {retract-attributes? true}}]
+  (-save [this *txs-state db {:keys [retract-attributes? retract-attributes outliner-op]
+                              :or {retract-attributes? true}}]
     (assert (ds/outliner-txs-state? *txs-state)
     (assert (ds/outliner-txs-state? *txs-state)
             "db should be satisfied outliner-tx-state?")
             "db should be satisfied outliner-tx-state?")
-    (let [db-based? (sqlite-util/db-based-graph? repo)
+    (let [db-graph? (entity-plus/db-based-graph? db)
           data (if (de/entity? this)
           data (if (de/entity? this)
                  (assoc (.-kv ^js this) :db/id (:db/id this))
                  (assoc (.-kv ^js this) :db/id (:db/id this))
                  this)
                  this)
-          data' (if db-based?
-                  (->> (dissoc data :block/properties)
-                       (remove-disallowed-inline-classes db))
-                  data)
+          data' (->> (dissoc data :block/properties)
+                     (remove-disallowed-inline-classes db))
           collapse-or-expand? (= outliner-op :collapse-expand-blocks)
           collapse-or-expand? (= outliner-op :collapse-expand-blocks)
           m* (cond->
           m* (cond->
               (-> data'
               (-> data'
                   (dissoc :block/children :block/meta :block/unordered
                   (dissoc :block/children :block/meta :block/unordered
                           :block.temp/ast-title :block.temp/ast-body :block/level :block.temp/load-status
                           :block.temp/ast-title :block.temp/ast-body :block/level :block.temp/load-status
                           :block.temp/has-children?)
                           :block.temp/has-children?)
-                  (fix-tag-ids db {:db-graph? db-based?}))
+                  (fix-tag-ids db {:db-graph? db-graph?}))
                (not collapse-or-expand?)
                (not collapse-or-expand?)
                block-with-updated-at)
                block-with-updated-at)
           db-id (:db/id this)
           db-id (:db/id this)
@@ -325,28 +319,27 @@
           eid (or db-id (when block-uuid [:block/uuid block-uuid]))
           eid (or db-id (when block-uuid [:block/uuid block-uuid]))
           block-entity (d/entity db eid)
           block-entity (d/entity db eid)
           page? (ldb/page? block-entity)
           page? (ldb/page? block-entity)
-          m* (if (and db-based? (:block/title m*)
+          m* (if (and (:block/title m*)
                       (not (:logseq.property.node/display-type block-entity)))
                       (not (:logseq.property.node/display-type block-entity)))
                (update m* :block/title common-util/clear-markdown-heading)
                (update m* :block/title common-util/clear-markdown-heading)
                m*)
                m*)
           block-title (:block/title m*)
           block-title (:block/title m*)
           page-title-changed? (and page? block-title
           page-title-changed? (and page? block-title
                                    (not= block-title (:block/title block-entity)))
                                    (not= block-title (:block/title block-entity)))
-          _ (when (and db-based? page? block-title)
+          _ (when (and page? block-title)
               (outliner-validate/validate-page-title-characters block-title {:node m*}))
               (outliner-validate/validate-page-title-characters block-title {:node m*}))
-          m* (if (and db-based? page-title-changed?)
+          m* (if page-title-changed?
                (let [_ (outliner-validate/validate-page-title (:block/title m*) {:node m*})
                (let [_ (outliner-validate/validate-page-title (:block/title m*) {:node m*})
                      page-name (common-util/page-name-sanity-lc (:block/title m*))]
                      page-name (common-util/page-name-sanity-lc (:block/title m*))]
                  (assoc m* :block/name page-name))
                  (assoc m* :block/name page-name))
                m*)
                m*)
-          _ (when (and db-based?
-                       ;; page or object changed?
-                       (or (ldb/page? block-entity) (ldb/object? block-entity))
-                       (:block/title m*)
-                       (not= (:block/title m*) (:block/title block-entity)))
+          _ (when (and ;; page or object changed?
+                   (or (ldb/page? block-entity) (ldb/object? block-entity))
+                   (:block/title m*)
+                   (not= (:block/title m*) (:block/title block-entity)))
               (outliner-validate/validate-block-title db (:block/title m*) block-entity))
               (outliner-validate/validate-block-title db (:block/title m*) block-entity))
           m (cond-> m*
           m (cond-> m*
-              db-based?
+              true
               (dissoc :block/format :block/pre-block? :block/priority :block/marker :block/properties-order))]
               (dissoc :block/format :block/pre-block? :block/priority :block/marker :block/properties-order))]
       ;; Ensure block UUID never changes
       ;; Ensure block UUID never changes
       (let [e (d/entity db db-id)]
       (let [e (d/entity db db-id)]
@@ -361,9 +354,7 @@
         (when (or (and retract-attributes? (:block/title m))
         (when (or (and retract-attributes? (:block/title m))
                   (seq retract-attributes))
                   (seq retract-attributes))
           (let [retract-attributes (concat
           (let [retract-attributes (concat
-                                    (if db-based?
-                                      db-schema/retract-attributes
-                                      file-schema/retract-attributes)
+                                    db-schema/retract-attributes
                                     retract-attributes)]
                                     retract-attributes)]
             (swap! *txs-state (fn [txs]
             (swap! *txs-state (fn [txs]
                                 (vec
                                 (vec
@@ -377,7 +368,7 @@
           (update-page-when-save-block *txs-state block-entity m))
           (update-page-when-save-block *txs-state block-entity m))
         ;; Remove orphaned refs from block
         ;; Remove orphaned refs from block
         (when (and (:block/title m) (not= (:block/title m) (:block/title block-entity)))
         (when (and (:block/title m) (not= (:block/title m) (:block/title block-entity)))
-          (remove-orphaned-refs-when-save db *txs-state block-entity m {:db-graph? db-based?})))
+          (remove-orphaned-refs-when-save db *txs-state block-entity m {:db-graph? db-graph?})))
 
 
       ;; handle others txs
       ;; handle others txs
       (let [other-tx (:db/other-tx m)]
       (let [other-tx (:db/other-tx m)]
@@ -387,16 +378,15 @@
         (swap! *txs-state conj
         (swap! *txs-state conj
                (dissoc m :db/other-tx)))
                (dissoc m :db/other-tx)))
 
 
-      (when (and db-based? (:block/tags block-entity) block-entity)
+      (when (and (:block/tags block-entity) block-entity)
         (let [;; delete tags when title changed
         (let [;; delete tags when title changed
               tx-data (remove-tags-when-title-changed block-entity (:block/title m))]
               tx-data (remove-tags-when-title-changed block-entity (:block/title m))]
           (when (seq tx-data)
           (when (seq tx-data)
             (swap! *txs-state (fn [txs] (concat txs tx-data))))))
             (swap! *txs-state (fn [txs] (concat txs tx-data))))))
 
 
-      (when db-based?
-        (let [tx-data (add-missing-tag-idents db (:block/tags m))]
-          (when (seq tx-data)
-            (swap! *txs-state (fn [txs] (concat txs tx-data))))))
+      (let [tx-data (add-missing-tag-idents db (:block/tags m))]
+        (when (seq tx-data)
+          (swap! *txs-state (fn [txs] (concat txs tx-data)))))
 
 
       this))
       this))
 
 
@@ -519,7 +509,7 @@
 
 
 (defn ^:api save-block
 (defn ^:api save-block
   "Save the `block`."
   "Save the `block`."
-  [repo db date-formatter block opts]
+  [db block opts]
   {:pre [(map? block)]}
   {:pre [(map? block)]}
   (let [*txs-state (atom [])
   (let [*txs-state (atom [])
         block' (if (de/entity? block)
         block' (if (de/entity? block)
@@ -530,7 +520,7 @@
                      (let [ent (d/entity db eid)]
                      (let [ent (d/entity db eid)]
                        (assert (some? ent) "save-block entity not exists")
                        (assert (some? ent) "save-block entity not exists")
                        (merge ent block)))))]
                        (merge ent block)))))]
-    (otree/-save block' *txs-state db repo date-formatter opts)
+    (otree/-save block' *txs-state db opts)
     {:tx-data @*txs-state}))
     {:tx-data @*txs-state}))
 
 
 (defn- get-right-siblings
 (defn- get-right-siblings
@@ -543,28 +533,19 @@
            rest))))
            rest))))
 
 
 (defn- blocks-with-ordered-list-props
 (defn- blocks-with-ordered-list-props
-  [repo blocks target-block sibling?]
+  [blocks target-block sibling?]
   (let [target-block (if sibling? target-block (when target-block (ldb/get-down target-block)))
   (let [target-block (if sibling? target-block (when target-block (ldb/get-down target-block)))
         list-type-fn (fn [block]
         list-type-fn (fn [block]
-                       (if (sqlite-util/db-based-graph? repo)
-                         ;; Get raw id since insert-blocks doesn't auto-handle raw property values
-                         (:db/id (:logseq.property/order-list-type block))
-                         (get (:block/properties block) :logseq.order-list-type)))
-        db-based? (sqlite-util/db-based-graph? repo)]
+                       (:db/id (:logseq.property/order-list-type block)))]
     (if-let [list-type (and target-block (list-type-fn target-block))]
     (if-let [list-type (and target-block (list-type-fn target-block))]
       (mapv
       (mapv
-       (fn [{:block/keys [title format] :as block}]
+       (fn [block]
          (let [list?' (and (some? (:block/uuid block))
          (let [list?' (and (some? (:block/uuid block))
                            (nil? (list-type-fn block)))]
                            (nil? (list-type-fn block)))]
            (cond-> block
            (cond-> block
              list?'
              list?'
              ((fn [b]
              ((fn [b]
-                (if db-based?
-                  (assoc b :logseq.property/order-list-type list-type)
-                  (update b :block/properties assoc :logseq.order-list-type list-type))))
-
-             (not db-based?)
-             (assoc :block/title (gp-property/insert-property repo format title :logseq.order-list-type list-type)))))
+                (assoc b :logseq.property/order-list-type list-type))))))
        blocks)
        blocks)
       blocks)))
       blocks)))
 
 
@@ -615,13 +596,12 @@
 
 
 (defn- build-insert-blocks-tx
 (defn- build-insert-blocks-tx
   [db target-block blocks uuids get-new-id {:keys [sibling? outliner-op replace-empty-target? insert-template? keep-block-order?]}]
   [db target-block blocks uuids get-new-id {:keys [sibling? outliner-op replace-empty-target? insert-template? keep-block-order?]}]
-  (let [db-based? (entity-plus/db-based-graph? db)
-        block-ids (set (map :block/uuid blocks))
+  (let [block-ids (set (map :block/uuid blocks))
         target-page (get-target-block-page target-block sibling?)
         target-page (get-target-block-page target-block sibling?)
         orders (get-block-orders blocks target-block sibling? keep-block-order?)]
         orders (get-block-orders blocks target-block sibling? keep-block-order?)]
     (map-indexed (fn [idx {:block/keys [parent] :as block}]
     (map-indexed (fn [idx {:block/keys [parent] :as block}]
                    (when-let [uuid' (get uuids (:block/uuid block))]
                    (when-let [uuid' (get uuids (:block/uuid block))]
-                     (let [block (if db-based? (remove-disallowed-inline-classes db block) block)
+                     (let [block (remove-disallowed-inline-classes db block)
                            top-level? (= (:block/level block) 1)
                            top-level? (= (:block/level block) 1)
                            parent (compute-block-parent block parent target-block top-level? sibling? get-new-id outliner-op replace-empty-target? idx)
                            parent (compute-block-parent block parent target-block top-level? sibling? get-new-id outliner-op replace-empty-target? idx)
 
 
@@ -790,11 +770,11 @@
                                to replace it, it defaults to be `false`.
                                to replace it, it defaults to be `false`.
       `update-timestamps?`: whether to update `blocks` timestamps.
       `update-timestamps?`: whether to update `blocks` timestamps.
     ``"
     ``"
-  [repo db blocks target-block {:keys [_sibling? keep-uuid? keep-block-order?
-                                       outliner-op outliner-real-op replace-empty-target? update-timestamps?
-                                       insert-template?]
-                                :as opts
-                                :or {update-timestamps? true}}]
+  [db blocks target-block {:keys [_sibling? keep-uuid? keep-block-order?
+                                  outliner-op outliner-real-op replace-empty-target? update-timestamps?
+                                  insert-template?]
+                           :as opts
+                           :or {update-timestamps? true}}]
   {:pre [(seq blocks)
   {:pre [(seq blocks)
          (m/validate block-map-or-entity target-block)]}
          (m/validate block-map-or-entity target-block)]}
   (let [blocks (cond->>
   (let [blocks (cond->>
@@ -828,16 +808,15 @@
                                 (and sibling?
                                 (and sibling?
                                      (:block/title target-block)
                                      (:block/title target-block)
                                      (string/blank? (:block/title target-block))
                                      (string/blank? (:block/title target-block))
-                                     (> (count blocks) 1)))
-        db-based? (sqlite-util/db-based-graph? repo)]
+                                     (> (count blocks) 1)))]
     (when (seq blocks)
     (when (seq blocks)
       (let [blocks' (let [blocks' (blocks-with-level blocks)]
       (let [blocks' (let [blocks' (blocks-with-level blocks)]
-                      (cond->> (blocks-with-ordered-list-props repo blocks' target-block sibling?)
+                      (cond->> (blocks-with-ordered-list-props blocks' target-block sibling?)
                         update-timestamps?
                         update-timestamps?
                         (mapv #(dissoc % :block/created-at :block/updated-at))
                         (mapv #(dissoc % :block/created-at :block/updated-at))
                         true
                         true
                         (mapv block-with-timestamps)
                         (mapv block-with-timestamps)
-                        db-based?
+                        true
                         (mapv #(-> % (dissoc :block/properties)))))
                         (mapv #(-> % (dissoc :block/properties)))))
             insert-opts {:sibling? sibling?
             insert-opts {:sibling? sibling?
                          :replace-empty-target? replace-empty-target?
                          :replace-empty-target? replace-empty-target?
@@ -999,8 +978,8 @@
 
 
 (defn- move-blocks
 (defn- move-blocks
   "Move `blocks` to `target-block` as siblings or children."
   "Move `blocks` to `target-block` as siblings or children."
-  [_repo conn blocks target-block {:keys [_sibling? _top? _bottom? _up? outliner-op _indent?]
-                                   :as opts}]
+  [conn blocks target-block {:keys [_sibling? _top? _bottom? _up? outliner-op _indent?]
+                             :as opts}]
   {:pre [(seq blocks)
   {:pre [(seq blocks)
          (m/validate block-map-or-entity target-block)]}
          (m/validate block-map-or-entity target-block)]}
   (let [db @conn
   (let [db @conn
@@ -1039,7 +1018,7 @@
 
 
 (defn- move-blocks-up-down
 (defn- move-blocks-up-down
   "Move blocks up/down."
   "Move blocks up/down."
-  [repo conn blocks up?]
+  [conn blocks up?]
   {:pre [(seq blocks) (boolean? up?)]}
   {:pre [(seq blocks) (boolean? up?)]}
   (let [db @conn
   (let [db @conn
         top-level-blocks (filter-top-level-blocks db blocks)
         top-level-blocks (filter-top-level-blocks db blocks)
@@ -1058,8 +1037,8 @@
                          (:db/id left-left))
                          (:db/id left-left))
                    (not (and (:logseq.property/created-from-property first-block)
                    (not (and (:logseq.property/created-from-property first-block)
                              (nil? first-block-left-sibling))))
                              (nil? first-block-left-sibling))))
-          (move-blocks repo conn top-level-blocks left-left (merge opts {:sibling? sibling?
-                                                                         :up? up?}))))
+          (move-blocks conn top-level-blocks left-left (merge opts {:sibling? sibling?
+                                                                    :up? up?}))))
 
 
       (let [last-top-block (last top-level-blocks)
       (let [last-top-block (last top-level-blocks)
             last-top-block-right (ldb/get-right-sibling last-top-block)
             last-top-block-right (ldb/get-right-sibling last-top-block)
@@ -1072,12 +1051,12 @@
         (when (and right
         (when (and right
                    (not (and (:logseq.property/created-from-property last-top-block)
                    (not (and (:logseq.property/created-from-property last-top-block)
                              (nil? last-top-block-right))))
                              (nil? last-top-block-right))))
-          (move-blocks repo conn blocks right (merge opts {:sibling? sibling?
-                                                           :up? up?})))))))
+          (move-blocks conn blocks right (merge opts {:sibling? sibling?
+                                                      :up? up?})))))))
 
 
 (defn- ^:large-vars/cleanup-todo indent-outdent-blocks
 (defn- ^:large-vars/cleanup-todo indent-outdent-blocks
   "Indent or outdent `blocks`."
   "Indent or outdent `blocks`."
-  [repo conn blocks indent? & {:keys [parent-original logical-outdenting?]}]
+  [conn blocks indent? & {:keys [parent-original logical-outdenting?]}]
   {:pre [(seq blocks) (boolean? indent?)]}
   {:pre [(seq blocks) (boolean? indent?)]}
   (let [db @conn
   (let [db @conn
         top-level-blocks (filter-top-level-blocks db blocks)
         top-level-blocks (filter-top-level-blocks db blocks)
@@ -1105,30 +1084,30 @@
               (when (seq blocks')
               (when (seq blocks')
                 (if last-direct-child-id
                 (if last-direct-child-id
                   (let [last-direct-child (d/entity db last-direct-child-id)
                   (let [last-direct-child (d/entity db last-direct-child-id)
-                        result (move-blocks repo conn blocks' last-direct-child (merge opts {:sibling? true
-                                                                                             :indent? true}))
+                        result (move-blocks conn blocks' last-direct-child (merge opts {:sibling? true
+                                                                                        :indent? true}))
                         ;; expand `left` if it's collapsed
                         ;; expand `left` if it's collapsed
                         collapsed-tx (when (:block/collapsed? left)
                         collapsed-tx (when (:block/collapsed? left)
                                        {:tx-data [{:db/id (:db/id left)
                                        {:tx-data [{:db/id (:db/id left)
                                                    :block/collapsed? false}]})]
                                                    :block/collapsed? false}]})]
                     (concat-tx-fn result collapsed-tx))
                     (concat-tx-fn result collapsed-tx))
-                  (move-blocks repo conn blocks' left (merge opts {:sibling? false
-                                                                   :indent? true}))))))
+                  (move-blocks conn blocks' left (merge opts {:sibling? false
+                                                              :indent? true}))))))
           (if parent-original
           (if parent-original
             (let [blocks' (take-while (fn [b]
             (let [blocks' (take-while (fn [b]
                                         (not= (:db/id (:block/parent b))
                                         (not= (:db/id (:block/parent b))
                                               (:db/id (:block/parent parent))))
                                               (:db/id (:block/parent parent))))
                                       top-level-blocks)]
                                       top-level-blocks)]
-              (move-blocks repo conn blocks' parent-original (merge opts {:outliner-op :indent-outdent-blocks
-                                                                          :sibling? true
-                                                                          :indent? false})))
+              (move-blocks conn blocks' parent-original (merge opts {:outliner-op :indent-outdent-blocks
+                                                                     :sibling? true
+                                                                     :indent? false})))
 
 
             (when parent
             (when parent
               (let [blocks' (take-while (fn [b]
               (let [blocks' (take-while (fn [b]
                                           (not= (:db/id (:block/parent b))
                                           (not= (:db/id (:block/parent b))
                                                 (:db/id (:block/parent parent))))
                                                 (:db/id (:block/parent parent))))
                                         top-level-blocks)
                                         top-level-blocks)
-                    result (move-blocks repo conn blocks' parent (merge opts {:sibling? true}))]
+                    result (move-blocks conn blocks' parent (merge opts {:sibling? true}))]
                 (if logical-outdenting?
                 (if logical-outdenting?
                   result
                   result
                   ;; direct outdenting (default behavior)
                   ;; direct outdenting (default behavior)
@@ -1136,8 +1115,8 @@
                         right-siblings (get-right-siblings last-top-block)]
                         right-siblings (get-right-siblings last-top-block)]
                     (if (seq right-siblings)
                     (if (seq right-siblings)
                       (if-let [last-direct-child-id (ldb/get-block-last-direct-child-id db (:db/id last-top-block))]
                       (if-let [last-direct-child-id (ldb/get-block-last-direct-child-id db (:db/id last-top-block))]
-                        (move-blocks repo conn right-siblings (d/entity db last-direct-child-id) (merge opts {:sibling? true}))
-                        (move-blocks repo conn right-siblings last-top-block (merge opts {:sibling? false})))
+                        (move-blocks conn right-siblings (d/entity db last-direct-child-id) (merge opts {:sibling? true}))
+                        (move-blocks conn right-siblings last-top-block (merge opts {:sibling? false})))
                       result)))))))))))
                       result)))))))))))
 
 
 ;;; ### write-operations have side-effects (do transactions) ;;;;;;;;;;;;;;;;
 ;;; ### write-operations have side-effects (do transactions) ;;;;;;;;;;;;;;;;
@@ -1150,44 +1129,45 @@
       (when result
       (when result
         (let [tx-meta (assoc (:tx-meta result)
         (let [tx-meta (assoc (:tx-meta result)
                              :outliner-op outliner-op)]
                              :outliner-op outliner-op)]
-          (ldb/transact! (second args) (:tx-data result) tx-meta)))
+          (ldb/transact! (first args) (:tx-data result) tx-meta)))
       result)
       result)
     (catch :default e
     (catch :default e
+      (js/console.error e)
       (when-not (= "not-allowed-move-block-page" (ex-message e))
       (when-not (= "not-allowed-move-block-page" (ex-message e))
         (throw e)))))
         (throw e)))))
 
 
-(let [f (fn [repo conn date-formatter block opts]
-          (save-block repo @conn date-formatter block opts))]
+(let [f (fn [conn block opts]
+          (save-block @conn block opts))]
   (defn save-block!
   (defn save-block!
-    [repo conn date-formatter block & {:as opts}]
-    (op-transact! :save-block f repo conn date-formatter block opts)))
+    [conn block & {:as opts}]
+    (op-transact! :save-block f conn block opts)))
 
 
-(let [f (fn [repo conn blocks target-block opts]
-          (insert-blocks repo @conn blocks target-block opts))]
+(let [f (fn [conn blocks target-block opts]
+          (insert-blocks @conn blocks target-block opts))]
   (defn insert-blocks!
   (defn insert-blocks!
-    [repo conn blocks target-block opts]
-    (op-transact! :insert-blocks f repo conn blocks target-block
+    [conn blocks target-block opts]
+    (op-transact! :insert-blocks f conn blocks target-block
                   (if (:outliner-op opts)
                   (if (:outliner-op opts)
                     opts
                     opts
                     (assoc opts :outliner-op :insert-blocks)))))
                     (assoc opts :outliner-op :insert-blocks)))))
 
 
-(let [f (fn [_repo conn blocks _opts]
+(let [f (fn [conn blocks _opts]
           (delete-blocks @conn blocks))]
           (delete-blocks @conn blocks))]
   (defn delete-blocks!
   (defn delete-blocks!
-    [repo conn _date-formatter blocks opts]
-    (op-transact! :delete-blocks f repo conn blocks opts)))
+    [conn blocks opts]
+    (op-transact! :delete-blocks f conn blocks opts)))
 
 
 (defn move-blocks!
 (defn move-blocks!
-  [repo conn blocks target-block opts]
-  (op-transact! :move-blocks move-blocks repo conn blocks target-block
+  [conn blocks target-block opts]
+  (op-transact! :move-blocks move-blocks conn blocks target-block
                 (if (:outliner-op opts)
                 (if (:outliner-op opts)
                   opts
                   opts
                   (assoc opts :outliner-op :move-blocks))))
                   (assoc opts :outliner-op :move-blocks))))
 
 
 (defn move-blocks-up-down!
 (defn move-blocks-up-down!
-  [repo conn blocks up?]
-  (op-transact! :move-blocks-up-down move-blocks-up-down repo conn blocks up?))
+  [conn blocks up?]
+  (op-transact! :move-blocks-up-down move-blocks-up-down conn blocks up?))
 
 
 (defn indent-outdent-blocks!
 (defn indent-outdent-blocks!
-  [repo conn blocks indent? & {:as opts}]
-  (op-transact! :indent-outdent-blocks indent-outdent-blocks repo conn blocks indent? opts))
+  [conn blocks indent? & {:as opts}]
+  (op-transact! :indent-outdent-blocks indent-outdent-blocks conn blocks indent? opts))

+ 10 - 15
deps/outliner/src/logseq/outliner/op.cljs

@@ -1,7 +1,6 @@
 (ns logseq.outliner.op
 (ns logseq.outliner.op
   "Transact outliner ops"
   "Transact outliner ops"
-  (:require [clojure.string :as string]
-            [datascript.core :as d]
+  (:require [datascript.core :as d]
             [logseq.db :as ldb]
             [logseq.db :as ldb]
             [logseq.db.sqlite.export :as sqlite-export]
             [logseq.db.sqlite.export :as sqlite-export]
             [logseq.outliner.core :as outliner-core]
             [logseq.outliner.core :as outliner-core]
@@ -169,53 +168,49 @@
           (reset! *result {:error (str "Unexpected Import EDN error: " (pr-str (ex-message e)))}))))))
           (reset! *result {:error (str "Unexpected Import EDN error: " (pr-str (ex-message e)))}))))))
 
 
 (defn ^:large-vars/cleanup-todo apply-ops!
 (defn ^:large-vars/cleanup-todo apply-ops!
-  [repo conn ops date-formatter opts]
+  [conn ops opts]
   (assert (ops-validator ops) ops)
   (assert (ops-validator ops) ops)
   (let [opts' (assoc opts
   (let [opts' (assoc opts
                      :transact-opts {:conn conn}
                      :transact-opts {:conn conn}
                      :local-tx? true)
                      :local-tx? true)
-        *result (atom nil)
-        db-based? (ldb/db-based-graph? @conn)]
+        *result (atom nil)]
     (outliner-tx/transact!
     (outliner-tx/transact!
      opts'
      opts'
      (doseq [[op args] ops]
      (doseq [[op args] ops]
-       (when-not db-based?
-         (assert (not (or (string/includes? (name op) "property") (string/includes? (name op) "closed-value")))
-                 (str "Property related ops are only for db based graphs, ops: " ops)))
        (case op
        (case op
          ;; blocks
          ;; blocks
          :save-block
          :save-block
-         (apply outliner-core/save-block! repo conn date-formatter args)
+         (apply outliner-core/save-block! conn args)
 
 
          :insert-blocks
          :insert-blocks
          (let [[blocks target-block-id opts] args]
          (let [[blocks target-block-id opts] args]
            (when-let [target-block (d/entity @conn target-block-id)]
            (when-let [target-block (d/entity @conn target-block-id)]
-             (let [result (outliner-core/insert-blocks! repo conn blocks target-block opts)]
+             (let [result (outliner-core/insert-blocks! conn blocks target-block opts)]
                (reset! *result result))))
                (reset! *result result))))
 
 
          :delete-blocks
          :delete-blocks
          (let [[block-ids opts] args
          (let [[block-ids opts] args
                blocks (keep #(d/entity @conn %) block-ids)]
                blocks (keep #(d/entity @conn %) block-ids)]
-           (outliner-core/delete-blocks! repo conn date-formatter blocks (merge opts opts')))
+           (outliner-core/delete-blocks! conn blocks (merge opts opts')))
 
 
          :move-blocks
          :move-blocks
          (let [[block-ids target-block-id opts] args
          (let [[block-ids target-block-id opts] args
                blocks (keep #(d/entity @conn %) block-ids)
                blocks (keep #(d/entity @conn %) block-ids)
                target-block (d/entity @conn target-block-id)]
                target-block (d/entity @conn target-block-id)]
            (when (and target-block (seq blocks))
            (when (and target-block (seq blocks))
-             (outliner-core/move-blocks! repo conn blocks target-block opts)))
+             (outliner-core/move-blocks! conn blocks target-block opts)))
 
 
          :move-blocks-up-down
          :move-blocks-up-down
          (let [[block-ids up?] args
          (let [[block-ids up?] args
                blocks (keep #(d/entity @conn %) block-ids)]
                blocks (keep #(d/entity @conn %) block-ids)]
            (when (seq blocks)
            (when (seq blocks)
-             (outliner-core/move-blocks-up-down! repo conn blocks up?)))
+             (outliner-core/move-blocks-up-down! conn blocks up?)))
 
 
          :indent-outdent-blocks
          :indent-outdent-blocks
          (let [[block-ids indent? opts] args
          (let [[block-ids indent? opts] args
                blocks (keep #(d/entity @conn %) block-ids)]
                blocks (keep #(d/entity @conn %) block-ids)]
            (when (seq blocks)
            (when (seq blocks)
-             (outliner-core/indent-outdent-blocks! repo conn blocks indent? opts)))
+             (outliner-core/indent-outdent-blocks! conn blocks indent? opts)))
 
 
          ;; properties
          ;; properties
          :upsert-property
          :upsert-property
@@ -264,6 +259,6 @@
          (apply ldb/transact! conn args)
          (apply ldb/transact! conn args)
 
 
          (when-let [handler (get @*op-handlers op)]
          (when-let [handler (get @*op-handlers op)]
-           (reset! *result (handler repo conn args))))))
+           (reset! *result (handler conn args))))))
 
 
     @*result))
     @*result))

+ 3 - 3
deps/outliner/src/logseq/outliner/page.cljs

@@ -313,9 +313,9 @@
                      page-txs)
                      page-txs)
                 tx-meta (cond-> {:persist-op? persist-op?
                 tx-meta (cond-> {:persist-op? persist-op?
                                  :outliner-op :create-page}
                                  :outliner-op :create-page}
-                                today-journal?
-                                (assoc :create-today-journal? true
-                                       :today-journal-name title))]
+                          today-journal?
+                          (assoc :create-today-journal? true
+                                 :today-journal-name title))]
             {:tx-meta tx-meta
             {:tx-meta tx-meta
              :tx-data txs
              :tx-data txs
              :title title
              :title title

+ 1 - 1
deps/outliner/src/logseq/outliner/tree.cljs

@@ -6,7 +6,7 @@
             [logseq.db.common.property-util :as db-property-util]))
             [logseq.db.common.property-util :as db-property-util]))
 
 
 (defprotocol INode
 (defprotocol INode
-  (-save [this *txs-state conn repo date-formatter opts])
+  (-save [this *txs-state conn opts])
   (-del [this *txs-state db]))
   (-del [this *txs-state db]))
 
 
 (defn- blocks->vec-tree-aux
 (defn- blocks->vec-tree-aux

+ 2 - 2
deps/outliner/test/logseq/outliner/core_test.cljs

@@ -13,7 +13,7 @@
           property-value (:user.property/default (db-test/find-block-by-content @conn "b1"))
           property-value (:user.property/default (db-test/find-block-by-content @conn "b1"))
           _ (assert (:db/id property-value))
           _ (assert (:db/id property-value))
           block (db-test/find-block-by-content @conn "b1")]
           block (db-test/find-block-by-content @conn "b1")]
-      (outliner-core/delete-blocks! nil conn nil [block] {})
+      (outliner-core/delete-blocks! conn [block] {})
       (is (nil? (db-test/find-block-by-content @conn "b1")))
       (is (nil? (db-test/find-block-by-content @conn "b1")))
       (is (nil? (db-test/find-block-by-content @conn "test block"))))))
       (is (nil? (db-test/find-block-by-content @conn "test block"))))))
 
 
@@ -32,7 +32,7 @@
                                 :block/parent (:db/id page1)}])
                                 :block/parent (:db/id page1)}])
           b3 (db-test/find-block-by-content @conn "b3")
           b3 (db-test/find-block-by-content @conn "b3")
           b4 (db-test/find-block-by-content @conn "b4")]
           b4 (db-test/find-block-by-content @conn "b4")]
-      (outliner-core/delete-blocks! nil conn nil [b3 b4 page2] {})
+      (outliner-core/delete-blocks! conn [b3 b4 page2] {})
       (is (some? (db-test/find-block-by-content @conn "b3")))
       (is (some? (db-test/find-block-by-content @conn "b3")))
       (is (some? (db-test/find-block-by-content @conn "b4")))
       (is (some? (db-test/find-block-by-content @conn "b4")))
       (let [page2' (ldb/get-page @conn "page2")]
       (let [page2' (ldb/get-page @conn "page2")]

+ 1 - 1
deps/publishing/src/logseq/publishing/export.cljs

@@ -8,7 +8,7 @@
 
 
 (def ^:api js-files
 (def ^:api js-files
   "js files from publishing release build"
   "js files from publishing release build"
-  (->> ["main.js" "code-editor.js" "excalidraw.js" "tldraw.js"]
+  (->> ["main.js" "code-editor.js"]
        ;; Add source maps for all js files as it doesn't affect initial load time
        ;; Add source maps for all js files as it doesn't affect initial load time
        (mapcat #(vector % (str % ".map")))
        (mapcat #(vector % (str % ".map")))
        vec))
        vec))

+ 0 - 4
gulpfile.js

@@ -65,10 +65,6 @@ const common = {
   // NOTE: All assets from node_modules are copied to the output directory
   // NOTE: All assets from node_modules are copied to the output directory
   syncAssetFiles (...params) {
   syncAssetFiles (...params) {
     return gulp.series(
     return gulp.series(
-      () => gulp.src([
-        './node_modules/@excalidraw/excalidraw/dist/excalidraw-assets/**',
-        '!**/*/i18n-*.js',
-      ]).pipe(gulp.dest(path.join(outputPath, 'js', 'excalidraw-assets'))),
       () => gulp.src([
       () => gulp.src([
         'node_modules/katex/dist/katex.min.js',
         'node_modules/katex/dist/katex.min.js',
         'node_modules/katex/dist/contrib/mhchem.min.js',
         'node_modules/katex/dist/contrib/mhchem.min.js',

+ 1 - 1
ios/App/App/FsWatcher.swift

@@ -98,7 +98,7 @@ extension URL {
     }
     }
 
 
     func shouldNotifyWithContent() -> Bool {
     func shouldNotifyWithContent() -> Bool {
-        let allowedPathExtensions: Set = ["md", "markdown", "org", "js", "edn", "css", "excalidraw"]
+        let allowedPathExtensions: Set = ["md", "markdown", "org", "js", "edn", "css"]
         if allowedPathExtensions.contains(self.pathExtension.lowercased()) {
         if allowedPathExtensions.contains(self.pathExtension.lowercased()) {
             return true
             return true
         }
         }

+ 0 - 2
libs/src/LSPlugin.ts

@@ -283,8 +283,6 @@ export type ExternalCommandType =
   | 'logseq.editor/up'
   | 'logseq.editor/up'
   | 'logseq.editor/expand-block-children'
   | 'logseq.editor/expand-block-children'
   | 'logseq.editor/collapse-block-children'
   | 'logseq.editor/collapse-block-children'
-  | 'logseq.editor/open-file-in-default-app'
-  | 'logseq.editor/open-file-in-directory'
   | 'logseq.editor/select-all-blocks'
   | 'logseq.editor/select-all-blocks'
   | 'logseq.editor/toggle-open-blocks'
   | 'logseq.editor/toggle-open-blocks'
   | 'logseq.editor/zoom-in'
   | 'logseq.editor/zoom-in'

+ 1 - 6
package.json

@@ -102,10 +102,9 @@
         "cljs:lint": "clojure -M:clj-kondo --parallel --lint src --cache false",
         "cljs:lint": "clojure -M:clj-kondo --parallel --lint src --cache false",
         "ios:dev": "cross-env PLATFORM=ios gulp cap",
         "ios:dev": "cross-env PLATFORM=ios gulp cap",
         "android:dev": "cross-env PLATFORM=android gulp cap",
         "android:dev": "cross-env PLATFORM=android gulp cap",
-        "tldraw:build": "yarn --cwd packages/tldraw install",
         "amplify:build": "yarn --cwd packages/amplify install",
         "amplify:build": "yarn --cwd packages/amplify install",
         "ui:build": "yarn --cwd packages/ui install",
         "ui:build": "yarn --cwd packages/ui install",
-        "postinstall": "yarn tldraw:build && yarn ui:build"
+        "postinstall": "yarn ui:build"
     },
     },
     "dependencies": {
     "dependencies": {
         "@aparajita/capacitor-secure-storage": "^7.1.6",
         "@aparajita/capacitor-secure-storage": "^7.1.6",
@@ -131,7 +130,6 @@
         "@dnd-kit/sortable": "^7.0.2",
         "@dnd-kit/sortable": "^7.0.2",
         "@emoji-mart/data": "^1.1.2",
         "@emoji-mart/data": "^1.1.2",
         "@emoji-mart/react": "^1.1.1",
         "@emoji-mart/react": "^1.1.1",
-        "@excalidraw/excalidraw": "0.16.1",
         "@glidejs/glide": "^3.6.0",
         "@glidejs/glide": "^3.6.0",
         "@highlightjs/cdn-assets": "10.4.1",
         "@highlightjs/cdn-assets": "10.4.1",
         "@huggingface/transformers": "^3.6.3",
         "@huggingface/transformers": "^3.6.3",
@@ -139,7 +137,6 @@
         "@js-joda/core": "3.2.0",
         "@js-joda/core": "3.2.0",
         "@js-joda/locale_en-us": "3.1.1",
         "@js-joda/locale_en-us": "3.1.1",
         "@js-joda/timezone": "2.5.0",
         "@js-joda/timezone": "2.5.0",
-        "@logseq/diff-merge": "^0.2.2",
         "@logseq/react-tweet-embed": "1.3.1-1",
         "@logseq/react-tweet-embed": "1.3.1-1",
         "@logseq/simple-wave-record": "^0.0.3",
         "@logseq/simple-wave-record": "^0.0.3",
         "@radix-ui/colors": "^0.1.8",
         "@radix-ui/colors": "^0.1.8",
@@ -150,13 +147,11 @@
         "@tabler/icons-webfont": "^2.47.0",
         "@tabler/icons-webfont": "^2.47.0",
         "@tippyjs/react": "4.2.5",
         "@tippyjs/react": "4.2.5",
         "bignumber.js": "^9.0.2",
         "bignumber.js": "^9.0.2",
-        "check-password-strength": "2.0.7",
         "chokidar": "3.5.1",
         "chokidar": "3.5.1",
         "chrono-node": "2.2.4",
         "chrono-node": "2.2.4",
         "codemirror": "5.65.18",
         "codemirror": "5.65.18",
         "comlink": "^4.4.1",
         "comlink": "^4.4.1",
         "d3-force": "3.0.0",
         "d3-force": "3.0.0",
-        "diff": "5.0.0",
         "dompurify": "2.4.0",
         "dompurify": "2.4.0",
         "emoji-mart": "^5.5.2",
         "emoji-mart": "^5.5.2",
         "fs": "0.0.1-security",
         "fs": "0.0.1-security",

+ 0 - 19
packages/tldraw/.editorconfig

@@ -1,19 +0,0 @@
-
-# https://editorconfig.org
-root = true
-
-[*]
-charset = utf-8
-end_of_line = lf
-indent_size = 2
-indent_style = space
-insert_final_newline = true
-max_line_length = 80
-trim_trailing_whitespace = true
-
-[*.md]
-max_line_length = 0
-trim_trailing_whitespace = false
-
-[COMMIT_EDITMSG]
-max_line_length = 0

+ 0 - 3
packages/tldraw/.eslintignore

@@ -1,3 +0,0 @@
-**/node_modules/*
-**/out/*
-**/.next/*

+ 0 - 19
packages/tldraw/.eslintrc

@@ -1,19 +0,0 @@
-{
-  "root": true,
-  "parser": "@typescript-eslint/parser",
-  "plugins": ["@typescript-eslint"],
-  "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
-  "ignorePatterns": ["*.js", "*.jsx"],
-  "overrides": [
-    {
-      // enable the rule specifically for TypeScript files
-      "files": ["*.ts", "*.tsx"],
-      "rules": {
-        "@typescript-eslint/explicit-module-boundary-types": "off",
-        "@typescript-eslint/explicit-function-return-type": "off",
-        "@typescript-eslint/no-explicit-any": "off",
-        "@typescript-eslint/camelcase": "off"
-      }
-    }
-  ]
-}

+ 0 - 2
packages/tldraw/.gitattributes

@@ -1,2 +0,0 @@
-# Auto detect text files and perform LF normalization
-* text=auto

+ 0 - 17
packages/tldraw/.gitignore

@@ -1,17 +0,0 @@
-node_modules/
-build/
-dist/
-docs/
-.idea/*
-
-.DS_Store
-coverage
-*.log
-
-.vercel
-.next
-apps/www/public/workbox-*
-apps/www/public/worker-*
-apps/www/public/sw.js
-apps/www/public/sw.js.map
-.env

+ 0 - 17
packages/tldraw/.npmignore

@@ -1,17 +0,0 @@
-/.github/
-/.vscode/
-/node_modules/
-/build/
-/tmp/
-.idea/*
-/docs/
-
-coverage
-*.log
-.gitlab-ci.yml
-
-package-lock.json
-/*.tgz
-/tmp*
-/mnt/
-/package/

+ 0 - 11
packages/tldraw/.prettierrc

@@ -1,11 +0,0 @@
-{
-  "trailingComma": "es5",
-  "singleQuote": true,
-  "semi": false,
-  "printWidth": 100,
-  "tabWidth": 2,
-  "useTabs": false,
-  "jsxSingleQuote": false,
-  "jsxBracketSameLine": false,
-  "arrowParens": "avoid"
-}

+ 0 - 21
packages/tldraw/LICENSE.md

@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2021 Stephen Ruiz Ltd
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

+ 0 - 29
packages/tldraw/README.md

@@ -1,29 +0,0 @@
-# Developer Notes
-
-## Background
-
-This folder contains the JS codes for a custom build of Tldraw to fit the needs of Logseq, which originates from an abandoned next branch from the author of Tldraw.
-
-## Development
-
-### Prerequisites
-
-Modern JS eco tools like Node.js and yarn.
-
-### Run in dev mode
-
-- install dependencies with `yarn`
-- run dev mode with `yarn dev`, which will start a Vite server at http://127.0.0.1:3031/
-
-Note, the dev mode is a standalone web app running a demo Tldraw app in `tldraw/demo/src/App.jsx`. The Logseq component renderers and handlers are all mocked to make sure Tldraw only functions can be isolatedly developed.
-
-## Other useful commands
-
-- fixing styles: `yarn fix:style`
-- build: `yarn build`
-
-## How it works
-
-### Data flow between Tldraw & Logseq
-
-The data flow between Tldraw & Logseq can be found here: https://whimsical.com/9sdt5j7MabK6DVrxgTZw25

+ 0 - 3
packages/tldraw/apps/tldraw-logseq/README.md

@@ -1,3 +0,0 @@
-# @tldraw/core Simple Example
-
-A (relatively) simple example project for `@tldraw/core`.

+ 0 - 29
packages/tldraw/apps/tldraw-logseq/build.mjs

@@ -1,29 +0,0 @@
-#!/usr/bin/env zx
-/* eslint-disable no-undef */
-import 'zx/globals'
-import fs from 'fs'
-import path from 'path'
-
-if (process.platform === 'win32') {
-  defaults.shell = "cmd.exe";
-  defaults.prefix = "";
-}
-
-// Build with [tsup](https://tsup.egoist.sh)
-await $`npx tsup`
-
-
-// Prepare package.json file
-const packageJson = fs.readFileSync('package.json', 'utf8')
-const glob = JSON.parse(packageJson)
-Object.assign(glob, {
-  main: './index.js',
-  module: './index.mjs',
-})
-
-fs.writeFileSync('dist/package.json', JSON.stringify(glob, null, 2))
-
-const dest = path.join(__dirname, '/../../../../src/main/frontend/tldraw-logseq.js')
-
-if (fs.existsSync(dest)) fs.unlinkSync(dest)
-fs.linkSync(path.join(__dirname, '/dist/index.js'), dest)

+ 0 - 42
packages/tldraw/apps/tldraw-logseq/package.json

@@ -1,42 +0,0 @@
-{
-  "version": "0.0.0-dev",
-  "name": "@tldraw/logseq",
-  "license": "MIT",
-  "module": "./src/index.ts",
-  "scripts": {
-    "build": "zx build.mjs",
-    "build:packages": "yarn build",
-    "dev": "tsup --watch",
-    "dev:vite": "tsup --watch --sourcemap inline"
-  },
-  "devDependencies": {
-    "@radix-ui/react-context-menu": "^2.1.0",
-    "@tldraw/core": "2.0.0-alpha.1",
-    "@tldraw/react": "2.0.0-alpha.1",
-    "@tldraw/vec": "2.0.0-alpha.1",
-    "@types/node": "^18.13.0",
-    "@types/react": "^17.0.0",
-    "@types/react-dom": "^17.0.0",
-    "autoprefixer": "^10.4.13",
-    "concurrently": "^7.5.0",
-    "esbuild": "^0.15.14",
-    "mobx": "^6.7.0",
-    "mobx-react-lite": "^3.4.0",
-    "perfect-freehand": "^1.2.0",
-    "polished": "^4.0.0",
-    "postcss": "^8.4.19",
-    "lucide-react": "^0.292.0",
-    "react": "^17.0.0",
-    "react-dom": "^17.0.0",
-    "react-virtuoso": "^3.1.3",
-    "rimraf": "3.0.2",
-    "shadow-cljs": "^2.20.11",
-    "tsup": "^6.5.0",
-    "typescript": "^4.9.3",
-    "zx": "^7.2.2"
-  },
-  "peerDependencies": {
-    "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
-    "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
-  }
-}

+ 0 - 3
packages/tldraw/apps/tldraw-logseq/postcss.config.js

@@ -1,3 +0,0 @@
-module.exports = ctx => ({
-  plugins: [require('autoprefixer')()],
-})

+ 0 - 148
packages/tldraw/apps/tldraw-logseq/src/app.tsx

@@ -1,148 +0,0 @@
-/* eslint-disable @typescript-eslint/no-non-null-assertion */
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import type { TLDocumentModel } from '@tldraw/core'
-import {
-  AppCanvas,
-  AppProvider,
-  TLReactCallbacks,
-  TLReactToolConstructor,
-  useApp,
-} from '@tldraw/react'
-import * as React from 'react'
-import { AppUI } from './components/AppUI'
-import { ContextBar } from './components/ContextBar'
-import { ContextMenu } from './components/ContextMenu'
-import { QuickLinks } from './components/QuickLinks'
-import { useDrop } from './hooks/useDrop'
-import { usePaste } from './hooks/usePaste'
-import { useCopy } from './hooks/useCopy'
-import { useQuickAdd } from './hooks/useQuickAdd'
-import {
-  BoxTool,
-  EllipseTool,
-  HighlighterTool,
-  HTMLTool,
-  IFrameTool,
-  LineTool,
-  LogseqPortalTool,
-  NuEraseTool,
-  PencilTool,
-  PolygonTool,
-  shapes,
-  TextTool,
-  YouTubeTool,
-  type Shape,
-} from './lib'
-import { LogseqContext, type LogseqContextValue } from './lib/logseq-context'
-
-const tools: TLReactToolConstructor<Shape>[] = [
-  BoxTool,
-  EllipseTool,
-  PolygonTool,
-  NuEraseTool,
-  HighlighterTool,
-  LineTool,
-  PencilTool,
-  TextTool,
-  YouTubeTool,
-  IFrameTool,
-  HTMLTool,
-  LogseqPortalTool,
-]
-
-interface LogseqTldrawProps {
-  renderers: LogseqContextValue['renderers']
-  handlers: LogseqContextValue['handlers']
-  readOnly: boolean
-  model?: TLDocumentModel<Shape>
-  onMount?: TLReactCallbacks<Shape>['onMount']
-  onPersist?: TLReactCallbacks<Shape>['onPersist']
-}
-
-const BacklinksCount: LogseqContextValue['renderers']['BacklinksCount'] = props => {
-  const { renderers } = React.useContext(LogseqContext)
-
-  const options = { 'portal?': false }
-
-  return <renderers.BacklinksCount {...props} options={options} />
-}
-
-const AppImpl = () => {
-  const ref = React.useRef<HTMLDivElement>(null)
-  const app = useApp()
-
-  const components = React.useMemo(
-    () => ({
-      ContextBar,
-      BacklinksCount,
-      QuickLinks,
-    }),
-    []
-  )
-  return (
-    <ContextMenu collisionRef={ref}>
-      <div ref={ref} className="logseq-tldraw logseq-tldraw-wrapper" data-tlapp={app.uuid}>
-        <AppCanvas components={components}>
-          <AppUI />
-        </AppCanvas>
-      </div>
-    </ContextMenu>
-  )
-}
-
-const AppInner = ({
-  onPersist,
-  readOnly,
-  model,
-  ...rest
-}: Omit<LogseqTldrawProps, 'renderers' | 'handlers'>) => {
-  const onDrop = useDrop()
-  const onPaste = usePaste()
-  const onCopy = useCopy()
-  const onQuickAdd = readOnly ? null : useQuickAdd()
-
-  const onPersistOnDiff: TLReactCallbacks<Shape>['onPersist'] = React.useCallback(
-    (app, info) => {
-      onPersist?.(app, info)
-    },
-    [model]
-  )
-
-  return (
-    <AppProvider
-      Shapes={shapes}
-      Tools={tools}
-      onDrop={onDrop}
-      onPaste={onPaste}
-      onCopy={onCopy}
-      readOnly={readOnly}
-      onCanvasDBClick={onQuickAdd}
-      onPersist={onPersistOnDiff}
-      model={model}
-      {...rest}
-    >
-      <AppImpl />
-    </AppProvider>
-  )
-}
-
-export const App = function App({ renderers, handlers, ...rest }: LogseqTldrawProps): JSX.Element {
-  const memoRenders: any = React.useMemo(() => {
-    return Object.fromEntries(
-      Object.entries(renderers).map(([key, comp]) => {
-        return [key, React.memo(comp)]
-      })
-    )
-  }, [])
-
-  const contextValue = {
-    renderers: memoRenders,
-    handlers: handlers,
-  }
-
-  return (
-    <LogseqContext.Provider value={contextValue}>
-      <AppInner {...rest} />
-    </LogseqContext.Provider>
-  )
-}

+ 0 - 113
packages/tldraw/apps/tldraw-logseq/src/components/ActionBar/ActionBar.tsx

@@ -1,113 +0,0 @@
-/* eslint-disable @typescript-eslint/no-non-null-assertion */
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import { useApp } from '@tldraw/react'
-import { observer } from 'mobx-react-lite'
-import * as React from 'react'
-import type { Shape } from '../../lib'
-import { TablerIcon } from '../icons'
-import { Button } from '../Button'
-import { ToggleInput } from '../inputs/ToggleInput'
-import { ZoomMenu } from '../ZoomMenu'
-import { LogseqContext } from '../../lib/logseq-context'
-
-// @ts-ignore
-const LSUI = window.LSUI
-
-export const ActionBar = observer(function ActionBar(): JSX.Element {
-  const app = useApp<Shape>()
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-
-  const undo = React.useCallback(() => {
-    app.api.undo()
-  }, [app])
-
-  const redo = React.useCallback(() => {
-    app.api.redo()
-  }, [app])
-
-  const zoomIn = React.useCallback(() => {
-    app.api.zoomIn()
-  }, [app])
-
-  const zoomOut = React.useCallback(() => {
-    app.api.zoomOut()
-  }, [app])
-
-  const toggleGrid = React.useCallback(() => {
-    app.api.toggleGrid()
-  }, [app])
-
-  const toggleSnapToGrid = React.useCallback(() => {
-    app.api.toggleSnapToGrid()
-  }, [app])
-
-  const togglePenMode = React.useCallback(() => {
-    app.api.togglePenMode()
-  }, [app])
-
-  return (
-    <div className="tl-action-bar" data-html2canvas-ignore="true">
-      {!app.readOnly && (
-        <div className="tl-toolbar tl-history-bar mr-2 mb-2">
-          <Button tooltip={t('whiteboard/undo')} onClick={undo}>
-            <TablerIcon name="arrow-back-up" />
-          </Button>
-          <Button tooltip={t('whiteboard/redo')} onClick={redo}>
-            <TablerIcon name="arrow-forward-up" />
-          </Button>
-        </div>
-      )}
-
-      <div className={'tl-toolbar tl-zoom-bar mr-2 mb-2'}>
-        <Button tooltip={t('whiteboard/zoom-in')} onClick={zoomIn} id="tl-zoom-in">
-          <TablerIcon name="plus" />
-        </Button>
-        <Button tooltip={t('whiteboard/zoom-out')} onClick={zoomOut} id="tl-zoom-out">
-          <TablerIcon name="minus" />
-        </Button>
-        <LSUI.Separator orientation="vertical" />
-        <ZoomMenu />
-      </div>
-
-      <div className={'tl-toolbar tl-grid-bar mr-2 mb-2'}>
-        <ToggleInput
-            tooltip={t('whiteboard/toggle-grid')}
-            className="tl-button"
-            pressed={app.settings.showGrid}
-            id="tl-show-grid"
-            onPressedChange={toggleGrid}
-          >
-          <TablerIcon name="grid-dots" />
-        </ToggleInput>
-
-        {!app.readOnly && (
-          <ToggleInput
-              tooltip={t('whiteboard/snap-to-grid')}
-              className="tl-button"
-              pressed={app.settings.snapToGrid}
-              id="tl-snap-to-grid"
-              onPressedChange={toggleSnapToGrid}
-            >
-            <TablerIcon name={app.settings.snapToGrid ? "magnet" : "magnet-off"} />
-          </ToggleInput>
-        )}
-      </div>
-
-      {!app.readOnly && (
-        <div className="tl-toolbar tl-pen-mode-bar mb-2">
-          <ToggleInput
-            tooltip={t('whiteboard/toggle-pen-mode')}
-            className="tl-button"
-            pressed={app.settings.penMode}
-            id="tl-toggle-pen-mode"
-            onPressedChange={togglePenMode}
-          >
-          <TablerIcon name={app.settings.penMode ? "pencil" : "pencil-off"} />
-        </ToggleInput>
-        </div>
-      )}
-    </div>
-  )
-})

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/ActionBar/index.ts

@@ -1 +0,0 @@
-export * from './ActionBar'

+ 0 - 20
packages/tldraw/apps/tldraw-logseq/src/components/AppUI.tsx

@@ -1,20 +0,0 @@
-import { observer } from 'mobx-react-lite'
-import { ActionBar } from './ActionBar'
-import { DevTools } from './Devtools'
-import { PrimaryTools } from './PrimaryTools'
-import { StatusBar } from './StatusBar'
-import { isDev } from '@tldraw/core'
-import { useApp } from '@tldraw/react'
-
-export const AppUI = observer(function AppUI() {
-  const app = useApp()
-
-  return (
-    <>
-      {isDev() && <StatusBar />}
-      {isDev() && <DevTools />}
-      {!app.readOnly && <PrimaryTools />}
-      <ActionBar />
-    </>
-  )
-})

+ 0 - 71
packages/tldraw/apps/tldraw-logseq/src/components/BlockLink/BlockLink.tsx

@@ -1,71 +0,0 @@
-import { validUUID } from '@tldraw/core'
-import React from 'react'
-import { LogseqContext } from '../../lib/logseq-context'
-import { TablerIcon } from '../icons'
-
-export const BlockLink = ({
-  id,
-  showReferenceContent = false,
-}: {
-  id: string
-  showReferenceContent?: boolean
-}) => {
-  const {
-    handlers: { isWhiteboardPage, redirectToPage, sidebarAddBlock, queryBlockByUUID },
-    renderers: { Breadcrumb, PageName },
-  } = React.useContext(LogseqContext)
-
-  let iconName = ''
-  let linkType = validUUID(id) ? 'B' : 'P'
-  let blockContent = ''
-
-  if (validUUID(id)) {
-    const block = queryBlockByUUID(id)
-    if (!block) {
-      return <span className="p-2">Invalid reference. Did you remove it?</span>
-    }
-
-    blockContent = block.title
-
-    if (block.properties?.['ls-type'] === 'whiteboard-shape') {
-      iconName = 'link-to-whiteboard'
-    } else {
-      iconName = 'link-to-block'
-    }
-  } else {
-    if (isWhiteboardPage(id)) {
-      iconName = 'link-to-whiteboard'
-    } else {
-      iconName = 'link-to-page'
-    }
-  }
-
-  const slicedContent =
-    blockContent && blockContent.length > 23 ? blockContent.slice(0, 20) + '...' : blockContent
-
-  return (
-    <button
-      className="inline-flex gap-1 items-center w-full"
-      onPointerDown={e => {
-        e.stopPropagation()
-        if (e.shiftKey) {
-          sidebarAddBlock(id, linkType === 'B' ? 'block' : 'page')
-        } else {
-          redirectToPage(id)
-        }
-      }}
-    >
-      <TablerIcon name={iconName} />
-      <span className="pointer-events-none block-link-reference-row">
-        {linkType === 'P' ? (
-          <PageName pageName={id} />
-        ) : (
-          <>
-            <Breadcrumb levelLimit={1} blockId={id} endSeparator={showReferenceContent} />
-            {showReferenceContent && slicedContent}
-          </>
-        )}
-      </span>
-    </button>
-  )
-}

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/BlockLink/index.ts

@@ -1 +0,0 @@
-export * from './BlockLink'

+ 0 - 15
packages/tldraw/apps/tldraw-logseq/src/components/Button/Button.tsx

@@ -1,15 +0,0 @@
-import { Tooltip } from '../Tooltip'
-import type { Side } from '@radix-ui/react-popper'
-export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
-  children: React.ReactNode
-  tooltip?: React.ReactNode
-  tooltipSide?: Side
-}
-
-export function Button({ className, tooltip, tooltipSide, ...rest }: ButtonProps) {
-  return (
-    <Tooltip content={tooltip} side={tooltipSide}>
-      <button className={'tl-button ' + (className ?? '')} {...rest} />
-    </Tooltip>
-  )
-}

+ 0 - 26
packages/tldraw/apps/tldraw-logseq/src/components/Button/CircleButton.tsx

@@ -1,26 +0,0 @@
-import { TablerIcon } from '../icons'
-
-export const CircleButton = ({
-  style,
-  icon,
-  onClick,
-}: {
-  active?: boolean
-  style?: React.CSSProperties
-  icon: string
-  otherIcon?: string
-  onClick: () => void
-}) => {
-  return (
-    <button
-      data-html2canvas-ignore="true"
-      style={style}
-      className="tl-circle-button"
-      onPointerDown={onClick}
-    >
-      <div className="tl-circle-button-icons-wrapper">
-        <TablerIcon name={icon} />
-      </div>
-    </button>
-  )
-}

+ 0 - 2
packages/tldraw/apps/tldraw-logseq/src/components/Button/index.ts

@@ -1,2 +0,0 @@
-export * from './Button'
-export * from './CircleButton'

+ 0 - 67
packages/tldraw/apps/tldraw-logseq/src/components/ContextBar/ContextBar.tsx

@@ -1,67 +0,0 @@
-import {
-  getContextBarTranslation,
-  HTMLContainer,
-  TLContextBarComponent,
-  useApp,
-} from '@tldraw/react'
-import { observer } from 'mobx-react-lite'
-
-import * as React from 'react'
-import type { Shape } from '../../lib'
-import { getContextBarActionsForShapes } from './contextBarActionFactory'
-
-// @ts-ignore
-const LSUI = window.LSUI
-
-const _ContextBar: TLContextBarComponent<Shape> = ({ shapes, offsets, hidden }) => {
-  const app = useApp()
-  const rSize = React.useRef<[number, number] | null>(null)
-  const rContextBar = React.useRef<HTMLDivElement>(null)
-
-  React.useLayoutEffect(() => {
-    setTimeout(() => {
-      const elm = rContextBar.current
-      if (!elm) return
-      const { offsetWidth, offsetHeight } = elm
-      rSize.current = [offsetWidth, offsetHeight]
-    })
-  })
-
-  React.useLayoutEffect(() => {
-    const elm = rContextBar.current
-    if (!elm) return
-    const size = rSize.current ?? [0, 0]
-    const [x, y] = getContextBarTranslation(size, offsets)
-    elm.style.transform = `translateX(${x}px) translateY(${y}px)`
-  }, [offsets])
-
-  if (!app) return null
-
-  const Actions = getContextBarActionsForShapes(shapes)
-
-  return (
-    <HTMLContainer centered>
-      {Actions.length > 0 && (
-        <div
-          ref={rContextBar}
-          className="tl-toolbar tl-context-bar"
-          style={{
-            visibility: hidden ? 'hidden' : 'visible',
-            pointerEvents: hidden ? 'none' : 'all',
-          }}
-        >
-          {Actions.map((Action, idx) => (
-            <React.Fragment key={idx}>
-              <Action />
-              {idx < Actions.length - 1 && (
-                <LSUI.Separator className="tl-toolbar-separator" orientation="vertical" />
-              )}
-            </React.Fragment>
-          ))}
-        </div>
-      )}
-    </HTMLContainer>
-  )
-}
-
-export const ContextBar = observer(_ContextBar)

+ 0 - 560
packages/tldraw/apps/tldraw-logseq/src/components/ContextBar/contextBarActionFactory.tsx

@@ -1,560 +0,0 @@
-import { Decoration, isNonNullable } from '@tldraw/core'
-import { useApp } from '@tldraw/react'
-import { observer } from 'mobx-react-lite'
-import React from 'react'
-import type {
-  BoxShape,
-  EllipseShape,
-  HTMLShape,
-  IFrameShape,
-  LineShape,
-  LogseqPortalShape,
-  PencilShape,
-  PolygonShape,
-  Shape,
-  TextShape,
-  YouTubeShape,
-  TweetShape,
-} from '../../lib'
-import { Button } from '../Button'
-import { TablerIcon } from '../icons'
-import { ColorInput } from '../inputs/ColorInput'
-import { ScaleInput } from '../inputs/ScaleInput'
-import { ShapeLinksInput } from '../inputs/ShapeLinksInput'
-import { TextInput } from '../inputs/TextInput'
-import {
-  ToggleGroupInput,
-  ToggleGroupMultipleInput,
-  type ToggleGroupInputOption,
-} from '../inputs/ToggleGroupInput'
-import { ToggleInput } from '../inputs/ToggleInput'
-import { GeometryTools } from '../GeometryTools'
-import { LogseqContext } from '../../lib/logseq-context'
-import { KeyboardShortcut } from '../KeyboardShortcut'
-
-export const contextBarActionTypes = [
-  // Order matters
-  'EditPdf',
-  'LogseqPortalViewMode',
-  'Geometry',
-  'AutoResizing',
-  'Swatch',
-  'NoFill',
-  'StrokeType',
-  'ScaleLevel',
-  'TextStyle',
-  'YoutubeLink',
-  'TwitterLink',
-  'IFrameSource',
-  'ArrowMode',
-  'Links',
-] as const
-
-type ContextBarActionType = typeof contextBarActionTypes[number]
-const singleShapeActions: ContextBarActionType[] = [
-  'YoutubeLink',
-  'TwitterLink',
-  'IFrameSource',
-  'Links',
-  'EditPdf',
-]
-
-const contextBarActionMapping = new Map<ContextBarActionType, React.FC>()
-
-type ShapeType = Shape['props']['type']
-
-export const shapeMapping: Record<ShapeType, ContextBarActionType[]> = {
-  'logseq-portal': ['Swatch', 'LogseqPortalViewMode', 'ScaleLevel', 'AutoResizing', 'Links'],
-  youtube: ['YoutubeLink', 'Links'],
-  tweet: ['TwitterLink', 'Links'],
-  iframe: ['IFrameSource', 'Links'],
-  box: ['Geometry', 'TextStyle', 'Swatch', 'ScaleLevel', 'NoFill', 'StrokeType', 'Links'],
-  ellipse: ['Geometry', 'TextStyle', 'Swatch', 'ScaleLevel', 'NoFill', 'StrokeType', 'Links'],
-  polygon: ['Geometry', 'TextStyle', 'Swatch', 'ScaleLevel', 'NoFill', 'StrokeType', 'Links'],
-  line: ['TextStyle', 'Swatch', 'ScaleLevel', 'ArrowMode', 'Links'],
-  pencil: ['Swatch', 'Links', 'ScaleLevel'],
-  highlighter: ['Swatch', 'Links', 'ScaleLevel'],
-  text: ['TextStyle', 'Swatch', 'ScaleLevel', 'AutoResizing', 'Links'],
-  html: ['ScaleLevel', 'AutoResizing', 'Links'],
-  image: ['Links'],
-  video: ['Links'],
-  pdf: ['EditPdf', 'Links'],
-}
-
-export const withFillShapes = Object.entries(shapeMapping)
-  .filter(([key, types]) => {
-    return types.includes('NoFill') && types.includes('Swatch')
-  })
-  .map(([key]) => key) as ShapeType[]
-
-function filterShapeByAction<S extends Shape>(type: ContextBarActionType) {
-  const app = useApp<Shape>()
-  const unlockedSelectedShapes = app.selectedShapesArray.filter(s => !s.props.isLocked)
-  return unlockedSelectedShapes.filter(shape => shapeMapping[shape.props.type]?.includes(type))
-}
-
-const AutoResizingAction = observer(() => {
-  const app = useApp<Shape>()
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-  const shapes = filterShapeByAction<LogseqPortalShape | TextShape | HTMLShape>('AutoResizing')
-
-  const pressed = shapes.every(s => s.props.isAutoResizing)
-
-  return (
-    <ToggleInput
-      tooltip={t('whiteboard/auto-resize')}
-      toggle={shapes.every(s => s.props.type === 'logseq-portal')}
-      className="tl-button"
-      pressed={pressed}
-      onPressedChange={v => {
-        shapes.forEach(s => {
-          if (s.props.type === 'logseq-portal') {
-            s.update({
-              isAutoResizing: v,
-            })
-          } else {
-            s.onResetBounds({ zoom: app.viewport.camera.zoom })
-          }
-        })
-        app.persist()
-      }}
-    >
-      <TablerIcon name="dimensions" />
-    </ToggleInput>
-  )
-})
-
-const LogseqPortalViewModeAction = observer(() => {
-  const app = useApp<Shape>()
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-  const shapes = filterShapeByAction<LogseqPortalShape>('LogseqPortalViewMode')
-
-  const collapsed = shapes.every(s => s.collapsed)
-  if (!collapsed && !shapes.every(s => !s.collapsed)) {
-    return null
-  }
-
-  const tooltip = (
-    <div className="flex">
-      {collapsed ? t('whiteboard/expand') : t('whiteboard/collapse')}
-      <KeyboardShortcut
-        action={collapsed ? 'editor/expand-block-children' : 'editor/collapse-block-children'}
-      />
-    </div>
-  )
-
-  return (
-    <ToggleInput
-      tooltip={tooltip}
-      toggle={shapes.every(s => s.props.type === 'logseq-portal')}
-      className="tl-button"
-      pressed={collapsed}
-      onPressedChange={() => app.api.setCollapsed(!collapsed)}
-    >
-      <TablerIcon name={collapsed ? 'object-expanded' : 'object-compact'} />
-    </ToggleInput>
-  )
-})
-
-const ScaleLevelAction = observer(() => {
-  const {
-    handlers: { isMobile },
-  } = React.useContext(LogseqContext)
-
-  const shapes = filterShapeByAction<LogseqPortalShape>('ScaleLevel')
-  const scaleLevel = new Set(shapes.map(s => s.scaleLevel)).size > 1 ? '' : shapes[0].scaleLevel
-
-  return <ScaleInput scaleLevel={scaleLevel} compact={isMobile()} />
-})
-
-const IFrameSourceAction = observer(() => {
-  const app = useApp<Shape>()
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-  const shape = filterShapeByAction<IFrameShape>('IFrameSource')[0]
-
-  const handleChange = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-    shape.onIFrameSourceChange(e.target.value.trim().toLowerCase())
-    app.persist()
-  }, [])
-
-  const handleReload = React.useCallback(() => {
-    shape.reload()
-  }, [])
-
-  return (
-    <span className="flex gap-3">
-      <Button tooltip={t('whiteboard/reload')} type="button" onClick={handleReload}>
-        <TablerIcon name="refresh" />
-      </Button>
-      <TextInput
-        title={t('whiteboard/website-url')}
-        className="tl-iframe-src"
-        value={`${shape.props.url}`}
-        onChange={handleChange}
-      />
-      <Button
-        tooltip={t('whiteboard/open-website-url')}
-        type="button"
-        onClick={() => window.open(shape.props.url)}
-      >
-        <TablerIcon name="external-link" />
-      </Button>
-    </span>
-  )
-})
-
-const YoutubeLinkAction = observer(() => {
-  const app = useApp<Shape>()
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-  const shape = filterShapeByAction<YouTubeShape>('YoutubeLink')[0]
-  const handleChange = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-    shape.onYoutubeLinkChange(e.target.value)
-    app.persist()
-  }, [])
-
-  return (
-    <span className="flex gap-3">
-      <TextInput
-        title={t('whiteboard/youtube-url')}
-        className="tl-youtube-link"
-        value={`${shape.props.url}`}
-        onChange={handleChange}
-      />
-      <Button
-        tooltip={t('whiteboard/open-youtube-url')}
-        type="button"
-        onClick={() => window.logseq?.api?.open_external_link?.(shape.props.url)}
-      >
-        <TablerIcon name="external-link" />
-      </Button>
-    </span>
-  )
-})
-
-const TwitterLinkAction = observer(() => {
-  const app = useApp<Shape>()
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-  const shape = filterShapeByAction<TweetShape>('TwitterLink')[0]
-  const handleChange = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-    shape.onTwitterLinkChange(e.target.value)
-    app.persist()
-  }, [])
-
-  return (
-    <span className="flex gap-3">
-      <TextInput
-        title={t('whiteboard/twitter-url')}
-        className="tl-twitter-link"
-        value={`${shape.props.url}`}
-        onChange={handleChange}
-      />
-      <Button
-        tooltip={t('whiteboard/open-twitter-url')}
-        type="button"
-        onClick={() => window.logseq?.api?.open_external_link?.(shape.props.url)}
-      >
-        <TablerIcon name="external-link" />
-      </Button>
-    </span>
-  )
-})
-
-const EditPdfAction = observer(() => {
-  const app = useApp<Shape>()
-  const {
-    handlers: { t, setCurrentPdf },
-  } = React.useContext(LogseqContext)
-  const shape = app.selectedShapesArray[0]
-
-  return (
-    <Button
-      tooltip={t('whiteboard/edit-pdf')}
-      type="button"
-      onClick={() => setCurrentPdf(app.assets[shape.props.assetId].src)}
-    >
-      <TablerIcon name="edit" />
-    </Button>
-  )
-})
-
-const NoFillAction = observer(() => {
-  const app = useApp<Shape>()
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-  const shapes = filterShapeByAction<BoxShape | PolygonShape | EllipseShape>('NoFill')
-  const handleChange = React.useCallback((v: boolean) => {
-    app.selectedShapesArray.forEach(s => s.update({ noFill: v }))
-    app.persist()
-  }, [])
-
-  const noFill = shapes.every(s => s.props.noFill)
-
-  return (
-    <ToggleInput
-      tooltip={t('whiteboard/fill')}
-      className="tl-button"
-      pressed={noFill}
-      onPressedChange={handleChange}
-    >
-      <TablerIcon name={noFill ? 'droplet-off' : 'droplet'} />
-    </ToggleInput>
-  )
-})
-
-const SwatchAction = observer(() => {
-  const app = useApp<Shape>()
-  // Placeholder
-  const shapes = filterShapeByAction<
-    BoxShape | PolygonShape | EllipseShape | LineShape | PencilShape | TextShape
-  >('Swatch')
-
-  const handleSetColor = React.useCallback((color: string) => {
-    app.selectedShapesArray.forEach(s => {
-      s.update({ fill: color, stroke: color })
-    })
-    app.persist()
-  }, [])
-
-  const handleSetOpacity = React.useCallback((opacity: number) => {
-    app.selectedShapesArray.forEach(s => {
-      s.update({ opacity: opacity })
-    })
-    app.persist()
-  }, [])
-
-  const color = shapes[0].props.noFill ? shapes[0].props.stroke : shapes[0].props.fill
-  return (
-    <ColorInput
-      popoverSide="top"
-      color={color}
-      opacity={shapes[0].props.opacity}
-      setOpacity={handleSetOpacity}
-      setColor={handleSetColor}
-    />
-  )
-})
-
-const GeometryAction = observer(() => {
-  const app = useApp<Shape>()
-
-  const handleSetGeometry = React.useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
-    const type = e.currentTarget.dataset.tool
-    app.api.convertShapes(type)
-  }, [])
-
-  return <GeometryTools popoverSide="top" chevron={false} setGeometry={handleSetGeometry} />
-})
-
-const StrokeTypeAction = observer(() => {
-  const app = useApp<Shape>()
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-  const shapes = filterShapeByAction<
-    BoxShape | PolygonShape | EllipseShape | LineShape | PencilShape
-  >('StrokeType')
-
-  const StrokeTypeOptions: ToggleGroupInputOption[] = [
-    {
-      value: 'line',
-      icon: 'circle',
-      tooltip: 'Solid',
-    },
-    {
-      value: 'dashed',
-      icon: 'circle-dashed',
-      tooltip: 'Dashed',
-    },
-  ]
-
-  const value = shapes.every(s => s.props.strokeType === 'dashed')
-    ? 'dashed'
-    : shapes.every(s => s.props.strokeType === 'line')
-    ? 'line'
-    : 'mixed'
-
-  return (
-    <ToggleGroupInput
-      title={t('whiteboard/stroke-type')}
-      options={StrokeTypeOptions}
-      value={value}
-      onValueChange={v => {
-        shapes.forEach(shape => {
-          shape.update({
-            strokeType: v,
-          })
-        })
-        app.persist()
-      }}
-    />
-  )
-})
-
-const ArrowModeAction = observer(() => {
-  const app = useApp<Shape>()
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-  const shapes = filterShapeByAction<LineShape>('ArrowMode')
-
-  const StrokeTypeOptions: ToggleGroupInputOption[] = [
-    {
-      value: 'start',
-      icon: 'arrow-narrow-left',
-    },
-    {
-      value: 'end',
-      icon: 'arrow-narrow-right',
-    },
-  ]
-
-  const startValue = shapes.every(s => s.props.decorations?.start === Decoration.Arrow)
-  const endValue = shapes.every(s => s.props.decorations?.end === Decoration.Arrow)
-
-  const value = [startValue ? 'start' : null, endValue ? 'end' : null].filter(isNonNullable)
-
-  const valueToDecorations = (value: string[]) => {
-    return {
-      start: value.includes('start') ? Decoration.Arrow : null,
-      end: value.includes('end') ? Decoration.Arrow : null,
-    }
-  }
-
-  return (
-    <ToggleGroupMultipleInput
-      title={t('whiteboard/arrow-head')}
-      options={StrokeTypeOptions}
-      value={value}
-      onValueChange={v => {
-        shapes.forEach(shape => {
-          shape.update({
-            decorations: valueToDecorations(v),
-          })
-        })
-        app.persist()
-      }}
-    />
-  )
-})
-
-const TextStyleAction = observer(() => {
-  const app = useApp<Shape>()
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-  const shapes = filterShapeByAction<TextShape>('TextStyle')
-
-  const bold = shapes.every(s => s.props.fontWeight > 500)
-  const italic = shapes.every(s => s.props.italic)
-
-  return (
-    <span className="flex gap-1">
-      <ToggleInput
-        tooltip={t('whiteboard/bold')}
-        className="tl-button"
-        pressed={bold}
-        onPressedChange={v => {
-          shapes.forEach(shape => {
-            shape.update({
-              fontWeight: v ? 700 : 400,
-            })
-            shape.onResetBounds()
-          })
-          app.persist()
-        }}
-      >
-        <TablerIcon name="bold" />
-      </ToggleInput>
-      <ToggleInput
-        tooltip={t('whiteboard/italic')}
-        className="tl-button"
-        pressed={italic}
-        onPressedChange={v => {
-          shapes.forEach(shape => {
-            shape.update({
-              italic: v,
-            })
-            shape.onResetBounds()
-          })
-          app.persist()
-        }}
-      >
-        <TablerIcon name="italic" />
-      </ToggleInput>
-    </span>
-  )
-})
-
-const LinksAction = observer(() => {
-  const app = useApp<Shape>()
-  const shape = app.selectedShapesArray[0]
-
-  const handleChange = (refs: string[]) => {
-    shape.update({ refs: refs })
-    app.persist()
-  }
-
-  return (
-    <ShapeLinksInput
-      onRefsChange={handleChange}
-      refs={shape.props.refs ?? []}
-      shapeType={shape.props.type}
-      side="right"
-      pageId={shape.props.type === 'logseq-portal' ? shape.props.pageId : undefined}
-      portalType={shape.props.type === 'logseq-portal' ? shape.props.blockType : undefined}
-    />
-  )
-})
-
-contextBarActionMapping.set('Geometry', GeometryAction)
-contextBarActionMapping.set('AutoResizing', AutoResizingAction)
-contextBarActionMapping.set('LogseqPortalViewMode', LogseqPortalViewModeAction)
-contextBarActionMapping.set('ScaleLevel', ScaleLevelAction)
-contextBarActionMapping.set('YoutubeLink', YoutubeLinkAction)
-contextBarActionMapping.set('TwitterLink', TwitterLinkAction)
-contextBarActionMapping.set('IFrameSource', IFrameSourceAction)
-contextBarActionMapping.set('NoFill', NoFillAction)
-contextBarActionMapping.set('Swatch', SwatchAction)
-contextBarActionMapping.set('StrokeType', StrokeTypeAction)
-contextBarActionMapping.set('ArrowMode', ArrowModeAction)
-contextBarActionMapping.set('TextStyle', TextStyleAction)
-contextBarActionMapping.set('Links', LinksAction)
-contextBarActionMapping.set('EditPdf', EditPdfAction)
-const getContextBarActionTypes = (type: ShapeType) => {
-  return (shapeMapping[type] ?? []).filter(isNonNullable)
-}
-
-export const getContextBarActionsForShapes = (shapes: Shape[]) => {
-  const types = shapes.map(s => s.props.type)
-  const actionTypes = new Set(shapes.length > 0 ? getContextBarActionTypes(types[0]) : [])
-  for (let i = 1; i < types.length && actionTypes.size > 0; i++) {
-    const otherActionTypes = getContextBarActionTypes(types[i])
-    actionTypes.forEach(action => {
-      if (!otherActionTypes.includes(action)) {
-        actionTypes.delete(action)
-      }
-    })
-  }
-  if (shapes.length > 1) {
-    singleShapeActions.forEach(action => {
-      if (actionTypes.has(action)) {
-        actionTypes.delete(action)
-      }
-    })
-  }
-
-  return Array.from(actionTypes)
-    .sort((a, b) => contextBarActionTypes.indexOf(a) - contextBarActionTypes.indexOf(b))
-    .map(action => contextBarActionMapping.get(action)!)
-}

+ 0 - 2
packages/tldraw/apps/tldraw-logseq/src/components/ContextBar/index.ts

@@ -1,2 +0,0 @@
-export * from './ContextBar'
-export * from './contextBarActionFactory'

+ 0 - 369
packages/tldraw/apps/tldraw-logseq/src/components/ContextMenu/ContextMenu.tsx

@@ -1,369 +0,0 @@
-import { useApp } from '@tldraw/react'
-import { LogseqContext } from '../../lib/logseq-context'
-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 { toJS } from 'mobx'
-
-// @ts-ignore
-const LSUI = window.LSUI
-
-interface ContextMenuProps {
-  children: React.ReactNode
-  collisionRef: React.RefObject<HTMLDivElement>
-}
-
-export const ContextMenu = observer(function ContextMenu({
-  children,
-  collisionRef,
-}: ContextMenuProps) {
-  const app = useApp()
-  const { handlers } = React.useContext(LogseqContext)
-  const t = handlers.t
-  const rContent = React.useRef<HTMLDivElement>(null)
-
-  const runAndTransition = (f: Function) => {
-    f()
-    app.transition('select')
-  }
-
-  const developerMode = React.useMemo(() => {
-    return isDev()
-  }, [])
-
-  return (
-    <LSUI.ContextMenu
-      onOpenChange={(open: boolean) => {
-        if (open && !app.isIn('select.contextMenu')) {
-          app.transition('select').selectedTool.transition('contextMenu')
-        } else if (!open && app.isIn('select.contextMenu')) {
-          app.selectedTool.transition('idle')
-        }
-      }}
-    >
-      <LSUI.ContextMenuTrigger
-        disabled={app.editingShape && Object.keys(app.editingShape).length !== 0}
-      >
-        {children}
-      </LSUI.ContextMenuTrigger>
-      <LSUI.ContextMenuContent
-        className="tl-menu tl-context-menu"
-        ref={rContent}
-        onEscapeKeyDown={() => app.transition('select')}
-        collisionBoundary={collisionRef.current}
-        asChild
-        tabIndex={-1}
-      >
-        <div>
-          {app.selectedShapes?.size > 1 &&
-            !app.readOnly &&
-            app.selectedShapesArray?.some(s => !s.props.isLocked) && (
-              <>
-                <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"/>
-                    </Button>
-                    <Button
-                      tooltip={t('whiteboard/align-center-horizontally')}
-                      onClick={() => runAndTransition(() => app.align(AlignType.CenterHorizontal))}
-                    >
-                      <TablerIcon name="layout-align-center"/>
-                    </Button>
-                    <Button
-                      tooltip={t('whiteboard/align-right')}
-                      onClick={() => runAndTransition(() => app.align(AlignType.Right))}
-                    >
-                      <TablerIcon name="layout-align-right"/>
-                    </Button>
-                    <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"/>
-                    </Button>
-                  </div>
-                  <div className="tl-menu-button-row pt-0">
-                    <Button
-                      tooltip={t('whiteboard/align-top')}
-                      onClick={() => runAndTransition(() => app.align(AlignType.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"/>
-                    </Button>
-                    <Button
-                      tooltip={t('whiteboard/align-bottom')}
-                      onClick={() => runAndTransition(() => app.align(AlignType.Bottom))}
-                    >
-                      <TablerIcon name="layout-align-bottom"/>
-                    </Button>
-                    <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"/>
-                    </Button>
-                  </div>
-                </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"/>
-                  {t('whiteboard/pack-into-rectangle')}
-                </LSUI.ContextMenuItem>
-                <LSUI.ContextMenuSeparator className="menu-separator"/>
-              </>
-            )}
-          {app.selectedShapes?.size > 0 && (
-            <>
-              <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"/>
-              </LSUI.ContextMenuItem>
-              <LSUI.ContextMenuSeparator className="menu-separator"/>
-            </>
-          )}
-          {(app.selectedShapesArray.some(s => s.type === 'group' || app.getParentGroup(s)) ||
-              app.selectedShapesArray.length > 1) &&
-            app.selectedShapesArray?.some(s => !s.props.isLocked) &&
-            !app.readOnly && (
-              <>
-                {app.selectedShapesArray.some(s => s.type === 'group' || app.getParentGroup(s)) && (
-                  <LSUI.ContextMenuItem
-                    className="tl-menu-item"
-                    onClick={() => runAndTransition(app.api.unGroup)}
-                  >
-                    <TablerIcon className="tl-menu-icon" name="ungroup"/>
-                    {t('whiteboard/ungroup')}
-                    <KeyboardShortcut action="whiteboard/ungroup"/>
-                  </LSUI.ContextMenuItem>
-                )}
-                {app.selectedShapesArray.length > 1 &&
-                  app.selectedShapesArray?.some(s => !s.props.isLocked) && (
-                    <LSUI.ContextMenuItem
-                      className="tl-menu-item"
-                      onClick={() => runAndTransition(app.api.doGroup)}
-                    >
-                      <TablerIcon className="tl-menu-icon" name="group"/>
-                      {t('whiteboard/group')}
-                      <KeyboardShortcut action="whiteboard/group"/>
-                    </LSUI.ContextMenuItem>
-                  )}
-                <LSUI.ContextMenuSeparator className="menu-separator"/>
-              </>
-            )}
-          {app.selectedShapes?.size > 0 && app.selectedShapesArray?.some(s => !s.props.isLocked) && (
-            <>
-              {!app.readOnly && (
-                <LSUI.ContextMenuItem
-                  className="tl-menu-item"
-                  onClick={() => runAndTransition(app.cut)}
-                >
-                  <TablerIcon className="tl-menu-icon" name="cut"/>
-                  {t('whiteboard/cut')}
-                </LSUI.ContextMenuItem>
-              )}
-              <LSUI.ContextMenuItem
-                className="tl-menu-item"
-                onClick={() => runAndTransition(app.copy)}
-              >
-                <TablerIcon className="tl-menu-icon" name="copy"/>
-                {t('whiteboard/copy')}
-                <KeyboardShortcut action="editor/copy"/>
-              </LSUI.ContextMenuItem>
-            </>
-          )}
-          {!app.readOnly && (
-            <LSUI.ContextMenuItem
-              className="tl-menu-item"
-              onClick={() => runAndTransition(app.paste)}
-            >
-              <TablerIcon className="tl-menu-icon" name="clipboard"/>
-              {t('whiteboard/paste')}
-              <KeyboardShortcut shortcut={`${MOD_KEY}+v`}/>
-            </LSUI.ContextMenuItem>
-          )}
-          {app.selectedShapes?.size === 1 && !app.readOnly && (
-            <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 shortcut={`${MOD_KEY}+⇧+v`}/>
-            </LSUI.ContextMenuItem>
-          )}
-          {app.selectedShapes?.size > 0 && (
-            <>
-              <LSUI.ContextMenuSeparator className="menu-separator"/>
-              <LSUI.ContextMenuItem
-                className="tl-menu-item"
-                onClick={() =>
-                  runAndTransition(() =>
-                    handlers.exportToImage(app.currentPageId, {
-                      x: app.selectionBounds.minX + app.viewport.camera.point[0] - EXPORT_PADDING,
-                      y: app.selectionBounds.minY + app.viewport.camera.point[1] - EXPORT_PADDING,
-                      width: app.selectionBounds?.width + EXPORT_PADDING * 2,
-                      height: app.selectionBounds?.height + EXPORT_PADDING * 2,
-                      zoom: app.viewport.camera.zoom,
-                    })
-                  )
-                }
-              >
-                <TablerIcon className="tl-menu-icon" name="file-export"/>
-                {t('whiteboard/export')}
-                <div className="tl-menu-right-slot">
-                  <span className="keyboard-shortcut"></span>
-                </div>
-              </LSUI.ContextMenuItem>
-            </>
-          )}
-          <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"/>
-          </LSUI.ContextMenuItem>
-          {app.selectedShapes?.size > 1 && (
-            <LSUI.ContextMenuItem
-              className="tl-menu-item"
-              onClick={() => runAndTransition(app.api.deselectAll)}
-            >
-              <TablerIcon className="tl-menu-icon" name="circle-dotted"/>
-              {t('whiteboard/deselect-all')}
-            </LSUI.ContextMenuItem>
-          )}
-          {!app.readOnly &&
-            app.selectedShapes?.size > 0 &&
-            app.selectedShapesArray?.some(s => !s.props.isLocked) && (
-              <LSUI.ContextMenuItem
-                className="tl-menu-item"
-                onClick={() => runAndTransition(() => app.setLocked(true))}
-              >
-                <TablerIcon className="tl-menu-icon" name="lock"/>
-                {t('whiteboard/lock')}
-                <KeyboardShortcut action="whiteboard/lock"/>
-              </LSUI.ContextMenuItem>
-            )}
-          {!app.readOnly &&
-            app.selectedShapes?.size > 0 &&
-            app.selectedShapesArray?.some(s => s.props.isLocked) && (
-              <LSUI.ContextMenuItem
-                className="tl-menu-item"
-                onClick={() => runAndTransition(() => app.setLocked(false))}
-              >
-                <TablerIcon className="tl-menu-icon" name="lock-open"/>
-                {t('whiteboard/unlock')}
-                <KeyboardShortcut action="whiteboard/unlock"/>
-              </LSUI.ContextMenuItem>
-            )}
-          {app.selectedShapes?.size > 0 &&
-            !app.readOnly &&
-            app.selectedShapesArray?.some(s => !s.props.isLocked) && (
-              <>
-                <LSUI.ContextMenuItem
-                  className="tl-menu-item"
-                  onClick={() => runAndTransition(app.api.deleteShapes)}
-                >
-                  <TablerIcon className="tl-menu-icon" name="backspace"/>
-                  {t('whiteboard/delete')}
-                  <KeyboardShortcut action="editor/delete"/>
-                </LSUI.ContextMenuItem>
-                {app.selectedShapes?.size > 1 && !app.readOnly && (
-                  <>
-                    <LSUI.ContextMenuSeparator className="menu-separator"/>
-                    <LSUI.ContextMenuItem
-                      className="tl-menu-item"
-                      onClick={() => runAndTransition(app.flipHorizontal)}
-                    >
-                      <TablerIcon className="tl-menu-icon"
-                                  name="flip-horizontal"/>
-                      {t('whiteboard/flip-horizontally')}
-                    </LSUI.ContextMenuItem>
-                    <LSUI.ContextMenuItem
-                      className="tl-menu-item"
-                      onClick={() => runAndTransition(app.flipVertical)}
-                    >
-                      <TablerIcon className="tl-menu-icon"
-                                  name="flip-vertical"/>
-                      {t('whiteboard/flip-vertically')}
-                    </LSUI.ContextMenuItem>
-                  </>
-                )}
-                {!app.readOnly && (
-                  <>
-                    <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"/>
-                    </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"/>
-                    </LSUI.ContextMenuItem>
-                  </>
-                )}
-
-                {developerMode && (
-                  <LSUI.ContextMenuItem
-                    className="tl-menu-item"
-                    onClick={() => {
-                      if (app.selectedShapesArray.length === 1) {
-                        console.log(toJS(app.selectedShapesArray[0].serialized))
-                      } else {
-                        console.log(app.selectedShapesArray.map(s => toJS(s.serialized)))
-                      }
-                    }}
-                  >
-                    {t('whiteboard/dev-print-shape-props')}
-                  </LSUI.ContextMenuItem>
-                )}
-              </>
-            )}
-        </div>
-      </LSUI.ContextMenuContent>
-    </LSUI.ContextMenu>
-  )
-})

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/ContextMenu/index.ts

@@ -1 +0,0 @@
-export * from './ContextMenu'

+ 0 - 56
packages/tldraw/apps/tldraw-logseq/src/components/Devtools/Devtools.tsx

@@ -1,56 +0,0 @@
-import { useRendererContext } from '@tldraw/react'
-import { observer } from 'mobx-react-lite'
-import React from 'react'
-import ReactDOM from 'react-dom'
-
-const printPoint = (point: number[]) => {
-  return `[${point.map(d => d?.toFixed(2) ?? '-').join(', ')}]`
-}
-
-export const DevTools = observer(() => {
-  const {
-    viewport: {
-      bounds,
-      camera: { point, zoom },
-    },
-    inputs,
-  } = useRendererContext()
-
-  const statusbarAnchorRef = React.useRef<HTMLElement | null>()
-
-  React.useEffect(() => {
-    const statusbarAnchor = document.getElementById('tl-statusbar-anchor')
-    statusbarAnchorRef.current = statusbarAnchor
-  }, [])
-
-  const rendererStatusText = [
-    ['Z', zoom?.toFixed(2) ?? 'null'],
-    ['MP', printPoint(inputs.currentPoint)],
-    ['MS', printPoint(inputs.currentScreenPoint)],
-    ['VP', printPoint(point)],
-    ['VBR', printPoint([bounds.maxX, bounds.maxY])],
-  ]
-    .map(p => p.join(''))
-    .join('|')
-
-  const rendererStatus = statusbarAnchorRef.current
-    ? ReactDOM.createPortal(
-        <div
-          style={{
-            flex: 1,
-            display: 'flex',
-            alignItems: 'center',
-          }}
-        >
-          {rendererStatusText}
-        </div>,
-        statusbarAnchorRef.current
-      )
-    : null
-
-  return (
-    <>
-      {rendererStatus}
-    </>
-  )
-})

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/Devtools/index.ts

@@ -1 +0,0 @@
-export * from './Devtools'

+ 0 - 93
packages/tldraw/apps/tldraw-logseq/src/components/GeometryTools/GeometryTools.tsx

@@ -1,93 +0,0 @@
-import { observer } from 'mobx-react-lite'
-import type { Side } from '@radix-ui/react-popper'
-import { ToolButton } from '../ToolButton'
-import { TablerIcon } from '../icons'
-import React from 'react'
-import { LogseqContext } from '../../lib/logseq-context'
-
-// @ts-ignore
-const LSUI = window.LSUI
-
-interface GeometryToolsProps extends React.HTMLAttributes<HTMLElement> {
-  popoverSide?: Side
-  activeGeometry?: string
-  setGeometry: (e: React.MouseEvent<HTMLButtonElement>) => void
-  chevron?: boolean
-}
-
-export const GeometryTools = observer(function GeometryTools({
-  popoverSide = 'left',
-  setGeometry,
-  activeGeometry,
-  chevron = true,
-  ...rest
-}: GeometryToolsProps) {
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-
-  const geometries = [
-    {
-      id: 'box',
-      icon: 'square',
-      tooltip: t('whiteboard/rectangle'),
-    },
-    {
-      id: 'ellipse',
-      icon: 'circle',
-      tooltip: t('whiteboard/circle'),
-    },
-    {
-      id: 'polygon',
-      icon: 'triangle',
-      tooltip: t('whiteboard/triangle'),
-    },
-  ]
-
-  const shapes = {
-    id: 'shapes',
-    icon: 'triangle-square-circle',
-    tooltip: t('whiteboard/shape'),
-  }
-
-  const activeTool = activeGeometry ? geometries.find(geo => geo.id === activeGeometry) : shapes
-
-  return (
-    <LSUI.Popover>
-      <LSUI.PopoverTrigger asChild>
-        <div {...rest} className="tl-geometry-tools-pane-anchor">
-          <ToolButton {...activeTool} tooltipSide={popoverSide} />
-          {chevron && (
-            <TablerIcon
-              data-selected={activeGeometry}
-              className="tl-popover-indicator"
-              name="chevron-down-left"
-            />
-          )}
-        </div>
-      </LSUI.PopoverTrigger>
-
-      <LSUI.PopoverContent
-        className="p-0 w-auto"
-        side={popoverSide}
-        sideOffset={15}
-        collisionBoundary={document.querySelector('.logseq-tldraw')}>
-        <div
-          className={`tl-toolbar tl-geometry-toolbar ${
-            ['left', 'right'].includes(popoverSide) ? 'flex-col' : 'flex-row'
-          }`}
-        >
-          {geometries.map(props => (
-            <ToolButton
-              key={props.id}
-              id={props.id}
-              icon={props.icon}
-              handleClick={setGeometry}
-              tooltipSide={popoverSide}
-            />
-          ))}
-        </div>
-      </LSUI.PopoverContent>
-    </LSUI.Popover>
-  )
-})

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/GeometryTools/index.ts

@@ -1 +0,0 @@
-export * from './GeometryTools'

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

@@ -1,16 +0,0 @@
-import { LogseqContext } from '../../lib/logseq-context'
-import * as React from 'react'
-
-export const KeyboardShortcut = ({
-  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" {...props}>
-      <Shortcut action={action} shortcut={shortcut} opts={opts} />
-    </div>
-  )
-}

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/KeyboardShortcut/index.ts

@@ -1 +0,0 @@
-export * from './KeyboardShortcut'

+ 0 - 55
packages/tldraw/apps/tldraw-logseq/src/components/Minimap/Minimap.tsx

@@ -1,55 +0,0 @@
-import { deepEqual } from '@tldraw/core'
-import { useApp, useMinimapEvents } from '@tldraw/react'
-import { reaction } from 'mobx'
-import { observer } from 'mobx-react-lite'
-import React from 'react'
-import { PreviewManager } from '../../lib'
-import { TablerIcon } from '../icons'
-
-export const Minimap = observer(function Minimap() {
-  const app = useApp()
-
-  const [whiteboardPreviewManager] = React.useState(() => new PreviewManager(app.serialized))
-  const [preview, setPreview] = React.useState(() =>
-    whiteboardPreviewManager.generatePreviewJsx(app.viewport)
-  )
-
-  const [active, setActive] = React.useState(false)
-
-  const events = useMinimapEvents()
-
-  React.useEffect(() => {
-    return reaction(
-      () => {
-        return {
-          serialized: app.serialized,
-          viewport: app.viewport,
-          cameraPoint: app.viewport.camera.point,
-        }
-      },
-      ({ serialized, viewport }, prev) => {
-        if (!deepEqual(prev.serialized, serialized)) {
-          whiteboardPreviewManager.load(serialized)
-        }
-        setPreview(whiteboardPreviewManager.generatePreviewJsx(viewport))
-      }
-    )
-  }, [app])
-
-  return (
-    <>
-      {active && (
-        <div className="tl-preview-minimap" {...events}>
-          {preview}
-        </div>
-      )}
-      <button
-        // className="tl-preview-minimap-toggle"
-        data-active={active}
-        onClick={() => setActive(a => !a)}
-      >
-        <TablerIcon name="crosshair2" />
-      </button>
-    </>
-  )
-})

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/Minimap/index.ts

@@ -1 +0,0 @@
-export * from './Minimap'

+ 0 - 39
packages/tldraw/apps/tldraw-logseq/src/components/PopoverButton/PopoverButton.tsx

@@ -1,39 +0,0 @@
-import type { Side, Align } from '@radix-ui/react-popper'
-
-// @ts-ignore
-const LSUI = window.LSUI
-
-interface PopoverButton extends React.HTMLAttributes<HTMLButtonElement> {
-  side: Side // default side
-  align?: Align
-  alignOffset?: number
-  label: React.ReactNode
-  children: React.ReactNode
-  border?: boolean
-}
-
-export function PopoverButton({ side, align, alignOffset, label, children, border, ...rest }: PopoverButton) {
-  return (
-    <LSUI.Popover>
-      <LSUI.PopoverTrigger
-        {...rest}
-        data-border={border}
-        className="tl-button tl-popover-trigger-button"
-      >
-        {label}
-      </LSUI.PopoverTrigger>
-
-      <LSUI.PopoverContent
-        className="w-auto p-1"
-        align={align}
-        alignOffset={alignOffset}
-        side={side}
-        sideOffset={15}
-        collisionBoundary={document.querySelector('.logseq-tldraw')}
-      >
-        {children}
-        <LSUI.PopoverArrow className="popper-arrow" />
-      </LSUI.PopoverContent>
-    </LSUI.Popover>
-  )
-}

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/PopoverButton/index.ts

@@ -1 +0,0 @@
-export * from './PopoverButton'

+ 0 - 103
packages/tldraw/apps/tldraw-logseq/src/components/PrimaryTools/PrimaryTools.tsx

@@ -1,103 +0,0 @@
-import { useApp } from '@tldraw/react'
-import { Geometry } from '@tldraw/core'
-import { observer } from 'mobx-react-lite'
-import * as React from 'react'
-import { ToolButton } from '../ToolButton'
-import { GeometryTools } from '../GeometryTools'
-import { ColorInput } from '../inputs/ColorInput'
-import { ScaleInput } from '../inputs/ScaleInput'
-import { LogseqContext } from '../../lib/logseq-context'
-
-// @ts-ignore
-const LSUI = window.LSUI
-
-export const PrimaryTools = observer(function PrimaryTools() {
-  const app = useApp()
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-
-  const handleSetColor = React.useCallback((color: string) => {
-    app.api.setColor(color)
-  }, [])
-
-  const handleToolClick = React.useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
-    const tool = e.currentTarget.dataset.tool
-    if (tool) app.selectTool(tool)
-  }, [])
-
-  const [activeGeomId, setActiveGeomId] = React.useState(
-    () =>
-      Object.values(Geometry).find((geo: string) => geo === app.selectedTool.id) ??
-      Object.values(Geometry)[0]
-  )
-
-  React.useEffect(() => {
-    setActiveGeomId((prevId: Geometry) => {
-      return Object.values(Geometry).find((geo: string) => geo === app.selectedTool.id) ?? prevId
-    })
-  }, [app.selectedTool.id])
-
-  return (
-    <div className="tl-primary-tools" data-html2canvas-ignore="true">
-      <div className="tl-toolbar tl-tools-floating-panel">
-        <ToolButton
-          handleClick={() => app.selectTool('select')}
-          tooltip={t('whiteboard/select')}
-          id="select"
-          icon="select-cursor"
-        />
-        <ToolButton
-          handleClick={() => app.selectTool('move')}
-          tooltip={t('whiteboard/pan')}
-          id="move"
-          icon={app.isIn('move.panning') ? 'hand-grab' : 'hand-stop'}
-        />
-        <LSUI.Separator orientation="horizontal" />
-        <ToolButton
-          handleClick={() => app.selectTool('logseq-portal')}
-          tooltip={t('whiteboard/add-block-or-page')}
-          id="logseq-portal"
-          icon="circle-plus"
-        />
-        <ToolButton
-          handleClick={() => app.selectTool('pencil')}
-          tooltip={t('whiteboard/draw')}
-          id="pencil"
-          icon="ballpen"
-        />
-        <ToolButton
-          handleClick={() => app.selectTool('highlighter')}
-          tooltip={t('whiteboard/highlight')}
-          id="highlighter"
-          icon="highlight"
-        />
-        <ToolButton
-          handleClick={() => app.selectTool('erase')}
-          tooltip={t('whiteboard/eraser')}
-          id="erase"
-          icon="eraser"
-        />
-        <ToolButton
-          handleClick={() => app.selectTool('line')}
-          tooltip={t('whiteboard/connector')}
-          id="line"
-          icon="connector"
-        />
-        <ToolButton
-          handleClick={() => app.selectTool('text')}
-          tooltip={t('whiteboard/text')}
-          id="text"
-          icon="text"
-        />
-        <GeometryTools activeGeometry={activeGeomId} setGeometry={handleToolClick} />
-        <LSUI.Separator
-          orientation="horizontal"
-          style={{ margin: '0 -4px' }}
-        />
-        <ColorInput popoverSide="left" color={app.settings.color} setColor={handleSetColor} />
-        <ScaleInput scaleLevel={app.settings.scaleLevel} popoverSide="left" compact={true} />
-      </div>
-    </div>
-  )
-})

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/PrimaryTools/index.ts

@@ -1 +0,0 @@
-export * from './PrimaryTools'

+ 0 - 44
packages/tldraw/apps/tldraw-logseq/src/components/QuickLinks/QuickLinks.tsx

@@ -1,44 +0,0 @@
-import { TLQuickLinksComponent, useApp } from '@tldraw/react'
-import { observer } from 'mobx-react-lite'
-import React from 'react'
-import type { Shape } from '../../lib'
-import { LogseqContext } from '../../lib/logseq-context'
-import { BlockLink } from '../BlockLink'
-
-export const QuickLinks: TLQuickLinksComponent<Shape> = observer(({ shape }) => {
-  const app = useApp()
-  const { handlers } = React.useContext(LogseqContext)
-  const t = handlers.t
-  const links = React.useMemo(() => {
-    const links = [...(shape.props.refs ?? [])].map<[ref: string, showReferenceContent: boolean]>(
-      // user added links should show the referenced block content
-      l => [l, true]
-    )
-
-    if (shape.props.type === 'logseq-portal' && shape.props.pageId) {
-      // portal reference should not show the block content
-      links.unshift([shape.props.pageId, false])
-    }
-
-    // do not show links for the current page
-    return links.filter(
-      link =>
-        link[0].toLowerCase() !== app.currentPage.id &&
-        link[0] !== shape.props.pageId
-    )
-  }, [shape.props.id, shape.props.type, shape.props.parentId, shape.props.refs])
-
-  if (links.length === 0) return null
-
-  return (
-    <div className="tl-quick-links" title={t('whiteboard/shape-quick-links')}>
-      {links.map(([ref, showReferenceContent]) => {
-        return (
-          <div key={ref} className="tl-quick-links-row">
-            <BlockLink id={ref} showReferenceContent={showReferenceContent} />
-          </div>
-        )
-      })}
-    </div>
-  )
-})

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/QuickLinks/index.ts

@@ -1 +0,0 @@
-export * from './QuickLinks'

+ 0 - 437
packages/tldraw/apps/tldraw-logseq/src/components/QuickSearch/QuickSearch.tsx

@@ -1,437 +0,0 @@
-import { useDebouncedValue } from '@tldraw/react'
-import { observer } from 'mobx-react-lite'
-import React from 'react'
-import { Virtuoso } from 'react-virtuoso'
-import { LogseqPortalShape } from '../../lib'
-import { LogseqContext, SearchResult } from '../../lib/logseq-context'
-import { CircleButton } from '../Button'
-import { TablerIcon } from '../icons'
-import { TextInput } from '../inputs/TextInput'
-
-interface LogseqQuickSearchProps {
-  onChange: (id: string) => void
-  className?: string
-  placeholder?: string
-  style?: React.CSSProperties
-  onBlur?: () => void
-  onAddBlock?: (uuid: string) => void
-}
-
-const LogseqTypeTag = ({
-  type,
-  active,
-}: {
-  type: 'B' | 'P' | 'BA' | 'PA' | 'WA' | 'WP' | 'BS' | 'PS'
-  active?: boolean
-}) => {
-  const nameMapping = {
-    B: 'block',
-    P: 'page',
-    WP: 'whiteboard',
-    BA: 'new-block',
-    PA: 'new-page',
-    WA: 'new-whiteboard',
-    BS: 'block-search',
-    PS: 'page-search',
-  }
-  return (
-    <span className="tl-type-tag" data-active={active}>
-      <i className={`tie tie-${nameMapping[type]}`} />
-    </span>
-  )
-}
-
-function escapeRegExp(text: string) {
-  return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
-}
-
-const highlightedJSX = (input: string, keyword: string) => {
-  return (
-    <span>
-      {input
-        .split(new RegExp(`(${escapeRegExp(keyword)})`, 'gi'))
-        .map((part, index) => {
-          if (index % 2 === 1) {
-            return <mark className="tl-highlighted">{part}</mark>
-          }
-          return part
-        })
-        .map((frag, idx) => (
-          <React.Fragment key={idx}>{frag}</React.Fragment>
-        ))}
-    </span>
-  )
-}
-
-const useSearch = (q: string, searchFilter: 'B' | 'P' | null) => {
-  const { handlers } = React.useContext(LogseqContext)
-  const [results, setResults] = React.useState<SearchResult | null>(null)
-  const dq = useDebouncedValue(q, 200)
-
-  React.useEffect(() => {
-    let canceled = false
-    if (dq.length > 0) {
-      const filter = { 'pages?': true, 'blocks?': true, 'files?': false }
-      if (searchFilter === 'B') {
-        filter['pages?'] = false
-      } else if (searchFilter === 'P') {
-        filter['blocks?'] = false
-      }
-      handlers.search(dq, filter).then(_results => {
-        if (!canceled) {
-          setResults(_results)
-        }
-      })
-    } else {
-      setResults(null)
-    }
-    return () => {
-      canceled = true
-    }
-  }, [dq, handlers?.search])
-
-  return results
-}
-
-export const LogseqQuickSearch = observer(
-  ({ className, style, placeholder, onChange, onBlur, onAddBlock }: LogseqQuickSearchProps) => {
-    const [q, setQ] = React.useState(LogseqPortalShape.defaultSearchQuery)
-    const [searchFilter, setSearchFilter] = React.useState<'B' | 'P' | null>(
-      LogseqPortalShape.defaultSearchFilter
-    )
-    const rInput = React.useRef<HTMLInputElement>(null)
-    const { handlers, renderers } = React.useContext(LogseqContext)
-    const t = handlers.t
-
-    const finishSearching = React.useCallback((id: string, isPage: boolean) => {
-    console.log({id, isPage})
-      setTimeout(() => onChange(id, isPage))
-      rInput.current?.blur()
-      if (id) {
-        LogseqPortalShape.defaultSearchQuery = ''
-        LogseqPortalShape.defaultSearchFilter = null
-      }
-    }, [])
-
-    const handleAddBlock = React.useCallback(
-      async (content: string) => {
-        const uuid = await handlers?.addNewBlock(content)
-        if (uuid) {
-          finishSearching(uuid)
-          onAddBlock?.(uuid)
-        }
-        return uuid
-      },
-      [onAddBlock]
-    )
-
-    const optionsWrapperRef = React.useRef<HTMLDivElement>(null)
-
-    const [focusedOptionIdx, setFocusedOptionIdx] = React.useState<number>(0)
-
-    const searchResult = useSearch(q, searchFilter)
-
-    const [prefixIcon, setPrefixIcon] = React.useState<string>('circle-plus')
-
-    const [showPanel, setShowPanel] = React.useState<boolean>(false)
-
-    React.useEffect(() => {
-      // autofocus attr seems not to be working
-      setTimeout(() => {
-        rInput.current?.focus()
-      })
-    }, [searchFilter])
-
-    React.useEffect(() => {
-      LogseqPortalShape.defaultSearchQuery = q
-      LogseqPortalShape.defaultSearchFilter = searchFilter
-    }, [q, searchFilter])
-
-    type Option = {
-      actionIcon: 'search' | 'circle-plus'
-      onChosen: () => boolean // return true if the action was handled
-      element: React.ReactNode
-    }
-
-    const options: Option[] = React.useMemo(() => {
-      const options: Option[] = []
-
-      const Breadcrumb = renderers?.Breadcrumb
-
-      if (!Breadcrumb || !handlers) {
-        return []
-      }
-
-      if (onAddBlock) {
-        // New block option
-        options.push({
-          actionIcon: 'circle-plus',
-          onChosen: () => {
-            return !!handleAddBlock(q)
-          },
-          element: (
-            <div className="tl-quick-search-option-row">
-              <LogseqTypeTag active type="BA" />
-              {q.length > 0 ? (
-                <>
-                  <strong>{t('whiteboard/new-block')}</strong>
-                  {q}
-                </>
-              ) : (
-                <strong>{t('whiteboard/new-block-no-colon')}</strong>
-              )}
-            </div>
-          ),
-        })
-      }
-
-      // New page or whiteboard option when no exact match
-      if (!searchResult?.pages?.some(p => p.title.toLowerCase() === q.toLowerCase()) && q) {
-        options.push(
-          {
-            actionIcon: 'circle-plus',
-            onChosen: async () => {
-              let result = await handlers?.addNewPage(q)
-              finishSearching(result, true)
-              return true
-            },
-            element: (
-              <div className="tl-quick-search-option-row">
-                <LogseqTypeTag active type="PA" />
-                <strong>{t('whiteboard/new-page')}</strong>
-                {q}
-              </div>
-            ),
-          },
-          {
-            actionIcon: 'circle-plus',
-            onChosen: async () => {
-              let result = await handlers?.addNewWhiteboard(q)
-              finishSearching(result, true)
-              return true
-            },
-            element: (
-              <div className="tl-quick-search-option-row">
-                <LogseqTypeTag active type="WA" />
-                <strong>{t('whiteboard/new-whiteboard')}</strong>
-                {q}
-              </div>
-            ),
-          }
-        )
-      }
-
-      // search filters
-      if (q.length === 0 && searchFilter === null) {
-        options.push(
-          {
-            actionIcon: 'search',
-            onChosen: () => {
-              setSearchFilter('B')
-              return true
-            },
-            element: (
-              <div className="tl-quick-search-option-row">
-                <LogseqTypeTag type="BS" />
-                {t('whiteboard/search-only-blocks')}
-              </div>
-            ),
-          },
-          {
-            actionIcon: 'search',
-            onChosen: () => {
-              setSearchFilter('P')
-              return true
-            },
-            element: (
-              <div className="tl-quick-search-option-row">
-                <LogseqTypeTag type="PS" />
-                {t('whiteboard/search-only-pages')}
-              </div>
-            ),
-          }
-        )
-      }
-
-      // Page results
-      if ((!searchFilter || searchFilter === 'P') && searchResult && searchResult.pages) {
-        options.push(
-          ...searchResult.pages.map(page => {
-            return {
-              actionIcon: 'search' as 'search',
-              onChosen: () => {
-                finishSearching(page.id, true)
-                return true
-              },
-              element: (
-                <div className="tl-quick-search-option-row">
-                  <LogseqTypeTag type={handlers.isWhiteboardPage(page.id) ? 'WP' : 'P'} />
-                  {highlightedJSX(page.title, q)}
-                </div>
-              ),
-            }
-          })
-        )
-      }
-
-      // Block results
-      if ((!searchFilter || searchFilter === 'B') && searchResult && searchResult.blocks) {
-        options.push(
-          ...searchResult.blocks
-            .filter(block => block.title && block.uuid)
-            .map(({ title, uuid }) => {
-              const block = handlers.queryBlockByUUID(uuid)
-              return {
-                actionIcon: 'search' as 'search',
-                onChosen: () => {
-                  if (block) {
-                    finishSearching(uuid)
-                    window.logseq?.api?.set_blocks_id?.([uuid])
-                    return true
-                  }
-                  return false
-                },
-                // FIXME: breadcrumb not works here because of async loading
-                element: (
-                  <>
-                    <div className="tl-quick-search-option-row">
-                      <LogseqTypeTag type="B" />
-                      {highlightedJSX(title, q)}
-                    </div>
-                  </>
-                ),
-              }
-            })
-        )
-      }
-      return options
-    }, [q, searchFilter, searchResult, renderers?.Breadcrumb, handlers])
-
-    React.useEffect(() => {
-      const keydownListener = (e: KeyboardEvent) => {
-        let newIndex = focusedOptionIdx
-        if (e.key === 'ArrowDown') {
-          newIndex = Math.min(options.length - 1, focusedOptionIdx + 1)
-        } else if (e.key === 'ArrowUp') {
-          newIndex = Math.max(0, focusedOptionIdx - 1)
-        } else if (e.key === 'Enter') {
-          options[focusedOptionIdx]?.onChosen()
-          e.stopPropagation()
-          e.preventDefault()
-        } else if (e.key === 'Backspace' && q.length === 0) {
-          setSearchFilter(null)
-        } else if (e.key === 'Escape') {
-          finishSearching('')
-        }
-
-        if (newIndex !== focusedOptionIdx) {
-          const option = options[newIndex]
-          setFocusedOptionIdx(newIndex)
-          setPrefixIcon(option.actionIcon)
-          e.stopPropagation()
-          e.preventDefault()
-          const optionElement = optionsWrapperRef.current?.querySelector(
-            '.tl-quick-search-option:nth-child(' + (newIndex + 1) + ')'
-          )
-          if (optionElement) {
-            // @ts-expect-error we are using scrollIntoViewIfNeeded, which is not in standards
-            optionElement?.scrollIntoViewIfNeeded(false)
-          }
-        }
-      }
-      document.addEventListener('keydown', keydownListener, true)
-      return () => {
-        document.removeEventListener('keydown', keydownListener, true)
-      }
-    }, [options, focusedOptionIdx, q])
-
-    return (
-      <div className={'tl-quick-search ' + (className ?? '')} style={style}>
-        <CircleButton
-          icon={prefixIcon}
-          onClick={() => {
-            options[focusedOptionIdx]?.onChosen()
-          }}
-        />
-        <div className="tl-quick-search-input-container">
-          {searchFilter && (
-            <div className="tl-quick-search-input-filter">
-              <LogseqTypeTag type={searchFilter} />
-              {searchFilter === 'B' ? 'Search blocks' : 'Search pages'}
-              <div
-                className="tl-quick-search-input-filter-remove"
-                onClick={() => setSearchFilter(null)}
-              >
-                <TablerIcon name="x" />
-              </div>
-            </div>
-          )}
-          <TextInput
-            ref={rInput}
-            type="text"
-            value={q}
-            className="tl-quick-search-input"
-            placeholder={placeholder ?? 'Create or search your graph...'}
-            onChange={q => setQ(q.target.value)}
-            onKeyDown={e => {
-              if (e.key === 'Enter') {
-                finishSearching(q)
-              }
-              e.stopPropagation()
-            }}
-            onFocus={() => {
-              setShowPanel(true)
-            }}
-            onBlur={() => {
-              setShowPanel(false)
-              onBlur?.()
-            }}
-          />
-        </div>
-        {/* TODO: refactor to radix-ui popover */}
-        {options.length > 0 && (
-          <div
-            onWheelCapture={e => e.stopPropagation()}
-            className="tl-quick-search-options"
-            ref={optionsWrapperRef}
-            style={{
-              // not using display: none so we can persist the scroll position
-              visibility: showPanel ? 'visible' : 'hidden',
-              pointerEvents: showPanel ? 'all' : 'none',
-            }}
-          >
-            <Virtuoso
-              style={{ height: Math.min(Math.max(1, options.length), 12) * 40 }}
-              totalCount={options.length}
-              itemContent={index => {
-                const { actionIcon, onChosen, element } = options[index]
-                return (
-                  <div
-                    key={index}
-                    data-focused={index === focusedOptionIdx}
-                    className="tl-quick-search-option"
-                    tabIndex={0}
-                    onMouseEnter={() => {
-                      setPrefixIcon(actionIcon)
-                      setFocusedOptionIdx(index)
-                    }}
-                    // we have to use mousedown && stop propagation EARLY, otherwise some
-                    // default behavior of clicking the rendered elements will happen
-                    onPointerDownCapture={e => {
-                      if (onChosen()) {
-                        e.stopPropagation()
-                        e.preventDefault()
-                      }
-                    }}
-                  >
-                    {element}
-                  </div>
-                )
-              }}
-            />
-          </div>
-        )}
-      </div>
-    )
-  }
-)

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/QuickSearch/index.ts

@@ -1 +0,0 @@
-export * from './QuickSearch'

+ 0 - 16
packages/tldraw/apps/tldraw-logseq/src/components/StatusBar/StatusBar.tsx

@@ -1,16 +0,0 @@
-/* eslint-disable @typescript-eslint/no-non-null-assertion */
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import { useApp } from '@tldraw/react'
-import { observer } from 'mobx-react-lite'
-import type { Shape } from '../../lib'
-
-export const StatusBar = observer(function StatusBar() {
-  const app = useApp<Shape>()
-  return (
-    <div className="tl-statusbar" data-html2canvas-ignore="true">
-      {app.selectedTool.id} | {app.selectedTool.currentState.id}
-      <div style={{ flex: 1 }} />
-      <div id="tl-statusbar-anchor" className="flex gap-1" />
-    </div>
-  )
-})

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/StatusBar/index.ts

@@ -1 +0,0 @@
-export * from './StatusBar'

+ 0 - 50
packages/tldraw/apps/tldraw-logseq/src/components/ToolButton/ToolButton.tsx

@@ -1,50 +0,0 @@
-import { TLMoveTool, TLSelectTool } from '@tldraw/core'
-import { useApp } from '@tldraw/react'
-import type { Side } from '@radix-ui/react-popper'
-import { observer } from 'mobx-react-lite'
-import type * as React from 'react'
-import { Button } from '../Button'
-import { TablerIcon } from '../icons'
-import { KeyboardShortcut } from '../KeyboardShortcut'
-
-export interface ToolButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
-  id: string
-  icon: string | React.ReactNode
-  tooltip: string
-  tooltipSide?: Side
-  handleClick: (e: React.MouseEvent<HTMLButtonElement>) => void
-}
-
-export const ToolButton = observer(
-  ({ id, icon, tooltip, tooltipSide = 'left', handleClick, ...props }: ToolButtonProps) => {
-    const app = useApp()
-
-    // Tool must exist
-    const Tool = [...app.Tools, TLSelectTool, TLMoveTool]?.find(T => T.id === id)
-
-    const shortcut = (Tool as any)?.['shortcut']
-
-    const tooltipContent =
-      shortcut && tooltip ? (
-        <div className="flex">
-          {tooltip}
-          <KeyboardShortcut action={shortcut} />
-        </div>
-      ) : (
-        tooltip
-      )
-
-    return (
-      <Button
-        {...props}
-        tooltipSide={tooltipSide}
-        tooltip={tooltipContent}
-        data-tool={id}
-        data-selected={id === app.selectedTool.id}
-        onClick={handleClick}
-      >
-        {typeof icon === 'string' ? <TablerIcon name={icon} /> : icon}
-      </Button>
-    )
-  }
-)

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/ToolButton/index.ts

@@ -1 +0,0 @@
-export * from './ToolButton'

+ 0 - 31
packages/tldraw/apps/tldraw-logseq/src/components/Tooltip/Tooltip.tsx

@@ -1,31 +0,0 @@
-import type { Side } from '@radix-ui/react-popper'
-
-// @ts-ignore
-const LSUI = window.LSUI
-
-export interface TooltipProps {
-  children: React.ReactNode
-  side?: Side
-  sideOffset?: number
-  content?: React.ReactNode
-}
-
-export function Tooltip({ side, content, sideOffset = 10, ...rest }: TooltipProps) {
-  return content ? (
-    <LSUI.TooltipProvider delayDuration={300}>
-      <LSUI.Tooltip>
-        <LSUI.TooltipTrigger asChild>{rest.children}</LSUI.TooltipTrigger>
-          <LSUI.TooltipContent
-            sideOffset={sideOffset}
-            side={side}
-            {...rest}
-          >
-            {content}
-            <LSUI.TooltipArrow className="popper-arrow" />
-          </LSUI.TooltipContent>
-      </LSUI.Tooltip>
-    </LSUI.TooltipProvider>
-  ) : (
-    <>{rest.children}</>
-  )
-}

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/Tooltip/index.ts

@@ -1 +0,0 @@
-export * from './Tooltip'

+ 0 - 65
packages/tldraw/apps/tldraw-logseq/src/components/ZoomMenu/ZoomMenu.tsx

@@ -1,65 +0,0 @@
-import { useApp } from '@tldraw/react'
-import { KeyboardShortcut } from '../KeyboardShortcut'
-import { observer } from 'mobx-react-lite'
-
-// @ts-ignore
-const LSUI = window.LSUI
-
-export const ZoomMenu = observer(function ZoomMenu(): JSX.Element {
-  const app = useApp()
-  const preventEvent = (e: Event) => {
-    e.preventDefault()
-  }
-
-  return (
-    <LSUI.DropdownMenu>
-      <LSUI.DropdownMenuTrigger className="tl-button text-sm px-2 important" id="tl-zoom">
-        {(app.viewport.camera.zoom * 100).toFixed(0) + '%'}
-      </LSUI.DropdownMenuTrigger>
-      <LSUI.DropdownMenuContent
-        onCloseAutoFocus={e => e.preventDefault()}
-        id="zoomPopup"
-        sideOffset={12}
-      >
-        <LSUI.DropdownMenuItem
-          onSelect={preventEvent}
-          onClick={app.api.zoomToFit}
-        >
-          Zoom to drawing
-          <KeyboardShortcut action="whiteboard/zoom-to-fit" />
-        </LSUI.DropdownMenuItem>
-        <LSUI.DropdownMenuItem
-          onSelect={preventEvent}
-          onClick={app.api.zoomToSelection}
-          disabled={app.selectedShapesArray.length === 0}
-        >
-          Zoom to fit selection
-          <KeyboardShortcut action="whiteboard/zoom-to-selection" />
-        </LSUI.DropdownMenuItem>
-        <LSUI.DropdownMenuItem
-          onSelect={preventEvent}
-          onClick={app.api.zoomIn}
-        >
-          Zoom in
-          <KeyboardShortcut action="whiteboard/zoom-in" />
-        </LSUI.DropdownMenuItem>
-        <LSUI.DropdownMenuItem
-          onSelect={preventEvent}
-          onClick={app.api.zoomOut}
-        >
-          Zoom out
-          <KeyboardShortcut action="whiteboard/zoom-out" />
-        </LSUI.DropdownMenuItem>
-        <LSUI.DropdownMenuItem
-          onSelect={preventEvent}
-          onClick={app.api.resetZoom}
-        >
-          Reset zoom
-          <KeyboardShortcut action="whiteboard/reset-zoom" />
-        </LSUI.DropdownMenuItem>
-      </LSUI.DropdownMenuContent>
-    </LSUI.DropdownMenu>
-  )
-})
-
-export default ZoomMenu

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/ZoomMenu/index.ts

@@ -1 +0,0 @@
-export * from './ZoomMenu'

+ 0 - 35
packages/tldraw/apps/tldraw-logseq/src/components/icons/TablerIcon.tsx

@@ -1,35 +0,0 @@
-const extendedIcons = [
-  'add-link',
-  'block-search',
-  'block',
-  'connector',
-  'group',
-  'internal-link',
-  'link-to-block',
-  'link-to-page',
-  'link-to-whiteboard',
-  'move-to-sidebar-right',
-  'object-compact',
-  'object-expanded',
-  'open-as-page',
-  'page-search',
-  'page',
-  'references-hide',
-  'references-show',
-  'select-cursor',
-  'text',
-  'ungroup',
-  'whiteboard-element',
-  'whiteboard',
-]
-
-const cx = (...args: (string | undefined)[]) => args.join(' ')
-
-export const TablerIcon = ({
-  name,
-  className,
-  ...props
-}: { name: string } & React.HTMLAttributes<HTMLElement>) => {
-  const classNamePrefix = extendedIcons.includes(name) ? `tie tie-` : `ti ti-`
-  return <i className={cx(classNamePrefix + name, className)} {...props} />
-}

+ 0 - 1
packages/tldraw/apps/tldraw-logseq/src/components/icons/index.ts

@@ -1 +0,0 @@
-export * from './TablerIcon'

+ 0 - 122
packages/tldraw/apps/tldraw-logseq/src/components/inputs/ColorInput.tsx

@@ -1,122 +0,0 @@
-import type { Side } from '@radix-ui/react-popper'
-import { Color, isBuiltInColor, debounce } from '@tldraw/core'
-import { TablerIcon } from '../icons'
-import { PopoverButton } from '../PopoverButton'
-import { Tooltip } from '../Tooltip'
-import React from 'react'
-import { LogseqContext } from '../../lib/logseq-context'
-// @ts-ignore
-const LSUI = window.LSUI
-
-interface ColorInputProps extends React.HTMLAttributes<HTMLButtonElement> {
-  color?: string
-  opacity?: number
-  popoverSide: Side
-  setColor: (value: string) => void
-  setOpacity?: (value: number) => void
-}
-
-export function ColorInput({
-  color,
-  opacity,
-  popoverSide,
-  setColor,
-  setOpacity,
-  ...rest
-}: ColorInputProps) {
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-
-  function renderColor(color?: string) {
-    return color ? (
-      <div className="tl-color-bg" style={{ backgroundColor: color }}>
-        <div className={`w-full h-full bg-${color}-500`}></div>
-      </div>
-    ) : (
-      <div className={'tl-color-bg'}>
-        <TablerIcon name="color-swatch" />
-      </div>
-    )
-  }
-
-  function isHexColor(color: string) {
-    return /^#(?:[0-9a-f]{3}){1,2}$/i.test(color)
-  }
-
-  const handleChangeDebounced = React.useMemo(() => {
-    let latestValue = ''
-
-    const handler: React.ChangeEventHandler<HTMLInputElement> = e => {
-      setColor(latestValue)
-    }
-
-    return debounce(handler, 100, e => {
-      latestValue = e.target.value
-    })
-  }, [])
-
-  return (
-    <PopoverButton
-      {...rest}
-      border
-      side={popoverSide}
-      label={
-        <Tooltip content={t('whiteboard/color')} side={popoverSide} sideOffset={14}>
-          {renderColor(color)}
-        </Tooltip>
-      }
-    >
-      <div className="p-1">
-        <div className={'tl-color-palette'}>
-          {Object.values(Color).map(value => (
-            <button
-              key={value}
-              className={`tl-color-drip m-1${value === color ? ' active' : ''}`}
-              onClick={() => setColor(value)}
-            >
-              {renderColor(value)}
-            </button>
-          ))}
-        </div>
-
-        <div className="flex items-center tl-custom-color">
-          <div className={`tl-color-drip m-1 mr-3 ${!isBuiltInColor(color) ? 'active' : ''}`}>
-            <div className="color-input-wrapper tl-color-bg">
-              <input
-                className="color-input cursor-pointer"
-                id="tl-custom-color-input"
-                type="color"
-                value={isHexColor(color) ? color : '#000000'}
-                onChange={handleChangeDebounced}
-                style={{ opacity: isBuiltInColor(color) ? 0 : 1 }}
-                {...rest}
-              />
-            </div>
-          </div>
-          <label htmlFor="tl-custom-color-input" className="text-xs cursor-pointer">
-            {t('whiteboard/select-custom-color')}
-          </label>
-        </div>
-
-        {setOpacity && (
-          <div className="mx-1 my-2">
-            <LSUI.Slider
-              defaultValue={[opacity ?? 0]}
-              onValueCommit={value => setOpacity(value[0])}
-              max={1}
-              step={0.1}
-              aria-label={t('whiteboard/opacity')}
-              className="tl-slider-root"
-            >
-              <LSUI.SliderTrack className="tl-slider-track">
-                <LSUI.SliderRange className="tl-slider-range" />
-              </LSUI.SliderTrack>
-              <LSUI.SliderThumb className="tl-slider-thumb" />
-            </LSUI.Slider>
-          </div>
-        )}
-      </div>
-    </PopoverButton>
-  )
-}

+ 0 - 12
packages/tldraw/apps/tldraw-logseq/src/components/inputs/NumberInput.tsx

@@ -1,12 +0,0 @@
-interface NumberInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
-  label: string
-}
-
-export function NumberInput({ label, ...rest }: NumberInputProps) {
-  return (
-    <div className="input">
-      <label htmlFor={`number-${label}`}>{label}</label>
-      <input className="number-input" name={`number-${label}`} type="number" {...rest} />
-    </div>
-  )
-}

+ 0 - 59
packages/tldraw/apps/tldraw-logseq/src/components/inputs/ScaleInput.tsx

@@ -1,59 +0,0 @@
-import { SelectInput, type SelectOption } from '../inputs/SelectInput'
-import type { Side } from '@radix-ui/react-popper'
-import type { SizeLevel } from '../../lib'
-import { useApp } from '@tldraw/react'
-import React from 'react'
-import { LogseqContext } from '../../lib/logseq-context'
-
-interface ScaleInputProps extends React.HTMLAttributes<HTMLButtonElement> {
-  scaleLevel?: SizeLevel
-  compact?: boolean
-  popoverSide?: Side
-}
-
-export function ScaleInput({ scaleLevel, compact, popoverSide, ...rest }: ScaleInputProps) {
-  const app = useApp<Shape>()
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-
-  const sizeOptions: SelectOption[] = [
-    {
-      label: compact ? 'XS' : t('whiteboard/extra-small'),
-      value: 'xs',
-    },
-    {
-      label: compact ? 'SM' : t('whiteboard/small'),
-      value: 'sm',
-    },
-    {
-      label: compact ? 'MD' : t('whiteboard/medium'),
-      value: 'md',
-    },
-    {
-      label: compact ? 'LG' : t('whiteboard/large'),
-      value: 'lg',
-    },
-    {
-      label: compact ? 'XL' : t('whiteboard/extra-large'),
-      value: 'xl',
-    },
-    {
-      label: compact ? 'XXL' : t('whiteboard/huge'),
-      value: 'xxl',
-    },
-  ]
-
-  return (
-    <SelectInput
-      tooltip={t('whiteboard/scale-level')}
-      options={sizeOptions}
-      value={scaleLevel}
-      popoverSide={popoverSide}
-      compact={compact}
-      onValueChange={v => {
-        app.api.setScaleLevel(v)
-      }}
-    />
-  )
-}

+ 0 - 75
packages/tldraw/apps/tldraw-logseq/src/components/inputs/SelectInput.tsx

@@ -1,75 +0,0 @@
-import * as React from 'react'
-import { Tooltip } from '../Tooltip'
-import { ChevronDown } from 'lucide-react'
-import type { Side } from '@radix-ui/react-popper'
-
-// @ts-ignore
-const LSUI = window.LSUI
-
-export interface SelectOption {
-  value: string
-  label: React.ReactNode
-}
-
-interface SelectInputProps extends React.HTMLAttributes<HTMLElement> {
-  options: SelectOption[]
-  value: string
-  tooltip?: React.ReactNode
-  popoverSide?: Side
-  compact?: boolean
-  onValueChange: (value: string) => void
-}
-
-export function SelectInput({
-  options,
-  tooltip,
-  popoverSide,
-  compact = false,
-  value,
-  onValueChange,
-  ...rest
-}: SelectInputProps) {
-  const [isOpen, setIsOpen] = React.useState(false)
-  return (
-    <div {...rest}>
-      <LSUI.Select
-        open={isOpen}
-        onOpenChange={setIsOpen}
-        value={value}
-        onValueChange={onValueChange}
-      >
-        <Tooltip content={tooltip} side={popoverSide}>
-          <LSUI.SelectTrigger
-            className={`tl-select-trigger ${compact ? "compact" : ""}`}>
-            <LSUI.SelectValue />
-            {!compact && (
-              <LSUI.SelectIcon asChild>
-                <ChevronDown className="h-4 w-4 opacity-50"/>
-              </LSUI.SelectIcon>
-            )}
-          </LSUI.SelectTrigger>
-        </Tooltip>
-
-        <LSUI.SelectContent
-          className="min-w-min"
-          side={popoverSide}
-          position="popper"
-          sideOffset={14}
-          align="center"
-          onKeyDown={e => e.stopPropagation()}
-        >
-          {options.map(option => {
-            return (
-              <LSUI.SelectItem
-                key={option.value}
-                value={option.value}
-              >
-                {option.label}
-              </LSUI.SelectItem>
-            )
-          })}
-        </LSUI.SelectContent>
-      </LSUI.Select>
-    </div>
-  )
-}

+ 0 - 162
packages/tldraw/apps/tldraw-logseq/src/components/inputs/ShapeLinksInput.tsx

@@ -1,162 +0,0 @@
-import type { Side } from '@radix-ui/react-popper'
-import { validUUID } from '@tldraw/core'
-import { useApp } from '@tldraw/react'
-import React from 'react'
-
-import { observer } from 'mobx-react-lite'
-import { LogseqContext } from '../../lib/logseq-context'
-import { BlockLink } from '../BlockLink'
-import { Button } from '../Button'
-import { Tooltip } from '../Tooltip'
-import { TablerIcon } from '../icons'
-import { PopoverButton } from '../PopoverButton'
-import { LogseqQuickSearch } from '../QuickSearch'
-
-interface ShapeLinksInputProps extends React.HTMLAttributes<HTMLButtonElement> {
-  shapeType: string
-  side: Side
-  refs: string[]
-  pageId?: string // the portal referenced block id or page name
-  portalType?: 'B' | 'P'
-  onRefsChange: (value: string[]) => void
-}
-
-function ShapeLinkItem({
-  id,
-  type,
-  onRemove,
-  showContent,
-}: {
-  id: string
-  type: 'B' | 'P'
-  onRemove?: () => void
-  showContent?: boolean
-}) {
-  const app = useApp<Shape>()
-  const { handlers } = React.useContext(LogseqContext)
-  const t = handlers.t
-
-  return (
-    <div className="tl-shape-links-panel-item color-level relative">
-      <div className="whitespace-pre break-all overflow-hidden text-ellipsis inline-flex">
-        <BlockLink id={id} showReferenceContent={showContent} />
-      </div>
-      <div className="flex-1" />
-      {handlers.getBlockPageName(id) !== app.currentPage.name && (
-        <Button
-          tooltip={t('whiteboard/open-page')}
-          type="button"
-          onClick={() => handlers?.redirectToPage(id)}
-        >
-          <TablerIcon name="open-as-page" />
-        </Button>
-      )}
-      <Button
-        tooltip={t('whiteboard/open-page-in-sidebar')}
-        type="button"
-        onClick={() => handlers?.sidebarAddBlock(id, type === 'B' ? 'block' : 'page')}
-      >
-        <TablerIcon name="move-to-sidebar-right" />
-      </Button>
-      {onRemove && (
-        <Button
-          className="tl-shape-links-panel-item-remove-button"
-          tooltip={t('whiteboard/remove-link')}
-          type="button"
-          onClick={onRemove}
-        >
-          <TablerIcon name="x" className="!translate-y-0" />
-        </Button>
-      )}
-    </div>
-  )
-}
-
-export const ShapeLinksInput = observer(function ShapeLinksInput({
-  pageId,
-  portalType,
-  shapeType,
-  refs,
-  side,
-  onRefsChange,
-  ...rest
-}: ShapeLinksInputProps) {
-  const {
-    handlers: { t },
-  } = React.useContext(LogseqContext)
-
-  const noOfLinks = refs.length + (pageId ? 1 : 0)
-  const canAddLink = refs.length === 0
-
-  const addNewRef = (value?: string) => {
-    if (value && !refs.includes(value) && canAddLink) {
-      onRefsChange([...refs, value])
-    }
-  }
-
-  const showReferencePanel = !!(pageId && portalType)
-
-  return (
-    <PopoverButton
-      {...rest}
-      side={side}
-      align="start"
-      alignOffset={-6}
-      label={
-        <Tooltip content={t('whiteboard/link')} sideOffset={14}>
-          <div className="flex gap-1 relative items-center justify-center px-1">
-            <TablerIcon name={noOfLinks > 0 ? 'link' : 'add-link'} />
-            {noOfLinks > 0 && <div className="tl-shape-links-count">{noOfLinks}</div>}
-          </div>
-        </Tooltip>
-      }
-    >
-      <div className="color-level rounded-lg" data-show-reference-panel={showReferencePanel}>
-        {showReferencePanel && (
-          <div className="tl-shape-links-reference-panel">
-            <div className="text-base inline-flex gap-1 items-center">
-              <TablerIcon className="opacity-50" name="internal-link" />
-              {t('whiteboard/references')}
-            </div>
-            <ShapeLinkItem type={portalType} id={pageId} />
-          </div>
-        )}
-        <div className="tl-shape-links-panel color-level">
-          <div className="text-base inline-flex gap-1 items-center">
-            <TablerIcon className="opacity-50" name="add-link" />
-            {t('whiteboard/link-to-any-page-or-block')}
-          </div>
-
-          {canAddLink && (
-            <LogseqQuickSearch
-              style={{
-                width: 'calc(100% - 46px)',
-                marginLeft: '46px',
-              }}
-              placeholder={t('whiteboard/start-typing-to-search')}
-              onChange={addNewRef}
-            />
-          )}
-
-          {refs.length > 0 && (
-            <div className="flex flex-col items-stretch gap-2">
-              {refs.map((ref, i) => {
-                return (
-                  <ShapeLinkItem
-                    key={ref}
-                    id={ref}
-                    type={validUUID(ref) ? 'B' : 'P'}
-                    onRemove={() => {
-                      onRefsChange(refs.filter((_, j) => i !== j))
-                    }}
-                    showContent
-                  />
-                )
-              })}
-            </div>
-          )}
-        </div>
-      </div>
-    </PopoverButton>
-  )
-})

+ 0 - 18
packages/tldraw/apps/tldraw-logseq/src/components/inputs/TextInput.tsx

@@ -1,18 +0,0 @@
-import * as React from 'react'
-
-interface TextInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
-  autoResize?: boolean
-}
-
-export const TextInput = React.forwardRef<HTMLInputElement, TextInputProps>(
-  ({ autoResize = true, value, className, ...rest }, ref) => {
-    return (
-      <div className={'tl-input' + (className ? ' ' + className : '')}>
-        <div className="tl-input-sizer">
-          <div className="tl-input-hidden">{value}</div>
-          <input ref={ref} value={value} className="tl-text-input" type="text" {...rest} />
-        </div>
-      </div>
-    )
-  }
-)

+ 0 - 76
packages/tldraw/apps/tldraw-logseq/src/components/inputs/ToggleGroupInput.tsx

@@ -1,76 +0,0 @@
-import { TablerIcon } from '../icons'
-import { Tooltip } from '../Tooltip'
-
-// @ts-ignore
-const LSUI = window.LSUI
-
-export interface ToggleGroupInputOption {
-  value: string
-  icon: string
-  tooltip?: string
-}
-
-interface ToggleGroupInputProps extends React.HTMLAttributes<HTMLElement> {
-  options: ToggleGroupInputOption[]
-  value: string
-  onValueChange: (value: string) => void
-}
-
-interface ToggleGroupMultipleInputProps extends React.HTMLAttributes<HTMLElement> {
-  options: ToggleGroupInputOption[]
-  value: string[]
-  onValueChange: (value: string[]) => void
-}
-
-export function ToggleGroupInput({ options, value, onValueChange }: ToggleGroupInputProps) {
-  return (
-    <LSUI.ToggleGroup
-      type="single"
-      value={value}
-      onValueChange={onValueChange}
-    >
-      {options.map(option => {
-        return (
-          <Tooltip content={option.tooltip} key={option.value}>
-            <div className="inline-flex">
-              <LSUI.ToggleGroupItem
-                className="tl-button"
-                value={option.value}
-                disabled={option.value === value}
-              >
-                <TablerIcon name={option.icon} />
-              </LSUI.ToggleGroupItem>
-            </div>
-          </Tooltip>
-        )
-      })}
-    </LSUI.ToggleGroup>
-  )
-}
-
-export function ToggleGroupMultipleInput({
-  options,
-  value,
-  onValueChange,
-}: ToggleGroupMultipleInputProps) {
-  return (
-    <LSUI.ToggleGroup
-      className="inline-flex"
-      type="multiple"
-      value={value}
-      onValueChange={onValueChange}
-    >
-      {options.map(option => {
-        return (
-          <LSUI.ToggleGroupItem
-            className="tl-button"
-            key={option.value}
-            value={option.value}
-          >
-            <TablerIcon name={option.icon} />
-          </LSUI.ToggleGroupItem>
-        )
-      })}
-    </LSUI.ToggleGroup>
-  )
-}

+ 0 - 34
packages/tldraw/apps/tldraw-logseq/src/components/inputs/ToggleInput.tsx

@@ -1,34 +0,0 @@
-import { Tooltip } from '../Tooltip'
-
-// @ts-ignore
-const LSUI = window.LSUI
-
-interface ToggleInputProps extends React.HTMLAttributes<HTMLElement> {
-  toggle?: boolean
-  pressed: boolean
-  tooltip?: React.ReactNode
-  onPressedChange: (value: boolean) => void
-}
-
-export function ToggleInput({
-  toggle = true,
-  pressed,
-  onPressedChange,
-  className,
-  tooltip,
-  ...rest
-}: ToggleInputProps) {
-  return (
-    <Tooltip content={tooltip}>
-      <div className="inline-flex">
-        <LSUI.Toggle
-          {...rest}
-          data-toggle={toggle}
-          className={'tl-button' + (className ? ' ' + className : '')}
-          pressed={pressed}
-          onPressedChange={onPressedChange}
-        />
-      </div>
-    </Tooltip>
-  )
-}

+ 0 - 6
packages/tldraw/apps/tldraw-logseq/src/hooks/useCameraMoving.ts

@@ -1,6 +0,0 @@
-import { useApp } from '@tldraw/react'
-
-export function useCameraMovingRef() {
-  const app = useApp()
-  return app.inputs.state === 'panning' || app.inputs.state === 'pinching'
-}

+ 0 - 11
packages/tldraw/apps/tldraw-logseq/src/hooks/useCopy.ts

@@ -1,11 +0,0 @@
-import type { TLReactCallbacks } from '@tldraw/react'
-import * as React from 'react'
-import { LogseqContext } from '../lib/logseq-context'
-
-export function useCopy() {
-  const { handlers } = React.useContext(LogseqContext)
-
-  return React.useCallback<TLReactCallbacks['onCopy']>((app, { text, html }) => {
-    handlers.copyToClipboard(text, html)
-  }, [])
-}

+ 0 - 14
packages/tldraw/apps/tldraw-logseq/src/hooks/useDrop.ts

@@ -1,14 +0,0 @@
-import type { TLReactCallbacks } from '@tldraw/react'
-import * as React from 'react'
-import type { Shape } from '../lib'
-import { usePaste } from './usePaste'
-
-export function useDrop() {
-  const handlePaste = usePaste()
-  return React.useCallback<TLReactCallbacks<Shape>['onDrop']>(
-    async (app, { dataTransfer, point }) => {
-      handlePaste(app, { point, shiftKey: false, dataTransfer, fromDrop: true })
-    },
-    []
-  )
-}

+ 0 - 515
packages/tldraw/apps/tldraw-logseq/src/hooks/usePaste.ts

@@ -1,515 +0,0 @@
-import {
-  getSizeFromSrc,
-  isNonNullable,
-  TLAsset,
-  TLBinding,
-  TLCursor,
-  TLPasteEventInfo,
-  TLShapeModel,
-  uniqueId,
-  validUUID,
-} from '@tldraw/core'
-import type { TLReactApp, TLReactCallbacks } from '@tldraw/react'
-import Vec from '@tldraw/vec'
-import * as React from 'react'
-import { NIL as NIL_UUID } from 'uuid'
-import {
-  HTMLShape,
-  IFrameShape,
-  ImageShape,
-  PdfShape,
-  LogseqPortalShape,
-  VideoShape,
-  YouTubeShape,
-  YOUTUBE_REGEX,
-  TweetShape,
-  X_OR_TWITTER_REGEX,
-  type Shape,
-} from '../lib'
-import { LogseqContext, LogseqContextValue } from '../lib/logseq-context'
-
-const isValidURL = (url: string) => {
-  try {
-    const parsedUrl = new URL(url)
-    return parsedUrl.host && ['http:', 'https:'].includes(parsedUrl.protocol)
-  } catch {
-    return false
-  }
-}
-
-interface Asset extends TLAsset {
-  size?: number[]
-}
-
-const assetExtensions = {
-  image: ['.png', '.svg', '.jpg', '.jpeg', '.gif'],
-  video: ['.mp4', '.webm', '.ogg'],
-  pdf: ['.pdf'],
-}
-
-function getFileType(filename: string) {
-  // Get extension, verify that it's an image
-  const extensionMatch = filename.match(/\.[0-9a-z]+$/i)
-  if (!extensionMatch) return 'unknown'
-  const extension = extensionMatch[0].toLowerCase()
-
-  const [type, _extensions] = Object.entries(assetExtensions).find(([_type, extensions]) =>
-    extensions.includes(extension)
-  ) ?? ['unknown', null]
-
-  return type
-}
-
-type MaybeShapes = TLShapeModel[] | null | undefined
-
-type CreateShapeFN<Args extends any[]> = (...args: Args) => Promise<MaybeShapes> | MaybeShapes
-
-/**
- * Try create a shape from a list of create shape functions. If one of the functions returns a
- * shape, return it, otherwise try again for the next one until all have been tried.
- */
-function tryCreateShapeHelper<Args extends any[]>(...fns: CreateShapeFN<Args>[]) {
-  return async (...args: Args) => {
-    for (const fn of fns) {
-      const result = await fn(...(args as any))
-      if (result && result.length > 0) {
-        return result
-      }
-    }
-    return null
-  }
-}
-
-// TODO: support file types
-async function getDataFromType(item: DataTransfer | ClipboardItem, type: `text/${string}`) {
-  if (!item.types.includes(type)) {
-    return null
-  }
-  if (item instanceof DataTransfer) {
-    return item.getData(type)
-  }
-  const blob = await item.getType(type)
-  return await blob.text()
-}
-
-const handleCreatingShapes = async (
-  app: TLReactApp<Shape>,
-  { point, shiftKey, dataTransfer, fromDrop }: TLPasteEventInfo,
-  handlers: LogseqContextValue['handlers']
-) => {
-  let imageAssetsToCreate: Asset[] = []
-  let assetsToClone: TLAsset[] = []
-  const bindingsToCreate: TLBinding[] = []
-
-  async function createAssetsFromURL(url: string, type: string): Promise<Asset> {
-    // Do we already have an asset for this image?
-    const existingAsset = Object.values(app.assets).find(asset => asset.src === url)
-    if (existingAsset) {
-      return existingAsset as Asset
-    }
-
-    // Create a new asset for this image
-    const asset: Asset = {
-      id: uniqueId(),
-      type: type,
-      src: url,
-      size: await getSizeFromSrc(handlers.makeAssetUrl(url), type),
-    }
-    return asset
-  }
-
-  async function createAssetsFromFiles(files: File[]) {
-    const tasks = files
-      .filter(file => getFileType(file.name) !== 'unknown')
-      .map(async file => {
-        try {
-          const dataurl = await handlers.saveAsset(file)
-          return await createAssetsFromURL(dataurl, getFileType(file.name))
-        } catch (err) {
-          console.error(err)
-        }
-        return null
-      })
-    return (await Promise.all(tasks)).filter(isNonNullable)
-  }
-
-  function createHTMLShape(text: string) {
-    return [
-      {
-        ...HTMLShape.defaultProps,
-        html: text,
-        point: [point[0], point[1]],
-      },
-    ]
-  }
-
-  async function tryCreateShapesFromDataTransfer(dataTransfer: DataTransfer) {
-    return tryCreateShapeHelper(
-      tryCreateShapeFromFilePath,
-      tryCreateShapeFromFiles,
-      tryCreateShapeFromPageName,
-      tryCreateShapeFromBlockUUID,
-      tryCreateShapeFromTextPlain,
-      tryCreateShapeFromTextHTML,
-      tryCreateLogseqPortalShapesFromString
-    )(dataTransfer)
-  }
-
-  async function tryCreateShapesFromClipboard() {
-    const items = await navigator.clipboard.read()
-    const createShapesFn = tryCreateShapeHelper(
-      tryCreateShapeFromTextPlain,
-      tryCreateShapeFromTextHTML,
-      tryCreateLogseqPortalShapesFromString
-    )
-    const allShapes = (await Promise.all(items.map(item => createShapesFn(item))))
-      .flat()
-      .filter(isNonNullable)
-
-    return allShapes
-  }
-
-  async function tryCreateShapeFromFilePath(item: DataTransfer) {
-    const file = item.getData('file')
-    if (!file) return null
-
-    const asset = await createAssetsFromURL(file, 'pdf')
-    app.addAssets([asset])
-
-    const newShape = {
-      ...PdfShape.defaultProps,
-      id: uniqueId(),
-      assetId: asset.id,
-      url: file,
-      opacity: 1,
-    }
-
-    if (asset.size) {
-      Object.assign(newShape, {
-        point: [point[0] - asset.size[0] / 4 + 16, point[1] - asset.size[1] / 4 + 16],
-        size: Vec.div(asset.size, 2),
-      })
-    }
-    return [newShape]
-  }
-
-  async function tryCreateShapeFromFiles(item: DataTransfer) {
-    const files = Array.from(item.files)
-    if (files.length > 0) {
-      const assets = await createAssetsFromFiles(files)
-      // ? could we get rid of this side effect?
-      imageAssetsToCreate = assets
-
-      return assets.map((asset, i) => {
-        let defaultProps = null
-
-        switch (asset.type) {
-          case 'video':
-            defaultProps = VideoShape.defaultProps
-            break
-          case 'image':
-            defaultProps = ImageShape.defaultProps
-            break
-          case 'pdf':
-            defaultProps = PdfShape.defaultProps
-            break
-          default:
-            return null
-        }
-
-        const newShape = {
-          ...defaultProps,
-          id: uniqueId(),
-          // TODO: Should be place near the last edited shape
-          assetId: asset.id,
-          opacity: 1,
-        }
-
-        if (asset.size) {
-          Object.assign(newShape, {
-            point: [point[0] - asset.size[0] / 4 + i * 16, point[1] - asset.size[1] / 4 + i * 16],
-            size: Vec.div(asset.size, 2),
-          })
-        }
-
-        return newShape
-      })
-    }
-    return null
-  }
-
-  async function tryCreateShapeFromTextHTML(item: DataTransfer | ClipboardItem) {
-    // skips if it's a drop event or using shift key
-    if (item.types.includes('text/plain') && (shiftKey || fromDrop)) {
-      return null
-    }
-    const rawText = await getDataFromType(item, 'text/html')
-    if (rawText) {
-      return tryCreateShapeHelper(tryCreateClonedShapesFromJSON, createHTMLShape)(rawText)
-    }
-    return null
-  }
-
-  async function tryCreateShapeFromBlockUUID(dataTransfer: DataTransfer) {
-    // This is a Logseq custom data type defined in frontend.components.block
-    const rawText = dataTransfer.getData('block-uuid')
-    if (rawText) {
-      const text = rawText.trim()
-      const allSelectedBlocks = window.logseq?.api?.get_selected_blocks?.()
-      const blockUUIDs =
-        allSelectedBlocks && allSelectedBlocks?.length > 1
-          ? allSelectedBlocks.map(b => b.uuid)
-          : [text]
-      // ensure all uuid in blockUUIDs is persisted
-      window.logseq?.api?.set_blocks_id?.(blockUUIDs)
-      const tasks = blockUUIDs.map(uuid => tryCreateLogseqPortalShapesFromUUID(`((${uuid}))`))
-      const newShapes = (await Promise.all(tasks)).flat().filter(isNonNullable)
-      return newShapes.map((s, idx) => {
-        // if there are multiple shapes, shift them to the right
-        return {
-          ...s,
-          // TODO: use better alignment?
-          point: [point[0] + (LogseqPortalShape.defaultProps.size[0] + 16) * idx, point[1]],
-        }
-      })
-    }
-    return null
-  }
-
-  async function tryCreateShapeFromPageName(dataTransfer: DataTransfer) {
-    // This is a Logseq custom data type defined in frontend.components.block
-    const rawText = dataTransfer.getData('page-name')
-    if (rawText) {
-      const text = rawText.trim()
-
-      return tryCreateLogseqPortalShapesFromUUID(`[[${text}]]`)
-    }
-    return null
-  }
-
-  async function tryCreateShapeFromTextPlain(item: DataTransfer | ClipboardItem) {
-    const rawText = await getDataFromType(item, 'text/plain')
-    if (rawText) {
-      const text = rawText.trim()
-      return tryCreateShapeHelper(tryCreateShapeFromURL, tryCreateShapeFromIframeString)(text)
-    }
-
-    return null
-  }
-
-  function tryCreateClonedShapesFromJSON(rawText: string) {
-    const result = app.api.getClonedShapesFromTldrString(decodeURIComponent(rawText), point)
-    if (result) {
-      const { shapes, assets, bindings } = result
-      assetsToClone.push(...assets)
-      bindingsToCreate.push(...bindings)
-      return shapes
-    }
-    return null
-  }
-
-  async function tryCreateShapeFromURL(rawText: string) {
-    if (isValidURL(rawText) && !shiftKey) {
-      if (YOUTUBE_REGEX.test(rawText)) {
-        return [
-          {
-            ...YouTubeShape.defaultProps,
-            url: rawText,
-            point: [point[0], point[1]],
-          },
-        ]
-      }
-
-      if (X_OR_TWITTER_REGEX.test(rawText)) {
-        return [
-          {
-            ...TweetShape.defaultProps,
-            url: rawText,
-            point: [point[0], point[1]],
-          },
-        ]
-      }
-
-      return [
-        {
-          ...IFrameShape.defaultProps,
-          url: rawText,
-          point: [point[0], point[1]],
-        },
-      ]
-    }
-    return null
-  }
-
-  function tryCreateShapeFromIframeString(rawText: string) {
-    // if rawText is iframe text
-    if (rawText.startsWith('<iframe')) {
-      return [
-        {
-          ...HTMLShape.defaultProps,
-          html: rawText,
-          point: [point[0], point[1]],
-        },
-      ]
-    }
-    return null
-  }
-
-  async function tryCreateLogseqPortalShapesFromUUID(rawText: string) {
-    if (/^\(\(.*\)\)$/.test(rawText) && rawText.length === NIL_UUID.length + 4) {
-      const blockRef = rawText.slice(2, -2)
-      if (validUUID(blockRef)) {
-        return [
-          {
-            ...LogseqPortalShape.defaultProps,
-            point: [point[0], point[1]],
-            size: [400, 0], // use 0 here to enable auto-resize
-            pageId: blockRef,
-            fill: app.settings.color,
-            stroke: app.settings.color,
-            scaleLevel: app.settings.scaleLevel,
-            blockType: 'B' as 'B',
-          },
-        ]
-      }
-    }
-    // [[page name]] ?
-    else if (/^\[\[.*\]\]$/.test(rawText)) {
-      const pageName = rawText.slice(2, -2)
-      return [
-        {
-          ...LogseqPortalShape.defaultProps,
-          point: [point[0], point[1]],
-          size: [400, 0], // use 0 here to enable auto-resize
-          pageId: pageName,
-          fill: app.settings.color,
-          stroke: app.settings.color,
-          scaleLevel: app.settings.scaleLevel,
-          blockType: 'P' as 'P',
-        },
-      ]
-    }
-
-    return null
-  }
-
-  async function tryCreateLogseqPortalShapesFromString(item: DataTransfer | ClipboardItem) {
-    const rawText = await getDataFromType(item, 'text/plain')
-    if (rawText) {
-      const text = rawText.trim()
-      // Create a new block that belongs to the current whiteboard
-      const uuid = await handlers?.addNewBlock(text)
-      if (uuid) {
-        // create text shape
-        return [
-          {
-            ...LogseqPortalShape.defaultProps,
-            size: [400, 0], // use 0 here to enable auto-resize
-            point: [point[0], point[1]],
-            pageId: uuid,
-            fill: app.settings.color,
-            stroke: app.settings.color,
-            scaleLevel: app.settings.scaleLevel,
-            blockType: 'B' as 'B',
-            compact: true,
-          },
-        ]
-      }
-    }
-
-    return null
-  }
-
-  app.cursors.setCursor(TLCursor.Progress)
-
-  let newShapes: TLShapeModel[] = []
-  try {
-    if (dataTransfer) {
-      newShapes.push(...((await tryCreateShapesFromDataTransfer(dataTransfer)) ?? []))
-    } else {
-      // from Clipboard app or Shift copy etc
-      // in this case, we do not have the dataTransfer object
-      newShapes.push(...((await tryCreateShapesFromClipboard()) ?? []))
-    }
-  } catch (error) {
-    console.error(error)
-  }
-
-  const allShapesToAdd: TLShapeModel<Shape['props']>[] = newShapes.map(shape => {
-    return {
-      ...shape,
-      parentId: app.currentPageId,
-      isLocked: false,
-      id: validUUID(shape.id) ? shape.id : uniqueId(),
-    }
-  })
-
-  const filesOnly = dataTransfer?.types.every(t => t === 'Files')
-
-  app.wrapUpdate(() => {
-    const allAssets = [...imageAssetsToCreate, ...assetsToClone]
-    if (allAssets.length > 0) {
-      app.createAssets(allAssets)
-    }
-    if (allShapesToAdd.length > 0) {
-      app.createShapes(allShapesToAdd)
-    }
-    app.currentPage.updateBindings(Object.fromEntries(bindingsToCreate.map(b => [b.id, b])))
-
-    if (app.selectedShapesArray.length === 1 && allShapesToAdd.length === 1 && fromDrop) {
-      const source = app.selectedShapesArray[0]
-      const target = app.getShapeById(allShapesToAdd[0].id!)!
-      app.createNewLineBinding(source, target)
-    }
-
-    app.setSelectedShapes(allShapesToAdd.map(s => s.id))
-    app.selectedTool.transition('idle') // clears possible editing states
-    app.cursors.setCursor(TLCursor.Default)
-
-    if (fromDrop || filesOnly) {
-      app.packIntoRectangle()
-    }
-  })
-}
-
-// FIXME: for assets, we should prompt the user a loading spinner
-export function usePaste() {
-  const { handlers } = React.useContext(LogseqContext)
-
-  return React.useCallback<TLReactCallbacks<Shape>['onPaste']>(async (app, info) => {
-    // there is a special case for SHIFT+PASTE
-    // it will set the link to the current selected shape
-
-    if (info.shiftKey && app.selectedShapesArray.length === 1) {
-      // TODO: thinking about how to make this more generic with usePaste hook
-      // TODO: handle whiteboard shapes?
-      const items = await navigator.clipboard.read()
-      let newRef: string | undefined
-      if (items.length > 0) {
-        const blob = await items[0].getType('text/plain')
-        const rawText = (await blob.text()).trim()
-
-        if (rawText) {
-          if (/^\(\(.*\)\)$/.test(rawText) && rawText.length === NIL_UUID.length + 4) {
-            const blockRef = rawText.slice(2, -2)
-            if (validUUID(blockRef)) {
-              newRef = blockRef
-            }
-          } else if (/^\[\[.*\]\]$/.test(rawText)) {
-            newRef = rawText.slice(2, -2)
-          }
-        }
-      }
-      if (newRef) {
-        app.selectedShapesArray[0].update({
-          refs: [newRef],
-        })
-        app.persist()
-        return
-      }
-      // fall through to creating shapes
-    }
-
-    handleCreatingShapes(app, info, handlers)
-  }, [])
-}

+ 0 - 12
packages/tldraw/apps/tldraw-logseq/src/hooks/useQuickAdd.ts

@@ -1,12 +0,0 @@
-import type { TLReactCallbacks } from '@tldraw/react'
-import React from 'react'
-import type { Shape } from '../lib'
-
-export function useQuickAdd() {
-  return React.useCallback<TLReactCallbacks<Shape>['onCanvasDBClick']>(async app => {
-    // Give a timeout so that the quick add input will not be blurred too soon
-    setTimeout(() => {
-      app.transition('logseq-portal').selectedTool.transition('creating')
-    }, 100)
-  }, [])
-}

+ 0 - 18
packages/tldraw/apps/tldraw-logseq/src/index.ts

@@ -1,18 +0,0 @@
-export * from './app'
-export * from './lib/preview-manager'
-
-declare global {
-  interface Window {
-    logseq?: {
-      api?: {
-        make_asset_url?: (url: string) => string
-        get_page_blocks_tree?: (pageName: string) => any[]
-        edit_block?: (uuid: string) => void
-        set_blocks_id?: (uuids: string[]) => void
-        open_external_link?: (url: string) => void
-        get_selected_blocks?: () => { uuid: string }[]
-        get_state_from_store?: (path: string) => any
-      }
-    }
-  }
-}

+ 0 - 3
packages/tldraw/apps/tldraw-logseq/src/lib/index.ts

@@ -1,3 +0,0 @@
-export * from './shapes'
-export * from './tools'
-export * from './preview-manager'

+ 0 - 70
packages/tldraw/apps/tldraw-logseq/src/lib/logseq-context.ts

@@ -1,70 +0,0 @@
-import React from 'react'
-
-export interface SearchResult {
-  pages?: string[]
-  blocks?: { content: string; page: number; uuid: string }[]
-  files?: string[]
-}
-
-export interface LogseqContextValue {
-  renderers: {
-    Page: React.FC<{
-      pageName: string
-    }>
-    Block: React.FC<{
-      blockId: string
-    }>
-    Breadcrumb: React.FC<{
-      blockId: string
-      levelLimit?: number
-      endSeparator?: boolean
-    }>
-    Tweet: React.FC<{
-      tweetId: string
-    }>
-    PageName: React.FC<{
-      pageName: string
-    }>
-    BlockReference: React.FC<{
-      blockId: string
-    }>
-    BacklinksCount: React.FC<{
-      id: string
-      className?: string
-      options?: {
-        'portal?'?: boolean
-        'hover?'?: boolean
-        renderFn?: (open?: boolean, count?: number) => React.ReactNode
-      }
-    }>
-    KeyboardShortcut: React.FC<{
-      action?: string,
-      shortcut?: string,
-      opts?: any
-    }>
-  }
-  handlers: {
-    t: (key: string) => any
-    search: (
-      query: string,
-      filters: { 'pages?': boolean; 'blocks?': boolean; 'files?': boolean }
-    ) => Promise<SearchResult>
-    addNewWhiteboard: (pageName: string) => void
-    exportToImage: (pageName: string, options: object) => void
-    addNewBlock: (content: string) => string // returns the new block uuid
-    queryBlockByUUID: (uuid: string) => any
-    getBlockPageName: (uuid: string) => string
-    getRedirectPageName: (uuidOrPageName: string) => string
-    isWhiteboardPage: (pageName: string) => boolean
-    isMobile: () => boolean
-    saveAsset: (file: File) => Promise<string>
-    makeAssetUrl: (relativeUrl: string | null) => string
-    inflateAsset: (src: string) => object
-    setCurrentPdf: (src: string | null) => void
-    sidebarAddBlock: (uuid: string, type: 'block' | 'page') => void
-    redirectToPage: (uuidOrPageName: string) => void
-    copyToClipboard: (text: string, html: string) => void
-  }
-}
-
-export const LogseqContext = React.createContext<LogseqContextValue>({} as LogseqContextValue)

+ 0 - 148
packages/tldraw/apps/tldraw-logseq/src/lib/preview-manager.tsx

@@ -1,148 +0,0 @@
-import { BoundsUtils, TLAsset, TLDocumentModel, TLShapeConstructor, TLViewport } from '@tldraw/core'
-import ReactDOMServer from 'react-dom/server'
-import { Shape, shapes } from './shapes'
-
-const SVG_EXPORT_PADDING = 16
-
-const ShapesMap = new Map(shapes.map(shape => [shape.id, shape]))
-
-const getShapeClass = (type: string): TLShapeConstructor<Shape> => {
-  if (!type) throw Error('No shape type provided.')
-  const Shape = ShapesMap.get(type)
-  if (!Shape) throw Error(`Could not find shape class for ${type}`)
-  return Shape
-}
-
-export class PreviewManager {
-  shapes: Shape[] | undefined
-  pageId: string | undefined
-  assets: TLAsset[] | undefined
-  constructor(serializedApp?: TLDocumentModel<Shape>) {
-    if (serializedApp) {
-      this.load(serializedApp)
-    }
-  }
-
-  load(snapshot: TLDocumentModel) {
-    const page = snapshot?.pages?.[0]
-    this.pageId = page?.id
-    this.assets = snapshot.assets
-    this.shapes = page?.shapes
-      .map(s => {
-        const ShapeClass = getShapeClass(s.type)
-        return new ShapeClass(s)
-      })
-      // do not need to render group shape because it is invisible in preview
-      .filter(s => s.type !== 'group')
-  }
-
-  generatePreviewJsx(viewport?: TLViewport, ratio?: number) {
-    const allBounds = [...(this.shapes ?? []).map(s => s.getRotatedBounds())]
-    const vBounds = viewport?.currentView
-    if (vBounds) {
-      allBounds.push(vBounds)
-    }
-    let commonBounds = BoundsUtils.getCommonBounds(allBounds)
-    if (!commonBounds) {
-      return null
-    }
-
-    commonBounds = BoundsUtils.expandBounds(commonBounds, SVG_EXPORT_PADDING)
-
-    // make sure commonBounds is of ratio 4/3 (should we have another ratio setting?)
-    commonBounds = ratio ? BoundsUtils.ensureRatio(commonBounds, ratio) : commonBounds
-
-    const translatePoint = (p: [number, number]): [string, string] => {
-      return [(p[0] - commonBounds.minX).toFixed(2), (p[1] - commonBounds.minY).toFixed(2)]
-    }
-
-    const [vx, vy] = vBounds ? translatePoint([vBounds.minX, vBounds.minY]) : [0, 0]
-
-    const svgElement = commonBounds && (
-      <svg
-        xmlns="http://www.w3.org/2000/svg"
-        data-common-bound-x={commonBounds.minX.toFixed(2)}
-        data-common-bound-y={commonBounds.minY.toFixed(2)}
-        data-common-bound-width={commonBounds.width.toFixed(2)}
-        data-common-bound-height={commonBounds.height.toFixed(2)}
-        viewBox={[0, 0, commonBounds.width, commonBounds.height].join(' ')}
-      >
-        <defs>
-          {vBounds && (
-            <>
-              <rect
-                id={this.pageId + '-camera-rect'}
-                transform={`translate(${vx}, ${vy})`}
-                width={vBounds.width}
-                height={vBounds.height}
-              />
-              <mask id={this.pageId + '-camera-mask'}>
-                <rect width={commonBounds.width} height={commonBounds.height} fill="white" />
-                <use href={`#${this.pageId}-camera-rect`} fill="black" />
-              </mask>
-            </>
-          )}
-        </defs>
-        <g id={this.pageId + '-preview-shapes'}>
-          {this.shapes?.map(s => {
-            const {
-              bounds,
-              props: { rotation },
-            } = s
-            const [tx, ty] = translatePoint([bounds.minX, bounds.minY])
-            const r = +((((rotation ?? 0) + (bounds.rotation ?? 0)) * 180) / Math.PI).toFixed(2)
-            const [rdx, rdy] = [(bounds.width / 2).toFixed(2), (bounds.height / 2).toFixed(2)]
-            const transformArr = [`translate(${tx}, ${ty})`, `rotate(${r}, ${rdx}, ${rdy})`]
-            return (
-              <g transform={transformArr.join(' ')} key={s.id}>
-                {s.getShapeSVGJsx({
-                  assets: this.assets ?? [],
-                })}
-              </g>
-            )
-          })}
-        </g>
-        <rect
-          mask={vBounds ? `url(#${this.pageId}-camera-mask)` : ''}
-          width={commonBounds.width}
-          height={commonBounds.height}
-          fill="transparent"
-        />
-        {vBounds && (
-          <use
-            id="minimap-camera-rect"
-            data-x={vx}
-            data-y={vy}
-            data-width={vBounds.width}
-            data-height={vBounds.height}
-            href={`#${this.pageId}-camera-rect`}
-            fill="transparent"
-            stroke="red"
-            strokeWidth={4 / viewport.camera.zoom}
-          />
-        )}
-      </svg>
-    )
-    return svgElement
-  }
-
-  exportAsSVG(ratio: number) {
-    const svgElement = this.generatePreviewJsx(undefined, ratio)
-    return svgElement ? ReactDOMServer.renderToString(svgElement) : ''
-  }
-}
-
-/**
- * One off helper to generate tldraw preview
- *
- * @param serializedApp
- */
-export function generateSVGFromModel(serializedApp: TLDocumentModel<Shape>, ratio = 4 / 3) {
-  const preview = new PreviewManager(serializedApp)
-  return preview.exportAsSVG(ratio)
-}
-
-export function generateJSXFromModel(serializedApp: TLDocumentModel<Shape>, ratio = 4 / 3) {
-  const preview = new PreviewManager(serializedApp)
-  return preview.generatePreviewJsx(undefined, ratio)
-}

+ 0 - 32
packages/tldraw/apps/tldraw-logseq/src/lib/shapes/BindingIndicator.tsx

@@ -1,32 +0,0 @@
-interface BindingIndicatorProps {
-  strokeWidth: number
-  size: number[]
-  mode: 'svg' | 'html'
-}
-export function BindingIndicator({ strokeWidth, size, mode }: BindingIndicatorProps) {
-  return mode === 'svg' ? (
-    <rect
-      className="tl-binding-indicator"
-      x={strokeWidth}
-      y={strokeWidth}
-      rx={2}
-      ry={2}
-      width={Math.max(0, size[0] - strokeWidth * 2)}
-      height={Math.max(0, size[1] - strokeWidth * 2)}
-      strokeWidth={strokeWidth * 4}
-    />
-  ) : (
-    <div
-      className="tl-binding-indicator"
-      style={{
-        position: 'absolute',
-        left: 0,
-        top: 0,
-        right: 0,
-        bottom: 0,
-        boxShadow: '0 0 0 4px var(--tl-binding)',
-        borderRadius: 4,
-      }}
-    />
-  )
-}

+ 0 - 195
packages/tldraw/apps/tldraw-logseq/src/lib/shapes/BoxShape.tsx

@@ -1,195 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import { SVGContainer, TLComponentProps } from '@tldraw/react'
-import { TLBoxShape, TLBoxShapeProps, getComputedColor, getTextLabelSize } from '@tldraw/core'
-import Vec from '@tldraw/vec'
-import * as React from 'react'
-import { observer } from 'mobx-react-lite'
-import { CustomStyleProps, withClampedStyles } from './style-props'
-import { BindingIndicator } from './BindingIndicator'
-import { TextLabel } from './text/TextLabel'
-import type { SizeLevel } from '.'
-import { action, computed } from 'mobx'
-
-export interface BoxShapeProps extends TLBoxShapeProps, CustomStyleProps {
-  borderRadius: number
-  type: 'box'
-  label: string
-  fontSize: number
-  fontWeight: number
-  italic: boolean
-  scaleLevel?: SizeLevel
-}
-
-const font = '20px / 1 var(--ls-font-family)'
-
-const levelToScale = {
-  xs: 10,
-  sm: 16,
-  md: 20,
-  lg: 32,
-  xl: 48,
-  xxl: 60,
-}
-
-export class BoxShape extends TLBoxShape<BoxShapeProps> {
-  static id = 'box'
-
-  static defaultProps: BoxShapeProps = {
-    id: 'box',
-    parentId: 'page',
-    type: 'box',
-    point: [0, 0],
-    size: [100, 100],
-    borderRadius: 2,
-    stroke: '',
-    fill: '',
-    noFill: false,
-    fontWeight: 400,
-    fontSize: 20,
-    italic: false,
-    strokeType: 'line',
-    strokeWidth: 2,
-    opacity: 1,
-    label: '',
-  }
-
-  canEdit = true
-
-  ReactComponent = observer(
-    ({ events, isErasing, isBinding, isSelected, isEditing, onEditingEnd }: TLComponentProps) => {
-      const {
-        props: {
-          size: [w, h],
-          stroke,
-          fill,
-          noFill,
-          strokeWidth,
-          strokeType,
-          borderRadius,
-          opacity,
-          label,
-          italic,
-          fontWeight,
-          fontSize,
-        },
-      } = this
-
-      const labelSize =
-        label || isEditing
-          ? getTextLabelSize(
-              label,
-              { fontFamily: 'var(--ls-font-family)', fontSize, lineHeight: 1, fontWeight },
-              4
-            )
-          : [0, 0]
-      const midPoint = Vec.mul(this.props.size, 0.5)
-      const scale = Math.max(0.5, Math.min(1, w / labelSize[0], h / labelSize[1]))
-      const bounds = this.getBounds()
-
-      const offset = React.useMemo(() => {
-        return Vec.sub(midPoint, Vec.toFixed([bounds.width / 2, bounds.height / 2]))
-      }, [bounds, scale, midPoint])
-
-      const handleLabelChange = React.useCallback(
-        (label: string) => {
-          this.update?.({ label })
-        },
-        [label]
-      )
-
-      return (
-        <div
-          {...events}
-          style={{ width: '100%', height: '100%', overflow: 'hidden' }}
-          className="tl-box-container"
-        >
-          <TextLabel
-            font={font}
-            text={label}
-            color={getComputedColor(stroke, 'text')}
-            offsetX={offset[0]}
-            offsetY={offset[1]}
-            fontSize={fontSize}
-            scale={scale}
-            isEditing={isEditing}
-            onChange={handleLabelChange}
-            onBlur={onEditingEnd}
-            fontStyle={italic ? 'italic' : 'normal'}
-            fontWeight={fontWeight}
-            pointerEvents={!!label}
-          />
-          <SVGContainer opacity={isErasing ? 0.2 : opacity}>
-            {isBinding && <BindingIndicator mode="svg" strokeWidth={strokeWidth} size={[w, h]} />}
-            <rect
-              className={isSelected || !noFill ? 'tl-hitarea-fill' : 'tl-hitarea-stroke'}
-              x={strokeWidth / 2}
-              y={strokeWidth / 2}
-              rx={borderRadius}
-              ry={borderRadius}
-              width={Math.max(0.01, w - strokeWidth)}
-              height={Math.max(0.01, h - strokeWidth)}
-              pointerEvents="all"
-            />
-            <rect
-              x={strokeWidth / 2}
-              y={strokeWidth / 2}
-              rx={borderRadius}
-              ry={borderRadius}
-              width={Math.max(0.01, w - strokeWidth)}
-              height={Math.max(0.01, h - strokeWidth)}
-              strokeWidth={strokeWidth}
-              stroke={getComputedColor(stroke, 'stroke')}
-              strokeDasharray={strokeType === 'dashed' ? '8 2' : undefined}
-              fill={noFill ? 'none' : getComputedColor(fill, 'background')}
-            />
-          </SVGContainer>
-        </div>
-      )
-    }
-  )
-
-  @computed get scaleLevel() {
-    return this.props.scaleLevel ?? 'md'
-  }
-
-  @action setScaleLevel = async (v?: SizeLevel) => {
-    this.update({
-      scaleLevel: v,
-      fontSize: levelToScale[v ?? 'md'],
-      strokeWidth: levelToScale[v ?? 'md'] / 10,
-    })
-    this.onResetBounds()
-  }
-
-  ReactIndicator = observer(() => {
-    const {
-      props: {
-        size: [w, h],
-        borderRadius,
-        isLocked,
-      },
-    } = this
-
-    return (
-      <g>
-        <rect
-          width={w}
-          height={h}
-          rx={borderRadius}
-          ry={borderRadius}
-          fill="transparent"
-          strokeDasharray={isLocked ? '8 2' : undefined}
-        />
-      </g>
-    )
-  })
-
-  validateProps = (props: Partial<BoxShapeProps>) => {
-    if (props.size !== undefined) {
-      props.size[0] = Math.max(props.size[0], 1)
-      props.size[1] = Math.max(props.size[1], 1)
-    }
-    if (props.borderRadius !== undefined) props.borderRadius = Math.max(0, props.borderRadius)
-    return withClampedStyles(this, props)
-  }
-}

+ 0 - 62
packages/tldraw/apps/tldraw-logseq/src/lib/shapes/DotShape.tsx

@@ -1,62 +0,0 @@
-import { TLDotShape, TLDotShapeProps } from '@tldraw/core'
-import { SVGContainer, TLComponentProps } from '@tldraw/react'
-import { observer } from 'mobx-react-lite'
-import { CustomStyleProps, withClampedStyles } from './style-props'
-
-export interface DotShapeProps extends TLDotShapeProps, CustomStyleProps {
-  type: 'dot'
-}
-
-export class DotShape extends TLDotShape<DotShapeProps> {
-  static id = 'dot'
-
-  static defaultProps: DotShapeProps = {
-    id: 'dot',
-    parentId: 'page',
-    type: 'dot',
-    point: [0, 0],
-    radius: 4,
-    stroke: '#000000',
-    fill: 'var(--ls-secondary-background-color)',
-    noFill: false,
-    strokeType: 'line',
-    strokeWidth: 2,
-    opacity: 1,
-  }
-
-  ReactComponent = observer(({ events, isErasing }: TLComponentProps) => {
-    const { radius, stroke, fill, strokeWidth, opacity } = this.props
-    return (
-      <SVGContainer {...events} opacity={isErasing ? 0.2 : opacity}>
-        <circle className="tl-hitarea-fill" cx={radius} cy={radius} r={radius} />
-        <circle
-          cx={radius}
-          cy={radius}
-          r={radius}
-          stroke={stroke}
-          fill={fill}
-          strokeWidth={strokeWidth}
-          pointerEvents="none"
-        />
-      </SVGContainer>
-    )
-  })
-
-  ReactIndicator = observer(() => {
-    const { radius, isLocked } = this.props
-    return (
-      <circle
-        cx={radius}
-        cy={radius}
-        r={radius}
-        pointerEvents="all"
-        strokeDasharray={isLocked ? '8 2' : 'undefined'}
-      />
-    )
-  })
-
-  validateProps = (props: Partial<DotShapeProps>) => {
-    if (props.radius !== undefined) props.radius = Math.max(props.radius, 1)
-    return withClampedStyles(this, props)
-  }
-}

+ 0 - 223
packages/tldraw/apps/tldraw-logseq/src/lib/shapes/EllipseShape.tsx

@@ -1,223 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import {
-  TLEllipseShapeProps,
-  TLEllipseShape,
-  getComputedColor,
-  getTextLabelSize,
-} from '@tldraw/core'
-import { SVGContainer, TLComponentProps } from '@tldraw/react'
-import Vec from '@tldraw/vec'
-import * as React from 'react'
-import { observer } from 'mobx-react-lite'
-import { CustomStyleProps, withClampedStyles } from './style-props'
-import { TextLabel } from './text/TextLabel'
-import type { SizeLevel } from '.'
-import { action, computed } from 'mobx'
-
-export interface EllipseShapeProps extends TLEllipseShapeProps, CustomStyleProps {
-  type: 'ellipse'
-  size: number[]
-  label: string
-  fontSize: number
-  fontWeight: number
-  italic: boolean
-  scaleLevel?: SizeLevel
-}
-
-const font = '18px / 1 var(--ls-font-family)'
-
-const levelToScale = {
-  xs: 10,
-  sm: 16,
-  md: 20,
-  lg: 32,
-  xl: 48,
-  xxl: 60,
-}
-
-export class EllipseShape extends TLEllipseShape<EllipseShapeProps> {
-  static id = 'ellipse'
-
-  static defaultProps: EllipseShapeProps = {
-    id: 'ellipse',
-    parentId: 'page',
-    type: 'ellipse',
-    point: [0, 0],
-    size: [100, 100],
-    stroke: '',
-    fill: '',
-    noFill: false,
-    fontWeight: 400,
-    fontSize: 20,
-    italic: false,
-    strokeType: 'line',
-    strokeWidth: 2,
-    opacity: 1,
-    label: '',
-  }
-
-  canEdit = true
-
-  ReactComponent = observer(
-    ({ isSelected, isErasing, events, isEditing, onEditingEnd }: TLComponentProps) => {
-      const {
-        size: [w, h],
-        stroke,
-        fill,
-        noFill,
-        strokeWidth,
-        strokeType,
-        opacity,
-        label,
-        italic,
-        fontWeight,
-        fontSize,
-      } = this.props
-
-      const labelSize =
-        label || isEditing
-          ? getTextLabelSize(
-              label,
-              { fontFamily: 'var(--ls-font-family)', fontSize, lineHeight: 1, fontWeight },
-              4
-            )
-          : [0, 0]
-      const midPoint = Vec.mul(this.props.size, 0.5)
-      const scale = Math.max(0.5, Math.min(1, w / labelSize[0], h / labelSize[1]))
-      const bounds = this.getBounds()
-
-      const offset = React.useMemo(() => {
-        return Vec.sub(midPoint, Vec.toFixed([bounds.width / 2, bounds.height / 2]))
-      }, [bounds, scale, midPoint])
-
-      const handleLabelChange = React.useCallback(
-        (label: string) => {
-          this.update?.({ label })
-        },
-        [label]
-      )
-
-      return (
-        <div
-          {...events}
-          style={{ width: '100%', height: '100%', overflow: 'hidden' }}
-          className="tl-ellipse-container"
-        >
-          <TextLabel
-            font={font}
-            text={label}
-            color={getComputedColor(stroke, 'text')}
-            offsetX={offset[0]}
-            offsetY={offset[1]}
-            scale={scale}
-            isEditing={isEditing}
-            onChange={handleLabelChange}
-            onBlur={onEditingEnd}
-            fontStyle={italic ? 'italic' : 'normal'}
-            fontSize={fontSize}
-            fontWeight={fontWeight}
-            pointerEvents={!!label}
-          />
-          <SVGContainer {...events} opacity={isErasing ? 0.2 : opacity}>
-            <ellipse
-              className={isSelected || !noFill ? 'tl-hitarea-fill' : 'tl-hitarea-stroke'}
-              cx={w / 2}
-              cy={h / 2}
-              rx={Math.max(0.01, (w - strokeWidth) / 2)}
-              ry={Math.max(0.01, (h - strokeWidth) / 2)}
-            />
-            <ellipse
-              cx={w / 2}
-              cy={h / 2}
-              rx={Math.max(0.01, (w - strokeWidth) / 2)}
-              ry={Math.max(0.01, (h - strokeWidth) / 2)}
-              strokeWidth={strokeWidth}
-              stroke={getComputedColor(stroke, 'stroke')}
-              strokeDasharray={strokeType === 'dashed' ? '8 2' : undefined}
-              fill={noFill ? 'none' : getComputedColor(fill, 'background')}
-            />
-          </SVGContainer>
-        </div>
-      )
-    }
-  )
-
-  @computed get scaleLevel() {
-    return this.props.scaleLevel ?? 'md'
-  }
-
-  @action setScaleLevel = async (v?: SizeLevel) => {
-    this.update({
-      scaleLevel: v,
-      fontSize: levelToScale[v ?? 'md'],
-      strokeWidth: levelToScale[v ?? 'md'] / 10,
-    })
-    this.onResetBounds()
-  }
-
-  ReactIndicator = observer(() => {
-    const {
-      size: [w, h],
-      isLocked,
-    } = this.props
-
-    return (
-      <g>
-        <ellipse
-          cx={w / 2}
-          cy={h / 2}
-          rx={w / 2}
-          ry={h / 2}
-          strokeWidth={2}
-          fill="transparent"
-          strokeDasharray={isLocked ? '8 2' : 'undefined'}
-        />
-      </g>
-    )
-  })
-
-  validateProps = (props: Partial<EllipseShapeProps>) => {
-    if (props.size !== undefined) {
-      props.size[0] = Math.max(props.size[0], 1)
-      props.size[1] = Math.max(props.size[1], 1)
-    }
-    return withClampedStyles(this, props)
-  }
-
-  /**
-   * Get a svg group element that can be used to render the shape with only the props data. In the
-   * base, draw any shape as a box. Can be overridden by subclasses.
-   */
-  getShapeSVGJsx(opts: any) {
-    const {
-      size: [w, h],
-      stroke,
-      fill,
-      noFill,
-      strokeWidth,
-      strokeType,
-      opacity,
-    } = this.props
-    return (
-      <g opacity={opacity}>
-        <ellipse
-          className={!noFill ? 'tl-hitarea-fill' : 'tl-hitarea-stroke'}
-          cx={w / 2}
-          cy={h / 2}
-          rx={Math.max(0.01, (w - strokeWidth) / 2)}
-          ry={Math.max(0.01, (h - strokeWidth) / 2)}
-        />
-        <ellipse
-          cx={w / 2}
-          cy={h / 2}
-          rx={Math.max(0.01, (w - strokeWidth) / 2)}
-          ry={Math.max(0.01, (h - strokeWidth) / 2)}
-          strokeWidth={strokeWidth}
-          stroke={getComputedColor(stroke, 'stroke')}
-          strokeDasharray={strokeType === 'dashed' ? '8 2' : undefined}
-          fill={noFill ? 'none' : getComputedColor(fill, 'background')}
-        />
-      </g>
-    )
-  }
-}

+ 0 - 65
packages/tldraw/apps/tldraw-logseq/src/lib/shapes/GroupShape.tsx

@@ -1,65 +0,0 @@
-import { GROUP_PADDING, TLGroupShape, TLGroupShapeProps } from '@tldraw/core'
-import { SVGContainer, TLComponentProps, useApp } from '@tldraw/react'
-import { observer } from 'mobx-react-lite'
-
-export interface GroupShapeProps extends TLGroupShapeProps {}
-
-export class GroupShape extends TLGroupShape<GroupShapeProps> {
-  static id = 'group'
-
-  static defaultProps: GroupShapeProps = {
-    id: 'group',
-    type: 'group',
-    parentId: 'page',
-    point: [0, 0],
-    size: [0, 0],
-    children: [],
-  }
-
-  // TODO: add styles for arrow binding states
-  ReactComponent = observer(({ events }: TLComponentProps) => {
-    const strokeWidth = 2
-    const bounds = this.getBounds()
-    const app = useApp()
-
-    const childSelected = app.selectedShapesArray.some(s => {
-      return app.shapesInGroups([this]).includes(s)
-    })
-
-    const Indicator = this.ReactIndicator
-
-    return (
-      <SVGContainer {...events} className="tl-group-container">
-        <rect
-          className={'tl-hitarea-fill'}
-          x={strokeWidth / 2}
-          y={strokeWidth / 2}
-          width={Math.max(0.01, bounds.width - strokeWidth)}
-          height={Math.max(0.01, bounds.height - strokeWidth)}
-          pointerEvents="all"
-        />
-        {childSelected && (
-          <g stroke="var(--color-selectedFill)">
-            <Indicator />
-          </g>
-        )}
-      </SVGContainer>
-    )
-  })
-
-  ReactIndicator = observer(() => {
-    const bounds = this.getBounds()
-    return (
-      <rect
-        strokeDasharray="8 2"
-        x={-GROUP_PADDING}
-        y={-GROUP_PADDING}
-        rx={GROUP_PADDING / 2}
-        ry={GROUP_PADDING / 2}
-        width={bounds.width + GROUP_PADDING * 2}
-        height={bounds.height + GROUP_PADDING * 2}
-        fill="transparent"
-      />
-    )
-  })
-}

+ 0 - 159
packages/tldraw/apps/tldraw-logseq/src/lib/shapes/HTMLShape.tsx

@@ -1,159 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import { delay, TLBoxShape, TLBoxShapeProps, TLResetBoundsInfo } from '@tldraw/core'
-import { HTMLContainer, TLComponentProps, useApp } from '@tldraw/react'
-import Vec from '@tldraw/vec'
-import { action, computed } from 'mobx'
-import { observer } from 'mobx-react-lite'
-import * as React from 'react'
-import type { SizeLevel, Shape } from '.'
-import { useCameraMovingRef } from '../../hooks/useCameraMoving'
-import { withClampedStyles } from './style-props'
-
-export interface HTMLShapeProps extends TLBoxShapeProps {
-  type: 'html'
-  html: string
-  scaleLevel?: SizeLevel
-}
-
-const levelToScale = {
-  xs: 0.5,
-  sm: 0.8,
-  md: 1,
-  lg: 1.5,
-  xl: 2,
-  xxl: 3,
-}
-
-export class HTMLShape extends TLBoxShape<HTMLShapeProps> {
-  static id = 'html'
-
-  static defaultProps: HTMLShapeProps = {
-    id: 'html',
-    type: 'html',
-    parentId: 'page',
-    point: [0, 0],
-    size: [600, 0],
-    html: '',
-  }
-
-  canChangeAspectRatio = true
-  canFlip = false
-  canEdit = true
-  htmlAnchorRef = React.createRef<HTMLDivElement>()
-
-  @computed get scaleLevel() {
-    return this.props.scaleLevel ?? 'md'
-  }
-
-  @action setScaleLevel = async (v?: SizeLevel) => {
-    const newSize = Vec.mul(
-      this.props.size,
-      levelToScale[(v as SizeLevel) ?? 'md'] / levelToScale[this.props.scaleLevel ?? 'md']
-    )
-    this.update({
-      scaleLevel: v,
-    })
-    await delay()
-    this.update({
-      size: newSize,
-    })
-  }
-
-  onResetBounds = (info?: TLResetBoundsInfo) => {
-    if (this.htmlAnchorRef.current) {
-      const rect = this.htmlAnchorRef.current.getBoundingClientRect()
-      const [w, h] = Vec.div([rect.width, rect.height], info?.zoom ?? 1)
-      const clamp = (v: number) => Math.max(Math.min(v || 400, 1400), 10)
-      this.update({
-        size: [clamp(w), clamp(h)],
-      })
-    }
-    return this
-  }
-
-  ReactComponent = observer(({ events, isErasing, isEditing }: TLComponentProps) => {
-    const {
-      props: { html, scaleLevel },
-    } = this
-    const isMoving = useCameraMovingRef()
-    const app = useApp<Shape>()
-    const isSelected = app.selectedIds.has(this.id)
-
-    const tlEventsEnabled =
-      isMoving || (isSelected && !isEditing) || app.selectedTool.id !== 'select'
-    const stop = React.useCallback(
-      e => {
-        if (!tlEventsEnabled) {
-          // TODO: pinching inside Logseq Shape issue
-          e.stopPropagation()
-        }
-      },
-      [tlEventsEnabled]
-    )
-
-    const scaleRatio = levelToScale[scaleLevel ?? 'md']
-
-    React.useEffect(() => {
-      if (this.props.size[1] === 0) {
-        this.onResetBounds({ zoom: app.viewport.camera.zoom })
-        app.persist()
-      }
-    }, [])
-
-    return (
-      <HTMLContainer
-        style={{
-          overflow: 'hidden',
-          pointerEvents: 'all',
-          opacity: isErasing ? 0.2 : 1,
-        }}
-        {...events}
-      >
-        <div
-          onWheelCapture={stop}
-          onPointerDown={stop}
-          onPointerUp={stop}
-          className="tl-html-container"
-          style={{
-            pointerEvents: !isMoving && (isEditing || isSelected) ? 'all' : 'none',
-            overflow: isEditing ? 'auto' : 'hidden',
-            width: `calc(100% / ${scaleRatio})`,
-            height: `calc(100% / ${scaleRatio})`,
-            transform: `scale(${scaleRatio})`,
-          }}
-        >
-          <div
-            ref={this.htmlAnchorRef}
-            className="tl-html-anchor"
-            dangerouslySetInnerHTML={{ __html: html.trim() }}
-          />
-        </div>
-      </HTMLContainer>
-    )
-  })
-
-  ReactIndicator = observer(() => {
-    const {
-      props: {
-        size: [w, h],
-        isLocked,
-      },
-    } = this
-    return (
-      <rect
-        width={w}
-        height={h}
-        fill="transparent"
-        strokeDasharray={isLocked ? '8 2' : 'undefined'}
-      />
-    )
-  })
-
-  validateProps = (props: Partial<HTMLShapeProps>) => {
-    if (props.size !== undefined) {
-      props.size[0] = Math.max(props.size[0], 1)
-      props.size[1] = Math.max(props.size[1], 1)
-    }
-    return withClampedStyles(this, props)
-  }
-}

+ 0 - 116
packages/tldraw/apps/tldraw-logseq/src/lib/shapes/HighlighterShape.tsx

@@ -1,116 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import { SvgPathUtils, TLDrawShape, TLDrawShapeProps, getComputedColor } from '@tldraw/core'
-import { SVGContainer, TLComponentProps } from '@tldraw/react'
-import { observer } from 'mobx-react-lite'
-import { action, computed, makeObservable } from 'mobx'
-import type { SizeLevel } from '.'
-import { CustomStyleProps, withClampedStyles } from './style-props'
-
-export interface HighlighterShapeProps extends TLDrawShapeProps, CustomStyleProps {
-  type: 'highlighter'
-  scaleLevel?: SizeLevel
-}
-
-const levelToScale = {
-  xs: 1,
-  sm: 1.6,
-  md: 2,
-  lg: 3.2,
-  xl: 4.8,
-  xxl: 6,
-}
-
-export class HighlighterShape extends TLDrawShape<HighlighterShapeProps> {
-  constructor(props = {} as Partial<HighlighterShapeProps>) {
-    super(props)
-    makeObservable(this)
-  }
-
-  static id = 'highlighter'
-
-  static defaultProps: HighlighterShapeProps = {
-    id: 'highlighter',
-    parentId: 'page',
-    type: 'highlighter',
-    point: [0, 0],
-    points: [],
-    isComplete: false,
-    stroke: '',
-    fill: '',
-    noFill: true,
-    strokeType: 'line',
-    strokeWidth: 2,
-    opacity: 0.5,
-  }
-
-  @computed get pointsPath() {
-    const { points } = this.props
-    return SvgPathUtils.getCurvedPathForPoints(points)
-  }
-
-  ReactComponent = observer(({ events, isErasing }: TLComponentProps) => {
-    const {
-      pointsPath,
-      props: { stroke, strokeWidth, opacity },
-    } = this
-
-    return (
-      <SVGContainer {...events} opacity={isErasing ? 0.2 : 1}>
-        <path
-          d={pointsPath}
-          strokeWidth={strokeWidth * 16}
-          stroke={getComputedColor(stroke, 'stroke')}
-          fill="none"
-          pointerEvents="all"
-          strokeLinejoin="round"
-          strokeLinecap="round"
-          opacity={opacity}
-        />
-      </SVGContainer>
-    )
-  })
-
-  @computed get scaleLevel() {
-    return this.props.scaleLevel ?? 'md'
-  }
-
-  @action setScaleLevel = async (v?: SizeLevel) => {
-    this.update({
-      scaleLevel: v,
-      strokeWidth: levelToScale[v ?? 'md'],
-    })
-    this.onResetBounds()
-  }
-
-  ReactIndicator = observer(() => {
-    const { pointsPath, props } = this
-    return (
-      <path d={pointsPath} fill="none" strokeDasharray={props.isLocked ? '8 2' : 'undefined'} />
-    )
-  })
-
-  validateProps = (props: Partial<HighlighterShapeProps>) => {
-    props = withClampedStyles(this, props)
-    if (props.strokeWidth !== undefined) props.strokeWidth = Math.max(props.strokeWidth, 1)
-    return props
-  }
-
-  getShapeSVGJsx() {
-    const {
-      pointsPath,
-      props: { stroke, strokeWidth, opacity },
-    } = this
-    return (
-      <path
-        d={pointsPath}
-        strokeWidth={strokeWidth * 16}
-        stroke={getComputedColor(stroke, 'stroke')}
-        fill="none"
-        pointerEvents="all"
-        strokeLinejoin="round"
-        strokeLinecap="round"
-        opacity={opacity}
-      />
-    )
-  }
-}

+ 0 - 100
packages/tldraw/apps/tldraw-logseq/src/lib/shapes/IFrameShape.tsx

@@ -1,100 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import * as React from 'react'
-import { TLBoxShape, TLBoxShapeProps } from '@tldraw/core'
-import { HTMLContainer, TLComponentProps, useApp } from '@tldraw/react'
-import { action } from 'mobx'
-import { observer } from 'mobx-react-lite'
-
-export interface IFrameShapeProps extends TLBoxShapeProps {
-  type: 'iframe'
-  url: string
-}
-
-export class IFrameShape extends TLBoxShape<IFrameShapeProps> {
-  static id = 'iframe'
-  frameRef = React.createRef<HTMLIFrameElement>()
-
-  static defaultProps: IFrameShapeProps = {
-    id: 'iframe',
-    type: 'iframe',
-    parentId: 'page',
-    point: [0, 0],
-    size: [853, 480],
-    url: '',
-  }
-
-  canEdit = true
-
-  @action onIFrameSourceChange = (url: string) => {
-    this.update({ url })
-  }
-
-  @action reload = () => {
-    if (this.frameRef.current) {
-      this.frameRef.current.src = this.frameRef?.current?.src
-    }
-  }
-
-  ReactComponent = observer(({ events, isErasing, isEditing }: TLComponentProps) => {
-    const ref = React.useRef<HTMLIFrameElement>(null)
-    const app = useApp<Shape>()
-
-    return (
-      <HTMLContainer
-        style={{
-          overflow: 'hidden',
-          pointerEvents: 'all',
-          opacity: isErasing ? 0.2 : 1,
-        }}
-        {...events}
-      >
-        <div
-          className="tl-iframe-container"
-          style={{
-            pointerEvents: isEditing || app.readOnly ? 'all' : 'none',
-            userSelect: 'none',
-          }}
-        >
-          {this.props.url && (
-            <div
-              style={{
-                overflow: 'hidden',
-                position: 'relative',
-                height: '100%',
-              }}
-            >
-              <iframe
-                ref={this.frameRef}
-                className="absolute inset-0 w-full h-full m-0"
-                width="100%"
-                height="100%"
-                src={`${this.props.url}`}
-                frameBorder="0"
-                sandbox="allow-scripts allow-same-origin allow-presentation"
-              />
-            </div>
-          )}
-        </div>
-      </HTMLContainer>
-    )
-  })
-
-  ReactIndicator = observer(() => {
-    const {
-      props: {
-        size: [w, h],
-        isLocked,
-      },
-    } = this
-    return (
-      <rect
-        width={w}
-        height={h}
-        fill="transparent"
-        rx={8}
-        ry={8}
-        strokeDasharray={isLocked ? '8 2' : 'undefined'}
-      />
-    )
-  })
-}

+ 0 - 119
packages/tldraw/apps/tldraw-logseq/src/lib/shapes/ImageShape.tsx

@@ -1,119 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import { TLAsset, TLImageShape, TLImageShapeProps } from '@tldraw/core'
-import { HTMLContainer, TLComponentProps } from '@tldraw/react'
-import { observer } from 'mobx-react-lite'
-import * as React from 'react'
-import { LogseqContext } from '../logseq-context'
-import { BindingIndicator } from './BindingIndicator'
-
-export interface ImageShapeProps extends TLImageShapeProps {
-  type: 'image'
-  assetId: string
-  opacity: number
-}
-
-export class ImageShape extends TLImageShape<ImageShapeProps> {
-  static id = 'image'
-
-  static defaultProps: ImageShapeProps = {
-    id: 'image1',
-    parentId: 'page',
-    type: 'image',
-    point: [0, 0],
-    size: [100, 100],
-    opacity: 1,
-    assetId: '',
-    clipping: 0,
-    objectFit: 'fill',
-    isAspectRatioLocked: true,
-  }
-
-  ReactComponent = observer(({ events, isErasing, isBinding, asset }: TLComponentProps) => {
-    const {
-      props: {
-        opacity,
-        objectFit,
-        clipping,
-        size: [w, h],
-      },
-    } = this
-
-    const [t, r, b, l] = Array.isArray(clipping)
-      ? clipping
-      : [clipping, clipping, clipping, clipping]
-
-    const { handlers } = React.useContext(LogseqContext)
-
-    return (
-      <HTMLContainer {...events} opacity={isErasing ? 0.2 : opacity}>
-        {isBinding && <BindingIndicator mode="html" strokeWidth={4} size={[w, h]} />}
-
-        <div data-asset-loaded={!!asset} className="tl-image-shape-container">
-          {asset ? (
-            <img
-              src={handlers ? handlers.makeAssetUrl(asset.src) : asset.src}
-              draggable={false}
-              style={{
-                position: 'relative',
-                top: -t,
-                left: -l,
-                width: w + (l - r),
-                height: h + (t - b),
-                objectFit,
-              }}
-            />
-          ) : (
-            'Asset is missing'
-          )}
-        </div>
-      </HTMLContainer>
-    )
-  })
-
-  ReactIndicator = observer(() => {
-    const {
-      props: {
-        size: [w, h],
-        isLocked,
-      },
-    } = this
-    return (
-      <rect
-        width={w}
-        height={h}
-        fill="transparent"
-        strokeDasharray={isLocked ? '8 2' : 'undefined'}
-      />
-    )
-  })
-
-  getShapeSVGJsx({ assets }: { assets: TLAsset[] }) {
-    // Do not need to consider the original point here
-    const bounds = this.getBounds()
-    const {
-      assetId,
-      clipping,
-      size: [w, h],
-    } = this.props
-    const asset = assets.find(ass => ass.id === assetId)
-
-    if (asset) {
-      // TODO: add clipping
-      const [t, r, b, l] = Array.isArray(clipping)
-        ? clipping
-        : [clipping, clipping, clipping, clipping]
-
-      const make_asset_url = window.logseq?.api?.make_asset_url
-
-      return (
-        <image
-          width={bounds.width}
-          height={bounds.height}
-          href={make_asset_url ? make_asset_url(asset.src) : asset.src}
-        />
-      )
-    } else {
-      return super.getShapeSVGJsx({})
-    }
-  }
-}

+ 0 - 252
packages/tldraw/apps/tldraw-logseq/src/lib/shapes/LineShape.tsx

@@ -1,252 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import { Decoration, TLLineShape, TLLineShapeProps, getComputedColor } from '@tldraw/core'
-import { SVGContainer, TLComponentProps } from '@tldraw/react'
-import Vec from '@tldraw/vec'
-import { observer } from 'mobx-react-lite'
-import * as React from 'react'
-import { Arrow } from './arrow/Arrow'
-import { getArrowPath } from './arrow/arrowHelpers'
-import { CustomStyleProps, withClampedStyles } from './style-props'
-import { getTextLabelSize } from '@tldraw/core'
-import { LabelMask } from './text/LabelMask'
-import { TextLabel } from './text/TextLabel'
-import type { SizeLevel } from '.'
-import { action, computed } from 'mobx'
-
-interface LineShapeProps extends CustomStyleProps, TLLineShapeProps {
-  type: 'line'
-  label: string
-  fontSize: number
-  fontWeight: number
-  italic: boolean
-  scaleLevel?: SizeLevel
-}
-
-const font = '20px / 1 var(--ls-font-family)'
-
-const levelToScale = {
-  xs: 10,
-  sm: 16,
-  md: 20,
-  lg: 32,
-  xl: 48,
-  xxl: 60,
-}
-
-export class LineShape extends TLLineShape<LineShapeProps> {
-  static id = 'line'
-
-  static defaultProps: LineShapeProps = {
-    id: 'line',
-    parentId: 'page',
-    type: 'line',
-    point: [0, 0],
-    handles: {
-      start: { id: 'start', canBind: true, point: [0, 0] },
-      end: { id: 'end', canBind: true, point: [1, 1] },
-    },
-    stroke: '',
-    fill: '',
-    noFill: true,
-    fontWeight: 400,
-    fontSize: 20,
-    italic: false,
-    strokeType: 'line',
-    strokeWidth: 1,
-    opacity: 1,
-    decorations: {
-      end: Decoration.Arrow,
-    },
-    label: '',
-  }
-
-  hideSelection = true
-  canEdit = true
-
-  ReactComponent = observer(({ events, isErasing, isEditing, onEditingEnd }: TLComponentProps) => {
-    const {
-      stroke,
-      handles: { start, end },
-      opacity,
-      label,
-      italic,
-      fontWeight,
-      fontSize,
-      id,
-    } = this.props
-    const labelSize =
-      label || isEditing
-        ? getTextLabelSize(
-            label || 'Enter text',
-            { fontFamily: 'var(--ls-font-family)', fontSize, lineHeight: 1, fontWeight },
-            6
-          )
-        : [0, 0]
-    const midPoint = Vec.med(start.point, end.point)
-    const dist = Vec.dist(start.point, end.point)
-    const scale = Math.max(
-      0.5,
-      Math.min(1, Math.max(dist / (labelSize[1] + 128), dist / (labelSize[0] + 128)))
-    )
-    const bounds = this.getBounds()
-    const offset = React.useMemo(() => {
-      return Vec.sub(midPoint, Vec.toFixed([bounds.width / 2, bounds.height / 2]))
-    }, [bounds, scale, midPoint])
-    const handleLabelChange = React.useCallback(
-      (label: string) => {
-        this.update?.({ label })
-      },
-      [label]
-    )
-    return (
-      <div
-        {...events}
-        style={{ width: '100%', height: '100%', overflow: 'hidden' }}
-        className="tl-line-container"
-      >
-        <TextLabel
-          font={font}
-          text={label}
-          fontSize={fontSize}
-          color={getComputedColor(stroke, 'text')}
-          offsetX={offset[0]}
-          offsetY={offset[1]}
-          scale={scale}
-          isEditing={isEditing}
-          onChange={handleLabelChange}
-          onBlur={onEditingEnd}
-          fontStyle={italic ? 'italic' : 'normal'}
-          fontWeight={fontWeight}
-          pointerEvents={!!label}
-        />
-        <SVGContainer opacity={isErasing ? 0.2 : opacity} id={id + '_svg'}>
-          <LabelMask id={id} bounds={bounds} labelSize={labelSize} offset={offset} scale={scale} />
-          <g pointerEvents="none" mask={label || isEditing ? `url(#${id}_clip)` : ``}>
-            {this.getShapeSVGJsx({ preview: false })}
-          </g>
-        </SVGContainer>
-      </div>
-    )
-  })
-
-  @computed get scaleLevel() {
-    return this.props.scaleLevel ?? 'md'
-  }
-
-  @action setScaleLevel = async (v?: SizeLevel) => {
-    this.update({
-      scaleLevel: v,
-      fontSize: levelToScale[v ?? 'md'],
-    })
-    this.onResetBounds()
-  }
-
-  ReactIndicator = observer(({ isEditing }: TLComponentProps) => {
-    const {
-      id,
-      decorations,
-      label,
-      strokeWidth,
-      fontSize,
-      fontWeight,
-      handles: { start, end },
-      isLocked,
-    } = this.props
-    const bounds = this.getBounds()
-    const labelSize =
-      label || isEditing
-        ? getTextLabelSize(
-            label,
-            { fontFamily: 'var(--ls-font-family)', fontSize, lineHeight: 1, fontWeight },
-            6
-          )
-        : [0, 0]
-    const midPoint = Vec.med(start.point, end.point)
-    const dist = Vec.dist(start.point, end.point)
-    const scale = Math.max(
-      0.5,
-      Math.min(1, Math.max(dist / (labelSize[1] + 128), dist / (labelSize[0] + 128)))
-    )
-    const offset = React.useMemo(() => {
-      return Vec.sub(midPoint, Vec.toFixed([bounds.width / 2, bounds.height / 2]))
-    }, [bounds, scale, midPoint])
-    return (
-      <g>
-        <path
-          mask={label ? `url(#${id}_clip)` : ``}
-          d={getArrowPath(
-            { strokeWidth },
-            start.point,
-            end.point,
-            decorations?.start,
-            decorations?.end
-          )}
-          strokeDasharray={isLocked ? '8 2' : 'undefined'}
-        />
-        {label && !isEditing && (
-          <rect
-            x={bounds.width / 2 - (labelSize[0] / 2) * scale + offset[0]}
-            y={bounds.height / 2 - (labelSize[1] / 2) * scale + offset[1]}
-            width={labelSize[0] * scale}
-            height={labelSize[1] * scale}
-            rx={4 * scale}
-            ry={4 * scale}
-            fill="transparent"
-          />
-        )}
-      </g>
-    )
-  })
-
-  validateProps = (props: Partial<LineShapeProps>) => {
-    return withClampedStyles(this, props)
-  }
-
-  getShapeSVGJsx({ preview }: any) {
-    const {
-      stroke,
-      fill,
-      strokeWidth,
-      strokeType,
-      decorations,
-      label,
-      scaleLevel,
-      handles: { start, end },
-    } = this.props
-    const midPoint = Vec.med(start.point, end.point)
-    return (
-      <>
-        <Arrow
-          style={{
-            stroke: getComputedColor(stroke, 'text'),
-            fill,
-            strokeWidth,
-            strokeType,
-          }}
-          scaleLevel={scaleLevel}
-          start={start.point}
-          end={end.point}
-          decorationStart={decorations?.start}
-          decorationEnd={decorations?.end}
-        />
-        {preview && (
-          <>
-            <text
-              style={{
-                transformOrigin: 'top left',
-              }}
-              fontFamily="Inter"
-              fontSize={20}
-              transform={`translate(${midPoint[0]}, ${midPoint[1]})`}
-              textAnchor="middle"
-              fill={getComputedColor(stroke, 'text')}
-              stroke={getComputedColor(stroke, 'text')}
-            >
-              {label}
-            </text>
-          </>
-        )}
-      </>
-    )
-  }
-}

+ 0 - 605
packages/tldraw/apps/tldraw-logseq/src/lib/shapes/LogseqPortalShape.tsx

@@ -1,605 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import {
-  delay,
-  getComputedColor,
-  TLBoxShape,
-  TLBoxShapeProps,
-  TLResetBoundsInfo,
-  TLResizeInfo,
-  validUUID,
-  isBuiltInColor,
-} from '@tldraw/core'
-import { HTMLContainer, TLComponentProps, useApp } from '@tldraw/react'
-import Vec from '@tldraw/vec'
-import { action, computed, makeObservable } from 'mobx'
-import { observer } from 'mobx-react-lite'
-import * as React from 'react'
-import type { Shape, SizeLevel } from '.'
-import { LogseqQuickSearch } from '../../components/QuickSearch'
-import { useCameraMovingRef } from '../../hooks/useCameraMoving'
-import { LogseqContext } from '../logseq-context'
-import { BindingIndicator } from './BindingIndicator'
-import { CustomStyleProps, withClampedStyles } from './style-props'
-
-const HEADER_HEIGHT = 40
-const AUTO_RESIZE_THRESHOLD = 1
-
-export interface LogseqPortalShapeProps extends TLBoxShapeProps, CustomStyleProps {
-  type: 'logseq-portal'
-  pageId: string // page name or UUID
-  blockType?: 'P' | 'B'
-  collapsed?: boolean
-  compact?: boolean
-  borderRadius?: number
-  collapsedHeight?: number
-  scaleLevel?: SizeLevel
-}
-
-const levelToScale = {
-  xs: 0.5,
-  sm: 0.8,
-  md: 1,
-  lg: 1.5,
-  xl: 2,
-  xxl: 3,
-}
-
-const LogseqPortalShapeHeader = observer(
-  ({
-    type,
-    fill,
-    opacity,
-    children,
-  }: {
-    type: 'P' | 'B'
-    fill?: string
-    opacity: number
-    children: React.ReactNode
-  }) => {
-    const bgColor =
-      fill !== 'var(--ls-secondary-background-color)'
-        ? getComputedColor(fill, 'background')
-        : 'var(--ls-tertiary-background-color)'
-
-    const fillGradient =
-      fill && fill !== 'var(--ls-secondary-background-color)'
-        ? isBuiltInColor(fill)
-          ? `var(--ls-highlight-color-${fill})`
-          : fill
-        : 'var(--ls-secondary-background-color)'
-
-    return (
-      <div
-        className={`tl-logseq-portal-header tl-logseq-portal-header-${
-          type === 'P' ? 'page' : 'block'
-        }`}
-      >
-        <div
-          className="absolute inset-0 tl-logseq-portal-header-bg"
-          style={{
-            opacity,
-            background:
-              type === 'P' ? bgColor : `linear-gradient(0deg, ${fillGradient}, ${bgColor})`,
-          }}
-        ></div>
-        <div className="relative">{children}</div>
-      </div>
-    )
-  }
-)
-
-export class LogseqPortalShape extends TLBoxShape<LogseqPortalShapeProps> {
-  static id = 'logseq-portal'
-  static defaultSearchQuery = ''
-  static defaultSearchFilter: 'B' | 'P' | null = null
-
-  static defaultProps: LogseqPortalShapeProps = {
-    id: 'logseq-portal',
-    type: 'logseq-portal',
-    parentId: 'page',
-    point: [0, 0],
-    size: [400, 50],
-    // collapsedHeight is the height before collapsing
-    collapsedHeight: 0,
-    stroke: '',
-    fill: '',
-    noFill: false,
-    borderRadius: 8,
-    strokeWidth: 2,
-    strokeType: 'line',
-    opacity: 1,
-    pageId: '',
-    collapsed: false,
-    compact: false,
-    scaleLevel: 'md',
-    isAutoResizing: true,
-  }
-
-  hideRotateHandle = true
-  canChangeAspectRatio = true
-  canFlip = true
-  canEdit = true
-
-  persist: ((replace?: boolean) => void) | null = null
-  // For quick add shapes, we want to calculate the page height dynamically
-  initialHeightCalculated = true
-  getInnerHeight: (() => number) | null = null // will be overridden in the hook
-
-  constructor(props = {} as Partial<LogseqPortalShapeProps>) {
-    super(props)
-    makeObservable(this)
-    if (props.collapsed) {
-      Object.assign(this.canResize, [true, false])
-    }
-    if (props.size?.[1] === 0) {
-      this.initialHeightCalculated = false
-    }
-  }
-
-  static isPageOrBlock(id: string): 'P' | 'B' | false {
-    const blockRefEg = '((62af02d0-0443-42e8-a284-946c162b0f89))'
-    if (id) {
-      return /^\(\(.*\)\)$/.test(id) && id.length === blockRefEg.length ? 'B' : 'P'
-    }
-    return false
-  }
-
-  @computed get collapsed() {
-    return this.props.blockType === 'B' ? this.props.compact : this.props.collapsed
-  }
-
-  @action setCollapsed = async (collapsed: boolean) => {
-    if (this.props.blockType === 'B') {
-      this.update({ compact: collapsed })
-      this.canResize[1] = !collapsed
-      if (!collapsed) {
-        this.onResetBounds()
-      }
-    } else {
-      const originalHeight = this.props.size[1]
-      this.canResize[1] = !collapsed
-      this.update({
-        isAutoResizing: !collapsed,
-        collapsed: collapsed,
-        size: [this.props.size[0], collapsed ? this.getHeaderHeight() : this.props.collapsedHeight],
-        collapsedHeight: collapsed ? originalHeight : this.props.collapsedHeight,
-      })
-    }
-    this.persist?.()
-  }
-
-  @computed get scaleLevel() {
-    return this.props.scaleLevel ?? 'md'
-  }
-
-  @action setScaleLevel = async (v?: SizeLevel) => {
-    const newSize = Vec.mul(
-      this.props.size,
-      levelToScale[(v as SizeLevel) ?? 'md'] / levelToScale[this.props.scaleLevel ?? 'md']
-    )
-    this.update({
-      scaleLevel: v,
-    })
-    await delay()
-    this.update({
-      size: newSize,
-    })
-  }
-
-  useComponentSize<T extends HTMLElement>(ref: React.RefObject<T> | null, selector = '') {
-    const [size, setSize] = React.useState<[number, number]>([0, 0])
-    const app = useApp<Shape>()
-    React.useEffect(() => {
-      setTimeout(() => {
-        if (ref?.current) {
-          const el = selector ? ref.current.querySelector<HTMLElement>(selector) : ref.current
-          if (el) {
-            const updateSize = () => {
-              const { width, height } = el.getBoundingClientRect()
-              const bound = Vec.div([width, height], app.viewport.camera.zoom) as [number, number]
-              setSize(bound)
-              return bound
-            }
-            updateSize()
-            // Hacky, I know 🤨
-            this.getInnerHeight = () => updateSize()[1]
-            const resizeObserver = new ResizeObserver(() => {
-              updateSize()
-            })
-            resizeObserver.observe(el)
-            return () => {
-              resizeObserver.disconnect()
-            }
-          }
-        }
-        return () => {}
-      }, 10);
-    }, [ref, selector])
-    return size
-  }
-
-  getHeaderHeight() {
-    const scale = levelToScale[this.props.scaleLevel ?? 'md']
-    return this.props.compact ? 0 : HEADER_HEIGHT * scale
-  }
-
-  getAutoResizeHeight() {
-    if (this.getInnerHeight) {
-      return this.getHeaderHeight() + this.getInnerHeight()
-    }
-    return null
-  }
-
-  onResetBounds = (info?: TLResetBoundsInfo) => {
-    const height = this.getAutoResizeHeight()
-    if (height !== null && Math.abs(height - this.props.size[1]) > AUTO_RESIZE_THRESHOLD) {
-      this.update({
-        size: [this.props.size[0], height],
-      })
-      this.initialHeightCalculated = true
-    }
-    return this
-  }
-
-  onResize = (initialProps: any, info: TLResizeInfo): this => {
-    const {
-      bounds,
-      rotation,
-      scale: [scaleX, scaleY],
-    } = info
-    const nextScale = [...this.scale]
-    if (scaleX < 0) nextScale[0] *= -1
-    if (scaleY < 0) nextScale[1] *= -1
-
-    let height = bounds.height
-
-    if (this.props.isAutoResizing) {
-      height = this.getAutoResizeHeight() ?? height
-    }
-
-    return this.update({
-      point: [bounds.minX, bounds.minY],
-      size: [Math.max(1, bounds.width), Math.max(1, height)],
-      scale: nextScale,
-      rotation,
-    })
-  }
-
-  PortalComponent = observer(({}: TLComponentProps) => {
-    const {
-      props: { pageId, fill, opacity },
-    } = this
-    const { renderers } = React.useContext(LogseqContext)
-    const app = useApp<Shape>()
-
-    const cpRefContainer = React.useRef<HTMLDivElement>(null)
-
-    const [, innerHeight] = this.useComponentSize(
-      cpRefContainer,
-      this.props.compact
-        ? '.tl-logseq-cp-container > .single-block'
-        : '.tl-logseq-cp-container > .page'
-    )
-
-    if (!renderers?.Page) {
-      return null // not being correctly configured
-    }
-    const { Page, Block } = renderers
-    const [loaded, setLoaded] = React.useState(false)
-
-    React.useEffect(() => {
-      if (this.props.isAutoResizing) {
-        const latestInnerHeight = this.getInnerHeight?.() ?? innerHeight
-        const newHeight = latestInnerHeight + this.getHeaderHeight()
-        if (innerHeight && Math.abs(newHeight - this.props.size[1]) > AUTO_RESIZE_THRESHOLD) {
-          this.update({
-            size: [this.props.size[0], newHeight],
-          })
-
-          if (loaded) app.persist({})
-        }
-      }
-    }, [innerHeight, this.props.isAutoResizing])
-
-    React.useEffect(() => {
-      if (!this.initialHeightCalculated) {
-        setTimeout(() => {
-          this.onResetBounds()
-          app.persist({})
-        })
-      }
-    }, [this.initialHeightCalculated])
-
-    React.useEffect(() => {
-      setTimeout(function () {
-        setLoaded(true)
-      })
-    }, [])
-
-    return (
-      <>
-        <div
-          className="absolute inset-0 tl-logseq-cp-container-bg"
-          style={{
-            textRendering: app.viewport.camera.zoom < 0.5 ? 'optimizeSpeed' : 'auto',
-            background:
-              fill && fill !== 'var(--ls-secondary-background-color)'
-                ? isBuiltInColor(fill)
-                  ? `var(--ls-highlight-color-${fill})`
-                  : fill
-                : 'var(--ls-secondary-background-color)',
-            opacity,
-          }}
-        ></div>
-        <div
-          ref={cpRefContainer}
-          className="relative tl-logseq-cp-container"
-          style={{ overflow: this.props.isAutoResizing ? 'visible' : 'auto' }}
-        >
-          {(loaded || !this.initialHeightCalculated) &&
-            (this.props.blockType === 'B' && this.props.compact ? (
-              <Block blockId={pageId} />
-            ) : (
-              <Page pageName={pageId} />
-            ))}
-        </div>
-      </>
-    )
-  })
-
-  ReactComponent = observer((componentProps: TLComponentProps) => {
-    const { events, isErasing, isEditing, isBinding } = componentProps
-    const {
-      props: { opacity, pageId, fill, scaleLevel, strokeWidth, size, isLocked },
-    } = this
-
-    const app = useApp<Shape>()
-    const { renderers, handlers } = React.useContext(LogseqContext)
-
-    this.persist = () => app.persist()
-    const isMoving = useCameraMovingRef()
-    const isSelected = app.selectedIds.has(this.id) && app.selectedIds.size === 1
-
-    const isCreating = app.isIn('logseq-portal.creating') && !pageId
-    const tlEventsEnabled =
-      (isMoving || (isSelected && !isEditing) || app.selectedTool.id !== 'select') && !isCreating
-    const stop = React.useCallback(
-      e => {
-        if (!tlEventsEnabled) {
-          // TODO: pinching inside Logseq Shape issue
-          e.stopPropagation()
-        }
-      },
-      [tlEventsEnabled]
-    )
-
-    // There are some other portal sharing the same page id are selected
-    const portalSelected =
-      app.selectedShapesArray.length === 1 &&
-      app.selectedShapesArray.some(
-        shape =>
-          shape.type === 'logseq-portal' &&
-          shape.props.id !== this.props.id &&
-          pageId &&
-          (shape as LogseqPortalShape).props['pageId'] === pageId
-      )
-
-    const scaleRatio = levelToScale[scaleLevel ?? 'md']
-
-    // It is a bit weird to update shapes here. Is there a better place?
-    React.useEffect(() => {
-      if (this.props.collapsed && isEditing) {
-        // Should temporarily disable collapsing
-        this.update({
-          size: [this.props.size[0], this.props.collapsedHeight],
-        })
-        return () => {
-          this.update({
-            size: [this.props.size[0], this.getHeaderHeight()],
-          })
-        }
-      }
-      return () => {
-        // no-ops
-      }
-    }, [isEditing, this.props.collapsed])
-
-    React.useEffect(() => {
-      if (isCreating) {
-        const screenSize = [app.viewport.bounds.width, app.viewport.bounds.height]
-        const boundScreenCenter = app.viewport.getScreenPoint([this.bounds.minX, this.bounds.minY])
-
-        if (
-          boundScreenCenter[0] > screenSize[0] - 400 ||
-          boundScreenCenter[1] > screenSize[1] - 240 ||
-          app.viewport.camera.zoom > 1.5 ||
-          app.viewport.camera.zoom < 0.5
-        ) {
-          app.viewport.zoomToBounds({ ...this.bounds, minY: this.bounds.maxY + 25 })
-        }
-      }
-    }, [app.viewport.bounds.height.toFixed(2)])
-
-    const onPageNameChanged = React.useCallback((id: string, isPage: boolean) => {
-      this.initialHeightCalculated = false
-      const blockType = isPage ? 'P' : 'B'
-      const height = isPage ? 320 : 40
-      this.update({
-        pageId: id,
-        size: [400, height],
-        blockType: blockType,
-        compact: blockType === 'B',
-      })
-      app.selectTool('select')
-      app.history.resume()
-      app.history.persist()
-    }, [])
-
-    const PortalComponent = this.PortalComponent
-
-    const blockContent = React.useMemo(() => {
-      if (pageId && this.props.blockType === 'B') {
-        return handlers?.queryBlockByUUID(pageId)?.title
-      }
-    }, [handlers?.queryBlockByUUID, pageId])
-
-    const targetNotFound = this.props.blockType === 'B' && typeof blockContent !== 'string'
-    const showingPortal = (!this.props.collapsed || isEditing) && !targetNotFound
-
-    if (!renderers?.Page) {
-      return null // not being correctly configured
-    }
-
-    const { Breadcrumb, PageName } = renderers
-
-    const portalStyle: React.CSSProperties = {
-      width: `calc(100% / ${scaleRatio})`,
-      height: `calc(100% / ${scaleRatio})`,
-      opacity: isErasing ? 0.2 : 1,
-    }
-
-    // Reduce the chance of blurry text
-    if (scaleRatio !== 1) {
-      portalStyle.transform = `scale(${scaleRatio})`
-    }
-
-    return (
-      <HTMLContainer
-        style={{
-          pointerEvents: 'all',
-        }}
-        {...events}
-      >
-        {isBinding && <BindingIndicator mode="html" strokeWidth={strokeWidth} size={size} />}
-        <div
-          data-inner-events={!tlEventsEnabled}
-          onWheelCapture={stop}
-          onPointerDown={stop}
-          onPointerUp={stop}
-          style={{
-            width: '100%',
-            height: '100%',
-            pointerEvents: !isMoving && (isEditing || isSelected) ? 'all' : 'none',
-          }}
-        >
-          {isCreating ? (
-            <LogseqQuickSearch
-              onChange={onPageNameChanged}
-              onAddBlock={uuid => {
-                // wait until the editor is mounted
-                setTimeout(() => {
-                  app.api.editShape(this)
-                  window.logseq?.api?.edit_block?.(uuid)
-                }, 128)
-              }}
-              placeholder="Create or search your graph..."
-            />
-          ) : (
-            <div
-              className="tl-logseq-portal-container"
-              data-collapsed={this.collapsed}
-              data-page-id={pageId}
-              data-portal-selected={portalSelected}
-              data-editing={isEditing}
-              style={portalStyle}
-            >
-              {!this.props.compact && !targetNotFound && (
-                <LogseqPortalShapeHeader
-                  type={this.props.blockType ?? 'P'}
-                  fill={fill}
-                  opacity={opacity}
-                >
-                  {this.props.blockType === 'P' ? (
-                    <PageName pageName={pageId} />
-                  ) : (
-                    <Breadcrumb blockId={pageId} />
-                  )}
-                </LogseqPortalShapeHeader>
-              )}
-              {targetNotFound && <div className="tl-target-not-found">Target not found</div>}
-              {showingPortal && <PortalComponent {...componentProps} />}
-            </div>
-          )}
-        </div>
-      </HTMLContainer>
-    )
-  })
-
-  ReactIndicator = observer(() => {
-    const bounds = this.getBounds()
-    return (
-      <rect
-        width={bounds.width}
-        height={bounds.height}
-        fill="transparent"
-        rx={8}
-        ry={8}
-        strokeDasharray={this.props.isLocked ? '8 2' : 'undefined'}
-      />
-    )
-  })
-
-  validateProps = (props: Partial<LogseqPortalShapeProps>) => {
-    if (props.size !== undefined) {
-      const scale = levelToScale[this.props.scaleLevel ?? 'md']
-      props.size[0] = Math.max(props.size[0], 60 * scale)
-      props.size[1] = Math.max(props.size[1], HEADER_HEIGHT * scale)
-    }
-    return withClampedStyles(this, props)
-  }
-
-  getShapeSVGJsx({ preview }: any) {
-    // Do not need to consider the original point here
-    const bounds = this.getBounds()
-
-    return (
-      <>
-        <rect
-          fill={
-            this.props.fill && this.props.fill !== 'var(--ls-secondary-background-color)'
-              ? isBuiltInColor(this.props.fill)
-                ? `var(--ls-highlight-color-${this.props.fill})`
-                : this.props.fill
-              : 'var(--ls-secondary-background-color)'
-          }
-          stroke={getComputedColor(this.props.fill, 'background')}
-          strokeWidth={this.props.strokeWidth ?? 2}
-          fillOpacity={this.props.opacity ?? 0.2}
-          width={bounds.width}
-          rx={8}
-          ry={8}
-          height={bounds.height}
-        />
-        {!this.props.compact && (
-          <rect
-            fill={
-              this.props.fill && this.props.fill !== 'var(--ls-secondary-background-color)'
-                ? getComputedColor(this.props.fill, 'background')
-                : 'var(--ls-tertiary-background-color)'
-            }
-            fillOpacity={this.props.opacity ?? 0.2}
-            x={1}
-            y={1}
-            width={bounds.width - 2}
-            height={HEADER_HEIGHT - 2}
-            rx={8}
-            ry={8}
-          />
-        )}
-        <text
-          style={{
-            transformOrigin: 'top left',
-          }}
-          transform={`translate(${bounds.width / 2}, ${10 + bounds.height / 2})`}
-          textAnchor="middle"
-          fontFamily="var(--ls-font-family)"
-          fontSize="32"
-          fill="var(--ls-secondary-text-color)"
-          stroke="var(--ls-secondary-text-color)"
-        >
-          {this.props.blockType === 'P' ? this.props.pageName : ''}
-        </text>
-      </>
-    )
-  }
-}

+ 0 - 83
packages/tldraw/apps/tldraw-logseq/src/lib/shapes/PdfShape.tsx

@@ -1,83 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import * as React from 'react'
-import { TLBoxShape, TLBoxShapeProps } from '@tldraw/core'
-import { HTMLContainer, TLComponentProps, useApp } from '@tldraw/react'
-import { observer } from 'mobx-react-lite'
-import { LogseqContext } from '../logseq-context'
-import { useCameraMovingRef } from '../../hooks/useCameraMoving'
-
-export interface PdfShapeProps extends TLBoxShapeProps {
-  type: 'pdf'
-  assetId: string
-}
-
-export class PdfShape extends TLBoxShape<PdfShapeProps> {
-  static id = 'pdf'
-  frameRef = React.createRef<HTMLElement>()
-
-  static defaultProps: PdfShapeProps = {
-    id: 'pdf',
-    type: 'pdf',
-    parentId: 'page',
-    point: [0, 0],
-    size: [595, 842],
-    assetId: '',
-  }
-
-  canChangeAspectRatio = true
-  canFlip = true
-  canEdit = true
-
-  ReactComponent = observer(({ events, asset, isErasing, isEditing }: TLComponentProps) => {
-    const ref = React.useRef<HTMLElement>(null)
-    const { handlers } = React.useContext(LogseqContext)
-    const app = useApp<Shape>()
-
-    const isMoving = useCameraMovingRef()
-
-    return (
-      <HTMLContainer
-        style={{
-          overflow: 'hidden',
-          pointerEvents: 'all',
-          opacity: isErasing ? 0.2 : 1,
-        }}
-        {...events}
-      >
-        {asset ? (
-          <embed
-            src={handlers ? handlers.inflateAsset(asset.src).url : asset.src}
-            className="relative tl-pdf-container"
-            onWheelCapture={stop}
-            onPointerDown={stop}
-            onPointerUp={stop}
-            style={{
-              width: '100%',
-              height: '100%',
-              pointerEvents: !isMoving && isEditing ? 'all' : 'none',
-            }}
-          />
-        ) : null}
-      </HTMLContainer>
-    )
-  })
-
-  ReactIndicator = observer(() => {
-    const {
-      props: {
-        size: [w, h],
-        isLocked,
-      },
-    } = this
-    return (
-      <rect
-        width={w}
-        height={h}
-        fill="transparent"
-        rx={8}
-        ry={8}
-        strokeDasharray={isLocked ? '8 2' : 'undefined'}
-      />
-    )
-  })
-}

+ 0 - 77
packages/tldraw/apps/tldraw-logseq/src/lib/shapes/PenShape.tsx

@@ -1,77 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import { getStroke } from 'perfect-freehand'
-import { SvgPathUtils, TLDrawShape, TLDrawShapeProps, getComputedColor } from '@tldraw/core'
-import { SVGContainer, TLComponentProps } from '@tldraw/react'
-import { observer } from 'mobx-react-lite'
-import { computed, makeObservable } from 'mobx'
-import { CustomStyleProps, withClampedStyles } from './style-props'
-
-export interface PenShapeProps extends TLDrawShapeProps, CustomStyleProps {
-  type: 'pen'
-}
-
-export class PenShape extends TLDrawShape<PenShapeProps> {
-  constructor(props = {} as Partial<PenShapeProps>) {
-    super(props)
-    makeObservable(this)
-  }
-
-  static id = 'pen'
-
-  static defaultProps: PenShapeProps = {
-    id: 'pen',
-    parentId: 'page',
-    type: 'pen',
-    point: [0, 0],
-    points: [],
-    isComplete: false,
-    stroke: '',
-    fill: '',
-    noFill: false,
-    strokeType: 'line',
-    strokeWidth: 2,
-    opacity: 1,
-  }
-
-  @computed get pointsPath() {
-    const {
-      props: { points, isComplete, strokeWidth },
-    } = this
-    if (points.length < 2) {
-      return `M -4, 0
-      a 4,4 0 1,0 8,0
-      a 4,4 0 1,0 -8,0`
-    }
-    const stroke = getStroke(points, { size: 4 + strokeWidth * 2, last: isComplete })
-    return SvgPathUtils.getCurvedPathForPolygon(stroke)
-  }
-
-  ReactComponent = observer(({ events, isErasing }: TLComponentProps) => {
-    const {
-      pointsPath,
-      props: { stroke, strokeWidth, opacity },
-    } = this
-    return (
-      <SVGContainer {...events} opacity={isErasing ? 0.2 : opacity}>
-        <path
-          d={pointsPath}
-          strokeWidth={strokeWidth}
-          stroke={getComputedColor(stroke, 'stroke')}
-          fill={getComputedColor(stroke, 'stroke')}
-          pointerEvents="all"
-        />
-      </SVGContainer>
-    )
-  })
-
-  ReactIndicator = observer(() => {
-    const { pointsPath } = this
-    return <path d={pointsPath} strokeDasharray={this.props.isLocked ? '8 2' : 'undefined'} />
-  })
-
-  validateProps = (props: Partial<PenShapeProps>) => {
-    props = withClampedStyles(this, props)
-    if (props.strokeWidth !== undefined) props.strokeWidth = Math.max(props.strokeWidth, 1)
-    return props
-  }
-}

Some files were not shown because too many files changed in this diff